⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wm.c

📁 在ucos上实现了图形用户接口GUI;值得一看
💻 C
📖 第 1 页 / 共 3 页
字号:
    r.x0 = ClipContext.ClientRect.x0;
    r.y0 = ClipContext.ClientRect.y0;
  } else {
    r.x0 = ClipContext.CurRect.x1+1;
    r.y0 = ClipContext.CurRect.y0;
    if (r.x0 > ClipContext.ClientRect.x1) {
NextStripe:  // go down to next stripe
      r.x0 = ClipContext.ClientRect.x0;
      r.y0 = ClipContext.CurRect.y1+1;
    }
  }
  //
  //   STEP 2:
  //     Check if we are done completely.

  if (r.y0 >ClipContext.ClientRect.y1)
    return 0;

  // STEP 3:
  //     Find out the max. height (r.y1) if we are at the left border.
  //     Since we are using the same height for all IVRs at the same y0,
  //     we do this only for the leftmost one.

  pAWin = WM_H2P(GUI_Context.hAWin);
  if (r.x0 == ClipContext.ClientRect.x0) {
    r.y1 = ClipContext.ClientRect.y1;
    r.x1 = ClipContext.ClientRect.x1;
    // Iterate over all windows which are above
    // Check all siblings above (Iterate over Parents and top siblings (hNext)
    for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
      pParent = WM_H2P(hParent);
      for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) {
	Status = (pWin = WM_H2P(iWin))->Status;
	// Check if this window affects us at all
	if ((Status & WM_SF_ISVIS)  && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {
	  if (pWin->Rect.y0 > r.y0) {
	    ASSIGN_IF_LESS(r.y1, pWin->Rect.y0-1);      // Check upper border of window
	  } else {
	    ASSIGN_IF_LESS(r.y1, pWin->Rect.y1);        // Check lower border of window
	  }
	}
      }
    }
    // Check all children
    for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) {
      Status = (pWin = WM_H2P(iWin))->Status;
      // Check if this window affects us at all
      if ((Status & WM_SF_ISVIS)  && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {
	if (pWin->Rect.y0 > r.y0) {
	  ASSIGN_IF_LESS(r.y1, pWin->Rect.y0-1);      // Check upper border of window
	} else {
	  ASSIGN_IF_LESS(r.y1, pWin->Rect.y1);        // Check lower border of window
	}
      }
    }
  }
  //
  //  STEP 4
  //    Find out x0 for the given y0, y1 by iterating over windows above.
  //    if we find one that intersects, adjust x0 to the right.
  //

Find_x0:
  r.x1 = r.x0;
  // Iterate over all windows which are above
  // Check all siblings above
    for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
    pParent = WM_H2P(hParent);
    for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) {
      Status = (pWin = WM_H2P(iWin))->Status;
      if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     // Check if this window affects us at all
	r.x0 = pWin->Rect.x1+1;
	goto Find_x0;
      }
    }
  }
  // Check all children
  for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) {
    Status = (pWin = WM_H2P(iWin))->Status;
    if ( (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     // Check if this window affects us at all
      r.x0 = pWin->Rect.x1+1;
      goto Find_x0;
    }
  }
  //
  // STEP 5:
  //   If r.x0 out of right border, this stripe is done. Set next stripe and goto STEP 2
  //   Find out x1 for the given x0, y0, y1

  r.x1 = ClipContext.ClientRect.x1;
  if (r.x1 < r.x0) {// horizontal border reached ?
    ClipContext.CurRect = r;
    goto NextStripe;
  }
  //
  // STEP 6:
  //   Find r.x1. We have to Iterate over all windows which are above

  // Check all siblings above (Iterate over Parents and top siblings (hNext)

  for (hParent = GUI_Context.hAWin; hParent; hParent = pParent->hParent) {
    pParent = WM_H2P(hParent);
    for (iWin= pParent->hNext; iWin !=0; iWin = pWin->hNext) {
      Status = (pWin = WM_H2P(iWin))->Status;
      if (    (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     // Check if this window affects us at all
	r.x1 = pWin->Rect.x0-1;
      }
    }
  }
  // Check all children
  for (iWin= pAWin->hFirstChild; iWin !=0; iWin = pWin->hNext) {
    Status = (pWin = WM_H2P(iWin))->Status;
    if (    (Status & WM_SF_ISVIS) && (!(Status & WM_SF_HASTRANS)) && GUI_RectsIntersect(&r, &pWin->Rect)) {     // Check if this window affects us at all
      r.x1 = pWin->Rect.x0-1;
    }
  }
  // We are done. Return the rectangle we found in the ClipContext.
  if (ClipContext.Cnt >200) {
    return 0;  // error !!! This should not happen !
  }
  ClipContext.CurRect = r;
  return 1;  // IVR is valid !
}

#else
static int FindNext_IVR(void) {
  if (ClipContext.Cnt ==0) {
    ClipContext.CurRect = GUI_Context.pAWin->Rect;
    return 1;  // IVR is valid !
  }
  return 0;  // Nothing left to draw
}
#endif



/********************************************************************
*
*              Get next IVR

  Sets the next clipping rectangle. If a valid one has
  been found (and set), 1 is returned in order to indicate
  that the drawing operation needs to be executed.
  Returning 0 signals that we have iterated over all
  rectangles.

  Returns: 0 if no valid rectangle is found
	   1 if rectangle has been found
*/


int  WM__GetNextIVR   (void) {
  #if GUI_SUPPORT_CURSOR
    static char _CursorHidden;
  #endif
  // If WM is not active, we have no rectangles to return
  if (WM_IsActive==0)
    return 0;
  if (ClipContext.EntranceCnt > 1) {
    ClipContext.EntranceCnt--;
    return 0;
  }
  #if GUI_SUPPORT_CURSOR
    if (_CursorHidden) {
      _CursorHidden = 0;
      (*GUI_CURSOR_pfTempUnhide) ( &ClipContext.CurRect);
    }
  #endif
  ++ClipContext.Cnt;
  // Find next rectangle and use it as ClipRect
  if (!FindNext_IVR()) {
    ClipContext.EntranceCnt--;  // This search is over !
    return 0;        // Could not find an other one !
  }
  // Hide cursor if necessary
  LCD_SetClipRectEx(&ClipContext.CurRect);
  #if GUI_SUPPORT_CURSOR
    if (GUI_CURSOR_pfTempHide) {
      _CursorHidden = 1;
      (*GUI_CURSOR_pfTempHide) ( &ClipContext.CurRect);
    }
  #endif
  return 1;
}


/********************************************************************
*
*              Init IVR  search

  This routine is called from the clipping level
  (the WM_ITERATE_START macro) when starting an iteration over the
  visible rectangles.

  Return value:
    0 : There is no valid rectangle (nothing to do ...)
    1 : There is a valid rectangle
*/


int WM__InitIVRSearch(const GUI_RECT* pMaxRect) {
  GUI_RECT r;
  WM_Obj* pAWin;
   // If WM is not active -> nothing to do, leave cliprect alone
  if (WM_IsActive==0)
    return 1;
  // If we entered multiple times, leave Cliprect alone
  if (++ClipContext.EntranceCnt > 1)
    return 1;
  pAWin = WM_H2P(GUI_Context.hAWin);
  ClipContext.Cnt        = -1;
  // When using callback mechanism, it is legal to reduce drawing
  //  area to the invalid area !
  if (IsInCallback) {
    WM__GetInvalidRectAbs(pAWin, &r);
  } else {  // Not using callback mechanism, therefor allow entire rectangle
    if (pAWin->Status & WM_SF_ISVIS) {
      r = pAWin->Rect;
    } else {
      --ClipContext.EntranceCnt;
      return 0;  // window is not even visible !
    }
  }
  // If the drawing routine has specified a rectangle, use it to reduce the rectangle
  if (pMaxRect) {
    GUI__IntersectRect(&r, pMaxRect);
  }
  // If user has reduced the cliprect size, reduce the rectangle
  if (GUI_Context.WM__pUserClipRect) {
    GUI_RECT rUser = *(GUI_Context.WM__pUserClipRect);
    WM__Client2Screen(pAWin, &rUser);
    GUI__IntersectRect(&r, &rUser);
  }
  // Iterate over all ancestors and clip at their borders
  _ClipAtParentBorders(&r, pAWin);
  // Store the rectangle and find the first rectangle of the area
  ClipContext.ClientRect = r;
  return WM__GetNextIVR();
}


/*
	  ********************************************
	  *                                          *
	  *       Set default                        *
	  *                                          *
	  ********************************************

  This routine sets the defaults for WM and the layers below.
  It is used before a drawing routine is called in order to
  make sure that defaults are set (in case the default settings
  had been altered before by the application)
*/

void WM_SetDefault(void) {
  GL_SetDefault();
  GUI_Context.WM__pUserClipRect = NULL;   // No add. clipping
}

/*
  ********************************************
  *
  *        Callback for Paint message
  *
  ********************************************

  This callback is used by the window manger in conjunction with banding
  memory devices. A pointer to this routine is given to the banding memory device.
  This callback in turn will send the paint message to the window.
*/


#if GUI_SUPPORT_MEMDEV
static void cbPaint(void* pMsg) {
  WM_SendMessage(((WM_MESSAGE*)pMsg)->hWin, (WM_MESSAGE*) pMsg);
}

#endif

/*
	  ********************************************
	  *                                          *
	  *       Draw next window                   *
	  *                                          *
	  ********************************************
*/

static void _DrawNext(void) {
  int UpdateRem = 1;
  WM_HWIN iWin = (NextDrawWin == WM_HWIN_NULL) ? WM__FirstWin : NextDrawWin;
  GUI_CONTEXT ContextOld;
  GUI_SaveContext(&ContextOld);          //save old context
  // Make sure the next window to redraw is valid
  for (; (iWin!=WM_HWIN_NULL) && UpdateRem; ) {
    WM_Obj* pWin = WM_H2P(iWin);
    if (pWin->Status & WM_SF_INVALID) { //if status flag is invalue
      U8 Status = (pWin->Status &=  ~WM_SF_INVALID); // Clear invalid flag
      WM__NumInvalidWindows--;          //update the number of invalue windows
      // Send WM_PAINT if window is visible and a callback is defined
      if ((pWin->cb != NULL)  && (Status & WM_SF_ISVIS)) {
	WM_MESSAGE Msg;
	Msg.hWin   = iWin;
	Msg.MsgId  = WM_PAINT;
	Msg.Data.p = (GUI_RECT*)&pWin->InvalidRect;
	WM_SelectWindow(iWin);  //select the new window
	WM_SetDefault();        //set default config,e.g. font,pensize...
	/*
	#if GUI_SUPPORT_MEMDEV
	  if (Status & WM_SF_MEMDEV) {
	    GUI_RECT r = pWin->InvalidRect;
	    GUI_MoveRect (&r, pWin->Rect.x0, pWin->Rect.y0);
	    //GUI_MEMDEV_Draw(&r, cbPaint, &Msg, 0, (Status & WM_SF_HASTRANS) ? GUI_MEMDEV_HASTRANS : 0);
	  } else
	#endif
	*/
	WM_SendMessage(iWin, &Msg);//send message "WM_PAINT" to current window.
	UpdateRem--;  // Only the given number of windows at a time ...
      }
    }
    iWin = pWin->hNextLin;
  }
  NextDrawWin = iWin;   // Remember the window
  GUI_RestoreContext(&ContextOld);
}

/*
	  *****************************************************************
	  *                                                               *
	  *                 Idle loop                                     *
	  *                                                               *
	  *****************************************************************
*/

int WM_Exec1(void) {
  if (WM_pfHandleHID) {
    if (WM_pfHandleHID())
      return 1;               // We have done something ...
  }
  if (GUI_PollKeyMsg()) {
    return 1;               // We have done something ...
  }
  if (WM_IsActive && WM__NumInvalidWindows) {
    WM_LOCK();
    _DrawNext();
    WM_UNLOCK();
    return 1;               // We have done something ...
  }
  return 0;                  // There was nothing to do ...
}

int WM_Exec(void) {
  int r = 0;
  while (WM_Exec1()) {
    r = 1;                  // We have done something
  }
  return r;
}

/***************************************************************
*                                                               *
*              Callback for background window                   *
*                                                               *
*****************************************************************
*/

static WM_RESULT cbBackWin(WM_MESSAGE* pMsg) {
  WM_KEY_INFO* pKeyInfo;
  switch (pMsg->MsgId) {
  case WM_KEY:
    pKeyInfo = (WM_KEY_INFO*)pMsg->Data.p;
    if (pKeyInfo->PressedCnt == 0) {
      GUI_StoreKey(pKeyInfo->Key);
    }
    break;
  case WM_PAINT:
    if (WM__BkColor != GUI_INVALID_COLOR) {
      GUI_SetBkColor(WM__BkColor);
      GUI_Clear();
    }
  default:
    WM_DefaultProc(pMsg);
  }
}


/***************************************************************
*
*                    WM_Activate  / WM_Deactivate
*
*****************************************************************
*/


void WM_Activate(void) {
  WM_IsActive = 1;       // Running
}


void WM_Deactivate(void) {
  WM_IsActive = 0;       // No clipping performed by WM
  WM__SetMaxClipRect(WM_H2P(WM_HBKWIN));
}


/*
	  *****************************************************************
	  *                                                               *
	  *              WM_Init                                         *
	  *                                                               *
	  *****************************************************************
*/

void WM_Init(void) {
	if (!_IsInited) {
	  WM_HWIN hWin;
	  NextDrawWin = WM__FirstWin = WM_HWIN_NULL;
	  GUI_Context.WM__pUserClipRect = NULL;
	  WM__NumWindows = WM__NumInvalidWindows =0;
	  // Make sure we have at least one window. This greatly simplifies the
	  // drawing routines as they do not have to check if the window is valid.

	  hWin = WM_CreateWindow(LCD_ORGX, LCD_ORGY, GUI_XMAX, GUI_YMAX, WM_CF_SHOW, cbBackWin, 0);
	  //hWin = WM_CreateWindow(0, 0, 320, 240, WM_CF_SHOW, cbBackWin, 0);

	  WM_SelectWindow(hWin);
	  WM_Activate();
    _IsInited =1;
	}
}



/*
	  ******************************************************
	  *                                                    *
	  *              Default procedure                     *
	  *                                                    *
	  ******************************************************
*/


WM_RESULT WM_DefaultProc(WM_MESSAGE* pMsg) {
  WM_HWIN hWin = pMsg->hWin;
  void *p = pMsg->Data.p;
  WM_Obj* pWin = WM_H2P(hWin);
  // Exec message
  switch (pMsg->MsgId) {
  case WM_GETORG:
    ((GUI_POINT*)p)->x = pWin->Rect.x0;
    ((GUI_POINT*)p)->y = pWin->Rect.y0;
    break;
  case WM_GETCLIENTRECT:     // return client window in window coordinates
    WM__GetClientRectWin(pWin, (GUI_RECT*)p);
    break;
  case WM_GETCLIENTRECT_ABS:      // return client window in absolute (screen) coordinates
    WM__GetClientRectWin(pWin, (GUI_RECT*)p);
    GUI_MoveRect((GUI_RECT*)p, pWin->Rect.x0, pWin->Rect.y0);
    break;
  case WM_GET_CLIENT_WINDOW:      // return handle to client window. For most windows, there is no seperate client window, so it is the same handle
    pMsg->Data.v = hWin;
    return;                       // Message handled
  case WM_KEY:
    WM_SendToParent(hWin, pMsg);
    return;                       // Message handled
  case WM_GET_BKCOLOR:
    pMsg->Data.Color = GUI_INVALID_COLOR;
    return;                       // Message handled
  }
  // Message not handled. If it queries something, we return 0 to be on the safe side.
  pMsg->Data.v = 0;
  pMsg->Data.p = 0;
}

#else

void WM(void) {} // avoid empty object files

#endif // WM_MAX_WINDOW

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -