Details drawn with DrawThemeBackground on Windows 10 are incorrect

Description of the problem

I want to create a Windows API application in C that displays menus and title buttons in the same non-client area as Firefox pay attention to the menu and title buttons

To do this, I decided that the solution should:

  • type WS_POPUP so that the menu is aligned at the top
  • take ownership of a non-client area (where the menu is displayed)
  • manually show the minimize / enlarge / close buttons

The solution should work on Windows 7, 8 and 10 (and, ideally, in future versions).

What does it look like now

I have a test program available on GitHub .

In my application, I redefined the relevant events:

WM_NCCALCSIZE , WM_NCHITTEST , WM_NCLBUTTONDOWN , WM_NCLBUTTONUP , WM_NCMOUSEMOVE , WM_NCPAINT

And then I repaint the non-client areas for these events: WM_NCACTIVATE , WM_SETTEXT

Here is an example of how I am rendering:

 // globals set elsewhere RECT customAreaRect, minRect, maxRect, closeRect, coverMenuRect; BOOL maximized; // ... LRESULT OnPaintNCA(HWND hWnd, WPARAM wParam, LPARAM lParam) { RECT windowRect; HRGN hRgn = NULL; GetWindowRect(hWnd, &windowRect); if (wParam == 1) { hRgn = CreateRectRgnIndirect(&windowRect); } else { hRgn = (HRGN)wParam; } if (hRgn) { // Carve out the area for custom content HRGN captionButtonRgn = CreateRectRgnIndirect(&customAreaRect); CombineRgn(hRgn, hRgn, captionButtonRgn, RGN_XOR); DeleteObject(captionButtonRgn); // Force default painting for non-client area LRESULT ret = DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0); // black background covering part of menu, behind buttons HDC hDC = GetWindowDC(hWnd); FillRect(hDC, &coverMenuRect, (HBRUSH)GetStockObject(BLACK_BRUSH)); HTHEME hTheme = OpenThemeData(hWnd, TEXT("WINDOW")); DrawThemeBackground(hTheme, hDC, WP_MINBUTTON, partState, minRect, NULL); DrawThemeBackground(hTheme, hDC, maximized ? WP_RESTOREBUTTON : WP_MAXBUTTON, partState, maxRect, NULL); DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, partState, closeRect, NULL); CloseThemeData(hTheme); } } 

The result obtained is as follows: screenshot showing what i have Unfortunately, the styles used for parts (minimize, maximize / restore, close) look like styles for Windows 7/8, and not the native Windows 10 controls . I was looking for a way to do this for a few days without any luck. I need help on how to display these buttons for Windows 10 using the Windows API.

Current state (and what I have tried so far)

My first guess was that I needed to include visual styles correctly.

Here are some screenshots of the relevant project settings that I tried: target platform version

embed manifest

Other ideas

It works a little for me to try. Before throwing a towel, I tried to do some things:

  • Idea 1: using GetThemeStream , which allows you to get the size / bitmap for the controls.

    • Download the aero msstyles file as follows:

    HMODULE themeFile = LoadLibraryEx(TEXT("C:\\Windows\\Resources\\Themes\\aero\\aero.msstyles"), NULL, LOAD_LIBRARY_AS_DATAFILE);

    • Get a bitmap for the part (shutter button, maximize button, etc.) like this (transfer of the downloaded theme file):

    GetThemeStream(h, WP_MAXBUTTON, MAXBS_NORMAL, TMT_DISKSTREAM, (void**)&buffer, &bufferSize, themeFile);

    • Download the bitmap; it seems to be in PNG format (I didn’t get that far).
    • Draw a bitmap
  • Idea 2: copy the non-client area from a hidden window in which there is a title area (and minimize, enlarge, close the buttons).

    • Create a window with an inscription and min / max buttons, never activating it.
    • In non-client paint, get the DC for this window and grab the pixels for the min / max / close button.
    • Extract them using bitblt
+8
c visual-c ++ winapi
source share
1 answer

I think the problem is related to trying to use WM_NCPAINT in OS>> = Win Vista. Since Vista all NC rendering is managed by DWM (Desktop Window Manager). If you still dare to handle WM_NCPAINT , DWM rendering will be disabled and you will get an "old school":

From an open blog :

DWM has no worries about inheritance, because applications cannot draw inside a glass frame, since it is rendered and a completely different process is controlled. If an application tries to do this, Windows will detect it and completely remove the glass frame (and therefore, return to the main frame) so that the application can draw what it wants to draw.

To get the correct results, you have to do this “ DWM method ” (in particular, the sections “Removing the standard frame” and “Removing the standard frame”, “Drawing in the window of the extended frame”). This works by allowing DWM to render the frame inside the client area so that you could draw it. Also with this solution you don’t need to draw the header buttons yourself. This answer summarizes the necessary steps (in the section “Supported Aero Solutions”).

The caveat is that it’s convenient for you to draw the menu yourself, and you cannot use most of the GDI APIs for this, because GDI ignores the alpha channel and everything will look ugly if the frame is translucent (Vista and Win 7 by default, Win8 + with extensions). BitBlt() works if the source is a DC memory that contains a 32bpp bitmap with alpha. GDI + also works.

0
source share

All Articles