【问题标题】:After calling MoveWindow() with TRUE, the window client area is still invalid使用TRUE调用MoveWindow()后,窗口客户区仍然无效
【发布时间】:2010-08-19 22:21:12
【问题描述】:

MSDN doc's for MoveWindow() says:

“如果bRepaint参数为TRUE,则系统在移动窗口后立即向窗口过程发送WM_PAINT消息(即MoveWindow函数调用UpdateWindow函数)。”

但是当我在 MoveWindow() 之后调用 GetUpdateRect() 时,在处理父级中的 WM_LBUTTONDOWN 消息时,我得到一个哔哔声,这表明子级无效。什么解释???

#include <windows.h>
#include <windowsx.h>
#include <tchar.h>

HINSTANCE   ghInstance;

LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);

int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
    HWND        hWnd;
    MSG     msg;
    WNDCLASSEX  wndclassx;

    ghInstance = hInstance;

    wndclassx.cbSize        = sizeof(WNDCLASSEX);
    wndclassx.style         = 0;
    wndclassx.lpfnWndProc   = WindowProc;
    wndclassx.cbClsExtra    = 0;
    wndclassx.cbWndExtra    = 0;
    wndclassx.hInstance     = hInstance;
    wndclassx.hIcon         = 0;
    wndclassx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wndclassx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclassx.lpszMenuName  = NULL;
    wndclassx.lpszClassName = _T("ParentWindow");
    wndclassx.hIconSm       = NULL;

    if( !RegisterClassEx(&wndclassx) ) return 0;

    wndclassx.cbSize        = sizeof(WNDCLASSEX);
    wndclassx.style         = 0;
    wndclassx.lpfnWndProc   = ChildProc;
    wndclassx.cbClsExtra    = 0;
    wndclassx.cbWndExtra    = 0;
    wndclassx.hInstance     = hInstance;
    wndclassx.hIcon         = 0;
    wndclassx.hCursor       = 0;
    wndclassx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclassx.lpszMenuName  = NULL;
    wndclassx.lpszClassName = _T("ChildWindow");
    wndclassx.hIconSm       = NULL;

    if( !RegisterClassEx(&wndclassx) ) return 0;

    if( !(hWnd = CreateWindow(_T("ParentWindow"), _T("Parent Window"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                              CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance,
                              NULL)) ) return 0;

    ShowWindow(hWnd, SW_SHOW);
    UpdateWindow(hWnd);

    while( GetMessage(&msg, NULL, 0, 0) )
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
    HWND    hWnd;

    switch ( message )
    {
        case WM_CREATE:

        CreateWindow(_T("ChildWindow"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 100, 100, hwnd, (HMENU)0,
                          ghInstance, NULL);
        break;

        case WM_LBUTTONDOWN:

        hWnd = GetWindow(hwnd, GW_CHILD);

        MoveWindow(hWnd, 10, 10, 200, 200, true);

        if( GetUpdateRect(hWnd, NULL, FALSE) ) MessageBeep(-1);
        break;

        case WM_DESTROY:
        PostQuitMessage(0);
        break;

        default:

        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
    return DefWindowProc(hwnd, message, wParam, lParam);
}

【问题讨论】:

  • 需要一些格式。尝试编辑这篇文章;标记您的所有代码,并且;按编辑菜单中的“代码”图标
  • 您检查过CreateWindowGetWindow 的返回值并确保您没有得到NULL?
  • 程序运行正常。 CreateWindow() 创建子句柄,GetWindow() 返回子句柄。 “标记所有代码”是什么意思?
  • 如您所见,您的某些代码位于灰色框中。如果单击编辑按钮,选择/标记所有应该是代码的文本,然后单击“代码示例”按钮(101010 按钮)会更容易阅读

标签: winapi


【解决方案1】:

MSDN 文档是错误的。如文档所述,带有 TRUE 的 MoveWindow() 不会调用 UpdateWindow()。它只是使窗口客户区无效。如果我在 MoveWindow() 之后调用 UpdateWindow(),程序会按预期运行。

【讨论】:

  • 不错的收获。这超出了我的知识范围,但它可能与线程以及 Windows 如何处理不同消息有关。虽然,我想如果你睡一小段时间它仍然会不正确?
【解决方案2】:

我自己尝试过,WM_PAINTif(GetUpdateRect()) 之前被触发。另外,GetUpdateRect 为我返回 FALSE。 我在 XP 上运行 Visual Studio 2008。 我想这可能取决于您使用的编译器,使用的操作系统等等。根据你传递的代码,一切都是在同一个线程中完成的,但如果它是一个多线程程序,我认为这也会造成一些问题。

【讨论】:

  • MoveWindow() 调用 UpdateWindow() 函数。此函数清除无效区域。但是,GetUpdateRect() 仍然返回 TRUE,确认子窗口的矩形无效,这显然是矛盾的。代码没有问题。前面说了,程序运行正常,点击父窗口客户区后可以听到哔声!
  • 我只是想知道这是 MoveWindow() 函数中的 BUG,还是只是文档中的错误陈述。
  • MSDN 文档是错误的。正如文档所述,MoveWindow() 不会调用 UpdateWindow()。它只是使窗口客户区无效。如果我在 MoveWindow() 之后调用 UpdateWindow(),程序会按预期运行。
猜你喜欢
  • 2014-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 2010-11-01
相关资源
最近更新 更多