The Old New Thing
Practical development throughout the evolution of Windows.
Latest posts
Drawing a monochrome bitmap with transparency
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 MaskBlt. void RootWindow::PaintContent(PAINTSTRUCT *pps) { HDC hdcMem = CreateCompatibleDC(pps->hdc); if (hdcMem) { int cxCheck = GetSystemMetrics(SM_CXMENUCHECK); int cyCheck = GetSystemMet...
Rendering menu glyphs is slightly trickier
Last time, we saw how to draw themed and unthemed radio buttons, and I mentioned that menu glyphs are trickier. They're trickier because they are provided as raw monochrome bitmaps instead of fully-formed color-coordinated bitmaps. First, let's do it wrong in order to see what we get. Then we'll try to fix it. Start with a clean new scratch program class RootWindow : public Window { ... protected: void PaintContent(PAINTSTRUCT *pps); BOOL WinRegisterClass(WNDCLASS *pwc) { pwc->hbrBackground = (HBRUSH)(COLOR_MENU + 1); return __super::WinRegisterClass(pwc); } ... }; void RootWindow::PaintContent...
Rendering standard Windows elements
The DrawFrameControl function allows you to render standard Windows elements in your custom controls. Let's start by simply rendering a selected radio button. Start with our new scratch program and make this very simple change: class RootWindow : public Window { ... protected: void PaintContent(PAINTSTRUCT *pps); ... }; void RootWindow::PaintContent(PAINTSTRUCT *pps) { RECT rc = { 0, 0, 32, 32 }; DrawFrameControl(pps->hdc, &rc, DFC_BUTTON, DFCS_BUTTONRADIO | DFCS_CHECKED); } When you run the program, you'll see a little radio button in the corner. Woo-hoo. You might also no...
Microsoft Company Picnic 2005
This weekend, it was Microsoft's turn to rent Mountain Meadows Farm for the company picnic. As I noted last year, the picnic is put on by a company that just puts on company picnics all summer. In addition to Microsoft, they also do Alaska Air, Honeywell, T-Mobile, and Amazon. I decided to bicycle to the picnic this year. The route was approximately 25 miles from Marymoor Park (6046 W Lake Sammamish Pkwy NW, Redmond WA) to Mountain Meadows Farm (10106 422nd Ln SE, North Bend, WA: three out of four web-based mapping services can find the farm given the address) along State Highway 202. According to the Fat Cy...
Does Windows have a limit of 2000 threads per process?
Often I see people asking why they can't create more than around 2000 threads in a process. The reason is not that there is any particular limit inherent in Windows. Rather, the programmer failed to take into account the amount of address space each thread uses. A thread consists of some memory in kernel mode (kernel stacks and object management), some memory in user mode (the thread environment block, thread-local storage, that sort of thing), plus its stack. (Or stacks if you're on an Itanium system.) Usually, the limiting factor is the stack size. This program will typically print a value around 2000 for ...
What is this “web site” thing you are talking about?
One reaction I've seen when people learn about all the compatibility work done in the Windows 95 kernel is to say, Why not add code to the installer wizard [alas, page is now 404] which checks to see if you're installing SimCity and, if so, informs you of a known design flaw, then asks you to visit Electronic Arts' webpage for a patch? Let's ignore the issue of the "installer wizard"; most people do not go through the Add and Remove Programs control panel to install programs, so any changes to that control panel wouldn't have helped anyway. But what about detecting that you're running SimCity and t...
When the normal window destruction messages are thrown for a loop
Last time, I alluded to weirdness that can result in the normal cycle of destruction messages being thrown out of kilter. Commenter Adrian noted that the WM_GETMINMAXINFO message arrives before WM_NCCREATE for top-level windows. This is indeed unfortunate but (mistake or not) it's been that way for over a decade and changing it now would introduce serious compatibility risk. But that's not the weirdness I had in mind. Some time ago I was helping to debug a problem with a program that was using the ListView control, and the problem was traced to the program subclassing the ListView control and, through a...
What is the difference between WM_DESTROY and WM_NCDESTROY?
There are two window messages closely-associated with window destruction, the WM_DESTROY message and the WM_NCDESTROY message. What's the difference? The difference is that the WM_DESTROY message is sent at the start of the window destruction sequence, whereas the WM_NCDESTROY message is sent at the end. This is an important distinction when you have child windows. If you have a parent window with a child window, then the message traffic (in the absence of weirdness) will go like this: hwnd = parent, uMsg = WM_DESTROY hwnd = child, uMsg = WM_DESTROY hwnd = child, uMsg = WM_NCDESTROY hwnd = parent, uMsg = W...
On paying for your meal upon leaving a restaurant
Robert Scoble's embarrassment over forgetting to pay a restaurant bill reminds me of an even more embarrassing incident experienced by a component team from the Windows 95 team. To celebrate something or other, their team went to lunch at The Salish Lodge, a fine dining establishment. At the end of the meal, everybody thought somebody else was going to handle the bill, and they all walked out as a group. The administrative assistant who made the reservation received a somewhat concerned telephone call from the restaurant when they discovered that a large party just skipped the check. Profuse apologies we...