我有以下代码在用户调用项picture2.bmp
后应该绘制ID_FILE_32771
。
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case ID_FILE_32771:
hdc = BeginPaint(hWnd, &ps);
LoadAndBlitBitmap2(__T("D://picture2.bmp"), hdc);
EndPaint(hWnd, &ps);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
LoadAndBlitBitmap(__T("D://picture.bmp"), hdc);
EndPaint(hWnd, &ps);
break;
问题是,什么都没有画。 hdc
未正确初始化。我做错了什么,我该如何解决?
答案 0 :(得分:5)
处理BeginPaint
消息时,EndPaint
和WM_PAINT
函数仅 。在处理WM_COMMAND
时,你完成它的方式是错误的:
case ID_FILE_32771:
hdc = BeginPaint(hWnd, &ps); // WRONG, WRONG!
LoadAndBlitBitmap2(__T("D://picture2.bmp"), hdc);
EndPaint(hWnd, &ps); // ALSO WRONG!
break;
绘图代码的所有都需要在WM_PAINT
处理程序内。每当您需要绘制窗口时,您将收到WM_PAINT
条消息,有时这些消息不在您的控制之内。因此,WM_PAINT
处理程序中需要有逻辑,根据应用程序的当前状态知道要绘制的内容。
换句话说,您需要设置一个标记以响应ID_FILE_32771
上的点击,以便您的程序知道它应该在重新绘制时调用LoadAndBlitBitmap2
,而不是LoadAndBlitBitmap
(为什么它们不是同一个函数,你只需传递不同的文件名?)。
在WM_PAINT
处理程序之外,您可以通过使窗口内容无效来导致绘制事件。最简单,最普遍合适的方法是调用InvalidateRect
function。例如:
case ID_FILE_32771:
// Set a flag indicating that picture2 should be painted
// (or some other equivalent mechanism)
paintPicture2 = true;
// Signal that the window should be repainted.
InvalidateRect(hWnd, NULL, TRUE);
break;
在InvalidateRect
之后调用UpdateWindow
,您将强制立即重绘,但这很少需要。或者,您可以跳过双功能舞蹈并直接调用功能更强大的RedrawWindow
function。
无论哪种方式,您都将调用您的WM_PAINT
消息处理程序,它将查询应用程序的当前状态并绘制相应的图片。
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Paint the appropriate thing, depending on the app's current state
if (paintPicture2)
LoadAndBlitBitmap(__T("D://picture.bmp"), hdc);
else
LoadAndBlitBitmap(__T("D://picture.bmp"), hdc);
EndPaint(hWnd, &ps);
break;
答案 1 :(得分:2)
BeginPaint仅用于WM_PAINT。如果需要WM_PAINT之外的HDC,可以使用GetDC。但更好的解决方案通常是在WM_PAINT之外调用InvalidateRect。这将导致新的WM_PAINT很快进入,你在WM_PAINT中进行所有绘画。
答案 2 :(得分:2)
来自MSDN:
除响应WM_PAINT消息外,应用程序不应调用
BeginPaint
也就是说,您的修复方法是以所谓的方式使用API,这通常会通过InvalidateRect
使视图无效,然后在您被请求时通过WM_PAINT
进行绘制。