绘图代码在我的WM_COMMAND消息处理程序中无法正常工作

时间:2014-05-25 13:40:28

标签: c windows winapi hdc

我有以下代码在用户调用项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未正确初始化。我做错了什么,我该如何解决?

3 个答案:

答案 0 :(得分:5)

处理BeginPaint消息时,EndPaintWM_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进行绘制。