终于明白为什么在父窗口的wm_paint 中无法对子控件进行进行gdi操作了

woshidiyimm 2012-12-05 08:07:07
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd,&ps);

HDC hdc=GetDC(GetDlgItem(hwndList,IDC_LIST));

RECT rect;

GetWindowRect(hwndList,&rect);

POINT pt1,pt2;

pt1.x=rect.left;
pt1.y=rect.top;

pt2.x=rect.right;

pt2.y=rect.bottom;

ScreenToClient(hwnd,&pt1);
ScreenToClient(hwnd,&pt2);

rect.left=pt1.x;
rect.top=pt1.y;
rect.right=pt2.x;
rect.bottom=pt2.y;

FillRect(hdc,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));


ReleaseDC(GetDlgItem(hwndList,IDC_LIST),hdc);


EndPaint(hwnd,&ps);
}

return 0 ;

break;

代码里有意用 子控件的dc

就是为了有意避开使用主窗口客户区域的dc.


结果黑色区域出现了,不过是在 主窗口以外。

结论:

wm_paint是无法对 子控件进行gdi操作的。

...全文
396 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
傻X 2012-12-07
  • 打赏
  • 举报
回复
话说,楼主,你那个问题搞定了没有?
schlafenhamster 2012-12-07
  • 打赏
  • 举报
回复
有一个情况要 考虑, 就是 dlg 带 WS_CLIPCHILDREN 属性时, 或者 你的 validaterect 则控件 必须 全部 自绘。 InvalidateRect 是 在 原控件的 基础上 再加上 你的绘制。
woshidiyimm 2012-12-07
  • 打赏
  • 举报
回复
引用 19 楼 schlafenhamster 的回复:
/* InvalidateRect 的作用是无效窗口客户区, 发送低优先级的WM_PAINT消息 UpdateWindow的作用是马上重绘同时使客户区有效。 注意下面的PaintWindow 函数,函数用GetDC得到设备环境句柄,这里就是关键 。 GetDC和BeginPaint不同,从GetDC返回句柄之后 你可以用此句柄在客户区任何地方绘图, 不管是有效区……
有一事不明,不吐不快。 希望大师莫嫌小菜鸟打扰你清修 无论是你还是作者,都提到invalidaterect void PaintTheBlock (HWND hCtrl, int iColor, int iFigure) { InvalidateRect (hCtrl, NULL, FALSE);//TRUE) ; 我却相反理解: 我是采用validaterect或者updatewindow 原因附上: 为什么会进行wm_paint?原因是无效导致发出wm_paint. 好了,进入case wm_paint后, 2个工作: (1)使之有效,否则不断的发出 (2)进行你自己的一些操作 所以我才用validataerect使控件有效, 或者upatewindow
woshidiyimm 2012-12-07
  • 打赏
  • 举报
回复
引用 19 楼 schlafenhamster 的回复:
/* InvalidateRect 的作用是无效窗口客户区, 发送低优先级的WM_PAINT消息 UpdateWindow的作用是马上重绘同时使客户区有效。 注意下面的PaintWindow 函数,函数用GetDC得到设备环境句柄,这里就是关键 。 GetDC和BeginPaint不同,从GetDC返回句柄之后 你可以用此句柄在客户区任何地方绘图, 不管是有效区……
引用 19 楼 schlafenhamster 的回复:
/* InvalidateRect 的作用是无效窗口客户区, 发送低优先级的WM_PAINT消息 UpdateWindow的作用是马上重绘同时使客户区有效。 注意下面的PaintWindow 函数,函数用GetDC得到设备环境句柄,这里就是关键 。 GetDC和BeginPaint不同,从GetDC返回句柄之后 你可以用此句柄在客户区任何地方绘图, 不管是有效区……
特意抽了一会功夫,看了这部分的代码, 大概理解你的意思了, 通过updatewindow使有效。这样就不会导致再次被默认的子空间的画刷填充。 也就说,一旦想在副窗口的wm_paint 里对子空间进行gdi操作,必须防止其自身的窗口过程中的wm_paint默认处理。 所以我们可以在副窗口的wm_ctlcolorbtn, wm_drawitem进行操作子控件,回避子控件自身的wm_paint进行默认处理.
Sidyhe 2012-12-06
  • 打赏
  • 举报
回复
MARK
woshidiyimm 2012-12-06
  • 打赏
  • 举报
回复
引用 7 楼 tiger9991 的回复:
首先,你这个结论是错误的。 按照你这个形式来做的话,其实是可以的。 但是你的坐标转换错了。 ScreenToClient(hwnd,&pt1); hwnd应该换成子控件的句柄
我的结论是对的, 这个函数就是这没用的,
傻X 2012-12-06
  • 打赏
  • 举报
回复
首先,你这个结论是错误的。 按照你这个形式来做的话,其实是可以的。 但是你的坐标转换错了。 ScreenToClient(hwnd,&pt1); hwnd应该换成子控件的句柄
schlafenhamster 2012-12-06
  • 打赏
  • 举报
回复
/* InvalidateRect 的作用是无效窗口客户区, 发送低优先级的WM_PAINT消息 UpdateWindow的作用是马上重绘同时使客户区有效。 注意下面的PaintWindow 函数,函数用GetDC得到设备环境句柄,这里就是关键 。 GetDC和BeginPaint不同,从GetDC返回句柄之后 你可以用此句柄在客户区任何地方绘图, 不管是有效区还是无效区,同时GetDC不会使无效区有效化。所以 你把 UpdateWindow去掉了, 下面的PaintWindow仍然执行,只不过画完图之后你的子窗口控件客户区已然是无效的, 这就导致系统发送一条WM_PAINT消息到子窗口的窗口过程,默认的窗口过程会用画刷填充, 这里应该是和背景色相同的画刷 所以什么都显示不了。 */ void PaintTheBlock (HWND hCtrl, int iColor, int iFigure) { InvalidateRect (hCtrl, NULL, FALSE);//TRUE) ; UpdateWindow (hCtrl) ; PaintWindow (hCtrl, iColor, iFigure) ; }
schlafenhamster 2012-12-06
  • 打赏
  • 举报
回复
"Windows 程序设计 第5 版 上册" 11.1.11 ‘在对话框上绘图’480 页
woshidiyimm 2012-12-06
  • 打赏
  • 举报
回复
引用 16 楼 schlafenhamster 的回复:
在对话框中画控件。 首先要 要 对话框 本身 画完。 然后 叫 控件 客户区 有效 (invalidate) 取控件的 DC 和 rect 画。。。

	 case WM_PAINT:
		 {
			 PAINTSTRUCT	 ps;

			 HDC hdc;

			 RECT rect;

			 POINT pt1,pt2;

			BeginPaint(hwnd,&ps);
			EndPaint(hwnd,&ps);

	
			GetWindowRect(hwndList,&rect);

			//使自控件有效
			ValidateRect(GetDlgItem(hwnd,ID_LIST),&rect);


			pt1.x=rect.left;
			pt1.y=rect.top;

			pt2.x=rect.right;
			pt2.y=rect.bottom;

			ScreenToClient(hwnd,&pt1);
			ScreenToClient(hwnd,&pt2);

			rect.left=pt1.x;
			rect.top=pt1.y;
			rect.right=pt2.x;
			rect.bottom=pt2.y;
			//取客户区域,使之变黑色

			GetClientRect(hwndList,&rect);
			hdc=GetDC(GetDlgItem(hwnd,ID_LIST));

			FillRect(hdc,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));


			ReleaseDC(GetDlgItem(hwnd,ID_LIST),hdc);
		

		 return 0 ;  

		 }

		 break;

很明显没看到黑色
schlafenhamster 2012-12-06
  • 打赏
  • 举报
回复
在对话框中画控件。 首先要 要 对话框 本身 画完。 然后 叫 控件 客户区 有效 (invalidate) 取控件的 DC 和 rect 画。。。
枫桦沐阳 2012-12-06
  • 打赏
  • 举报
回复
shandongmn 2012-12-06
  • 打赏
  • 举报
回复
引用 13 楼 VisualEleven 的回复:
本帖最后由 VisualEleven 于 2012-12-06 14:34:53 编辑 引用 12 楼 woshidiyimm 的回复:引用 11 楼 VisualEleven 的回复: 引用 8 楼 woshidiyimm 的回复:引用 7 楼 tiger9991 的回复: 首先,你这个结论是错误的。 按照你这个形式来做的话,其实是……
更加说明我的结论是对的, 我没想到坐标的计算会与dc的拥有着有关系。
Eleven 2012-12-06
  • 打赏
  • 举报
回复
引用 12 楼 woshidiyimm 的回复:
引用 11 楼 VisualEleven 的回复:
引用 8 楼 woshidiyimm 的回复:引用 7 楼 tiger9991 的回复:
首先,你这个结论是错误的。
按照你这个形式来做的话,其实是可以的。
但是你的坐标转换错了。

ScreenToClient(hwnd,&pt1); hwnd应该换成子控件的句柄

我的结论是对的,


……

你的坐标计算完全错误~
FillRect(hdc, ..);
这里你用的hdc是CListBox控件窗口相关联的DC,所以rect的计算,直接GetClientRect(hwndlistbox, &rect);就是了。

不过你FillRect()应该是看不到背景是黑色的效果的,因为子窗口listbox会自己绘制一下,把你黑色的背景色又给盖住了。你可以会看到listbox区域闪一下,先黑一下,然后又被刷白了。
woshidiyimm 2012-12-06
  • 打赏
  • 举报
回复
引用 11 楼 VisualEleven 的回复:
引用 8 楼 woshidiyimm 的回复:引用 7 楼 tiger9991 的回复: 首先,你这个结论是错误的。 按照你这个形式来做的话,其实是可以的。 但是你的坐标转换错了。 ScreenToClient(hwnd,&pt1); hwnd应该换成子控件的句柄 我的结论是对的, 这个函数就是这没用的, ……
不对,有反例吗 我目前找不到反例
Eleven 2012-12-06
  • 打赏
  • 举报
回复
引用 8 楼 woshidiyimm 的回复:
引用 7 楼 tiger9991 的回复: 首先,你这个结论是错误的。 按照你这个形式来做的话,其实是可以的。 但是你的坐标转换错了。 ScreenToClient(hwnd,&pt1); hwnd应该换成子控件的句柄 我的结论是对的, 这个函数就是这没用的,
woshidiyimm 2012-12-06
  • 打赏
  • 举报
回复
woshidiyimm 2012-12-06
  • 打赏
  • 举报
回复
引用 8 楼 woshidiyimm 的回复:
引用 7 楼 tiger9991 的回复:首先,你这个结论是错误的。 按照你这个形式来做的话,其实是可以的。 但是你的坐标转换错了。 ScreenToClient(hwnd,&pt1); hwnd应该换成子控件的句柄 我的结论是对的, 这个函数就是这没用的,
woshidiyimm 2012-12-05
  • 打赏
  • 举报
回复


图在这里
woshidiyimm 2012-12-05
  • 打赏
  • 举报
回复
截图如

[img=http://img.my.csdn.net/uploads/201212/05/1354712322_7131.jpg]
加载更多回复(4)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧