WM_ERASEBKGND与WM_PAINT

最近开发一个Wtl自绘界面程序。我在WM_ERASEBKGND消息中绘制背景图,在客户区域的右上角绘制控制按钮。最初对话框是不可改变大小的,后来由于需求需要支持拖拉改变对话框大小,相应的控制按钮的位置也要随着对话框的大小变化而变化。于是我在WM_SIZE消息中改变控制按钮的位置:

	void OnSize(UINT nType, CSize size)
	{
		::OutputDebugString(_T("OnSize\n"));
		CWindow btnOK(GetDlgItem(IDOK));
		RECT btnRC;
		btnOK.GetClientRect(&btnRC);
		btnOK.MoveWindow(size.cx - btnRC.right - 20, 10, btnRC.right, btnRC.bottom);
	}

发现在拖拉改变对话框的大小时按钮的刷新不及时,经常发生按钮显示不完全或者完全消失的情况。后来调研得知是因为按钮处理WM_PAINT消息比较滞后的原因导致,于是我在OnSize函数中加入的对控制按钮的RedrawWindow Api的调用,控制按钮的显示才正常起来。

	void OnSize(UINT nType, CSize size)
	{
		::OutputDebugString(_T("OnSize\n"));
		CWindow btnOK(GetDlgItem(IDOK));
		RECT btnRC;
		btnOK.GetClientRect(&btnRC);
		btnOK.MoveWindow(size.cx - btnRC.right - 20, 10, btnRC.right, btnRC.bottom);
		btnOK.RedrawWindow();
	}

RedrawWindow会直接调用窗口的WM_PAINT消息过程,并在消息处理完毕后返回。具体请Google其与Invalidate的区别。

我又测试了下WM_ERASEBKGND消息执行情况,发现在对话框程序中,WM_ERASEBKGND消息不断的发送到窗口,即使窗口不需要被重绘(原因未知,希望有牛人告知)。我怀疑这个消息的不断执行影响了界面的刷新,于是我更改了界面绘制流程,处理WM_ERASEBKGND消息直接返回TRUE,而在处理WM_PAINT消息中绘制背景图。发现即使不对按钮使用RedrawWindow函数,按钮也可以快速的刷新。

	BOOL OnEraseBkgnd(HDC hDC)
	{
		return TRUE;
	}

	void OnPaint(CDCHandle dc)
	{
		PAINTSTRUCT ps;
		HDC hdc;

		hdc = BeginPaint(&ps);

		CRect rcClient;
		GetClientRect(&rcClient);

		//SetMsgHandled(FALSE);
		Gdiplus::Bitmap bmp(rcClient.right,rcClient.bottom);
		Gdiplus::Graphics graphics(&bmp);

		graphics.DrawImage(m_pImage, Gdiplus::Rect(0,0,rcClient.Width(),rcClient.Height()),
			0,0,rcClient.Width(),rcClient.Height(),Gdiplus::UnitPixel);

		Gdiplus::Graphics g(hdc);
		g.DrawImage(&bmp,0,0);
		EndPaint(&ps);

		::OutputDebugString(_T("---- OnPaint\n"));
	}

	void OnSize(UINT nType, CSize size)
	{
		::OutputDebugString(_T("OnSize\n"));
		CWindow btnOK(GetDlgItem(IDOK));
		RECT btnRC;
		btnOK.GetClientRect(&btnRC);
		btnOK.MoveWindow(size.cx - btnRC.right - 20, 10, btnRC.right, btnRC.bottom);
	}
但是如果快速的改变对话框的大小,控制按钮还是少许的刷新不及时的现象,还是要加入对控制按钮的RedrawWindow函数的调用,这样就完美了。好了记住重绘对话框步骤:

1. 处理消息WM_ERASEBKGND返回TRUE

2. 在消息WM_PAINT绘制背景

3. 在对话框的WM_SIZE函数中处理子控件的重绘要调用子控件的RedrawWindow函数(据说在WM_WINDOWPOSCHANGED处理更高效)。


PS,以上为个人总结,非官方,非权威,若有异议,评论即可!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值