Date: | August 3, 2005 / year-entry #210 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050803-16/?p=34733 |
Comments: | 6 |
Summary: | Last time, I left you with a brief puzzle. Here are two approaches. I am not a GDI expert, so there may be even better solutions out there. To emphasize the transparency, I'll change the window background color to the application workspace color. BOOL WinRegisterClass(WNDCLASS *pwc) { pwc->hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); return __super::WinRegisterClass(pwc); }... |
Last time, I left you with a brief puzzle. Here are two approaches. I am not a GDI expert, so there may be even better solutions out there. To emphasize the transparency, I'll change the window background color to the application workspace color. BOOL WinRegisterClass(WNDCLASS *pwc) { pwc->hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); return __super::WinRegisterClass(pwc); }
Method 1:
A big
void RootWindow::PaintContent(PAINTSTRUCT *pps) { HDC hdcMem = CreateCompatibleDC(pps->hdc); if (hdcMem) { int cxCheck = GetSystemMetrics(SM_CXMENUCHECK); int cyCheck = GetSystemMetrics(SM_CYMENUCHECK); HBITMAP hbmMono = CreateBitmap(cxCheck, cyCheck, 1, 1, NULL); if (hbmMono) { HBITMAP hbmPrev = SelectBitmap(hdcMem, hbmMono); if (hbmPrev) { RECT rc = { 0, 0, cxCheck, cyCheck }; DrawFrameControl(hdcMem, &rc, DFC_MENU, DFCS_MENUCHECK); COLORREF clrTextPrev = SetTextColor(pps->hdc, GetSysColor(COLOR_MENUTEXT));
This has the least amount of typing but feels like
overkill to me, using a quaternary raster operation
as if were a ternary, just because I didn't want to create a
pattern brush.
(The raster operation 0x00AA0029 is the NOP operator; it leaves
the destination alone. I didn't have this memorized;
I looked it up
in the documentation.)
The Notice that the background color is never used (since it's supposed to be transparent); consequently, we can delete the code that sets and restores the DC's background color. Method 2: The traditional two-step. void RootWindow::PaintContent(PAINTSTRUCT *pps) { HDC hdcMem = CreateCompatibleDC(pps->hdc); if (hdcMem) { int cxCheck = GetSystemMetrics(SM_CXMENUCHECK); int cyCheck = GetSystemMetrics(SM_CYMENUCHECK); HBITMAP hbmMono = CreateBitmap(cxCheck, cyCheck, 1, 1, NULL); if (hbmMono) { HBITMAP hbmPrev = SelectBitmap(hdcMem, hbmMono); if (hbmPrev) { RECT rc = { 0, 0, cxCheck, cyCheck }; DrawFrameControl(hdcMem, &rc, DFC_MENU, DFCS_MENUCHECK); COLORREF clrTextPrev = SetTextColor(pps->hdc, RGB(0,0,0)); COLORREF clrBkPrev = SetBkColor(pps->hdc, RGB(255,255,255)); BitBlt(pps->hdc, cxCheck, 0, cxCheck, cyCheck, hdcMem, 0, 0, SRCAND); SetTextColor(pps->hdc, GetSysColor(COLOR_MENUTEXT)); SetBkColor(pps->hdc, RGB(0,0,0)); BitBlt(pps->hdc, cxCheck, 0, cxCheck, cyCheck, hdcMem, 0, 0, SRCPAINT); SetBkColor(pps->hdc, clrBkPrev); SetTextColor(pps->hdc, clrTextPrev); SelectBitmap(hdcMem, hbmPrev); } DeleteObject(hbmMono); } DeleteDC(hdcMem); } }
This is the traditional two-step blit.
The first erases the pixels that are about to be overwritten
by setting the foreground to black and background to white,
then using This method can be shortened by negating the first blit, reversing the sense of foreground and background, so that the color black doesn't have to move between the background color and the text color. void RootWindow::PaintContent(PAINTSTRUCT *pps) { HDC hdcMem = CreateCompatibleDC(pps->hdc); if (hdcMem) { int cxCheck = GetSystemMetrics(SM_CXMENUCHECK); int cyCheck = GetSystemMetrics(SM_CYMENUCHECK); HBITMAP hbmMono = CreateBitmap(cxCheck, cyCheck, 1, 1, NULL); if (hbmMono) { HBITMAP hbmPrev = SelectBitmap(hdcMem, hbmMono); if (hbmPrev) { RECT rc = { 0, 0, cxCheck, cyCheck }; DrawFrameControl(hdcMem, &rc, DFC_MENU, DFCS_MENUCHECK); COLORREF clrTextPrev = SetTextColor(pps->hdc, RGB(255,255,255)); COLORREF clrBkPrev = SetBkColor(pps->hdc, RGB(0,0,0)); BitBlt(pps->hdc, cxCheck, 0, cxCheck, cyCheck, hdcMem, 0, 0, 0x00220326); // DSna SetTextColor(pps->hdc, GetSysColor(COLOR_MENUTEXT)); BitBlt(pps->hdc, cxCheck, 0, cxCheck, cyCheck, hdcMem, 0, 0, SRCPAINT); SetBkColor(pps->hdc, clrBkPrev); SetTextColor(pps->hdc, clrTextPrev); SelectBitmap(hdcMem, hbmPrev); } DeleteObject(hbmMono); } DeleteDC(hdcMem); } }
Whether this shortening is actually an overall
improvement is difficult to tell.
It's possible that some display drivers have a highly optimized
(Exercise: Why can't you instead reverse the second blit,
converting it to a |
Comments (6)
Comments are closed. |
Why is it that I have a hard time taking seriously a webpage (as linked in the article) whose filename is "pantdraw"? :-)
I’m scared to click the link in case I get busted by the "URL cops" in my company. 8))
On CE (therefore with very limited font options) I needed to emulate a monospaced character cell display, but with colour – the font also needs to be user-modifiable (the platform emulated permitted this). The font is designed as a monochrome bitmap – black represents text, white is background.
I used to have a horrible sequence of BitBlts with a temporary DC to do the composition in, for coloured (not black or white) text and/or backgrounds. Thanks to your article on ternary ROPs I managed to work out a single ROP code that would do most of the work in one go. I forget exactly what it is – I think the official RPN definition involves XORs, which I’d never have figured out myself. I’d always assumed that the only supported ROP3s were the ones listed in the BitBlt documentation.
I’m still using the ‘special case’ code that does black-on-white and white-on-black (SRCCOPY and NOTSRCCOPY respectively). In those cases I don’t need to do a background fill first, nor select different brushes.
Mike D: Not sure why your CE font options are so limited, unless you’re distributing to existing PocketPC devices. Using CE 4.2 (not even 5.0) we have the option of including any TTF font in our platform.
Still, I’d be interested in knowing what ROP codes you used to paint a b/w modifiable font.
Mike D: Sounds like all you needed to do was to set the destination DC’s colours before using SRCCOPY.
The text foreground and background colors play a role.