如何在没有WS_VISIBLE可见的情况下创建Win32控件?

时间:2017-10-30 09:16:40

标签: c++ winapi controls

假设hCtl是创建没有 WS_VISIBLE标志的控件的句柄,例如:

HWND hCtl = CreateWindowEx(0, WC_STATIC, L"some text",
                           WS_CHILD | SS_NOTIFY, // no WS_VISIBLE flag
                           0, 0, 0, 0, hWndParent, (HMENU)IDC_STATIC1, g_hInst, 0);

是否有比以下更直接的方式让它可见?

void make_visible(HWND hCtl, HWND hWndParent) {
    SetWindowLongPtr(hCtl, GWL_STYLE,
                     GetWindowLongPtr(hCtl, GWL_STYLE) | WS_VISIBLE);
    RECT rc{};
    GetClientRect(hCtl, &rc);
    MapWindowRect(hCtl, hWndParent, &rc);
    InvalidateRect(hWndParent, &rc, TRUE);
    UpdateWindow(hWndParent);

    //ShowWindow(hCtl, SW_SHOW); // no use: does not update window
    //SetWindowPos(hCtl, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);   // no use: does not update window
}

3 个答案:

答案 0 :(得分:3)

要使子控件可见,请像这样调用SetWindowPos

SetWindowPos(hCtl, 0, 0, 0, 0, 0, 
  SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);

应删除您拨打MapWindowRectInvalidateRectUpdateRect等的代码。

也许你遇到的真正问题是你创建了零宽度和高度的静态控件。

答案 1 :(得分:2)

使窗口可见的常规方法只是函数ShowWindow。没有必要处理标志等等。通常使用SW_SHOW作为子窗口的参数。检查其他值并使用您认为合适的值。

如果窗口有一个可见的矩形,并且没有被另一个窗口覆盖,它将显示出来。甚至不需要UpdateWindow调用。窗口将显示在下一个绘制周期中。如果您的控件的大小为0,0,0,0(因为它已创建),它将永远不会显示。

如果窗口位于不同的线程上以避免阻塞,还有一个ShowWindowAsync函数可供使用。

BTW:我不明白您尝试使父窗口区域无效。如果存在子窗口剪辑(WS_CLIPCHILDREN),则它无效。

答案 2 :(得分:2)

我相信你的问题是你明确地设置WS_VISIBLE样式然后然后调用ShowWindow,这会让Windows感到困惑,认为窗口已经可见并且不需要重新粉刷。

只需致电ShowWindow即可。 There should be no need to explicitly set WS_VISIBLE yourself因为ShowWindow already does it。你不应该强行重绘你的控制。

此外,如果您发现某些内容需要明确地使您的控件无效,那么只需执行InvalidateRect(hCtl, NULL)即可,而不必担心GetClientRectMapWindowRect