Self-willed behavior in response to return from handling of WM_NCHITTEST

infinityeternity 21 Reputation points
2020-09-16T13:32:39.057+00:00

I'm redrawing the non-client area completely, but willing to keep some default functionality. Windows doesn't allow me to put a close button wherever I want. Though it perfectly works when I say to windows that I want the whole window to be HTCAPTION, but not a close button. I know I can easily go around and make an appropriate direct api call. But there are always some doubts, what if windows do some extra things that I'm not aware of. Why do Windows do this? Maybe there is some solution that you know. Please, share.
#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;
}

This code means that wherever a user presses a mouse button an application should close. But that's not the case.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,615 questions
0 comments No comments
{count} votes

Accepted answer
  1. Strive Sun-MSFT 426 Reputation points
    2020-09-17T03:27:45.497+00:00

    Hello @infinityeternity ,

    You need to handle WM_NCLBUTTONDOWN separately.

    wParam

    The hit-test value returned by the DefWindowProc function as a result of processing the WM_NCHITTEST message. For a list of hit-test values, see WM_NCHITTEST.

    Therefore, the value you return from WM_NCHITTEST is sent in the wParam of other messages, notably WM_NCLBUTTONDOWN and WM_NCLBUTTONUP.

    Modify it like this:

    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);  
    }  
    ...  
    

    Thank you!

    ----------

    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


1 additional answer

Sort by: Most helpful
  1. Castorix31 85,131 Reputation points
    2020-09-16T14:24:20.993+00:00

    You must use DWM and you can customize completely the Caption/Borders
    See Custom Window Frame Using DWM


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.