浅析μC/GUI-v3.98之WM_InvalidateWindow函数
文章来源:http://gliethttp.cublog.cn
------------------------------------------------------------------------------------- 1.WM_InvalidateWindow()函数 gui/wm/WM.c void WM_InvalidateWindow(WM_HWIN hWin) { WM_InvalidateRect(hWin, NULL); //NULL表示使整个hWin窗体无效,以便重绘整个窗体 } void WM_InvalidateRect(WM_HWIN hWin, const GUI_RECT*pRect) { GUI_RECT r; WM_Obj* pWin; int Status; if (hWin) { WM_LOCK(); pWin = WM_H2P(hWin); //请参见《浅析μC/GUI-v3.98之WM_H2P()句柄hWin转内存函数》 Status = pWin->Status; if (Status & WM_SF_ISVIS) { r = pWin->Rect; if (pRect) { //和pRect剪切,缩小r的区域,如果pRect=NULL,那么r即为hWin窗体本身 GUI_RECT rPara; rPara = *pRect; WM__Client2Screen(pWin, &rPara); //相对pWin(x0,y0)左上角,平移rPara矩形体到屏幕的绝对地址处 GUI__IntersectRect(&r, &rPara); //综合pWin窗体对rPara作剪切域计算,将结果存入r } if (WM__ClipAtParentBorders(&r, hWin)) { //快速与hWin所有hParent~desktop之间的单元向上进行边框剪切计算 if ((Status & (WM_SF_HASTRANS | WM_SF_CONST_OUTLINE)) == WM_SF_HASTRANS) { WM__InvalidateRectEx(&r, pWin->hParent, pWin->hNext);//本hWin透明 } else { WM__Invalidate1Abs(hWin, &r); //将InvalidateRect经运算后赋值给pWin->InvalidRect } } } WM_UNLOCK(); } } ------------------------------------------------------------------------------------- 2.WM__Client2Screen()和GUI_MoveRect()函数 gui/wm/WM.c gui/core/GUI_MoveRect.c void WM__Client2Screen(const WM_Obj* pWin, GUI_RECT *pRect) { GUI_MoveRect(pRect, pWin->Rect.x0, pWin->Rect.y0); //相对地址pWin->Rect.x0,y0就是屏幕绝对地址 } void GUI_MoveRect(GUI_RECT *pRect, int dx, int dy) { if (pRect) { //将pRect平移(dx,dy) pRect->x0 += dx; pRect->x1 += dx; pRect->y0 += dy; pRect->y1 += dy; } } ------------------------------------------------------------------------------------- 3.GUI__IntersectRect()函数 gui/core/GUI_InvertRect.c void GUI__IntersectRect(GUI_RECT* pDest, const GUI_RECT* pr0) { if (pDest->x0 < pr0->x0) { //pDest剪切计算结果存放单元,pr0剪切参考单元 pDest->x0 = pr0->x0; } if (pDest->y0 < pr0->y0) { pDest->y0 = pr0->y0; } if (pDest->x1 > pr0->x1) { pDest->x1 = pr0->x1; } if (pDest->y1 > pr0->y1) { pDest->y1 = pr0->y1; } //交叠区域计算完成pDest存放了交叠区的矩形数据 } ------------------------------------------------------------------------------------- 4.GUI__IntersectRect()函数 gui/wm/WM.c int WM__ClipAtParentBorders(GUI_RECT* pRect, WM_HWIN hWin) { WM_Obj* pWin; //与pWin的hParent及hParent的hParent等,进行剪切计算,如果任何一个hParent属性不可见,均会导致失败0的返回 do { pWin = WM_H2P(hWin); if ((pWin->Status & WM_SF_ISVIS) == 0) { return 0; //该pWin窗体不可见,将直接返回0 } GUI__IntersectRect(pRect, &pWin->Rect); if (pWin->hParent == 0) { //已经到达desktop,计算完毕 break; } hWin = pWin->hParent; //继续剪切pWin的hParent } while (1); if (_DesktopHandle2Index(hWin) < 0) { return 0; //hWin如果非desktop,那么非窗口载体单元,不可见[应该不出现] } return 1; //pRect剪切域计算有效返回1
} ------------------------------------------------------------------------------------- 5._DesktopHandle2Index()函数 gui/wm/WM.c static int _DesktopHandle2Index(WM_HWIN hDesktop) { #if GUI_NUM_LAYERS > 1 int i; for (i = 0; i < GUI_NUM_LAYERS; i++) { if (hDesktop == WM__ahDesktopWin[i]) { return i; } } #else if (hDesktop == WM__ahDesktopWin[0]) { //因为是1个LCD,所以简单的比较WM__ahDesktopWin[0]即可 return 0; } #endif return -1; } ------------------------------------------------------------------------------------- 6.WM__InvalidateRectEx()函数 gui/wm/WM.c void WM__InvalidateRectEx(const GUI_RECT* pInvalidRect, WM_HWIN hParent, WM_HWIN hStop) { //透明区域处理 //2007-07-10 gliethttp 与hParen及hParent->hFirstChild到hStop之间窗体进行剪切运算 GUI_RECT Rect; WM_Obj* pParent; WM_Obj* pi; WM_HWIN hi; int Status; if (hParent == 0) { return; } pParent = WM_H2P(hParent); Status = pParent->Status; if ((Status & WM_SF_ISVIS) == 0) { return; } if (GUI__IntersectRects(&Rect, pInvalidRect, &pParent->Rect) == 0) {//将矩形弄到hParent矩形内部 return; } /* Invalidate the rectangle in the parent */ /* If the parent is (partially) transparent, we need to move up in the hierarchy */ if ((Status & (WM_SF_HASTRANS | WM_SF_CONST_OUTLINE)) == WM_SF_HASTRANS) { WM__InvalidateRectEx(&Rect, pParent->hParent, pParent->hNext); } else { WM__Invalidate1Abs(hParent, &Rect); } /* Invalidate siblings up to hStop */ for (hi = pParent->hFirstChild; hi; hi = pi->hNext) { if (hi == hStop) { break; } WM_InvalidateWindowAndDescsEx(hi, &Rect); //令hi和hi下的孩子、孙子、孙孙子...与Rect剪切的区域作为相应控件失效矩形重绘区 pi = WM_H2P(hi); } } ------------------------------------------------------------------------------------- 7.GUI__IntersectRects()函数 gui/core/GUI__IntersectRects.c int GUI__IntersectRects(GUI_RECT* pDest, const GUI_RECT* pr0, const GUI_RECT* pr1) { pDest->x0 = MAX (pr0->x0, pr1->x0); //进行最小赋值 pDest->y0 = MAX (pr0->y0, pr1->y0); pDest->x1 = MIN (pr0->x1, pr1->x1); pDest->y1 = MIN (pr0->y1, pr1->y1); if (pDest->x1 < pDest->x0) { return 0; } if (pDest->y1 < pDest->y0) { return 0; } return 1; } ------------------------------------------------------------------------------------- 8.WM__Invalidate1Abs()函数 gui/wm/WM.c void WM__Invalidate1Abs(WM_HWIN hWin, const GUI_RECT * pRect) { GUI_RECT r; WM_Obj* pWin; int Status; pWin = WM_H2P(hWin); Status = pWin->Status; if ((Status & WM_SF_ISVIS) == 0) { return; } if ((Status & (WM_SF_HASTRANS | WM_SF_CONST_OUTLINE)) == WM_SF_HASTRANS) {//本pWin透明 return; } if (WM__RectIsNZ(pRect) == 0) { //确保pRect有效 return; } //计算剪切区域 GUI__IntersectRects(&r, pRect, &pWin->Rect); //进行最小赋值 if (WM__RectIsNZ(&r)) { #if WM_SUPPORT_NOTIFY_VIS_CHANGED //=0,否则通过回调函数响应WM_NOTIFY_VIS_CHANGED消息 WM__SendMsgNoData(hWin, WM_NOTIFY_VIS_CHANGED); #endif if (pWin->Status & WM_SF_INVALID) { //pWin->InvalidRect赋更小的值 GUI_MergeRect(&pWin->InvalidRect, &pWin->InvalidRect, &r); } else { pWin->InvalidRect = r; //该pWin第一次无效,那么r作为pWin->InvalidRect pWin->Status |= WM_SF_INVALID; WM__NumInvalidWindows++; //更新无效窗体管理单元 /* Optional code: Call external routine to notify that drawing is required */ #ifdef GUI_X_REDRAW if (_IsInited) { GUI_RECT r; r = pWin->Rect; if (WM__ClipAtParentBorders(&r, hWin)) { GUI_X_REDRAW(); //存在用户hook函数则调用之 } } #endif GUI_X_SIGNAL_EVENT(); } /* Debug code: shows invalid areas */ #if (WM_SUPPORT_DIAG) if (WM__pfShowInvalid) { (WM__pfShowInvalid)(hWin); //hook信息输出调试函数 } #endif } } ------------------------------------------------------------------------------------- 8.WM_InvalidateWindowAndDescsEx()函数 gui/wm/WM.c void WM_InvalidateWindowAndDescsEx(WM_HWIN hWin, const GUI_RECT * pInvalidRect) { GUI_RECT Rect; WM_Obj* pWin; WM_Obj* pChild; WM_HWIN hChild; int Status; if (hWin) { pWin = WM_H2P(hWin); Status = pWin->Status; if ((Status & WM_SF_ISVIS) == 0) { return; } if (GUI__IntersectRects(&Rect, pInvalidRect, &pWin->Rect) == 0) { return; } WM__Invalidate1Abs(hWin, &Rect); //2007-07-10 gliethttp俺的孙子获得失效重绘区域pWin->InvalidRect for (hChild = WM_GetFirstChild(hWin); hChild; hChild = pChild->hNext) { WM_InvalidateWindowAndDescsEx(hChild, &Rect); //让孩子的孩子,俺的孙子和Rect剪切,如果存在剪切剪切域,则作为俺的孙子的失效重绘区域 pChild = WM_H2P(hChild); } } }
|