Click here to Skip to main content
16,004,574 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am at the moment handling the WM_NCPAINT for my app. I painted a section of the top non-client area using the return value of GetWindowRect but the coordinates fell inside my applications client area. I decided to Use GetMenuBarInfo to get the menubar coordinates but the experience was the same. Using the update region made avilable by wParam is about the same result. How can I remedy these?

The relevant codes are shown below.

In the codes below, I expect GetWindowRect to return the coordinates of the window in question such that when I replace the RECT.bottom value of the returned value by 100, a band of colour starting from the top of the window and down until 100 pixels below is reached is drawn. I do not expect the band of colour to fall within the client rect not to talk of starting in it, but what I see is a displaced colour band stating at a distance in the client rect,
C++
 hdc = GetWindowDC(hWnd);
 HBRUSH hBrush = CreateSolidBrush(AppColor);
 RECT rcWindow;
 GetWindowRect(hWnd,&rcWindow);
 rcWindow.bottom = 100;
 RECT rcFill{ rcWindow };

 FillRect(hdc, &rcFill, hBrush);
 DeleteObject(hBrush);

ReleaseDC(hWnd,hdc);



In the code below, I expect the menu bar to be filled with the specified colour, but what I get is a band of colour equal in size to the menu bar but displaced insde the client region.
C++
hdc = GetWindowDC(hWnd);
MENUBARINFO menuInfo = { sizeof(MENUBARINFO) };
if (GetMenuBarInfo(hWnd, OBJID_MENU, 0, &menuInfo))
{
    HBRUSH hBrush = CreateSolidBrush(AppColor);
    RECT rcFill{ menuInfo.rcBar };

    FillRect(hdc, &rcFill, hBrush);
    DeleteObject(hBrush);
}
ReleaseDC(hWnd,hdc);



In the code below, I expect the entire window non-client area to be filled with a specified colour. Instead what I see is a band of area with size identical to the window frame but displaced from the window frame filled with the specified colour.

C++
HDC hdc = GetWindowDC(hWnd);

HBRUSH hBrush = CreateSolidBrush(AppColor);
HRGN hFillRgn = (HRGN)wParam;
if (!FillRgn(hdc, hFillRgn, hBrush))

{
    long lErrorCode = GetLastError();
    GetErrorMessageBox(lErrorCode);
}
DeleteObject(hBrush);

ReleaseDC(hWnd,hdc);


What I have tried:

I have read documentation on the two functions. It did not help.
Posted
Updated 13-Jul-24 6:39am
v5

If I understand it correctly, the menu bar of a Win32 program written in C++ is to be painted over with a rectangle for testing by using the WM_NCPAINT message. It works with a test program under Windows 10. The relevant code for WM_NCPAINT in the window procedure to color the entire area of the menu bar and the area directly below it could look like this:
C++
case WM_NCPAINT: {
    RECT windowRect, menuRect;
    HDC hdc = GetWindowDC(hWnd);
    GetWindowRect(hWnd, &windowRect);
    OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
    DefWindowProc(hWnd, WM_NCPAINT, wParam, lParam);
    HMENU hMenu = GetMenu(hWnd);
    if (hMenu) {
        int menuHeight = GetSystemMetrics(SM_CYMENU);
        int frameHeight = GetSystemMetrics(SM_CYFRAME);
        int captionHeight = GetSystemMetrics(SM_CYCAPTION);

        menuRect.top = captionHeight + frameHeight;
        menuRect.bottom = menuRect.top + menuHeight + frameHeight;
        menuRect.left = windowRect.left;
        menuRect.right = windowRect.right;

        HBRUSH brush = CreateSolidBrush(RGB(255, 0, 0));  // Rote Farbe
        FillRect(hdc, &menuRect, brush);
        DeleteObject(brush);
    }
    ReleaseDC(hWnd, hdc);
    return 0;
}
 
Share this answer
 
Comments
Gbenbam 15-Jul-24 13:04pm    
OK. Thanks. I'll try it out.
Gbenbam 15-Jul-24 13:43pm    
My actual intention is to change the colour of the non-client area to match the colour of my dialog boxes. I already have a funtioning owner drawn menu. What do you suggest?
merano99 15-Jul-24 17:45pm    
Changes to the non-client area, i.e. title bar and menu bar, are not trivial. I would be interested in the functional owner drawn menu. It would probably be best to open a new question and post the already working code there first.
Gbenbam 16-Jul-24 21:03pm    
I hope you know that owner drawn menus have nothing to do with WM_NCPAINT message. If I start a new question on WM_NCPAINT, I would have to exclude it.
Gbenbam 17-Jul-24 14:18pm    
I will shortly share the owner drawn menu code with you here as a reply to your last comment. Right now I will shortly create a new question on painting or re-colouring the non-client area like you suggested.
The MSDN documentation at WM_NCPAINT message (Winuser.h) - Win32 apps | Microsoft Learn[^] explains (and provides sample code) that the message provides a handle to the actual update region that needs to be painted.
 
Share this answer
 
Comments
Gbenbam 13-Jul-24 8:35am    
So, can you help with sample code on how to paint the menu bar? Is the menu bar part of the windows frame? I thought WM_NCPAINT is for repainting the non-client region. The term "window frame" is it the same as the non-client region?
Richard MacCutchan 13-Jul-24 9:16am    
I have tried a number of tests and it seems that the WM_NCPAINT message does not send a valid region handle with it. I guess this is either a bug in the Windows library, or the documentation is not up to date.
Gbenbam 13-Jul-24 10:03am    
The documentation is dated 01/07/202101. It is reasonably up to date? Perhaps, your interpretation of the documentation is incorrect. My own interpretation is that the documentation was this: get a dc to the region to update and then draw whaterver you wish to draw in the region bearing in mind that drawing outside the region will be clipped. That is what the example code of WM_NCPAINT seem to suggest.
Richard MacCutchan 13-Jul-24 10:09am    
Well that has nothing to do with the actual issue. If you use your debugger and step through the code you can clearly see that the WPARAM value is not a handle (it is the integer 1). Also a call to FillRgn returns zero, which means the call failed. So you can deduce from that that either the documentation is not up to date, or the system has a bug. So your best bet is to report this to Microsoft.
Gbenbam 13-Jul-24 10:13am    
Can you help to report it to Microsoft?
The following code works for me, if there is an existing menu:
C++
case WM_NCPAINT:
     HDC hdc = GetWindowDC( hWnd );
     MENUBARINFO menuInfo = {sizeof( MENUBARINFO )};
     if ( GetMenuBarInfo( hWnd, OBJID_MENU, 0L, &menuInfo ) )
     {
       HBRUSH hBrush = CreateSolidBrush( RGB(255,128,128) );
       RECT rcFill = menuInfo.rcBar;

       FillRect( hdc, &rcFill, hBrush );
       DeleteObject( hBrush );
     }
     ReleaseDC( hWnd, hdc );
     return 0;


C++
RECT rcFill = {menuInfo.rcBar};

Seems to be wrong.

Uwe
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900