窗口刷新问题。其它窗口在窗口上方移动时,出现白色闪烁

like961116 2008-06-03 09:59:33
就是一个最简单的Hello World程序(VC自动生成的工程)。更改部分就是在WM_PAINT消息中画了一个与窗口客户区同样大的蓝色矩形。代码如下所示:
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RECT rt;
GetClientRect(hWnd, &rt);
hBrush = CreateSolidBrush(0xff0000);
SelectObject(hdc,hBrush);
Rectangle(hdc,rt.left,rt.top,rt.right,rt.bottom);
EndPaint(hWnd, &ps);
break;
执行时,如果将另外一个窗口在程序窗口上方拖动,那么会出现明显的白色闪烁。同样打开一个Excel,将Excel表格中的单元格背景设置为蓝色,将同一个窗口在Excel上方拖动,则基本看不到闪烁。其实出现闪烁倒是好解释,考虑提高刷新效率即可(如使用内存设备环境、或者只刷新需要更新的区域等),关键是为什么出现白色闪烁。想来想去,估计是注册窗口类时使用了白色画刷的缘故,即:
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
将这一句改为:
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOWTEXT);
果然变成黑色闪烁了。
由于函数BeginPaint中默认使用窗口类中注册的画刷刷新背景。因此考虑不使用BeginPaint,程序改成如下形式:
case WM_PAINT:
hdc = GetDC(hWnd);
ValidateRect(hWnd,NULL);
RECT rt;
GetClientRect(hWnd,&rt);
hBrush = CreateSolidBrush(0xff0000);
SelectObject(hdc,hBrush);
Rectangle(hdc,rt.left,rt.top,rt.right,rt.bottom);
ReleaseDC(hWnd,hdc);
break;
发现还是不行。仍然有白色闪烁。
请大家帮忙看看怎么解决,多谢。
...全文
400 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
like961116 2008-06-05
  • 打赏
  • 举报
回复
通过处理WM_ERASEBKGND消息是可以阻止窗口刷新背景,此时调用InvalidateRect可以发现背景并没有闪烁。但是唯独将一个窗口在程序窗口上方拖动时不起作用,此时可以明显感觉到刷新背景时的闪烁。又试了一下其它程序,大多数都存在刷新背景的闪烁,微软的软件(word,visio,excel等软件)在其窗口上方移动其它窗口时都没有闪烁。非微软的Edit plus,smart draw也没有。过节回家,暂时结帖了。多谢大家。
like961116 2008-06-04
  • 打赏
  • 举报
回复
现在问题感觉就是擦除背景时出现的闪烁。但是如何禁止擦除背景却没能实现。增加了
case WM_ERASEBKGND: return TRUE; 仍然有闪烁。我是这样试效果的:

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_ERASEBKGND:
return TRUE;

这时程序执行之后,客户区虽然显示是乱的,但是由于我们在WM_ERASEBKGND和WM_PAINT中都什么也没做,因此也是正常的。此时将一个程序(记事本)窗口缩小(缩小到只剩标题栏与菜单栏),在测试程序窗口上方拖动,此时可以看到,测试程序窗口上残留的并不是记事本的残影,而是记事本窗口边沿+白色的残影。其中白色残影就应该是默认背景画刷绘制背景时导致的。为了证明这一点,我将测试程序窗口的背景画刷改为黑色:
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOWTEXT);
然后再重复上面的拖动操作,则果然出现了黑色残影。

明明MSDN中就是说WM_ERASEBKGND返回非0值可以阻止使用背景画刷绘制背景,为什么不起作用呢?

cnzdgs 2008-06-03
  • 打赏
  • 举报
回复
1、响应WM_PAINT消息时只需要刷新ps.rcPaint指定的区域。
2、不擦背景。
3、用双缓冲。
like961116 2008-06-03
  • 打赏
  • 举报
回复
加上了:
case WM_ERASEBKGND: break;
好像有效果,但是不明显。仍然比Excel差
菜牛 2008-06-03
  • 打赏
  • 举报
回复
根本原因就是你说的背景色刷新,可以响应WM_ERASEBKGND消息不调用默认的窗口过程防止背景自动刷新,前提是你在WM_PAINT中必须绘制客户区背景。双缓冲的处理要求就是这样。
like961116 2008-06-03
  • 打赏
  • 举报
回复
之前也不认为是问题,跟Excel比较了一下,显示效果明显比不上Excel。
like961116 2008-06-03
  • 打赏
  • 举报
回复
是使用一个小窗口在程序窗口上方拖动。小窗口移动过的地方会有一个白色的影子,然后又恢复成蓝色了。
like961116 2008-06-03
  • 打赏
  • 举报
回复
应该不行吧。Invalidate是使客户区无效,在WM_PAINT消息处理中再令客户区无效,会导致重复发送WM_PAINT消息。成了死循环了。
Chivalry 2008-06-03
  • 打赏
  • 举报
回复
贴出完整代码,我这边试了一下,没有闪烁阿
#include <windows.h> 
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.cbWndExtra = 0;
wndclass.cbClsExtra = 0;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hInstance = hInstance;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "HCT";
wndclass.lpfnWndProc = WndProc;
wndclass.hbrBackground =(HBRUSH)(COLOR_WINDOW+1); //(HBRUSH)GetStockObject(BLACK_BRUSH);
HWND hwnd;
RegisterClass(&wndclass);
hwnd = CreateWindow("HCT","HCT-0063",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
HBRUSH hBrush;

switch(message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
RECT rt;
GetClientRect(hwnd, &rt);
hBrush = CreateSolidBrush(0xff0000);
SelectObject(hdc,hBrush);
Rectangle(hdc,rt.left,rt.top,rt.right,rt.bottom);
EndPaint(hwnd, &ps);
break;
case WM_CLOSE:
//if(IDYES==MessageBox(hwnd,TEXT("确实要退出?"),TEXT("退出!"),MB_YESNO))
//{
DestroyWindow(hwnd);
//}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}
iu_81 2008-06-03
  • 打赏
  • 举报
回复
之前加上Invalidate()试试

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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