【问题标题】:How can I remove a window's non-client area completely?如何完全删除窗口的非客户区?
【发布时间】:2021-08-16 22:56:10
【问题描述】:

我需要一个没有标题栏、没有控制框、没有系统菜单和框架的窗口(所有这些功能都由单独的控件提供)。

我怀疑这应该与CreateWindowExA 的窗口样式参数dwStyle 和可能的lpWindowName 有关,如下所述:https://docs.microsoft.com/en-us/windows/desktop/winmsg/window-styles

这是参数最初的样子:

HWND hwnd = CreateWindowEx(
    0,                              // Optional window styles.
    CLASS_NAME,                     // Window class.
    L"",                            // No window name (title text).
    WS_OVERLAPPEDWINDOW,            // Window style.

    // Size and position.
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

    NULL,       // Parent window.
    NULL,       // Menu.
    hInstance,  // Instance handle.
    NULL        // Additional application data.
);

但是,在dwStyle 中,普通窗口样式WS_OVERLAPPEDWINDOW 被定义为

WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX

WS_OVERLAPPED0x00000000L

仅提供 0 并省略其余部分是行不通的,正如文档所暗示的那样:“窗口是重叠的窗口。重叠的窗口有一个标题栏和一个边框。”

(有趣的是,通过将ControlBox 属性设置为False,然后使用Text = "" 删除标题栏,我完全能够在VB.NET(甚至在VB6)中完成此任务,所以我强烈怀疑在可能的情况下在 VB 中......)

我将如何在 C++ 中完成我的任务?


以防万一需要WindowProc 来处理不同的消息,这里是它的简约版本:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        case WM_PAINT:
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
            EndPaint(hwnd, &ps);
            return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

(使用 VS 2017 编译。)

【问题讨论】:

  • @RetiredNinja,不幸的是,它没有。可能我还应该显示我的 WindowProc,以防我没有收到所需的消息。现在更新。
  • 正如@RetiredNinja 指出的那样,无边框/无框窗口的装饰应该是WS_POPUP。如果我提醒正确的话,VS2017生成的默认windows类将背景颜色设置为(COLOR_WINDOW + 1),而你正在用颜色(COLOR_WINDOW + 1)绘制一个矩形...
  • WS_POPUP 正常工作。它不适用于您的情况,因为您仍然有 CW_USEDEFAULT 参数,这些参数仅对重叠的窗口有效。 "如果为弹出窗口或子窗口指定了 CW_USEDEFAULT,则 nWidth 和 nHeight 设置为零。"
  • Another technique,删除边框但保留投影。

标签: c++ winapi nonclient-area


【解决方案1】:

仅使用WS_POPUP 样式可以删除顶级窗口的非客户区:

HWND hwnd = CreateWindowEx(
    0,                              // Optional window styles.
    CLASS_NAME,                     // Window class.
    L"",                            // No window name (title text).
    WS_POPUP,                       // Window style.

    // Size and position.
    100, 100, 400, 300,

    NULL,       // Parent window.
    NULL,       // Menu.
    hInstance,  // Instance handle.
    NULL        // Additional application data.
);

请注意,CW_USEDEFAULT 的大小和位置仅对重叠的窗口有效。对于弹出窗口,您必须明确。

根据您的用例,this answer 描述的技术可能更适合。使用 DWM API,它允许您移除非客户区,但保留投影以使窗口从背景中更加突出。

【讨论】:

    猜你喜欢
    • 2011-03-16
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 2011-01-09
    • 1970-01-01
    • 2011-06-16
    相关资源
    最近更新 更多