<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nanoANT &#187; C/C++</title>
	<atom:link href="http://www.nanoant.com/category/programming/c/feed" rel="self" type="application/rss+xml" />
	<link>http://www.nanoant.com</link>
	<description>Yet another self-employee site &#38; blog</description>
	<lastBuildDate>Fri, 03 Sep 2010 17:06:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>MinGW on Mac, hell yeah!</title>
		<link>http://www.nanoant.com/programming/mingw-on-mac-hell-yeah</link>
		<comments>http://www.nanoant.com/programming/mingw-on-mac-hell-yeah#comments</comments>
		<pubDate>Thu, 19 Mar 2009 14:18:18 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.nanoant.com/?p=223</guid>
		<description><![CDATA[Want to build some small/or not, neat Windows/or Linux application on your Mac? Just use MinGW/Linux GCC cross compiler package from Pierre Molinaro. Those were recently updated to GCC 4.2 and do cross-compile really fast, especially when using make -j2. It is hard to be Switcher and totally forget/abandon Windows projects, since most of my clients&#8230; well [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-227" title="GCC" src="http://www.nanoant.com/wp/wp-content/uploads/2009/03/gccegg-65.gif" alt="GCC Logo" width="109" height="130" />Want to build some small/or not, neat <em>Windows</em>/or <em>Linux</em> application on your <em>Mac</em>? Just use <em>MinGW</em>/<em>Linux GCC</em> cross compiler package from <a href="http://crossgcc.rts-software.org/">Pierre Molinaro</a>. Those were recently updated to <em>GCC 4.2</em> and do cross-compile really fast, especially when using <tt>make -j2.</tt></p>
<p>It is hard to be Switcher and totally forget/abandon <em>Windows</em> projects, since most of my clients&#8230; well almost all of them are on *indows. So since I switched, I am constant user of <a href="http://www.vmware.com/products/fusion/">VMWare Fusion</a> + XP (Win7, Win98) as a guest OS having <em>Visual Studio</em> installed inside. But sometimes if you want to create small cute application for *indows I prefer do it 100% on <em>Mac</em> with <em>TextMate</em>, then just test it on <em>Windows</em>. This is what <em>MinGW</em> cross compiler is perfect for. Not to mention I did <em>Miranda&#8217;s</em> <em>MinGW</em> <a href="https://miranda.svn.sourceforge.net/svnroot/miranda/trunk/miranda/Makefile">Makefile</a> that successfully builds miranda on Linux/Mac using cross-compiler, so it can be queued for nightly builds on SF.net servers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nanoant.com/programming/mingw-on-mac-hell-yeah/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No more free lunch, maybe a pie for free?</title>
		<link>http://www.nanoant.com/publications/no-more-free-lunch-maybe-a-pie-for-free</link>
		<comments>http://www.nanoant.com/publications/no-more-free-lunch-maybe-a-pie-for-free#comments</comments>
		<pubDate>Wed, 11 Mar 2009 23:40:11 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Publications]]></category>
		<category><![CDATA[core]]></category>
		<category><![CDATA[cpu]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[parallel]]></category>

		<guid isPermaLink="false">http://www.nanoant.com/?p=205</guid>
		<description><![CDATA[How to survive computing paradigm shift We cannot count on free &#8220;performance lunch&#8221; anymore, but how about at least a pie for free? Do we need to throw all our old source-code into the trash bin and start over again?  Certainly, not. We may think of our old software as a zombie of the new multi-core [...]]]></description>
			<content:encoded><![CDATA[<h4>How to survive computing paradigm shift</h4>
<p>We cannot count on free &#8220;performance lunch&#8221; anymore, but how about at least a pie for free?<span> Do we need to throw all our old source-code into the trash bin and start over again?<span> </span></span></p>
<p><img class="alignright size-full wp-image-214" title="Double Core flow" src="http://www.nanoant.com/wp/wp-content/uploads/2009/03/doublecore-flow.png" alt="" width="273" height="142" />Certainly, not. We may think of our old software as a zombie of the new multi-core era. Still<span> there is a way to make the zombie walk, even walk faster. Of course we will need to rewrite<span> our code sometime, but we may postpone this nasty need for a while.<span> </span></span></span></p>
<p>The computing paradigm shift is now a fact we need to learn how to live with. It is unques<span>tionable that processor manufacturers hit the barrier of 3 GHz. There pretty many news about<span> spinning the CPU up to 5 GHz or so, but do not try to do so at home unless you got liquid<span> nitrogen cylinder around. Over 3 GHz heat emission grows unreasonably making the CPU<span> economically worthwhile.<span> </span></span></span></span></span></p>
<p>So the only sensible way is now horizontal performance improvement, doubling the number<span> of processing units. This means we can expect soon 128 core CPUs. Oh, wait they are here<span> already; nVidia GeForce 9 series are perfect example of 128 core streaming processor.<span> </span></span></span></p>
<p>Now how to keep up with things that happen so fast. First we need focus more on performance<span> of our code. Something that was not important before, now cannot be ignored.</span><br />
<span id="more-205"></span><br />
<em>Want more, read my article draft below:</em></p>
<ul class="projects">
<li class="pdf"><a href="/uj/A Pie for free.pdf">A Pie for free.pdf</a> 256KB, 2008-06-16</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.nanoant.com/publications/no-more-free-lunch-maybe-a-pie-for-free/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Assigned to GNU</title>
		<link>http://www.nanoant.com/projects/assigned-to-gnu</link>
		<comments>http://www.nanoant.com/projects/assigned-to-gnu#comments</comments>
		<pubDate>Sat, 08 Mar 2008 15:17:37 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[idn]]></category>
		<category><![CDATA[sasl]]></category>

		<guid isPermaLink="false">http://www.nanoant.com/?p=249</guid>
		<description><![CDATA[Today I got assigned to two GNU projects: GNU IDN Library &#38; GNU SASL Library. As jabberd2 relays on both of them and I am the one responsible for making it running on Windows, I had to make few patches, that were gratefully accepted by Simon Josefsson &#8211; maintainer of those GNU libraries. Recently I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Today I got assigned to two GNU projects: <a href="http://www.gnu.org/software/libidn/">GNU IDN Library</a> &amp; <a href="http://www.gnu.org/software/gsasl/">GNU SASL Library</a>. As jabberd2 relays on both of them and I am the one responsible for making it running on Windows, I had to make few patches, that were gratefully accepted by Simon Josefsson &#8211; maintainer of those GNU libraries.</p>
<p>Recently I&#8217;ve received two papers from GNU (originated from U.S.) and few great stickers with gnus <img src='http://www.nanoant.com/wp/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I had to sign it back after carefully studying them. And now I am officially assigned and my changes went to the official repository.</p>
<p style="text-align: center;"><a href="http://www.nanoant.com/wp/wp-content/uploads/2009/03/gnu-libidn.gif"><img class="size-full wp-image-250  aligncenter" title="gnu-libidn" src="http://www.nanoant.com/wp/wp-content/uploads/2009/03/gnu-libidn.gif" alt="" width="499" height="140" /></a></p>
<p>Can I call myself genuine OpenSource developer now !?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nanoant.com/projects/assigned-to-gnu/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Themed menu&#8217;s icons, a complete Vista and XP solution (updated)</title>
		<link>http://www.nanoant.com/programming/themed-menus-icons-a-complete-vista-xp-solution</link>
		<comments>http://www.nanoant.com/programming/themed-menus-icons-a-complete-vista-xp-solution#comments</comments>
		<pubDate>Tue, 12 Jun 2007 15:43:01 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.nanoant.com/programming/themed-menus-icons-a-complete-vista-xp-solution</guid>
		<description><![CDATA[Update: Steve King has patched my Vista GDI+ based menus with pure GDI method at TortoiseSVN revision 14191 as described lately by Microsoft. Pure GDI method no longer requires GDI+, which is not present in Premium versions of Vista, maintaining full compatibility with older versions of Windows. I&#8217;m an author of few patches for both Tortoise [...]]]></description>
			<content:encoded><![CDATA[<h4>Update: <em>Steve King</em> has patched my <em>Vista</em> GDI+ based menus with pure GDI method at TortoiseSVN revision 14191 as described lately by <a href="http://msdn.microsoft.com/en-us/library/bb757020.aspx?s=6">Microsoft</a>. Pure GDI method no longer requires GDI+, which is not present in Premium versions of Vista, maintaining full compatibility with older versions of <em>Windows</em>.</h4>
<p>I&#8217;m an author of few patches for both <a href="http://tortoisesvn.tigris.org/">Tortoise SVN</a> and <a href="http://www.tortoisecvs.org/">Tortoise CVS</a> that makes them display the explorer&#8217;s context menu icons nicely on <em>XP</em> and <em>Windows 2000</em>. Both programs are implementing <tt>IContextMenu</tt> and using <tt>QueryContextMenu</tt> function to create items of popup menu of explorer. Briefly the called extension must fill menu items with <tt>InsertMenuItem</tt> using suplied <tt>HMENU hmenu</tt> parameter.</p>
<p>During development of those few patches I&#8217;ve learnt some few new things about way we make icons displayed next to menu items I want to share with you&#8230; <span id="more-18"></span></p>
<h2>How to get icons in context menus</h2>
<p>Methods described here are related to shell context menu extension, however they can be used in any <em>Windows</em> application.</p>
<h3>hbmp(Un)checked method</h3>
<p><img title="Old Tortoise CVS menu icons" src="/screenshots/tortoise/TortoiseCVS-hbmpUnchecked.png" alt="Old Tortoise CVS menu icons" hspace="10" width="211" height="85" align="right" />Initially both <em>Tortoises</em> were filling <tt>hbmpUnchecked</tt> &amp; <tt>hbmpChecked</tt> fields of <tt>MENUITEMINFO</tt> that is passed to <tt>InsertMenuItem</tt> with <tt>HBITMAP</tt> created from icon to get icons on menu item. This solution works on all <em>Windows</em> since 95. However the strong limitation is that <tt>HBITMAP</tt> must be <tt>SM_CXMENUCHECK</tt> x <tt>SM_CYMENUCHECK</tt> (usually 12 x 12). So if you are using 16 x 16 icon, the icon gets squished and looks awfully. The function used to convert icon to bitmap is:</p>
<pre class="textmate-source"><span class="source source_c++">HBITMAP<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c"> </span><span class="entity entity_name entity_name_function entity_name_function_c">CShellExt::IconToBitmap</span><span class="meta meta_parens meta_parens_c">(std::string <span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sIcon</span>)</span>
<span class="meta meta_block meta_block_c">{
    RECT rect;

    rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.right</span> = ::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">GetSystemMetrics</span>(</span>SM_CXMENUCHECK);
    rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.bottom</span> = ::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">GetSystemMetrics</span>(</span>SM_CYMENUCHECK);

    rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.left</span> = rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.top</span>  = <span class="constant constant_numeric constant_numeric_c">0</span>;

    HICON hIcon = (HICON)<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">LoadImageA</span>(</span>g_hInstance, <span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sIcon</span>.<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">c_str</span>(</span>), IMAGE_ICON, rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.right</span>, rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.bottom</span>, LR_DEFAULTCOLOR);
    <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>!hIcon)
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;

    HWND desktop = ::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">GetDesktopWindow</span>(</span>);
    <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>desktop == <span class="constant constant_language constant_language_c">NULL</span>)
    <span class="meta meta_block meta_block_c">{
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">        </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;
    }</span>

    HDC screen_dev = ::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">GetDC</span>(</span>desktop);
    <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>screen_dev == <span class="constant constant_language constant_language_c">NULL</span>)
    <span class="meta meta_block meta_block_c">{
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">        </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;
    }</span>

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> Create a compatible DC
</span>    HDC dst_hdc = ::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">CreateCompatibleDC</span>(</span>screen_dev);
    <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>dst_hdc == <span class="constant constant_language constant_language_c">NULL</span>)
    <span class="meta meta_block meta_block_c">{
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">        </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">        </span><span class="entity entity_name entity_name_function entity_name_function_c">::ReleaseDC</span><span class="meta meta_parens meta_parens_c">(desktop, screen_dev)</span>;</span>
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;
    }</span>

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> Create a new bitmap of icon size
</span>    HBITMAP bmp = ::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">CreateCompatibleBitmap</span>(</span>screen_dev, rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.right</span>, rect<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.bottom</span>);
    <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>bmp == <span class="constant constant_language constant_language_c">NULL</span>)
    <span class="meta meta_block meta_block_c">{
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">        </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">        </span><span class="entity entity_name entity_name_function entity_name_function_c">::DeleteDC</span><span class="meta meta_parens meta_parens_c">(dst_hdc)</span>;</span>
<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">        </span><span class="entity entity_name entity_name_function entity_name_function_c">::ReleaseDC</span><span class="meta meta_parens meta_parens_c">(desktop, screen_dev)</span>;</span>
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;
    }</span>

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> Select it into the compatible DC
</span>    HBITMAP old_dst_bmp = (HBITMAP)::<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">SelectObject</span>(</span>dst_hdc, bmp);
    <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>old_dst_bmp == <span class="constant constant_language constant_language_c">NULL</span>)
    <span class="meta meta_block meta_block_c">{
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">        </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;
    }</span>

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> Fill the background of the compatible DC with the given colour
</span><span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">    </span><span class="entity entity_name entity_name_function entity_name_function_c">::SetBkColor</span><span class="meta meta_parens meta_parens_c">(dst_hdc, RGB(<span class="constant constant_numeric constant_numeric_c">255</span>, <span class="constant constant_numeric constant_numeric_c">255</span>, <span class="constant constant_numeric constant_numeric_c">255</span>)</span>);</span>
<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">    </span><span class="entity entity_name entity_name_function entity_name_function_c">::ExtTextOut</span><span class="meta meta_parens meta_parens_c">(dst_hdc, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_numeric constant_numeric_c">0</span>, ETO_OPAQUE, &amp;rect, <span class="constant constant_language constant_language_c">NULL</span>, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_language constant_language_c">NULL</span>)</span>;</span>

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> Draw the icon into the compatible DC
</span><span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">    </span><span class="entity entity_name entity_name_function entity_name_function_c">::DrawIconEx</span><span class="meta meta_parens meta_parens_c">(dst_hdc, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_numeric constant_numeric_c">0</span>, hIcon, rect.right, rect.bottom, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_language constant_language_c">NULL</span>, DI_NORMAL)</span>;</span>

    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> Restore settings
</span><span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">    </span><span class="entity entity_name entity_name_function entity_name_function_c">::SelectObject</span><span class="meta meta_parens meta_parens_c">(dst_hdc, old_dst_bmp)</span>;</span>
<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">    </span><span class="entity entity_name entity_name_function entity_name_function_c">::DeleteDC</span><span class="meta meta_parens meta_parens_c">(dst_hdc)</span>;</span>
<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c">    </span><span class="entity entity_name entity_name_function entity_name_function_c">::ReleaseDC</span><span class="meta meta_parens meta_parens_c">(desktop, screen_dev)</span>;</span>
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">    </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
    <span class="keyword keyword_control keyword_control_c">return</span> bmp;
}</span></span>
</span></pre>
<h3>Ownerdraw method</h3>
<p><a href="http://tortoisesvn.tigris.org/">Tortoise SVN</a> was using also owner draw method. I won&#8217;t describe here details of this method. This relays on <tt>MENUITEMINFO</tt> <tt>fType</tt> flag set to <tt>MFT_OWNERDRAW</tt>. Shell extension in <tt>HandleMenuMsg2</tt> callback should handle <tt>WM_MEASUREITEM</tt> and <tt>WM_DRAWITEM</tt>.  This method is generally OK, however it has several flaws:</p>
<ol>
<li>We need to measure &amp; draw menu in all stated ourselves, which makes us write plenty of code.</li>
<li>Ownerdraw menus are not respecting visual styles of <em>Windows XP</em> or <em>Vista</em>. We would need to use uxtheme functions to somehow handle rendering of menu parts on those systems.</li>
<li>We need to keep exta context information for each menu item with text, icon handle, etc.</li>
<li>Keyboard shortcuts doesn&#8217;t work automatically, we must handle <tt>WM_MENUCHAR</tt> to make them work.</li>
</ol>
<h3>HBMMENU_CALLBACK method</h3>
<p>Since <em>Windows 98</em> <tt>MENUITEMINFO</tt> has extra field <tt>hbmpItem</tt>.  This field can be used for setting the <tt>HBITMAP</tt> with bitmap that is displayed next to the menu item. <tt>hbmpItem</tt> can be set also to <tt>HBMMENU_CALLBACK</tt> which will make menu item work like owner-draw, but <tt>WM_MEASUREITEM</tt> &amp; <tt>WM_DRAWITEM</tt> just need to handle icon drawing, rest will be done by <em>Windows</em>.  This method is easiest to implement and so it is used inside many application, I just name on I use or develop: <em>wxWidgets SDK,</em> <em>Miranda IM</em>. We just need to initialize menu item like that:</p>
<pre class="textmate-source"><span class="source source_c++">MENUITEMINFO menuiteminfo;
<span class="meta meta_function meta_function_c"><span class="entity entity_name entity_name_function entity_name_function_c">ZeroMemory</span><span class="meta meta_parens meta_parens_c">(&amp;menuiteminfo, <span class="keyword keyword_operator keyword_operator_sizeof keyword_operator_sizeof_c">sizeof</span>(menuiteminfo)</span>);</span>
menuiteminfo.cbSize = <span class="keyword keyword_operator keyword_operator_sizeof keyword_operator_sizeof_c">sizeof</span>(menuiteminfo);
menuiteminfo.<span class="variable variable_other variable_other_readwrite variable_other_readwrite_member variable_other_readwrite_member_c++">fMask</span> = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
menuiteminfo.<span class="variable variable_other variable_other_readwrite variable_other_readwrite_member variable_other_readwrite_member_c++">fType</span> = MFT_STRING;
menuiteminfo.dwTypeData = lpszMenuTitle;
menuiteminfo.cch = _tcslen(lpszMenuTitle);
menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
menuiteminfo.wID = id;
</span></pre>
<p>Rest is done in <tt>WM_MEASUREITEM</tt> where we need to just make sure we have space for 16 x 16 image using:</p>
<pre class="textmate-source"><span class="source source_c++">    <span class="keyword keyword_control keyword_control_c">case</span> WM_MEASUREITEM:
        <span class="meta meta_block meta_block_c">{
            MEASUREITEMSTRUCT* lpmis = (MEASUREITEMSTRUCT*)lParam;
            <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>lpmis==<span class="constant constant_language constant_language_c">NULL</span>)
                <span class="keyword keyword_control keyword_control_c">break</span>;
            lpmis-&gt;itemWidth += <span class="constant constant_numeric constant_numeric_c">2</span>;
            <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>lpmis-&gt;itemHeight &lt; <span class="constant constant_numeric constant_numeric_c">16</span>)
                lpmis-&gt;itemHeight = <span class="constant constant_numeric constant_numeric_c">16</span>;
            *pResult = <span class="constant constant_language constant_language_c">TRUE</span>;
        }</span>
        <span class="keyword keyword_control keyword_control_c">break</span>;
</span></pre>
<p>Then to draw an icon we need to handle WM_DRAWITEM, but just drawing the icon, nothing else:</p>
<pre class="textmate-source"><span class="source source_c++">    <span class="keyword keyword_control keyword_control_c">case</span> WM_DRAWITEM:
        <span class="meta meta_block meta_block_c">{
            LPCTSTR resource;
            DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
            <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>(lpdis==<span class="constant constant_language constant_language_c">NULL</span>)||(lpdis-&gt;CtlType != ODT_MENU))
                <span class="keyword keyword_control keyword_control_c">return</span> S_OK; <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> not for a menu
</span>            resource =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c">GetMenuIconResourceID</span>(</span>lpdis-&gt;itemID);
            <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>resource == <span class="constant constant_language constant_language_c">NULL</span>)
                <span class="keyword keyword_control keyword_control_c">return</span> S_OK;
            HICON hIcon = (HICON)<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">LoadImage</span>(</span>g_hResInst, resource, IMAGE_ICON, <span class="constant constant_numeric constant_numeric_c">16</span>, <span class="constant constant_numeric constant_numeric_c">16</span>, LR_DEFAULTCOLOR);
            <span class="keyword keyword_control keyword_control_c">if</span><span class="meta meta_initialization meta_initialization_c"> <span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_c">(</span></span>hIcon == <span class="constant constant_language constant_language_c">NULL</span>)
                <span class="keyword keyword_control keyword_control_c">return</span> S_OK;
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">            </span><span class="support support_function support_function_any-method support_function_any-method_c">DrawIconEx</span>(</span>lpdis-&gt;hDC,
                lpdis-&gt;rcItem<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.left</span> - <span class="constant constant_numeric constant_numeric_c">16</span>,
                lpdis-&gt;rcItem<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.top</span> + (lpdis-&gt;rcItem<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.bottom</span> - lpdis-&gt;rcItem<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.top</span> - <span class="constant constant_numeric constant_numeric_c">16</span>) / <span class="constant constant_numeric constant_numeric_c">2</span>,
                hIcon, <span class="constant constant_numeric constant_numeric_c">16</span>, <span class="constant constant_numeric constant_numeric_c">16</span>,
                <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_language constant_language_c">NULL</span>, DI_NORMAL);
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">            </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
            *pResult = <span class="constant constant_language constant_language_c">TRUE</span>;
        }</span>
        <span class="keyword keyword_control keyword_control_c">break</span>;</span></pre>
<p>Simple ? Yes it is. However there are some issues with this method as well:</p>
<ol>
<li>When this method is used on <em>Windows 2000</em> shell extension window background popup menu, then <tt>shell.dll</tt> is removing text from the menu, so we see just icons.This is obviously a bug of <em>Windows 2000</em> <tt>shell.dll</tt>, because MSDN documentation states this shall work regardless of the sittuation, but we need to somehow get over it. Surprisingly it does work fine when we right-click on explorer item (file or folder). The easiest solution is using <tt>hbmp(Un)checked</tt> method when <tt>uFlags == 0</tt> of <tt>QueryContextMenu</tt>, which indicated we clicked the background, so we fall back to most primitive method, but at least we got text and &#8220;some&#8221; icons in the menu.<strong>Note:</strong> This bug only appears in <em>Windows 2000</em> explorer&#8217;s background menu of shell extension, so in every other situation as standalone program menus <tt>HBMMENU_CALLBACK</tt> method can be used without any problem. So you may not care about it unless you are shell extension developer.</li>
<li><em>Vista</em> is removing menu theme when some menu item has <tt>hbmpItem</tt> set to <tt>HBMMENU_CALLBACK</tt>, so we will have nice icons and nice menu, but if we want to have nice icons with 100% themed menu on <em>Vista</em> we need to use last method&#8230;</li>
</ol>
<h3>Vista PARGB32 hbmpItem bitmap method (Updated)</h3>
<p><em>Vista</em> strongly relays on 32-bit pre-multiplied alpha RGB bitmaps for rendering its interface. In Vista hbmpItem can be set to PARGB32 HBITMAP and this bitmap will be nicely displayed by Vista together with theming as you can see on the screenshot at right.  I got know of this possibility reading nice article <a href="http://shellrevealed.com/blogs/shellblog/archive/2007/02/06/Vista-Style-Menus_2C00_-Part-1-_2D00_-Adding-icons-to-standard-menus.aspx">Vista Style Menus, Part 1 &#8211; Adding icons to standard menus</a> at <em>ShellRevealed</em> blog.</p>
<p>The most important question is how to we get our icon (regardless it is 32-bit with alpha, or 256-color with mask) converted to PARGB32 HBITMAP. <span style="text-decoration: line-through;">Windows API doesn&#8217;t give such possibility straight of the box.</span> Article from <em>ShellRevealed</em> proposes WIC (<em>Windows Imaging Component</em>) which is cool &amp; quite simple for conversion or <em>Vista</em>&#8216;s GDI method, but those require <em>Vista SDK</em>, which may be annoying for those using <em>Visual Studio</em>&#8216;s out of the box.</p>
<p><span style="text-decoration: line-through;">As an alternative to that I&#8217;ve used </span><em><span style="text-decoration: line-through;">Gdiplus</span></em><span style="text-decoration: line-through;"> which is present on most of the systems since </span><em><span style="text-decoration: line-through;">Windows 2000</span></em><span style="text-decoration: line-through;">, and most shipped with </span><em><span style="text-decoration: line-through;">Visual Studio</span></em><span style="text-decoration: line-through;">s </span><em><span style="text-decoration: line-through;">Platforms SDK</span></em><span style="text-decoration: line-through;">s.  This method is also much simpler than WIC or GDI method from described article</span>.</p>
<p>Alternative solution to WIC is to use pure <em>Vista GDI</em> (<em>UxTheme</em>) calls as described at <a href="http://msdn.microsoft.com/en-us/library/bb757020.aspx?s=6">http://msdn.microsoft.com/en-us/library/bb757020.aspx?s=6</a> (<tt><strong>GDI_CVistaMenuApp.cpp</strong></tt> sample). It was implemented in <em>TortoiseSVN</em> revision 14191 by <em>Steve King</em>. It uses <tt><em>BeginBufferedPaint</em></tt>, <tt><em>EndBufferedPaint</em></tt> and <tt><em>GetBufferedPaintBits</em></tt> dynamically loaded from <em>Vista</em>&#8216;s <tt>UXTHEME.DLL</tt> and <tt>Create32BitHBITMAP </tt>and <tt>ConvertBufferToPARGB32</tt> from <tt><strong>GDI_CVistaMenuApp.cpp</strong></tt> sample.</p>
<p>The PARGB32 function is as follows:</p>
<pre class="textmate-source"><span class="source source_c++">HBITMAP<span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c"> </span><span class="entity entity_name entity_name_function entity_name_function_c">CShellExt::IconToBitmapPARGB32</span><span class="meta meta_parens meta_parens_c">(std::string <span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sIcon</span>)</span>
<span class="meta meta_block meta_block_c">{
    HRESULT hr = E_OUTOFMEMORY;
    HBITMAP hBmp = <span class="constant constant_language constant_language_c">NULL</span>;

    HICON hIcon = (HICON)<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">LoadImageA</span>(</span>g_hResInst, <span class="variable variable_other variable_other_readwrite variable_other_readwrite_static variable_other_readwrite_static_mac-classic variable_other_readwrite_static_mac-classic_c">sIcon</span>.<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">c_str</span>(</span>), IMAGE_ICON, <span class="constant constant_numeric constant_numeric_c">16</span>, <span class="constant constant_numeric constant_numeric_c">16</span>, LR_DEFAULTCOLOR);
    <span class="keyword keyword_control keyword_control_c">if</span>(!hIcon)
        <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;

    SIZE sizIcon;
    sizIcon<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cx</span> =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c">GetSystemMetrics</span>(</span>SM_CXSMICON);
    sizIcon<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cy</span> =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c">GetSystemMetrics</span>(</span>SM_CYSMICON);

    RECT rcIcon;
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">    </span><span class="support support_function support_function_any-method support_function_any-method_c">SetRect</span>(</span>&amp;rcIcon, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_numeric constant_numeric_c">0</span>, sizIcon<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cx</span>, sizIcon<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cy</span>);

    HDC hdcDest =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c">CreateCompatibleDC</span>(</span><span class="constant constant_language constant_language_c">NULL</span>);
    <span class="keyword keyword_control keyword_control_c">if</span>(hdcDest) <span class="meta meta_block meta_block_c">{
        hr =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c"><strong>Create32BitHBITMAP</strong></span>(</span>hdcDest, &amp;sizIcon, <span class="constant constant_language constant_language_c">NULL</span>, &amp;hbmp);
        <span class="keyword keyword_control keyword_control_c">if</span>(<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">SUCCEEDED</span>(</span>hr)) <span class="meta meta_block meta_block_c">{
            hr = E_FAIL;

            HBITMAP hbmpOld = (HBITMAP)<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">SelectObject</span>(</span>hdcDest, hbmp);
            <span class="keyword keyword_control keyword_control_c">if</span>(hbmpOld) <span class="meta meta_block meta_block_c">{
                BLENDFUNCTION bfAlpha = <span class="meta meta_block meta_block_c">{ AC_SRC_OVER, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_numeric constant_numeric_c">255</span>, AC_SRC_ALPHA }</span>;
                BP_PAINTPARAMS paintParams = <span class="meta meta_block meta_block_c">{<span class="constant constant_numeric constant_numeric_c">0</span>}</span>;
                paintParams<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cbSize</span> =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c">sizeof</span>(</span>paintParams);
                paintParams<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.dwFlags</span> = BPPF_ERASE;
                paintParams<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.pBlendFunction</span> = &amp;bfAlpha;

                HDC hdcBuffer;
                HPAINTBUFFER hPaintBuffer =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c"><strong>pfnBeginBufferedPaint</strong></span>(</span>hdcDest, &amp;rcIcon, BPBF_DIB, &amp;paintParams, &amp;hdcBuffer);
                <span class="keyword keyword_control keyword_control_c">if</span>(hPaintBuffer) <span class="meta meta_block meta_block_c">{
                    <span class="keyword keyword_control keyword_control_c">if</span>(<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">DrawIconEx</span>(</span>hdcBuffer, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_numeric constant_numeric_c">0</span>, hIcon, sizIcon<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cx</span>, sizIcon<span class="variable variable_other variable_other_dot-access variable_other_dot-access_c">.cy</span>, <span class="constant constant_numeric constant_numeric_c">0</span>, <span class="constant constant_language constant_language_c">NULL</span>, DI_NORMAL)) <span class="meta meta_block meta_block_c">{
                        <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> If icon did not have an alpha channel, we need to convert buffer to PARGB.
</span>                        hr =<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c"> </span><span class="support support_function support_function_any-method support_function_any-method_c"><strong>ConvertBufferToPARGB32</strong></span>(</span>hPaintBuffer, hdcDest, hIcon, sizIcon);
                    }</span>

                    <span class="comment comment_line comment_line_double-slash comment_line_double-slash_c++"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">//</span> This will write the buffer contents to the destination bitmap.
</span><span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">                    </span><span class="support support_function support_function_any-method support_function_any-method_c"><strong>pfnEndBufferedPaint</strong></span>(</span>hPaintBuffer, <span class="constant constant_language constant_language_c">TRUE</span>);
                }</span>
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">                </span><span class="support support_function support_function_any-method support_function_any-method_c">SelectObject</span>(</span>hdcDest, hbmpOld);
            }</span>
        }</span>
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">        </span><span class="support support_function support_function_any-method support_function_any-method_c">DeleteDC</span>(</span>hdcDest);
    }</span>

<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">    </span><span class="support support_function support_function_any-method support_function_any-method_c">DestroyIcon</span>(</span>hIcon);
    <span class="keyword keyword_control keyword_control_c">if</span>(<span class="meta meta_function-call meta_function-call_c"><span class="support support_function support_function_any-method support_function_any-method_c">SUCCEEDED</span>(</span>hr)) <span class="meta meta_block meta_block_c">{
        <span class="keyword keyword_control keyword_control_c">return</span> hBmp;
    }</span>
<span class="meta meta_function-call meta_function-call_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function-call punctuation_whitespace_function-call_leading punctuation_whitespace_function-call_leading_c">    </span><span class="support support_function support_function_any-method support_function_any-method_c">DeleteObject</span>(</span>hBmp);
    <span class="keyword keyword_control keyword_control_c">return</span> <span class="constant constant_language constant_language_c">NULL</span>;
}</span></span>
</span></pre>
<p>So in this case instead <tt>menuiteminfo.hbmpItem = HBMMENU_CALLBACK</tt> we do <tt>menuiteminfo.hbmpItem = IconToBitmapPARGB32(lpszIconResourceID)</tt>. <span style="text-decoration: line-through;">We shouldn&#8217;t forget of initializing Gdiplus library with </span><tt><span style="text-decoration: line-through;">GdiplusStartup(&amp;m_gdipToken, &amp;gdiplusStartupInput, NULL)</span></tt><span style="text-decoration: line-through;"> in program/DLL initialization code and shutting it down after all with </span><tt><span style="text-decoration: line-through;">GdiplusShutdown(m_gdipToken)</span></tt><span style="text-decoration: line-through;">.</span></p>
<p>If we want to be compatible with older Windows versions, we shall load (map) the <em>Vista</em>&#8216;s <tt>UXTHEME.DLL</tt> functions dynamically only on Vista:</p>
<pre class="textmate-source"><span class="source source_c++"><span class="storage storage_type storage_type_c">typedef</span> DWORD ARGB;
<span class="storage storage_type storage_type_c">typedef</span><span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c"> </span><span class="entity entity_name entity_name_function entity_name_function_c">HRESULT</span> <span class="meta meta_parens meta_parens_c">(WINAPI *FN_GetBufferedPaintBits)</span> <span class="meta meta_parens meta_parens_c">(HPAINTBUFFER hBufferedPaint, RGBQUAD **ppbBuffer, <span class="storage storage_type storage_type_c">int</span> *pcxRow)</span>;</span>
<span class="storage storage_type storage_type_c">typedef</span><span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c"> </span><span class="entity entity_name entity_name_function entity_name_function_c">HPAINTBUFFER</span> <span class="meta meta_parens meta_parens_c">(WINAPI *FN_BeginBufferedPaint)</span> <span class="meta meta_parens meta_parens_c">(HDC hdcTarget, <span class="storage storage_modifier storage_modifier_c">const</span> RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc)</span>;</span>
<span class="storage storage_type storage_type_c">typedef</span><span class="meta meta_function meta_function_c"><span class="punctuation punctuation_whitespace punctuation_whitespace_function punctuation_whitespace_function_leading punctuation_whitespace_function_leading_c"> </span><span class="entity entity_name entity_name_function entity_name_function_c">HRESULT</span> <span class="meta meta_parens meta_parens_c">(WINAPI *FN_EndBufferedPaint)</span> <span class="meta meta_parens meta_parens_c">(HPAINTBUFFER hBufferedPaint, BOOL <span class="variable variable_other variable_other_readwrite variable_other_readwrite_member variable_other_readwrite_member_c++">fUpdateTarget</span>)</span>;</span>
<span class="comment comment_block comment_block_c"><span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">/*</span> (...) <span class="punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_c">*/</span></span>
HMODULE hUxTheme = ::GetModuleHandle (_T(<span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>UXTHEME.DLL<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>));
pfnGetBufferedPaintBits = (FN_GetBufferedPaintBits)::GetProcAddress(hUxTheme, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>GetBufferedPaintBits<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>);
pfnBeginBufferedPaint = (FN_BeginBufferedPaint)::GetProcAddress(hUxTheme, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>BeginBufferedPaint<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>);
pfnEndBufferedPaint = (FN_EndBufferedPaint)::GetProcAddress(hUxTheme, <span class="string string_quoted string_quoted_double string_quoted_double_c"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_c">"</span>EndBufferedPaint<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_c">"</span></span>);</span></pre>
<p><span style="text-decoration: line-through;">Since we are going to use </span><em><span style="text-decoration: line-through;">Gdiplus</span></em><span style="text-decoration: line-through;"> only on </span><em><span style="text-decoration: line-through;">Vista</span></em><span style="text-decoration: line-through;">, we may use </span><tt><span style="text-decoration: line-through;">Gdiplus.dll</span></tt><span style="text-decoration: line-through;"> as delayed load DLL, so it won&#8217;t be loaded on older systems using previous methods, saving us some memory.</span> Simple enough ?</p>
<p>Testing <em>Windows</em> version number with <tt>GetVersionEx</tt> and combining this method for <em>Vista</em> with <tt>HBMENU_CALLBACK</tt> method for <em>Windows XP</em> and older systems (with <tt>hbmp(Un)checked</tt> fallback on explorer extension on <em>Windows 2000</em> if needed) is my opinion best method of having nice menus in all modern <em>Windows</em> systems. This is also current display method of <a href="http://www.tortoisecvs.org/">Tortoise CVS</a> &amp; <a href="http://tortoisesvn.tigris.org/">Tortoise SVN</a> latest development versions. If you need full code to browse you may want look into <a href="http://tortoisesvn.tigris.org/">Tortoise SVN</a> SVN trunk files: <tt>srcTortoiseShellContextMenu.cpp</tt>, <tt>srcTortoiseShellShellExt.cpp</tt> and <tt>srcTortoiseShellShellExt.h</tt>.</p>
<h2>Conclustion</h2>
<p>All those hacks and recipes would be worthless if only there was simple consistent API for making menu item icons. Unfortunately menu icons, something that was always present in <em>Windows</em> and <em>Microsoft</em> applications, never got any decent API, moreover the methods to get those icons working change for every major <em>Windows</em> release, making us developers wasting our time &#8220;porting&#8221; our applications to new &#8220;shinny&#8221; <em>Windows</em> rather than doing something productive.</p>
<p>One thing that is simply unacceptable for me (even more since I now work regularly on OSX) is that <em>Windows</em> system apps and <em>Microsoft</em> regular applications are using so many UI hacks and mods that are never exposed to the developers trough API. Those are either closed libraries like one for <em>Office&#8217;s</em> or <em>Visual Studio</em> GUI, or <em>Vista</em> hacks with <tt>PARGB</tt> that require tricky in memory conversions rather than just pointing <tt>hbmpItem</tt> to <tt>HICON</tt> and making <em>Vista</em> to do the conversion on its own.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nanoant.com/programming/themed-menus-icons-a-complete-vista-xp-solution/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
