Scrollbars part 10 – Towards a deeper understanding of the WM_NCCALCSIZE message

Date:September 11, 2003 / year-entry #57
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20030911-00/?p=42553
Comments:    2
Summary:When your window is resized, Windows uses the WM_NCCALCSIZE message to determine where your window's client area lives inside your window rectangle. There are two forms of the WM_NCCALCSIZE message. The simple form merely takes a window rectangle and returns a client rectangle. This is useful for resizing a window to have a desired client...

When your window is resized, Windows uses the WM_NCCALCSIZE message to determine where your window's client area lives inside your window rectangle.

There are two forms of the WM_NCCALCSIZE message. The simple form merely takes a window rectangle and returns a client rectangle. This is useful for resizing a window to have a desired client rectangle, taking menu wrapping into account. The AdjustWindowRectEx function cannot take menu wrapping into account because it doesn't know which menu you are using. (Notice that there is no HMENU or HWND parameter to AdjustWindowRectEx.)

void
SetWindowClientSize(HWND hwnd, int cx, int cy)
{
    HMENU hmenu = GetMenu(hwnd);
    RECT rcWindow = { 0, 0, cx, cy };

    /*
     *  First convert the client rectangle to a window rectangle the
     *  menu-wrap-agnostic way.
     */
    AdjustWindowRectEx(&rcWindow, GetWindowStyle(hwnd), hmenu != NULL,
                       GetWindowExStyle(hwnd));

    /*
     *  If there is a menu, then check how much wrapping occurs
     *  when we set a window to the width specified by AdjustWindowRect
     *  and an infinite amount of height.  An infinite height allows
     *  us to see every single menu wrap.
     */
    if (hmenu) {
        RECT rcTemp = rcWindow;
        rcTemp.bottom = 0x7FFF;     /* "Infinite" height */
        SendMessage(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rcTemp);

        /*
         *  Adjust our previous calculation to compensate for menu
         *  wrapping.
         */
        rcWindow.bottom += rcTemp.top;
    }

    SetWindowPos(hwnd, NULL, 0, 0, rcWindow.right - rcWindow.left,
                 rcWindow.bottom - rcWindow.top, SWP_NOMOVE | SWP_NOZORDER);

}

Exercise: Explain why we used 0x7FFF to represent infinite height.

Exercise: Explain the line rcWindow.bottom += rcTemp.top.


Comments (2)
  1. Reiko says:

    Exercise: Explain why we used 0x7FFF to represent infinite height.

    OK, I’ll take a stab… In Win 9x, coordinates are limited to 16 bits, and 7FFF is the largest quantity a signed 16-bit int can hold. So 7FFF is the largest number you can use there and have it work on all versions of Windows.

    What do I win? ^_~

  2. scott says:

    Re: “Explain the line rcWindow.bottom += rcTemp.top.”
    Before calling sending WM_NCCALCSIZE, rcWindow contains the proposed area of the whole window (nonclient and client area). After sending WM_NCCALCSIZE, rcTemp contains the coordinates of the window’s client area. Therefore, rcTemp.top is actually the bottom most position of the top part of the window’s non-client area. This is the area that the wrapped menu occupies and for which is being compensating for. Therefore, the bottom of the window is moved down by that amount.

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index