A customer was using an MFC CHtmlDialog
as a child dialog and found that they needed to add the WS_
CLIPCHILDREN
style to ensure that the contents appeared on the screen; otherwise, the parent dialog would paint its background over the child dialog, and the child dialog would consequently appear to vanish.
On the other hand, they also had some transparent image controls on the parent dialog, and adding the WS_
CLIPCHILDREN
style prevented those controls from drawing transparently, meaning that instead of having the parent dialog’s background show through, it just used a black background.
How can they get the best of both worlds, with WS_
CLIPCHILDREN
style applying to some child controls but not others?
The controls that need the background to show through can ask the parent dialog to draw its background. They can do this the same way standard controls do it, by sending a WM_
CTLCOLORxxx
message to the parent to request the background brush and text colors. Of course, since it’s an image control, the text colors aren’t interesting.
case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); HBRUSH hbrBackground = (HBRUSH) SendMessage(GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd); FillRect(hdc, &ps.rcPaint, hbrBackground); DrawTheImage(...); EndPaint(hwnd, &ps); return 0; }
This technique assumes that the parent dialog responds to WM_
CTLCOLORxxx
messages. If the parent dialog has standard colors, then the DefWindowProc
function will return standard colors, and everything will work out. But if the parent dialog uses custom colors, it will have to add additional message handlers for these messages.
Alternatively, the image controls could render its background by forwarding the WM_
ERASEBKGND
message to its parent. Since the child and parent have different coordinates, you’ll have to do some coordinate manipulation to get the parent to receive a device context whose origin is what it expects.
case WM_ERASEBKGND: { HDC hdc = (HDC)wParam; HWND hwndParent = GetParent(hwnd); POINT ptOffset{}; MapWindowPoints(hwnd, hwndParent, &ptOffset, 1); OffsetWindowOrgEx(hdc, ptOffset.x, ptOffset.y, &ptOrig); LRESULT lres = SendMessage(hwndParent, WM_ERASEBKGND, wParam, lParam); SetWindowOrgEx(hdc, ptOrig.x, ptOrig.y, nullptr); return lres; }
Note that neither of these techniques actually draw the control transparently. Rather, they attempt to simulate the effect by asking the parent to draw its background into the control. It also means that if the parent draws something interesting in its WM_
PAINT
handler, it won’t show up in the “background” of the control.
Nevertheless, this usually works well enough for most purposes.
0 comments