Once and for all: how to get a completely transparent checkbox, button, switch, etc. In the Windows API, not with a black background?

First, sorry if I feel arrogant / rude here.

Okay, so everyone has come across this already (hopefully); I just did not find any adequate answer anywhere . We start with the manifest of Common Controls 6 and

case WM_CTLCOLORSTATIC: if (/* window has WS_EX_TRANSPARENT */) { SetBkMode((HDC) wParam, TRANSPARENT); return (LRESULT) GetStockObject(HOLLOW_BRUSH); } 

and give our tags WS_EX_TRANSPARENT . They become transparent; So far, so good. Now we need to add this style to our checkboxes (because for some reason the checkboxes respond to this, and not to WM_CTLCOLORBTN ). And ... the flags turn black!

Is there a way to make them completely transparent without resorting to attracting the owner? I would not draw flags myself; I would prefer not to guess if it looks right or what the dimensions are if the API ends up on me (and I will have to make checkboxes in the future when I add my own checkboxes to my lists and I’m not happy with how much guesses the participation) .

These checkboxes appear above the tab control. So far, I have found five dialog boxes in Windows XP with transparent flags on thematic tabs: the General tab for the Shortcut properties, the Taskbar tab for the taskbar and the Start menu properties, the System Restore tab, System Properties ”, the“ General ”tab of the folder options (radio buttons), and the“ Keyboard ”tab in the“ Accessibility Options ”section. So it certainly should be possible! I’m sure that the authors of the Windows user interface did not need to use a user draw on entire OS ... What are we all missing?

If I need to subclass it perfectly (I already have a subclass anyway for handling events), but I still don't need to draw myself.

As a bonus, what about the buttons? Overriding WM_CTLCOLORBTN gives the buttons a black border, but I notice that none of the standard dialogs mentioned above try to make the corners of the buttons transparent, so eh: /

Thanks!

0
source share
2 answers

Basically nailed it:

 void paintControlBackground(HWND hwnd, HDC dc) { HWND parent; RECT r; POINT p; int saved; parent = GetParent(hwnd); if (parent == NULL) xpanic("error getting parent container of control in paintControlBackground()", GetLastError()); if (GetWindowRect(hwnd, &r) == 0) xpanic("error getting control window rect in paintControlBackground()", GetLastError()); // the above is a window rect; convert to client rect px = r.left; py = r.top; if (ScreenToClient(parent, &p) == 0) xpanic("error getting client origin of control in paintControlBackground()", GetLastError()); saved = SaveDC(dc); if (saved == 0) xpanic("error saving DC info in paintControlBackground()", GetLastError()); if (SetWindowOrgEx(dc, px, py, NULL) == 0) xpanic("error moving window origin in paintControlBackground()", GetLastError()); SendMessageW(parent, WM_PRINTCLIENT, (WPARAM) dc, PRF_CLIENT); if (RestoreDC(dc, saved) == 0) xpanic("error restoring DC info in paintControlBackground()", GetLastError()); } case WM_CTLCOLORSTATIC: case WM_CTLCOLORBTN: if (SetBkMode((HDC) wParam, TRANSPARENT) == 0) xpanic("error setting transparent background mode to Labels", GetLastError()); paintControlBackground((HWND) lParam, (HDC) wParam); *lResult = (LRESULT) hollowBrush; return TRUE; 

There are several free ends:

This will not work if the immediate parent of this control is a group package; in this case, you need to check the class name and go to the parent chain.

You also need to implement WM_PRINTCLIENT in any custom AND containers in the window class.

This does not work for group box labels yet; you will see the texture drawn properly, but the line of the group group will be drawn on top of it. I will mark this as a solution when I find out and update this post with this information.

(The flicker I saw seems to be caused by the garbage collector, which is used by another part of the program, and thus is not yet controlled. It will change soon, I hope.)

Thanks, meanwhile!

0
source

You should return the hbrBackground element of the registered window class as follows:

 case WM_CTLCOLORBTN: case WM_CTLCOLORSTATIC: { wchar_t class_Name[100]; GetClassName(hWnd, class_Name, 100); WNDCLASS lpcls{}; GetClassInfo(g_hInstance, class_Name, &lpcls); return (LRESULT)lpcls.hbrBackground; } 
0
source

Source: https://habr.com/ru/post/1207506/


All Articles