Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15531854
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: C/C++

2007-07-10 15:37:00

浅析μ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);
    }
  }
}

阅读(6771) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

chinaunix网友2008-09-23 23:42:26

GUI_MoveRect的dx、dy是移动距离,而非移动到dx、dy