绘制窗口及窗口位置变化

        为了方便窗口的移动 ,及相交窗口关闭之后被遮挡窗口的重绘,因此给每个窗口建立一个内存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_BPP
	void* temp = kr_malloc(rectw * recth * VBE_BPP);
	//窗口列表循环
	LPWNDINFO elem = (LPWNDINFO) (lpWndInfoLists.tail.prev);
	while (elem != (LPWNDINFO) (&lpWndInfoLists.head)) {

		//子窗口没有单独的vram
		if (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)];
}

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麻雀123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值