<?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>apocryph.org &#187; exocortex</title>
	<atom:link href="http://apocryph.org/tag/exocortex/feed/" rel="self" type="application/rss+xml" />
	<link>http://apocryph.org</link>
	<description>Notes to my future self</description>
	<lastBuildDate>Mon, 09 Aug 2010 16:59:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Rendering disabled (&apos;grayed out&apos;) image buttons in WPF</title>
		<link>http://apocryph.org/2007/08/26/rendering_disabled_grayed_out_image_buttons_wpf/</link>
		<comments>http://apocryph.org/2007/08/26/rendering_disabled_grayed_out_image_buttons_wpf/#comments</comments>
		<pubDate>Mon, 27 Aug 2007 03:34:24 +0000</pubDate>
		<dc:creator>anelson</dc:creator>
				<category><![CDATA[Migrated from Drupal]]></category>
		<category><![CDATA[exocortex]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[tech diary]]></category>
		<category><![CDATA[wpf]]></category>

		<guid isPermaLink="false">http://apocryph.org/?p=465</guid>
		<description><![CDATA[Earlier today I was ranting about lack of built-in support for grayed-out image buttons in WPF. I&#8217;ve come up with two workarounds; one correct, and one workable. The first one I figured out by looking at some C# code here. The idea is to use a FormatConvertedBitmap to convert the original image to grayscale. This [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier today I was <a href="what_hell_wrong_wpf">ranting about lack of built-in support for grayed-out image buttons in WPF</a>.  I&#8217;ve come up with two workarounds; one correct, and one workable.</p>
<p>The first one I figured out by looking at some C# code <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=737933&amp;SiteID=1">here</a>.  The idea is to use a <code>FormatConvertedBitmap</code> to convert the original image to grayscale.  This works, but then kills the alpha channel so your transparent PNGs aren&#8217;t transparent anymore.  Thus, I also use the <code>OpaqueMask</code> property of <code>Image</code> set to an <code>ImageBrush</code> based on the original image.  It&#8217;s nasty, complicated, and (probably, in a real app) slow.  Here&#8217;s the markup:</p>
<pre><code>&lt;TextBlock&gt;
    This is a grayed Image loaded from a BitmapImage, with an opacity mask :
    &lt;Button IsEnabled="false"&gt;
    &lt;Image Height="16"&gt;
        &lt;Image.Source&gt;
            &lt;FormatConvertedBitmap DestinationFormat="Gray32Float"&gt;
                &lt;FormatConvertedBitmap.Source&gt;
                    &lt;BitmapImage UriSource="Images\OutdentHS.png" /&gt;
                &lt;/FormatConvertedBitmap.Source&gt;
            &lt;/FormatConvertedBitmap&gt;
        &lt;/Image.Source&gt;
        &lt;Image.OpacityMask&gt;
            &lt;ImageBrush&gt;
                &lt;ImageBrush.ImageSource&gt;
                    &lt;BitmapImage UriSource="Images\OutdentHS.png" /&gt;
                &lt;/ImageBrush.ImageSource&gt;
            &lt;/ImageBrush&gt;
        &lt;/Image.OpacityMask&gt;
    &lt;/Image&gt;
    &lt;/Button&gt;
&lt;/TextBlock&gt;
</code></pre>
<p>As you can see, the original image is read into <code>FormatConvertedBitmap</code>, which is used to convert to <code>Gray32Float</code> (<code>Gray8</code> is probably better), and used as the <code>Source</code> of an <code>Image</code>.  The <code>Image</code>&#8216;s <code>OpaqueMask</code> is set to the original image via an <code>ImageBrush</code>.  As you test this out, don&#8217;t use Expression Blend; the designer view renders the grayscale <code>Image</code> elements as blank, even though in IE or a desktop XAML app it looks fine.</p>
<p>I also have NFI how this solution could be generalized into a style so you don&#8217;t have to repeat this for every button.  Obviously the original image and grayscale version could be expressed as resources (I did it my way for clarity), but it&#8217;s a long way from there to a trigger based on <code>IsEnabled</code> that replaces an image with a grayscale version of itself.</p>
<p>That leads me to the other solution, which blows but is workable.  I found that <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1691587&amp;SiteID=1">here</a>.  The idea is that you don&#8217;t grayscale the image at all; you lower its opacity so it looks more faded, and in the case of a gray control background, grayed out.  This happens to be easily expressed as a style, like so:</p>
<pre><code>&lt;Window.Resources&gt;
    &lt;!-- El Cheapo hack to make images within disabled toolbar buttons appear 'grayed out'.  This doesn't
    gray them at all, but lowers their opacity so the (usually gray) background of the button shows through.
    If WPF had a built-in facility for grayscaling images in disabled buttons, this kind of icky kludgery wouldn't
    be necessary --&gt;
    &lt;Style TargetType="{x:Type Image}" x:Key="toolbarImageStyle"&gt;
        &lt;Style.Triggers&gt;
            &lt;DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=1}, Path=IsEnabled}" Value="False"&gt;
                &lt;Setter Property="Opacity" Value="0.50"&gt;&lt;/Setter&gt;
            &lt;/DataTrigger&gt;
        &lt;/Style.Triggers&gt;
    &lt;/Style&gt;
&lt;/Window.Resources&gt;
</code></pre>
<p>Any <code>Image</code>s contained within a button and with <code>Style</code> set to <code>toolbarImageStyle</code> will have their opacity adjusted to 50% when the button is disabled.  The original post called for an opacity of 25%, but that was too faded in my opinion.  Adjust the value to taste, but don&#8217;t expect to exactly duplicate the true grayscale effect; colors are still visible in the buttons, they just look a bit faded.</p>
<p>So, there you have it.  I&#8217;m going with the latter solution since it&#8217;s easily workable and almost right, but I&#8217;m still fuming over WPF&#8217;s inability to handle a feature that MFC has had for the duration of my programming career.  Pretty soon I&#8217;ll be like those old mainframe curmudgeons who bitch about C++ and insist C and 64K of RAM is all anyone ever needed.  Then I&#8217;ll know it&#8217;s time to quit the software industry and go into yoga instruction full time.</p>
]]></content:encoded>
			<wfw:commentRss>http://apocryph.org/2007/08/26/rendering_disabled_grayed_out_image_buttons_wpf/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>What the HELL is wrong with WPF?</title>
		<link>http://apocryph.org/2007/08/26/what_hell_wrong_wpf/</link>
		<comments>http://apocryph.org/2007/08/26/what_hell_wrong_wpf/#comments</comments>
		<pubDate>Sun, 26 Aug 2007 19:28:56 +0000</pubDate>
		<dc:creator>anelson</dc:creator>
				<category><![CDATA[Migrated from Drupal]]></category>
		<category><![CDATA[exocortex]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[tech diary]]></category>
		<category><![CDATA[wpf]]></category>

		<guid isPermaLink="false">http://apocryph.org/?p=464</guid>
		<description><![CDATA[This weekend I&#8217;ve been working on one of my many self-edification projects, and against my better judgment I was implementing it with .NET 3.0/Windows Presentation Foundation, mainly because of the markup-like UI model which fit nicely with a few of my project&#8217;s idioms. Anyway, I wanted to get a quick hit this weekend to keep [...]]]></description>
			<content:encoded><![CDATA[<p>This weekend I&#8217;ve been working on one of my many self-edification projects, and against my better judgment I was implementing it with .NET 3.0/Windows Presentation Foundation, mainly because of the markup-like UI model which fit nicely with a few of my project&#8217;s idioms.</p>
<p>Anyway, I wanted to get a quick hit this weekend to keep momentum going, so I thought I&#8217;d put together the rich text interface of the project first.  This should be stupid-easy, since WPF contains a <code>RichTextBox</code> class that does everything you could ask for with rich text, and the underlying content model is itself a XAML document, a <code>FlowDocument</code>.  Too easy.</p>
<p>Unfortunately, <code>RichTextBox</code> doesn&#8217;t ship with the standard rich text toolbar, for doing things like bold, italics, etc.  No problem; WPF has a toolbar element too.  I wired up a bunch of buttons, each using the standard icon for its corresponding function, and set the buttons to invoke WPF commands like <code>EditingCommands.ToggleBold</code>, which the rich text box knows how to handle.  &#8220;Wow&#8221;, I thought to myself, &#8220;this WPF thing isn&#8217;t half bad!&#8221;.</p>
<p>Then I noticed something.  When commands are disabled (for example, the &#8216;Cut&#8217; command is disabled when there&#8217;s nothing to cut), the toolbar button doesn&#8217;t respond to mouseovers or clicks just like a disabled button wouldn&#8217;t, but the icon on the button isn&#8217;t grayed out like one would expect.  Then I tried something simpler; I created a <code>Button</code> with an <code>Image</code> in it, and explicitly set the <code>Button</code>&#8216;s <code>IsEnabled</code> property to <code>false</code>.  Sure enough, the image was still not grayed out.</p>
<p>Then I used Microsoft Expression Blend (a tool about which I could write a whole stream of angry rants) to show me the built-in XAML template for the <code>Button</code> control.  Imagine my surprise when I discovered the only logic in the template that deals with rendering the disabled button is setting the foreground color to gray.  That&#8217;s _it_.  No wonder, then, that my images weren&#8217;t rendering differently; the foreground color has no effect on images.</p>
<p>You can see for yourself.  Type this XAML code into XamlPad and see what happens:</p>
<pre><code>&lt;Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
    &lt;StackPanel HorizontalAlignment="Left"&gt;
        &lt;Button&gt;
            &lt;TextBlock&gt;This button is enabled
                &lt;Image Source="http://apocryph.org/themes/apocryph/logo.png" Width="32" /&gt;
            &lt;/TextBlock&gt;
        &lt;/Button&gt;
        &lt;Button IsEnabled="false"&gt;
            &lt;TextBlock&gt;This button is disabled
                &lt;Image Source="http://apocryph.org/themes/apocryph/logo.png" Width="32" /&gt;
            &lt;/TextBlock&gt;
        &lt;/Button&gt;
    &lt;/StackPanel&gt;
&lt;/Page&gt;
</code></pre>
<p>You&#8217;ll see two buttons, one with grayed-out text, but both with the same fucking image.</p>
<p>So let&#8217;s ponder this a moment.  Back in 1995, I got my first copy of Visual C++ for free from a guy named Mike Strock (this was back when companies sold compilers for an outrageous sum, and thus I couldn&#8217;t afford them).  One of the kickass features that blew me away was the MFC document/view model, where toolbar buttons mapped to commands, and would automatically disable themselves if the commands were disabled.  Somehow, MFC automatically grayed out the toolbar button icons as well.  It was incredible.  &#8220;Surely&#8221;, I thought, &#8220;programming can&#8217;t get any easier than this&#8221;.</p>
<p>Apparently, I was right, coz here we are, 12 long years later, and we&#8217;ve taken a huge fucking step <em>backwards</em>.  Now, don&#8217;t get me wrong.  Using WPF I can easily make a button which contains a spinning 3D cube playing videos on each face that turns green when the mouse goes over it, all without any C# code.  Unfortunately, no one would ever want to do that, while it&#8217;s easy to imagine a situation wherein you&#8217;d want toolbar icons to gray themselves (like, I dunno, <em>every Windows application ever made</em>).</p>
<p>This gives me a great startup idea.  I&#8217;ll found a company in some tort-free jurisdiction like Costa Rica, called &#8220;FuckIt, Inc&#8221;.  We&#8217;d offer an exclusive &#8220;Fuck This Shit(tm)&#8221; package, wherein programmers who can no longer bear the absurdity and kludge which is modern software engineering would be cryogenically frozen in a bunker on a secret island off the coast, to be revived 100 years hence or when the software industry gets its head out of its ass, whichever comes first.  One of the test cases used to determine if the industry has its head out of its ass yet would be this one:</p>
<p>Using the latest development tools from the vendor of the most popular desktop operating system on the planet, is it easier to create toolbar buttons with icons that automatically disable themselves when the action they correspond to is disable, or to create a huge button containing a spinning 3D cube with video playing on each face?  If the answer is the latter, as it is today, then the programmers stay frozen.</p>
<p><strong>UPDATE</strong>: I&#8217;ve got a couple of solutions, <a href="rendering_disabled_grayed_out_image_buttons_wpf">here</a>.  Neither of them are optimal, but then, neither is life itself.</p>
]]></content:encoded>
			<wfw:commentRss>http://apocryph.org/2007/08/26/what_hell_wrong_wpf/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
