C++ 处理WM_NCHITTEST返回时的任性行为

C++ 处理WM_NCHITTEST返回时的任性行为,c++,windows,winapi,C++,Windows,Winapi,我正在完全重新绘制非客户端区域,但愿意保留一些默认功能。Windows不允许我将关闭按钮放在任何我想要的地方。虽然当我对windows说我希望整个窗口都是标题,而不是关闭按钮时,它非常有效。我知道我可以很容易地去做一个适当的直接api调用。但总有一些疑问,如果windows做了一些我不知道的额外的事情怎么办。为什么Windows会这样做?也许你知道有什么解决办法。请分享 #include <windows.h> LRESULT CALLBACK msg_proc(HWND hwnd

我正在完全重新绘制非客户端区域,但愿意保留一些默认功能。Windows不允许我将关闭按钮放在任何我想要的地方。虽然当我对windows说我希望整个窗口都是标题,而不是关闭按钮时,它非常有效。我知道我可以很容易地去做一个适当的直接api调用。但总有一些疑问,如果windows做了一些我不知道的额外的事情怎么办。为什么Windows会这样做?也许你知道有什么解决办法。请分享

#include <windows.h>

LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); // inform frame change
        break;
    case WM_NCCALCSIZE:
        if (wParam) return 0; // removing the standard frame
        break;
    case WM_NCHITTEST:
        return HTCLOSE; // HTCAPTION perfectly works 
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = msg_proc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wcex.hCursor = 0;
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"huge close button";
    wcex.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);

    RegisterClassEx(&wcex);
    HWND hwnd = CreateWindowExW(
        WS_EX_TOPMOST,
        L"huge close button", L"huge close button", WS_OVERLAPPEDWINDOW,
        100, 100, 1000, 1000,
        NULL, NULL, hInstance, 0 );
    ShowWindow(hwnd, nCmdShow);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}
这段代码意味着只要用户按下鼠标按钮,应用程序就会关闭。但事实并非如此。

您需要单独处理

wParam

结果是DefWindowProc函数返回的命中测试值 处理WM_NCHITTEST消息的方法。对于命中测试值列表, 参见WM_NCHITTEST

因此,您从WM_NCHITTEST返回的值将在其他消息的wParam中发送,特别是WM_NCLBUTTONDOWN和WM_NCLBUTTONUP

修改如下:

LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); // inform frame change
        break;
    case WM_NCCALCSIZE:
        if (wParam) return 0; // removing the standard frame
        break;
    case WM_NCHITTEST:
        return HTCLOSE; // HTCAPTION perfectly works
    case WM_NCLBUTTONDOWN:
        if (wParam == HTCLOSE)
        {
            PostQuitMessage(0);
            return 0;
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
...

案例WM_销毁:PostQuitMessage0;中断@HansPassant,我忘记了这个例子,但它没有帮助。问题在于windows对HTCLOSE的处理。它假定按钮始终必须是windows定义的矩形。谢谢。我需要3张反对票才能得到答案。我不太明白为什么人们不喜欢它。也许标题不好。也许他们不喜欢这个美丽的节目。@olekstolar别介意,你所需要做的就是提问并提供足够的细节。