<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Larry Osterman's WebLog : Nifty Win32 tricks.</title><link>http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx</link><description>Tags: Nifty Win32 tricks.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Building a flicker free volume control</title><link>http://blogs.msdn.com/larryosterman/archive/2009/09/16/building-a-flicker-free-volume-control.aspx</link><pubDate>Thu, 17 Sep 2009 00:50:09 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9896072</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>30</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/9896072.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=9896072</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=9896072</wfw:comment><description>&lt;p&gt;When we shipped Windows Vista, one of the really annoying UI annoyances with the volume control was that whenever you resized it, it would flicker.&amp;#160; &lt;/p&gt;  &lt;p&gt;To be more specific, the right side of the control would flicker – the rest didn’t flicker (which was rather strange).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Between the Win7 PDC release (what we called M3 internally) and the Win7 Beta, I decided to bit the bullet and see if I could fix the flicker.&amp;#160; It seems like I tried everything to make the flickering go away but I wasn’t able to do it until I ran into the &lt;a href="http://blogs.msdn.com/larryosterman/archive/2008/08/27/larry-s-new-favorite-windows-message-wm-printclient.aspx"&gt;WM_PRINTCLIENT&lt;/a&gt; message which allowed me to direct all of the internal controls on the window to paint themselves.&lt;/p&gt;  &lt;p&gt;Basically on a paint call, I’d take the paint DC and send a WM_PRINTCLIENT message to each of the controls in sndvol asking them each to paint themselves to the new DC.&amp;#160; This worked almost perfectly – I was finally able to build a flicker free version of the UI.&amp;#160; The UI wasn’t perfect (for instance the animations that faded in the “flat buttons” didn’t fire) but the UI worked just fine and looked great so I was happy that' I’d finally nailed the problem.&amp;#160; That happiness lasted until I got a bug report in that I simply couldn’t figure out.&amp;#160; It seems that if you launched the volume mixer, set the focus to another application then selected the volume mixer’s title bar and moved the mixer, there were a ton of drawing artifacts left on the screen.&lt;/p&gt;  &lt;p&gt;I dug into it a bunch and was stumped.&amp;#160; It appeared that the clipping rectangle sent in the WM_PAINT message to the top level message didn’t include the entire window, thus portions of the window weren’t erased.&amp;#160; I worked on this for a couple of days trying to figure out what was going wrong and I finally asked for help on one of our internal mailing lists.&lt;/p&gt;  &lt;p&gt;The first response I got was that I shouldn’t use WM_PRINTCLIENT because it was going to cause me difficulty.&amp;#160; I’d already come to that conclusion – by trying to control every aspect of the drawing experience for my app, I was essentially working against the window manager – that’s why the repaint problem was happening.&amp;#160; By calling WM_PRINTCLIENT I was essentially putting a band-aid on the real problem but I hadn’t solved the &lt;em&gt;real &lt;/em&gt;problem, all I’d done is to hide it. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;So I had to go back to the drawing board.&amp;#160; Eventually (with the help of one of the developers on the User team) I finally tracked down the original root cause of the problem and it turns out that the root cause was somewhere totally unexpected.&lt;/p&gt;  &lt;p&gt;Consider the volume UI:&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/Buildingaflickerfreevolumecontrol_D098/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/Buildingaflickerfreevolumecontrol_D098/image_thumb.png" width="493" height="353" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The UI is composed of two major areas: The “Devices” group and the “Applications” group.&amp;#160; There’s a group box control wrapped around the two areas.&lt;/p&gt;  &lt;p&gt;Now lets look at the group box control.&amp;#160; For reasons that are buried deep in the early history of Windows, a group box is actually a form of the “button” control.&amp;#160; If you look at the window styles for a button in SpyXX, you’ll see: &lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/Buildingaflickerfreevolumecontrol_D098/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/Buildingaflickerfreevolumecontrol_D098/image_thumb_1.png" width="400" height="302" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Notice the CS_VREDRAW and CS_HREDRAW window class styles.&amp;#160; The &lt;a href="http://msdn.microsoft.com/en-us/library/ms633574(VS.85).aspx#class_styles"&gt;MSDN documentation for class styles&lt;/a&gt; says:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;CS_HREDRAW - Redraws the entire window if a movement or size adjustment changes the width of the client area.     &lt;br /&gt;CS_VREDRAW - Redraws the entire window if a movement or size adjustment changes the height of the client area.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In other words every window class with the CS_HREDRAW or CS_VREDRAW style will &lt;em&gt;always &lt;/em&gt;be fully repainted whenever the window is resized (including all the controls inside the window).&amp;#160; And ALL buttons have these styles.&amp;#160; That means that whenever you resize &lt;em&gt;any&lt;/em&gt; buttons, they’re going to flicker, and so will all of the content that lives below the button.&amp;#160; For most buttons this isn’t a big deal but for group boxes it can be a big issue because group boxes contain other controls.&lt;/p&gt;  &lt;p&gt;In the case of sndvol, when you resize the volume control, we resize the applications group box (because it’s visually pinned to the right side of the dialog).&amp;#160; Which causes the group box and all of its contained controls to repaint and thus flicker like crazy.&amp;#160; The only way to fix this is to remove the CS_HREDRAW and CS_VREDRAW buttons from the window style for the control.&lt;/p&gt;  &lt;p&gt;The good news is that once I’d identified the root cause, the solution to my problem was relatively simple.&amp;#160; I needed to build my own custom version of the group box which handled its own painting and didn’t have the CS_HREDRAW and CS_VREDRAW class.&amp;#160; Fortunately it’s really easy to draw a group box – if themes are enabled a group box can be drawn with &lt;a href="http://social.msdn.microsoft.com/Search/en-US?query=drawthemebackground&amp;amp;ac=3"&gt;DrawThemeBackground&lt;/a&gt; API with the &lt;a href="http://msdn.microsoft.com/en-us/library/bb773210(VS.85).aspx"&gt;BP_GROUPBOX&lt;/a&gt; part and if theming is disabled, you can use the &lt;a href="http://msdn.microsoft.com/en-us/library/dd162477(VS.85).aspx"&gt;DrawEdge&lt;/a&gt; API to draw the group box.&amp;#160; Once I added the new control that and dealt with a number of other clean-up issues (making sure that the right portions of the window were invalidated when the window was resized for example), making sure that my top level control had the WS_CLIPCHILDREN style and that each of the sub windows had the WS_CLIPSIBLINGS style I had a version of sndvol that was flicker free AND which let the window manager handle all the drawing complexity.&amp;#160; There are still some minor visual gotchas in the UI (for example, if you resize the window using the left edge the right side of the group box “shudders” a bit – this is apparently an artifact that’s outside my control – other apps have similar issues when resized on the left edge) but they’re acceptable.&lt;/p&gt;  &lt;p&gt;As an added bonus, now that I was no longer painting everything manually, the fade-in animations on the flat buttons started working again!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;PS: While I was writing this post, I ran into this &lt;a href="http://www.catch22.net/tuts/flicker"&gt;tutorial on building flicker free applications&lt;/a&gt;, I wish I’d run into it while I was trying to deal with the flickering problem because it nicely lays out how to solve the problem.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9896072" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Windows+7/default.aspx">Windows 7</category></item><item><title>What’s the difference between GetTickCount and timeGetTime?</title><link>http://blogs.msdn.com/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx</link><pubDate>Thu, 03 Sep 2009 00:31:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9890595</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>26</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/9890595.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=9890595</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=9890595</wfw:comment><description>&lt;p&gt;I’ve always believed that the most frequently used multimedia API in winmm.dll was the PlaySound API.&amp;#160; However I recently was working with the results of some static analysis tools that were run on the Windows 7 codebase and I realized that in fact the most commonly used multimedia API (in terms of code breadth) was actually the timeGetTime API.&amp;#160; In fact almost all the multimedia APIs use timeGetTime which was somewhat surprising to me at the time.&lt;/p&gt;  &lt;p&gt;The MSDN article for &lt;a href="http://msdn.microsoft.com/en-us/library/aa912626.aspx"&gt;timeGetTime&lt;/a&gt; says that timeGetTime “retrieves the system time, in milliseconds. The system time is the time elapsed since the system started.”.&lt;/p&gt;  &lt;p&gt;But that’s almost exactly what the &lt;a href="http://msdn.microsoft.com/en-us/library/ms724408(VS.85).aspx"&gt;GetTickCount&lt;/a&gt; API returns “the number of milliseconds that have elapsed since the system was started, up to 49.7 days.” (obviously timeGetTime has the same 49.7 day limit since both APIs return 32bit counts of milliseconds).&lt;/p&gt;  &lt;p&gt;So why are all these multimedia APIs using timeGetTime and not GetTickCount since the two APIs apparently return the same value?&amp;#160; I wasn’t sure so I dug in a bit deeper.&lt;/p&gt;  &lt;p&gt;The answer is that they don’t.&amp;#160; You can see this with a tiny program:&lt;/p&gt;  &lt;blockquote&gt;   &lt;div class="csharpcode"&gt;     &lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; _tmain(&lt;span class="kwrd"&gt;int&lt;/span&gt; argc, _TCHAR* argv[])&lt;/pre&gt;

    &lt;pre&gt;{&lt;/pre&gt;

    &lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; i = 100;&lt;/pre&gt;

    &lt;pre&gt;    DWORD lastTick = 0;&lt;/pre&gt;

    &lt;pre class="alt"&gt;    DWORD lastTime = 0;&lt;/pre&gt;

    &lt;pre&gt;    &lt;span class="kwrd"&gt;while&lt;/span&gt; (--i)&lt;/pre&gt;

    &lt;pre class="alt"&gt;    {&lt;/pre&gt;

    &lt;pre&gt;        DWORD tick = GetTickCount();&lt;/pre&gt;

    &lt;pre class="alt"&gt;        DWORD time = timeGetTime();&lt;/pre&gt;

    &lt;pre&gt;        printf(&lt;span class="str"&gt;&amp;quot;Tick: %d, Time: %d, dTick: %3d, dTime: %3d\n&amp;quot;&lt;/span&gt;, tick, time, tick-lastTick, time-lastTime);&lt;/pre&gt;

    &lt;pre class="alt"&gt;        lastTick = tick;&lt;/pre&gt;

    &lt;pre&gt;        lastTime = time;&lt;/pre&gt;

    &lt;pre class="alt"&gt;        Sleep(53);&lt;/pre&gt;

    &lt;pre&gt;    }&lt;/pre&gt;

    &lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; 0;&lt;/pre&gt;

    &lt;pre&gt;}&lt;/pre&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;If you run this program, you’ll notice that the difference between the timeGetTime results is MUCH more stable than the difference between the GetTickCount results (note that the program sleeps for 53ms which usually doesn’t match the native system timer resolution):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tick: 175650292, Time: 175650296, dTick:&amp;#160; 46, dTime:&amp;#160; 54
    &lt;br /&gt;Tick: 175650355, Time: 175650351, dTick:&amp;#160; 63, dTime:&amp;#160; 55

    &lt;br /&gt;Tick: 175650417, Time: 175650407, dTick:&amp;#160; 62, dTime:&amp;#160; 56

    &lt;br /&gt;Tick: 175650464, Time: 175650462, dTick:&amp;#160; 47, dTime:&amp;#160; 55

    &lt;br /&gt;Tick: 175650526, Time: 175650517, dTick:&amp;#160; 62, dTime:&amp;#160; 55

    &lt;br /&gt;Tick: 175650573, Time: 175650573, dTick:&amp;#160; 47, dTime:&amp;#160; 56

    &lt;br /&gt;Tick: 175650636, Time: 175650628, dTick:&amp;#160; 63, dTime:&amp;#160; 55

    &lt;br /&gt;Tick: 175650682, Time: 175650683, dTick:&amp;#160; 46, dTime:&amp;#160; 55

    &lt;br /&gt;Tick: 175650745, Time: 175650739, dTick:&amp;#160; 63, dTime:&amp;#160; 56

    &lt;br /&gt;Tick: 175650792, Time: 175650794, dTick:&amp;#160; 47, dTime:&amp;#160; 55

    &lt;br /&gt;Tick: 175650854, Time: 175650850, dTick:&amp;#160; 62, dTime:&amp;#160; 56&lt;/p&gt;

  &lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s because GetTickCount is incremented by the clock tick frequency on every clock tick and as such the delta values waver around the actual time (note that the deltas average to 55ms so on average getTickCount returns an accurate result but not with spot measurements) but timeGetTime’s delta is highly predictable.&lt;/p&gt;

&lt;p&gt;It turns out that for isochronous applications (those that depend on clear timing) it is often important to be able to retrieve the current time in a fashion that doesn’t vary, that’s why those applications use timeGetTime to achieve their desired results.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9890595" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>Delay Load is not a good way to check for functionality</title><link>http://blogs.msdn.com/larryosterman/archive/2009/03/06/delay-load-is-not-a-good-way-to-check-for-functionality.aspx</link><pubDate>Fri, 06 Mar 2009 23:19:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9463386</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/9463386.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=9463386</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=9463386</wfw:comment><description>&lt;p&gt;On my &lt;a href="http://blogs.msdn.com/larryosterman/archive/2009/03/05/checking-file-versions-is-surprisingly-hard.aspx"&gt;previous post&lt;/a&gt;, Koro made the following &lt;a href="http://blogs.msdn.com/larryosterman/archive/2009/03/05/checking-file-versions-is-surprisingly-hard.aspx#9463283"&gt;comment&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“Don't ever check windows versions.&amp;#160; Instead check for functionality being present or not.&amp;quot;&lt;/p&gt;    &lt;p&gt;You can't always do that.&lt;/p&gt;    &lt;p&gt;Do I want to add a __try/__except to catch delay-load exceptions around every UxTheme call or just do:&lt;/p&gt;    &lt;p&gt;g_bTheme=(g_bWinNT&amp;amp;&amp;amp;(g_nWinVer&amp;gt;0x00050001));&lt;/p&gt;    &lt;p&gt;Then check that flag before calling OpenThemeData?&lt;/p&gt;    &lt;p&gt;In some other cases too (all the Crypt Hash functions - trying to compute an MD5) the functions is documented as working fine in Win98 but it just fails - there is no way to know except of checking the version beforewards.&lt;/p&gt;    &lt;p&gt;At least, as implied earlier, I just pack the Windows version in a DWORD at program startup to avoid nasty version comparision errors.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;IMHO Koro’s misusing the &lt;a href="http://msdn.microsoft.com/en-us/library/151kt790.aspx"&gt;delayload functionality&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;DelayLoad is primarily a performance tool – when you DelayLoad a function, a tiny stub for the DelayLoad function is inserted into your application which calls LoadLibrary/GetProcAddress on the function.&amp;#160; That then means that when your application is launched, the loader doesn’t resolve references to the DelayLoaded function and thus your application will launch faster.&lt;/p&gt;  &lt;p&gt;For example many components in the OS delay load WINMM.DLL because all they use in WINMM is the PlaySound API, and even then they only use it on relatively rare circumstances.&amp;#160; By delayloading WINMM.DLL they avoid having the performance penalty of having WINMM.DLL loaded into their address until it’s needed.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As Koro mentioned, DelayLoad &lt;em&gt;can&lt;/em&gt; also be used as a mechanism to check to see if a particular piece of OS functionality is present, but the challenge is that now you need to wrap every API call with an exception handler (or you need to specify a delay load handler that provides a more reasonable default behavior).&amp;#160; Personally I wouldn’t do that – instead I’d manually call LoadLibrary/GetProcAddress to load the required functions because it allows you to have complete control over when you access over your error handling.&amp;#160; It also allows you to avoid using structured exception handling (which should be avoided if at all possible).&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you DO have need to use DelayLoad as a functionality check, you could try this trick (which works only for Koro’s problem).&amp;#160; Instead of wrapping all the theme API calls with SEH, you just add code to your app like this (I haven’t compiled this code, it’s just an example):&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre class="csharpcode"&gt;BOOL g_EnableThemes = FALSE;
__try
{
    g_EnableThemes = IsThemeActive();
}
__except(&amp;lt;Your Exception Filter&amp;gt;)
{
}&lt;/pre&gt;

  &lt;pre class="csharpcode"&gt;if (g_EnableThemes)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;    g_ThemeHandle = OpenThemeData(…)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;pre class="csharpcode"&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;/pre&gt;

&lt;p&gt;In other words check for functionality being enabled once with an exception handler and later on use just the EnableThemes global variable to key off the behavior.&lt;/p&gt;

&lt;p&gt;But this doesn’t change the fact that (IMHO) you’re abusing the DelayLoad functionality and using it as a versioning mechanism.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9463386" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Things+you+shouldn_2700_t+do_2E00_/default.aspx">Things you shouldn't do.</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>Fixing an accessibility bug with the trackbar common control</title><link>http://blogs.msdn.com/larryosterman/archive/2009/01/27/fixing-an-accessibility-bug-with-the-trackbar-common-control.aspx</link><pubDate>Wed, 28 Jan 2009 04:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9379302</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/9379302.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=9379302</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=9379302</wfw:comment><description>&lt;P&gt;The trackbar common control is a strange beast.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The trackbar can be oriented either horizontally or vertically.&amp;nbsp; On LTR language machines, when the trackbar is horizontal, it works much as you’d expect it to: The minimum value of the trackbar is on the left, the maximum value is on the right (it’s reversed for RTL languages so it works consistently).&lt;/P&gt;
&lt;P&gt;When the trackbar is vertical, it’s a different beast entirely.&amp;nbsp; For whatever reason, the trackbar control designers set the minimum value of the trackbar at the top, the maximum value at the bottom.&amp;nbsp; If you think about how the trackbar designers actually implemented the trackbar this makes sense.&amp;nbsp; If you orient the trackbar so that the minimum value is at the top, then when you need to draw the trackbar you can use the same drawing code to draw the horizontal trackbar – you just swap the X and Y axis (I have absolutely no idea if that’s how it works internally, it just seems to make sense that way).&lt;/P&gt;
&lt;P&gt;While this works great for the implementer, for the &lt;EM&gt;consumer&lt;/EM&gt; of the trackbar, it’s a pain in the neck.&amp;nbsp; That’s because the users who interact with the control expect the maximum value to be at the top of the control, not the bottom.&lt;/P&gt;
&lt;P&gt;As a result, when you look at code that uses the trackbar control, you end up seeing a lot of:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;LRESULT MyDialog::OnNeedTTText(&lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; idCtrl, LPNMHDR pnmh)
{
    LPTOOLTIPTEXT pTT = (LPTOOLTIPTEXT)pnmh;
    &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (idCtrl == IDD_TRACKBAR)
    {
        &lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt; nPos = (&lt;SPAN class=kwrd&gt;int&lt;/SPAN&gt;)SendMessage(TBM_GETPOS, 0, 0);

        StringCchPrintf(pTT-&amp;gt;szText, ARRAYSIZE(pTT-&amp;gt;szText), TEXT(&lt;SPAN class=str&gt;"%d"&lt;/SPAN&gt;), 100 - nPos);
    }
    &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; 0;
}&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
&lt;STYLE type=text/css&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/STYLE&gt;
In other words, retrieve the position from the trackbar, convert it from 0..100 to 100..0 and return that as a tooltip text.&lt;/P&gt;
&lt;P&gt;All of this works great – you have a lot of 100 - &amp;lt;n&amp;gt; scattered throughout your code, but it’s not the end of the world.&amp;nbsp; And then one day a tester comes to you and says that when he uses the narrator tool to read the contents of your tool, it reports that the value reported by the control is wrong – when the slider’s at the top (tooltip 100), it reports that the value is 0, when it’s at the 1/4 point (tooltip 75), it reports that the value is 25.&lt;/P&gt;
&lt;P&gt;Crud.&amp;nbsp; At this point many developers start scratching their heads and start thinking about subclassing the trackbar to replace the reported position.&amp;nbsp; However that’s way more work than they need to do.&lt;/P&gt;
&lt;P&gt;It turns out that the designers of the trackbar control thought of this problem.&amp;nbsp; If you’re using version 5.8 or higher of the common controls, you can specify the TBS_REVERSED &lt;A href="http://msdn.microsoft.com/en-us/library/bb760147(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb760147(VS.85).aspx"&gt;trackbar control style&lt;/A&gt; to your trackbar.&amp;nbsp; If you do, the visuals of the trackbar are unchanged as is the trackbar functionality, but the Microsoft accessibility framework will look for the presence of the TBS_REVERSED style and if it is found, it assumes that the control is “backwards” and it reports the position for the toolbar as if the maximum and minimum values were reversed.&lt;/P&gt;
&lt;P&gt;And no, I didn’t know about this before today.&amp;nbsp; But it was too good a trick not to share.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9379302" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Fascinating+geek+stuff/default.aspx">Fascinating geek stuff</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>Fixing a customer problem: “No Audio Device is Installed” when launching sndvol on Windows Vista</title><link>http://blogs.msdn.com/larryosterman/archive/2009/01/06/fixing-a-customer-problem-no-audio-device-is-installed-when-launching-sndvol-on-windows-vista.aspx</link><pubDate>Tue, 06 Jan 2009 22:26:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9286006</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/9286006.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=9286006</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=9286006</wfw:comment><description>&lt;p&gt;Yesterday someone forwarded me an email from one of our DirectShow MVPs – he was having problems playing audio on his Windows Vista machine.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Fortunately David (the MVP) had done most of the diagnostic work – the symptoms he saw were that he was receiving a “No Audio Device is Installed” error launching sndvol (and other assorted problems).&amp;#160; &lt;/p&gt;  &lt;p&gt;David tried the usual things (confirming that the driver for his audio solution was correctly installed (this probably fixes 99% of the problems)).&amp;#160; He also tried reinstalling the driver to no avail.&lt;/p&gt;  &lt;p&gt;He next ran the Sysinternals &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;Process Monitor tool&lt;/a&gt; to see what was going on.&amp;#160; He very quickly found the following line in the output from process monitor:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;RegOpenKey&amp;quot;, &amp;quot;HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\{e4ee1234-fc70-4925-94e9-4117395f7995}&amp;quot;, &amp;quot;&lt;b&gt;ACCESS DENIED&lt;/b&gt;&amp;quot;, &amp;quot;Desired Access: Write&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;With that information, he looked for the ACL on that registry key:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/FixingacustomerproblemNoAudioDeviceisIns_A0BB/clip_image002_2.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/FixingacustomerproblemNoAudioDeviceisIns_A0BB/clip_image002_thumb.jpg" width="381" height="458" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;He then looked at the configuration for the Windows Audio service:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/FixingacustomerproblemNoAudioDeviceisIns_A0BB/image_4.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/FixingacustomerproblemNoAudioDeviceisIns_A0BB/image_thumb_1.png" width="424" height="478" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Woah – the Windows Audio service doesn’t have access rights to that registry key – the Windows Audio service is running as LocalService and the LocalService account doesn’t have any access to the registry key.&lt;/p&gt;  &lt;p&gt;At this point he decided to contact Microsoft with his problem.&lt;/p&gt;  &lt;p&gt;I looked at his info and quickly realized that the problem was that somehow the ACL on the registry key had been corrupted: something had removed the entries for the audio services.&amp;#160; On a normal Windows Vista installation this registry key’s ACL should look something like:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/FixingacustomerproblemNoAudioDeviceisIns_A0BB/endpointpermissions.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="endpointpermissions" border="0" alt="endpointpermissions" src="http://blogs.msdn.com/blogfiles/larryosterman/WindowsLiveWriter/FixingacustomerproblemNoAudioDeviceisIns_A0BB/endpointpermissions_thumb.png" width="383" height="456" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Something that ran on David’s machines went in and reset the permissions for this registry key to the ACL that is on the root node of the HKEY_LOCAL_MACHINE\Software registry hive.&amp;#160; I have no idea what did this, but messing with the ACLs on the registry is a known cause of various compatibility problems.&amp;#160; That’s why &lt;a href="http://support.microsoft.com/kb/885409/"&gt;Microsoft KB 885409&lt;/a&gt; has such strong warnings about why it’s important to not apply blind modifications to files or registry keys in Windows.&amp;#160; It’s unfortunate, but the warnings in the KB articles that say that modifying registry keys or permissions can cause your machine to malfunction are absolutely right – it’s not hard to make modifications to registry keys that can really screw up a machine, if you make the right ones.&amp;#160; From the KB article:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;For example, modifications to registry ACLs affect large parts of the registry hives and may cause systems to no longer function as expected. Modifying the ACLs on single registry keys poses less of a problem to many systems. However, we recommend that you carefully consider and test these changes before you implement them. Again, we can only guarantee that you can return to the recommended out-of-the-box settings if you reformat and reinstall the operating system.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The good news is that it should be relatively simple to fix David’s problem – As far as I know, he has two options.&amp;#160; The first is to reinstall Windows Vista – that should reset the ACLs on the property key to their default values (because it will recreate the property keys), which should resolve the problem.&lt;/p&gt;  &lt;p&gt;The second solution is to add an ACL to the registry keys under the MMDevices registry key to allow the LocalService account to have permissions to modify this registry key.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9286006" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Fascinating+geek+stuff/default.aspx">Fascinating geek stuff</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Things+you+shouldn_2700_t+do_2E00_/default.aspx">Things you shouldn't do.</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>What really happens when you shutdown Windows?</title><link>http://blogs.msdn.com/larryosterman/archive/2008/10/09/what-really-happens-when-you-shutdown-windows.aspx</link><pubDate>Thu, 09 Oct 2008 20:47:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8993084</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8993084.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8993084</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8993084</wfw:comment><description>&lt;p&gt;About a year or so ago, I wrote &lt;a href="http://blogs.msdn.com/larryosterman/archive/2007/08/02/hey-my-custom-shutdown-sound-got-cut-off-or-didn-t-play-what-s-up.aspx"&gt;a post&lt;/a&gt; that talked about the Windows shutdown experience.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;A couple of the people reading the post asked for more details, and it turns out that the performance folks have just issued &lt;a href="http://www.microsoft.com/whdc/system/sysperf/On-Off_Transition.mspx"&gt;this&lt;/a&gt; paper which describes (in great detail) what happens during system boot and shutdown.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I skimmed over it before posting and thought it was pretty cool.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8993084" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>The common control library sometimes sends an NMCUSTOMDRAW message for the NM_CUSTOMDRAW notification.</title><link>http://blogs.msdn.com/larryosterman/archive/2008/10/03/the-common-control-library-sometimes-sends-an-nmcustomdraw-message-for-the-nm-customdraw-notification.aspx</link><pubDate>Sat, 04 Oct 2008 02:37:55 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8976021</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8976021.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8976021</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8976021</wfw:comment><description>&lt;p&gt;I just fixed a bug in our UI that was caused by a misunderstanding of the API contract for the NM_CUSTOMDRAW handler for some of the common controls.&lt;/p&gt;  &lt;p&gt;On of October 3rd, 2008 The &lt;a href="http://msdn.microsoft.com/en-us/library/bb775487.aspx"&gt;common control documentation for the NM_CUSTOMDRAW message&lt;/a&gt; says:&lt;/p&gt;  &lt;blockquote&gt;&lt;dl&gt;&lt;dt&gt;&lt;i&gt;lpNMCustomDraw&lt;/i&gt;&lt;/dt&gt;&lt;dd&gt;A pointer to a custom draw-related structure that contains information about the drawing operation. The following list specifies the controls and their associated structures. &lt;/dd&gt;&lt;dl&gt;&lt;dt&gt;&lt;code&gt;List view&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb774778(VS.85).aspx"&gt;NMLVCUSTOMDRAW&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;&lt;code&gt;ToolTip&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb760254(VS.85).aspx"&gt;NMTTCUSTOMDRAW&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;&lt;code&gt;Tree view&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb773415(VS.85).aspx"&gt;NMTVCUSTOMDRAW&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;&lt;code&gt;Toolbar&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb760450(VS.85).aspx"&gt;NMTBCUSTOMDRAW&lt;/a&gt; &lt;/dd&gt;&lt;dt&gt;&lt;code&gt;All other supported controls&lt;/code&gt;&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb775483(VS.85).aspx"&gt;NMCUSTOMDRAW&lt;/a&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/dl&gt;&lt;/blockquote&gt;  &lt;p&gt;While this is correct in general it is NOT true for the CDDS_PREPAINT draw stage.&amp;#160; It turns out that some of the common controls only provide an NMCUSTOMDRAW structure when the drawing logic is in the CDDS_PREPAINT stage.&amp;#160; &lt;/p&gt;  &lt;p&gt;If you look VERY carefully at MSDN, you can find &lt;a href="http://msdn.microsoft.com/en-us/library/bb761817(VS.85).aspx#list_tree"&gt;this&lt;/a&gt; page which mentions that the first NM_CUSTOMDRAW notification receives an NMCUSTOMDRAW structure and not an NMLVCUSTOMDRAW handler but that’s the only page I was able to find to indicate this.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’ve notified the relevant documentation folks about this and hopefully the documents will be updated in the future.&amp;#160; You can consider this blog post as a pre-update to the SDK documentation.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8976021" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>DrawThemeText doesn’t really support the DT_CALCRECT format value</title><link>http://blogs.msdn.com/larryosterman/archive/2008/09/30/drawthemetext-doesn-t-really-support-the-dt-calcrect-format-value.aspx</link><pubDate>Wed, 01 Oct 2008 02:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8970902</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8970902.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8970902</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8970902</wfw:comment><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I just noticed this while working on a bug fix.&lt;/p&gt;  &lt;p&gt;We have some code that attempts to determine the size of a piece of text by calling DrawThemeText with the DT_CALCRECT format value.&lt;/p&gt;  &lt;p&gt;According to &lt;a href="http://msdn.microsoft.com/en-us/library/bb773199(VS.85).aspx"&gt;this&lt;/a&gt; page (as of 9/30/2008) the DT_CALCRECT option determines the width and height of the display rectangle.&lt;/p&gt;  &lt;p&gt;Unfortunately the DT_CALCRECT option doesn’t actually return the width and height of the display rectangle.&amp;#160; Instead it doesn’t modify the input LPRECT field.&amp;#160; I asked the developer and he indicated that the reason was that the pRect parameter to &lt;a href="http://msdn.microsoft.com/en-us/library/bb773312.aspx"&gt;DrawThemeText&lt;/a&gt; is actually defined as a LPCRECT and thus the implicit contract for the API is that it doesn’t change the contents of the pRect field.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt; There are two ways of working around this problem.&amp;#160; The first (and recommended) way is to call &lt;a href="http://msdn.microsoft.com/en-us/library/bb759798(VS.85).aspx"&gt;GetThemeTextExtent&lt;/a&gt; to retrieve the dimensions of the rectangle.&amp;#160; The second (which works on Vista and later operating systems) is to call &lt;a href="http://msdn.microsoft.com/en-us/library/bb773317(VS.85).aspx"&gt;DrawThemeTextEx&lt;/a&gt; passing in the DTT_CALCRECT flag – in that case the DrawThemeTextEx API will return the size of the text in the pRect parameter.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’ve sent emails to the SDK folks so it’s entirely likely that the page will be updated in the future but until it is, hopefully this will help someone using the search engines to find what’s going on.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8970902" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>Why specify SND_NODEFAULT when calling PlaySound?</title><link>http://blogs.msdn.com/larryosterman/archive/2008/09/25/why-specify-snd-nodefault-when-calling-playsound.aspx</link><pubDate>Fri, 26 Sep 2008 00:46:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8965597</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8965597.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8965597</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8965597</wfw:comment><description>&lt;p&gt;Because the alternative is often much worse.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Several months ago, I got a bug report that if you launched mmsys.cpl then set the “Select” sound to a value, then cleared the sound, the reporters application would ding whenever you moved around their tree control.&lt;/p&gt;  &lt;p&gt;I dug into the problem a bit and discovered that the problem was actually in the Windows common controls.&amp;#160; Under some circumstances the common controls would call PlaySound specifying a sound alias and the SND_ASYNC and SND_ALIAS flags only.&amp;#160; &lt;/p&gt;  &lt;p&gt;The problem with this is that if you specify SND_ALIAS without also specifying SND_NODEFAULT, the PlaySound API decides that you &lt;em&gt;really&lt;/em&gt; want the sound to be played and it will play the default “ding” sound instead.&amp;#160; &lt;/p&gt;  &lt;p&gt;From the PlaySound API’s point of view this makes sense.&amp;#160; After all, you asked the API to play a sound, it doesn’t know that you meant “only play this sound when the sound file represented by the alias exists”.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In fact, that’s the entire reason for the SND_NODEFAULT flag – it lets the PlaySound API that you only want to play a sound when the sound has been defined.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8965597" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Audio/default.aspx">Audio</category></item><item><title>Why call PlaySound(NULL, NULL, SND_NODEFAULT)?</title><link>http://blogs.msdn.com/larryosterman/archive/2008/09/15/why-call-playsound-null-null-snd-nodefault.aspx</link><pubDate>Tue, 16 Sep 2008 03:18:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8953279</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8953279.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8953279</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8953279</wfw:comment><description>&lt;p&gt;Someone just wandered over to my office and he had noticed the following pattern in his code:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre class="csharpcode"&gt;PlaySound(NULL, NULL, SND_NODEFAULT);
PlaySound(&lt;span class="str"&gt;&amp;quot;.Default&amp;quot;&lt;/span&gt;, NULL, SND_SYSTEM | SND_ASYNC | SND_NODEFAULT);&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;He was wondering why on earth the code would do that call to &lt;a href="http://msdn.microsoft.com/en-us/library/ms712879.aspx"&gt;PlaySound&lt;/a&gt;(NULL).&amp;#160; &lt;/p&gt;

&lt;p&gt;As I explained it to him, the reason is because you almost always want to cancel the current sound playing before you queue up the next sound.&lt;/p&gt;

&lt;p&gt;The problem is that the current implementation[1] of PlaySound(…, SND_ASYNC) simply queues the request to a worker thread which blocks waiting on the currently playing sound to complete.&amp;#160; So if you have a situation where you call PlaySound(…, SND_ASYNC) many times in succession, you’ll find that all the calls to PlaySound pile up behind each other, which means that you might end up playing sounds long after the action associated with the sound has completed.&lt;/p&gt;

&lt;p&gt;Of course you might want this behavior – it’s certainly possible to string lots of system sounds together to produce any number of interesting effects.&lt;/p&gt;

&lt;p&gt;But most of the time you just want to stop the current sound before you start playing the next.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;[1] There are obviously no guarantees that the implementation of PlaySound won’t change – I’m just describing what the current code does.&amp;#160; Even if the implementation is changed, it won’t change the underlying behavior.&lt;/p&gt;
&lt;style type="text/css"&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8953279" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Audio/default.aspx">Audio</category></item><item><title>Anatomy of a Heisenbug</title><link>http://blogs.msdn.com/larryosterman/archive/2008/09/03/anatomy-of-a-heisenbug.aspx</link><pubDate>Wed, 03 Sep 2008 20:43:12 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8922372</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8922372.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8922372</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8922372</wfw:comment><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;I just spent a half an hour debugging a &lt;a href="http://www.catb.org/jargon/html/H/heisenbug.html"&gt;heisenbug&lt;/a&gt; and thought I’d pass on what was happening.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I was running my unit tests for one of my features and they were reliably failing.&amp;#160; Unfortunately the instant I ran the test case under the debugger, the problem went away.&amp;#160; Problems that disappear under the debugger are a classic symptom of a heisenbug, this was no exception.&lt;/p&gt;  &lt;p&gt;If I attached the debugger AFTER the test started but before the failure hit, I was able to see the failure occur.&amp;#160; The problem only occurred when launching the app under the debugger.&amp;#160; At that point I realized what was happening.&lt;/p&gt;  &lt;p&gt;As MSDN &lt;a href="http://msdn.microsoft.com/en-us/library/cc266414.aspx"&gt;says&lt;/a&gt;:&amp;#160; &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Processes that the debugger creates (also known as &lt;i&gt;spawned processes&lt;/i&gt;) behave slightly differently than processes that the debugger does not create.&lt;/p&gt;    &lt;p&gt;Instead of using the standard heap API, processes that the debugger creates use a special &lt;i&gt;debug heap&lt;/i&gt;. On Microsoft Windows XP and later versions of Windows, you can force a spawned process to use the standard heap instead of the debug heap by using the _NO_DEBUG_HEAP &lt;a href="http://msdn.microsoft.com/en-us/library/cc266519.aspx"&gt;environment variable&lt;/a&gt; or the &lt;b&gt;-hd&lt;/b&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/cc266526.aspx"&gt;command-line option&lt;/a&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;It turns out that I had added a member variable to a class and failed to initialize it in the constructor of the class.&amp;#160; When launched under the debugger, the debug heap initializes all allocated memory to a known value.&amp;#160; That means that when launched under the debugger the member variable had that known value, when launched without the debugger it was uninitialized and happened to have the value of 0.&amp;#160; For a number of reasons, this value caused the test to fail.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I hate heisenbugs, but I like it when they’re really easy to find like this one.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8922372" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>Gotchas associated with using WM_PRINTCLIENT…</title><link>http://blogs.msdn.com/larryosterman/archive/2008/08/28/gotchas-associated-with-using-wm-printclient.aspx</link><pubDate>Thu, 28 Aug 2008 19:47:17 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8903657</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>22</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8903657.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8903657</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8903657</wfw:comment><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/larryosterman/archive/2008/08/27/larry-s-new-favorite-windows-message-wm-printclient.aspx"&gt;Yesterday&lt;/a&gt; I mentioned WM_PRINTCLIENT and how awesome it is when trying to strictly control the drawing of your application.&lt;/p&gt;  &lt;p&gt;Part of the reason it took over a week to change the drawing model is that there are a number of serious gotcha’s associated with using WM_PRINTCLIENT and controlling your own drawing story.&amp;#160; The first is that not all controls support WM_PRINTCLIENT.&amp;#160; It turns out that some controls don’t support the WM_PRINTCLIENT, however if you search the documentation for &lt;a href="http://msdn.microsoft.com/en-us/library/ms534901(VS.85).aspx"&gt;WM_PAINT&lt;/a&gt;, you’ll find the following comment:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;“For some common controls, the default &lt;b&gt;WM_PAINT&lt;/b&gt; message processing checks the &lt;i&gt;wParam&lt;/i&gt; parameter. If &lt;i&gt;wParam&lt;/i&gt; is non-NULL, the control assumes that the value is an HDC and paints using that device context.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;That means that if you find a common control that &lt;em&gt;doesn’t&lt;/em&gt; support WM_PRINTCLIENT, you can use WM_PAINT specifying wParam as the HDC[1].&amp;#160; Fortunately I didn’t run into this in my control.&lt;/p&gt;  &lt;p&gt;The next gotcha is that some controls (like buttons and toolbars etc) have animations that are launched when you mouse over the control.&amp;#160; These are often subtle (like the glow when you hover over a scrollbar thumb).&amp;#160; In order to continue to have these effects work, you need to let those controls paint themselves – in my experience it generally didn’t cause much of a problem with flickering, but your mileage might vary.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The last gotcha is a very big one and hung me up for about half a day.&amp;#160; The WM_PRINTCLIENT message only paints the client area of a window.&amp;#160; If you have a window with the WM_HSCROLL or WM_VSCROLL style then you won’t be able to paint the scroll bar.&amp;#160; Instead you need to create your own scrollbar control (with CreateWindow) and use that instead of the built-in scroll styles.&amp;#160; There &lt;em&gt;are &lt;/em&gt;ways you can convince the window to paint it’s non client region to an HDC but they are fraught with peril (one senior developer I was talking to about this problem described them as “unnatural acts”) and simply not worth the effort.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;[1] There’s also a corollary to that: If you ever send a WM_PAINT to a control you MUST ensure that wParam and lParam are 0 even though they’re documented as “not used”.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8903657" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>Larry’s new favorite windows message – WM_PRINTCLIENT</title><link>http://blogs.msdn.com/larryosterman/archive/2008/08/27/larry-s-new-favorite-windows-message-wm-printclient.aspx</link><pubDate>Thu, 28 Aug 2008 03:51:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8902108</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8902108.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8902108</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8902108</wfw:comment><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;As I’ve mentioned before, I’ve been fuddling around doing UI programming recently – it’s a bit different from my usual work deep in the bowels of the &amp;lt;insert whatever subsystem Larry happens to be working on (redirector, audio stack, POP3 server, whatever)&amp;gt;.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I’ve been having a great deal of fun doing the whole “UI programmer” thingy (although my grandboss is right – once you start doing UI, everyone thinks that you’ve done it wrong) recently, and I’ve learned a ton of stuff.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Most of the UI I work with is written as dialog box applications – for various reasons, many of the audio UI elements are actually dialog boxes[1].&amp;#160; As such, the system controls the actual drawing of the UI elements, especially if you specify the WS_CLIPCHILDREN window style.&lt;/p&gt;  &lt;p&gt;I recently had a bug where one of the UI elements wasn’t being painted correctly.&amp;#160; For a number of reasons, the element was being overwritten by another element.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;It took a lot of work to get to the scenario where the UI element got messed up, so I was going to ignore the problem (it was ugly but transient).&amp;#160; But then I got to browsing the web and I ran into &lt;a href="http://weblogs.asp.net/kennykerr/archive/2007/01/23/controls-and-the-desktop-window-manager.aspx"&gt;this article&lt;/a&gt;.&amp;#160; The article had nothing to do with the order of painting in a dialog, but it DID mention a windows message that I hadn’t heard of before, &lt;a href="http://msdn.microsoft.com/en-us/library/ms534913.aspx"&gt;WM_PRINTCLIENT&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Hmm, that’s interesting.&amp;#160; WM_PRINTCLIENT says “The &lt;b&gt;WM_PRINTCLIENT&lt;/b&gt; message is sent to a window to request that it draw its client area in the specified device context, most commonly in a printer device context.”.&amp;#160; Ooh, that’s interesting.&amp;#160; If I can just send a WM_PRINTCLIENT to each of the controls in the window, maybe I can control the order in which the controls are rendered, which would allow me to fix the problem (and remove a long-standing issue with the program in question).&lt;/p&gt;  &lt;p&gt;On Monday of last week, I came in and decided that I’d dedicate a couple of days to see if my idea might work – worst case I’d lose a couple of days of work, but if it &lt;em&gt;did&lt;/em&gt; work it would be really cool.&lt;/p&gt;  &lt;p&gt;By mid-afternoon on Monday, I had come to the point where I realized that my crazy idea would actually work.&amp;#160; &lt;/p&gt;  &lt;p&gt;Skip forward one very long week of debugging and tweaking and I had fixed the problem – I had rebuilt the painting algorithm for this application and it worked!&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Right now I’m highly enamored of the WM_PRINTCLIENT message simply because it’s so darned useful in scenarios like mine.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;PS: It’s possible that I might be able to achieve similar results with the WS_EX_COMPOSITED window style but it’s not clear given some of the UI requirements for the application – I may play around with that idea over the next couple of weeks.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;[1] One of the reasons for the apps being dialog box based is that it makes it easier for localizers if the application is built on dialog boxes because it gives the localizers greater flexibility when translating the OS – if the preferred text in the destination language doesn’t fit, they can adjust the layout of the dialog to make the text fit.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8902108" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>The SS_PATHELLIPSIS, SS_ENDELLIPSIS and SS_WORDELLIPSIS styles force static controls to disable word wrap.</title><link>http://blogs.msdn.com/larryosterman/archive/2008/08/14/the-ss-pathellipsis-ss-endellipsis-and-ss-wordellipsis-styles-force-static-controls-to-disable-word-wrap.aspx</link><pubDate>Thu, 14 Aug 2008 21:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8867517</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8867517.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8867517</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8867517</wfw:comment><description>&lt;P&gt;I didn’t find this in the documentation for the static standard window so I figured I’d put it out in my blog in the hopes that someone else won’t get stuck on this problem.&lt;/P&gt;
&lt;P&gt;The Windows “static” control has a number of &lt;A href="http://msdn.microsoft.com/en-us/library/bb760773(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb760773(VS.85).aspx"&gt;styles&lt;/A&gt; that control how the control draws text.&amp;nbsp; They can be extremely useful when controlling how the control lays out text.&lt;/P&gt;
&lt;P&gt;I recently had to write code that draws the name of an audio endpoint into a relatively size constrained static text control.&amp;nbsp; No problem, right[1]?&lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=2 width=79 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=77&gt;
&lt;P align=center&gt;Speakers &lt;BR&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Well what happens if the name of the endpoint is somewhat longer? No problem, the SS_CENTER style will wrap the words.&lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=2 width=79 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=79&gt;
&lt;P align=center&gt;Headset Microphone&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;But sometimes the endpoint name is longer than “Headset Microphone”.&amp;nbsp; In fact the user can set the endpoint name to anything they want.&lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=2 width=79 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=79&gt;
&lt;P align=center&gt;Long Headset M&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Uck, that looks ugly.&lt;/P&gt;
&lt;P&gt;Fortunately the static control has an option SS_WORDELLIPSIS that looks like it should be perfect for me:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;“Windows NT or later: Truncates any word that does not fit in the rectangle and adds ellipses.”&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;That sounds exactly like what I want.&amp;nbsp; But when I added SS_WORDELLIPSIS, I got:&lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=2 width=79 border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=79&gt;
&lt;P&gt;Long&amp;nbsp;He...&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hold on, that’s not right, what happened to the rest of my text?&lt;/P&gt;
&lt;P&gt;After a bit of digging, I finally figured out what was going on (by trial an error removing all the various static control styles I specified).&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It turns out that this behavior is by design, even though I couldn’t find any documentation of it.&amp;nbsp; If you specify any of the ellipsis styles for the static control, the control becomes a single line control.&amp;nbsp; The only way I’ve found to fix this is to make the static control an owner draw control and use the &lt;A href="http://msdn.microsoft.com/en-us/library/bb773312.aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb773312.aspx"&gt;DrawThemeText&lt;/A&gt; (or &lt;A href="http://msdn.microsoft.com/en-us/library/ms533909.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms533909.aspx"&gt;DrawText&lt;/A&gt;) API specifying the DT_WORDBREAK | DT_ENDELLIPSIS option.&lt;/P&gt;
&lt;P mce_keep="true"&gt;I’ve filed a documentation bug to ensure that this gets fixed sometime in the near future.&lt;/P&gt;
&lt;P&gt;[1] I’ve approximated what was going on in my UI with HTML tables, this is a rough approximation to show more-or-less what was going on.&lt;/P&gt;
&lt;P&gt;ETA: Thanks to Drew and Lindseth for reviewing this.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Edit: Fixed word wrap in edit control.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8867517" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item><item><title>What’s wrong with this code, Part 22 – the answers</title><link>http://blogs.msdn.com/larryosterman/archive/2008/08/04/what-s-wrong-with-this-code-part-22-the-answers.aspx</link><pubDate>Mon, 04 Aug 2008 23:32:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8832084</guid><dc:creator>LarryOsterman</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/larryosterman/comments/8832084.aspx</comments><wfw:commentRss>http://blogs.msdn.com/larryosterman/commentrss.aspx?PostID=8832084</wfw:commentRss><wfw:comment>http://blogs.msdn.com/larryosterman/rsscomments.aspx?PostID=8832084</wfw:comment><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;The other day, I wrote about &lt;a href="http://blogs.msdn.com/larryosterman/archive/2008/08/01/what-s-wrong-with-this-code-part-22-drawing-text.aspx"&gt;measuring the dimensions of a piece of text using the DrawText API&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;My code worked just great when I initially tested it (obviously it’s a part of a larger chunk of code that does more complicated work).&amp;#160; The problem showed up when I started testing it on a machine running in High DPI mode (144DPI).&lt;/p&gt;  &lt;p&gt;The code in question measured some text and then used that text to set the size of a button, when working in low DPI mode (96DPI), the font that is chosen had font metrics that closely matched the font that was used when painting the button.&amp;#160; The problem was that the button font that was used in high DPI mode had dramatically larger font metrics than the low DPI font.&amp;#160; &lt;/p&gt;  &lt;p&gt;As a result, the rectangle returned by the initial DrawText call didn’t match the rectangle that was used when the button was painted.&amp;#160; That meant that the button text overflowed the button.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The fix to the code is to retrieve the font that is going to be used to draw the button and to use SelectObject to set the font in the memory DC to match the button font.&amp;#160; Once I made that change, the button drew perfectly.&lt;/p&gt;  &lt;p&gt;Here’s the corrected code (new code in &lt;font color="#ff0000"&gt;red&lt;/font&gt;):&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;pre&gt;   HDC hdc = CreateCompatibleDC(&lt;span style="color: blue"&gt;NULL&lt;/span&gt;); 

   RECT rcText = {&lt;span style="color: maroon"&gt;0&lt;/span&gt;, &lt;span style="color: maroon"&gt;0&lt;/span&gt;, &lt;span style="color: maroon"&gt;88&lt;/span&gt;, &lt;span style="color: maroon"&gt;34&lt;/span&gt;}; 

&lt;font color="#ff0000"&gt;   HFONT hFont = &lt;span style="color: blue"&gt;reinterpret_cast&lt;/span&gt;&amp;lt;HFONT&amp;gt;(SendMessage(m_hWndControl, WM_GETFONT, &lt;span style="color: maroon"&gt;0&lt;/span&gt;, &lt;span style="color: maroon"&gt;0&lt;/span&gt;)); 
   HFONT hFontOld = &lt;span style="color: blue"&gt;reinterpret_cast&lt;/span&gt;&amp;lt;HFONT&amp;gt;(SelectObject(hdc, hFont));&lt;/font&gt; 

   DrawText(hdc, L&lt;span style="color: maroon"&gt;&amp;quot;My Text String&amp;quot;&lt;/span&gt;, -&lt;span style="color: maroon"&gt;1&lt;/span&gt;, &amp;amp;rcText, DT_CENTER | DT_END_ELLIPSIS | DT_EDITCONTROL | DT_WORDBREAK | DT_NOPREFIX | DT_CALCRECT); 

   CAtlString &lt;span style="color: blue"&gt;string&lt;/span&gt;; 
   &lt;span style="color: blue"&gt;string&lt;/span&gt;.Format(L&lt;span style="color: maroon"&gt;&amp;quot;Text String occupies: %d x %d pixels&amp;quot;&lt;/span&gt;, rcText.right - rcText.left, rcText.bottom - rcText.top); 
   MessageBox(hWnd, &lt;span style="color: blue"&gt;string&lt;/span&gt;, L&lt;span style="color: maroon"&gt;&amp;quot;String Size&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;0&lt;/span&gt;); 

&lt;font color="#ff0000"&gt;   SelectObject(hdc, hFontOld); 
   DeleteDC(hdc);&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;And yeah, I’m sure this is old-hat to experienced Windows UI programmers, but it stumped me for several hours so I figured I’d write it up for the blog in case someone else hits the same problem.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Kudos and omissions:&lt;/p&gt;

&lt;p&gt;Aaron Ballman caught that I forgot to call DeleteDC when I was done with using the DC.&amp;#160; Stupid boneheaded mistake.&lt;/p&gt;

&lt;p&gt;Shog9 and Ivo caught the root cause (selecting the wrong font).&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;And Eldan caught the Large Fonts implication.&amp;#160; There are other ways of catching this, but HighDPI is the easiest.&lt;/p&gt;

&lt;p&gt;I also agree with his assertion that font handling of GDI is “complicated”.&amp;#160; On the other hand, the alternative is adding a dozen parameters to the DrawText API (you’d have to add foreground color, background color, font, etc to the call, which would complicate the API dramatically).&amp;#160; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;PS For those who care about such things: When I’m testing UI changes, I start with standard DPI, then I retest the changes in HighDPI and again using high contrast mode.&amp;#160; Testing in high contrast mode also tests the code in a non themed mode, which helps to catch bugs where I accidentally depended on the theming logic.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8832084" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/larryosterman/archive/tags/Nifty+Win32+tricks_2E00_/default.aspx">Nifty Win32 tricks.</category></item></channel></rss>