为了方便窗口的移动 ,及相交窗口关闭之后被遮挡窗口的重绘,因此给每个窗口建立一个内存BUF,等到不涉及内容变更的重绘,只需要将该BUF复制到显存之中。
然而,重绘时存在一个被遮挡时如何操作的问题。比如下图中依次为从外到内1、2、3、4号窗口、桌面,现关闭1号窗口,那么将需要重绘桌面,4号、3号2、号窗口,还有空出的桌面。
具体过程如下:
1、取一块1号窗口大小的内存。
2、将1号区域分别与桌面、4号窗口、3号、2号窗口相交,所得区域用相应窗口内容重绘,
3、将内存的内容复制到显存中。
这种方法将计算过程与刷新屏内容分开,避免闪烁。移动1号窗口只需先做上述过程再重绘就可以。但是会存在多次重复绘制重叠区域,但复杂程度不高,比较实用。
另外则需要窗口是顺序保存。鼠标也可以用此方法刷新,
具体代码如下:
DWORD windows_draw_rect(LPWNDINFO wnd, LPRECT rect, BYTE* drawbuff) {void * wndvram;RECT newrect;//计算窗口被rect截取的区域if ((wnd->y0 > rect->bottom) || ((wnd->y0 + wnd->height) <= rect->top)|| ((wnd->x0 + wnd->width) <= rect->left)|| (rect->right < wnd->x0)) {//矩形不重合return 0;}//左、顶取两者最大,右、底取两都最小newrect.left = (wnd->x0 < rect->left) ? rect->left : wnd->x0;newrect.top = (wnd->y0 < rect->top) ? rect->top : wnd->y0;newrect.right =((wnd->x0 + wnd->width-1) < rect->right) ?(wnd->x0 + wnd->width-1) : rect->right;newrect.bottom =((wnd->y0 + wnd->height-1) < rect->bottom) ?(wnd->y0 + wnd->height-1) : rect->bottom;//print_farmat_msg("重合区域%d,%d,%d,%d\n", newrect.left, newrect.top, newrect.right, newrect.bottom);DWORD rectw = (rect->right - rect->left + 1);DWORD newrectw =(newrect.right - newrect.left + 1), newrecth = (newrect.bottom- newrect.top + 1);wndvram = wnd->vram+ ((newrect.left - wnd->x0) + (newrect.top - wnd->y0) * wnd->width)* VBE_BPP;drawbuff=(char *)drawbuff+((newrect.left-rect->left)+(newrect.top-rect->top)*(rect->right-rect->left+1))* VBE_BPP;for (int y = 0; y < newrecth; y++) {memcpy((char *) drawbuff + (y * rectw) * VBE_BPP,(char*) wndvram + (y * wnd->width) * VBE_BPP, newrectw * VBE_BPP);}return 1;
}//从窗口列表中恢复区域
void restore_rect(LPRECT rect) {//申请一块临时区域,从最底层画面开始在临时区域画,void *vbeVarm;DWORD rectw = (rect->right - rect->left + 1);DWORD recth = (rect->bottom - rect->top + 1);
// print_farmat_msg("恢复区域%d,%d,%d,%d\n", rect->left, rect->top, rect->right,
// rect->bottom);//每个象素点占VBE_BPPvoid* temp = kr_malloc(rectw * recth * VBE_BPP);//窗口列表循环LPWNDINFO elem = (LPWNDINFO) (lpWndInfoLists.tail.prev);while (elem != (LPWNDINFO) (&lpWndInfoLists.head)) {//子窗口没有单独的vramif (elem->dwStyle != WS_CHILD) {windows_draw_rect(elem, rect, temp);}elem = elem->prev;}vbeVarm = lpSysShareData->vbePhPtr+ (rect->left + rect->top * lpSysShareData->ScreenWidth) * VBE_BPP;//临时区域绘画完成,将临时区域写到屏上for (int y = 0; y < recth; y++) {memcpy((char *) vbeVarm + (y * lpSysShareData->ScreenWidth) * VBE_BPP,(char *) temp + (y * rectw) * VBE_BPP, rectw * VBE_BPP);//vbeVarm[x + y * lpSysShareData->ScreenWidth] = temp[x// + y * (rect->bottom - rect->top + 1)];
}