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

📄 wm.c

📁 在ucos上实现了图形用户接口GUI;值得一看
💻 C
📖 第 1 页 / 共 3 页
字号:
  GUI_MoveRect (pRect, pWin->Rect.x0, pWin->Rect.y0);
}


/*
	  *****************************************************************
	  *                                                               *
	  *              Invalidation functions                           *
	  *                                                               *
	  *****************************************************************
// Invalidate, using window coordinates
*/

static void WM_InvalidateBWin1(WM_HWIN hWin, const GUI_RECT*pRect) {
  GUI_RECT r;
  WM_Obj* pWin = WM_H2P(hWin);
  WM__GetClientRectWin(pWin, &r);
  if (pRect)
    GUI__IntersectRect(&r, pRect);
  if (WM__RectIsNZ(&r)) {
    if (pWin->Status & WM_SF_INVALID) {
      GUI_MergeRect(&pWin->InvalidRect, &pWin->InvalidRect, &r);
    } else {
      pWin->InvalidRect = r;
      pWin->Status |= WM_SF_INVALID;
      WM__NumInvalidWindows++;
      // Debug code: shows invalid areas
      #if (WM_SHOW_INVALID)
      {
	GUI_CONTEXT Context = GUI_Context;
	WM_SelectWindow(hWin);
	GUI_SetBkColor(GUI_GREEN);
	GUI_ClearRect(r.x0, r.y0, r.x1, r.y1);
	GUI_Context = Context;
      }
      #endif


    }
  }
}

// Invalidate, using desktop coordinates (only this window,
//   not the ones below !!!)

static void WM_InvalidateBWin1Abs(WM_HWIN hWin, const GUI_RECT*pRect) {
  GUI_RECT r = *pRect;
  WM_LOCK();
  GUI_MoveRect(&r, -WM_H2P(hWin)->Rect.x0, -WM_H2P(hWin)->Rect.y0);
  WM_InvalidateBWin1(hWin, &r);
  WM_UNLOCK();
}



/*
  Invalidate a certain section of the display. One main reason for this is
  that a window has been moved or destroyed.
  The following windows are affected:
  * windows below the window creating the invalidation.
  * transparent windows located above
  The coordinates given are absolute coordinates (desktop coordinates)
*/


void WM__InvalidateAreaBelow(const GUI_RECT* pRect, WM_HWIN StopWin) {
  WM_HWIN   iWin, iNext;
  // Iterate over windows below StopWin
  for (iWin = WM__FirstWin; iWin!=StopWin; iWin = iNext) {
    GUI_RECT r = *pRect;
    WM_Obj* pWin = WM_H2P(iWin);
    iNext = pWin->hNextLin;
    if (GUI__IntersectRects(&r, &r, &pWin->Rect)) {
      WM_InvalidateBWin1Abs (iWin, &r);
    }
  };
}


/*
  Invalidate any transparent window above the given area
*/

void WM__InvalidateTransAreaAbove(const GUI_RECT* pRect, WM_HWIN StopWin) {
  GUI_USE_PARA(pRect);
  GUI_USE_PARA(StopWin);
#if 0
  WM_HWIN   iWin;
  // Iterate over windows below StopWin
  for (iWin = StopWin; iWin!=WM_HWIN_NULL; iWin = WM_H2P(iWin)->Next) {
    WM_Obj *pWin = WM_H2P(iWin);
    if (pWin->Status & WM_SF_HASTRANS) {
      GUI_RECT r = *pRect;
      if (GUI__IntersectRects(&r, &r, &WM_H2P(iWin)->Rect)) {
	WM_InvalidateBWin1Abs (iWin, &r);
      }
    }
  }
#endif
}


/*
	  *****************************************************************
	  *                                                               *
	  *              Invalidation functions                           *
	  *                                                               *
	  *****************************************************************


// Invalidate a section of the window. The optional rectangle
   contains client coordinates, which are independent of the
   position of the window on the logical desktop area.
*/


void WM_InvalidateRect(WM_HWIN hWin, const GUI_RECT*pRect) {
  GUI_RECT r;
  WM_Obj* pWin;
  WM_LOCK();
  pWin = WM_H2P(hWin);
  WM__GetClientRectWin(pWin, &r);//get the window's max area

  if (pRect) {
    GUI__IntersectRect(&r, pRect);
  }
  WM_InvalidateBWin1(hWin, &r);
// Convert into absolute coordinates ...
  GUI_MoveRect (&r, pWin->Rect.x0, pWin->Rect.y0);
// Make sure windows below are invalidated if this one is transparent
  if (pWin->Status & WM_SF_HASTRANS) {
    ResetNextDrawWin();
    WM__InvalidateAreaBelow(&r, hWin);
  }
// Invalidate the transparent ones above
  WM__InvalidateTransAreaAbove(&r,hWin);
  WM_UNLOCK();
}


void WM_InvalidateWindow(WM_HWIN hWin) {
  WM_InvalidateRect(hWin, NULL);
}

// Invalidate, using desktop coordinates

void WM_InvalidateBWinAbs(WM_HWIN hWin, const GUI_RECT*pRect) {
  GUI_RECT r = *pRect;
  WM_LOCK();
  GUI_MoveRect(&r, -WM_H2P(hWin)->Rect.x0, -WM_H2P(hWin)->Rect.y0);
  WM_InvalidateRect(hWin, &r);
  WM_UNLOCK();
}


/*
  Invalidate a certain section of the display. One main reason for this is
  that the top window has been moved or destroyed.
  The coordinates given are absolute coordinates (desktop coordinates)
*/

void WM_InvalidateArea(GUI_RECT* pRect) {
  WM_HWIN   iWin;
  WM_LOCK();
  // Iterate over all windows
  for (iWin=WM__FirstWin; iWin !=0; ) {
    WM_Obj* pWin = WM_H2P(iWin);
    GUI_RECT r = *pRect;
    GUI__IntersectRect(&r, &pWin->Rect);
    // Calculate which area is actually visible by subtracting the
    //   windows which are on top of this one
    WM_InvalidateBWinAbs (iWin, &r);
    iWin = pWin->hNextLin;
  }
  WM_UNLOCK();
}


/*
  ********************************************************************
  *                                                                  *
  *              manage windows stack                                *
  *                                                                  *
  ********************************************************************
// Return index (handle) of the window which is bottom of stack.
   Note that in the current implementation, this is always
   window 0.
*/


WM_HWIN WM_GetDesktopWindow(void) {
  return WM__FirstWin;
}


/*
  ********************************************************************
  *
  *              Create window (as child)
  *
  ********************************************************************
*/


WM_HWIN WM_CreateWindowAsChild(
		    int x0, int y0, int width, int height
		   ,WM_HWIN hWinParent
		   ,U16 Style
		   ,WM_CALLBACK* cb
		   ,int NumExtraBytes)
{
  WM_Obj* pWin;
  WM_HWIN hWin;
  WM_LOCK();
  Style |= WM__CreateFlags;
  // Get Parent info
  if (!hWinParent) {//if this window has no parent,and WM__NumWindow>0 show now this window
		    //if not the background-window and background-window had been exist,
		    //so set this window's parent to background-window.
    if (WM__NumWindows) {
      hWinParent = WM_HBKWIN;
    }
  }
  if (hWinParent) {
    GUI_RECT Rect;
    WM_MESSAGE Msg;
    Msg.MsgId = WM_GETCLIENTRECT_ABS;
    Msg.Data.p = &Rect;
    WM_SendMessage(hWinParent, &Msg);
    x0 += Rect.x0;
    y0 += Rect.y0;
    if (width==0)
      width = Rect.x1-Rect.x0+1;
    if (height==0)
      height = Rect.y1-Rect.y0+1;
  }
  if (NumExtraBytes<0)
    NumExtraBytes=0;

  if ((hWin = (WM_HWIN) WM_ALLOC(NumExtraBytes+sizeof(WM_Obj))) == 0) {//Alloc some memory for this window
    //GUI_DEBUG_ERROROUT("WM_CreateWindow: No memory to create window");
  }
  else {
    WM__NumWindows++;
    pWin = WM_H2P(hWin);
    memset (pWin,   0, sizeof(WM_Obj));        // erase this data structure
	   //The explicit zero-init is no longer needed since the entire data structure
	   //is already zeroed. The advantage is that it reduces program size.

    pWin->Rect.x0 = x0;
    pWin->Rect.y0 = y0;
    pWin->Rect.x1 = x0+width-1;
    pWin->Rect.y1 = y0+height-1;
    pWin->Status = WM_SF_INUSE;     // Mark window as in use
    pWin->cb = cb;
    // Add to linked lists
    pWin->hParent = hWinParent;
    _AddChild(hWinParent, hWin, Style & WM_CF_STAYONTOP);//add hWin to be hWinParent's child
    _AddToLinList(hWin);//add hWin to the windows link,like : first_win(desktop window)->second_win->third_win....
  // Put Window on top (or bottom) of windows stack
    if (Style & WM_CF_ACTIVATE ) {//| (cb==NULL)
      WM_SelectWindow(hWin);  // This is not needed
			      //   if callbacks are being used, but it
			      //   does not cost a lot and makes life
			      //   easier ...
    }
  // Mark client area as invalid
    WM__SendMsgNoData(hWin, WM_CREATE);
  // Handle the Style flags, one at a time
    if (Style & WM_CF_SHOW) {
      WM_ShowWindow(hWin);
    }
  // Hide if parent is not visible
    if (hWinParent) {
      WM_Obj* pWinParent = WM_H2P(hWinParent);
      if (!(pWinParent->Status & WM_SF_ISVIS)) {
	WM_HideWindow(hWin);
      }
    }
    // Copy the flags which can simply be accepted
    pWin->Status |= (Style & (WM_SF_MEMDEV|WM_SF_STAYONTOP|WM_SF_HASTRANS));
  }
  WM_UNLOCK();
  return hWin;
}

WM_HWIN WM_CreateWindow(int x0, int y0, int width, int height, U16 Style, WM_CALLBACK* cb, int NumExtraBytes) {
  return WM_CreateWindowAsChild(x0,y0,width,height, 0  ,  Style, cb, NumExtraBytes);// No parent
}


/***************************************************************
*
*          Delete window
*
***************************************************************/


void WM_DeleteWindow (WM_HWIN Win) {
  WM_Obj* pWin;
  if (!Win)
    return;
  WM_LOCK();
  if (WM__IsWindow(Win)) {
    pWin = WM_H2P(Win);
    ResetNextDrawWin();              // Make sure the window will no longer receive drawing messages
  // Make sure that focus is set to an existing window
    if (WM__hWinFocus == Win) {
      WM__hWinFocus = 0;
    }
    if (Win == WM__hCapture) {
      WM__hCapture = 0;
    }
  // Delete all children
    _DeleteAllChildren(pWin->hFirstChild);
    _DeleteInSiblingList(Win);
  // Send WM_DELETE message to window in order to inform window itself
    WM__SendMsgNoData(Win, WM_DELETE);     // tell window about it
    // Inform other modules if necessary
    if (WM__pfDeleteWindowHook) {
      (*WM__pfDeleteWindowHook)(Win);
    }
  // Remove window from window stack
    if (pWin->Status & WM_SF_INVALID) {
      WM__NumInvalidWindows--;
    }
    WM__RemoveFromLinList(Win);
  // Clear area used by this window
    WM_InvalidateArea(&pWin->Rect);
  // Free window memory
    WM__NumWindows--;
    WM_FREE(Win);
  // Select a valid window
    WM_SelectWindow(WM__FirstWin);
  } else {
    //GUI_DEBUG_WARN("WM_DeleteWindow: Invalid handle");
  }
  WM_UNLOCK();
}


void WM__SetMaxClipRect(const WM_Obj* pWin) {
  WM_LOCK();
  LCD_SetClipRectEx(&pWin->Rect);
  WM_UNLOCK();
}


/***************************************************************
*
*              WM_SelectWindow
*
***************************************************************

Sets the active Window. The active Window is the one that is used for all
drawing (and text) operations.
*/


WM_HWIN WM_SelectWindow(WM_HWIN  hWin) {
  WM_HWIN hWinPrev;
  WM_LOCK();
  hWinPrev = GUI_Context.hAWin;
  if (hWin == 0) {
    hWin = WM__FirstWin;
  }
  if (!(WM_H2P(hWin)->Status & WM_SF_INUSE)) {
    //GUI_DEBUG_ERROROUT1("Selecting invalid window", hWin);
    hWin=0;
  }
  // Select new window
  GUI_Context.hAWin = hWin;
  //WM__SetMaxClipRect(WM_H2P(hWin));
  GUI_Context.ClipRect.x0 = 0;
  GUI_Context.ClipRect.y0 = 0;
  GUI_Context.ClipRect.x1 = LCD_XSIZE-1;
  GUI_Context.ClipRect.y1 = LCD_YSIZE-1;
  WM_UNLOCK();
  return hWinPrev;
}



WM_HWIN WM_GetActiveWindow(void) {
  return GUI_Context.hAWin;
}



/*
  ********************************************************************
  *                                                                  *
  *                 Show / hide window                               *
  *                                                                  *
  ********************************************************************
*/


void WM_ShowWindow   (WM_HWIN hWin) {
  WM_Obj *pWin;
  WM_LOCK();
  pWin = WM_H2P(hWin);
  // First check if this is necessary at all
  if ((pWin->Status&WM_SF_ISVIS)) {
    WM_UNLOCK();
    return;
  }
  // Set Visibility flag
  pWin->Status |= WM_SF_ISVIS;
  // Mark content as invalid
  WM_InvalidateWindow(hWin);
  WM_UNLOCK();
}



/*
	  *****************************************************************
	  *                                                               *
	  *                    GetOrg                                     *
	  *                                                               *
	  *****************************************************************

These routines return the offset of the client area in absolute coordinates.
They are used to convert window coordinates into absolute coordinates and are
used in the clipping libraries (CL_).
*/


int WM__GetOrgX(void) {
  return WM_H2P(GUI_Context.hAWin)->Rect.x0;
}


int WM__GetOrgY(void) {
  return WM_H2P(GUI_Context.hAWin)->Rect.y0;
}


/********************************************************************
*
*           IVR calculation

IVRs are invalid rectangles. When redrawing, only the portion of the
window which is
  a) within the window-rectangle
  b) not covered by an other window
  c) marked as invalid
  is actually redrawn. Unfortunately, this section is not always
  rectangular. If the window is partially covered by an other window,
  it consists of the sum of multiple rectangles. In all drawing
  operations, we have to iterate over every one of these rectangles in
  order to make sure the window is drawn completly.
Function works as follows:
  STEP 1: - Set upper left coordinates to next pixel. If end of line (right border), goto next line -> (r.x0, r.y0)
  STEP 2: - Check if we are done, return if we are.
  STEP 3: - If we are at the left border, find max. heigtht (r.y1) by iterating over windows above
  STEP 4: - Find x0 for the given y0, y1 by iterating over windows above
  STEP 5: - If r.x0 out of right border, this stripe is done. Set next stripe and goto STEP 2
  STEP 6: - Find r.x1. We have to Iterate over all windows which are above
*/



#if WM_SUPPORT_OBSTRUCT
static int FindNext_IVR(void) {
  int hParent;
  int iWin;
  GUI_RECT r;
  U8 Status;
  WM_Obj* pWin;
  WM_Obj* pAWin;
  WM_Obj* pParent;
  r = ClipContext.CurRect;  // temps  so we do not have to work with pointers too much

  //   STEP 1:
  //     Set the next position which could be part of the next IVR
  //     This will be the first unhandle pixel in reading order, i.e. next one to the right
  //     or next one down if we are at the right border.

  if (ClipContext.Cnt == 0) {       // First IVR starts in upper left

⌨️ 快捷键说明

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