<?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>Aaron Lerch &#187; windows forms</title>
	<atom:link href="http://www.aaronlerch.com/blog/category/windows-forms/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.aaronlerch.com/blog</link>
	<description></description>
	<lastBuildDate>Sun, 04 Apr 2010 03:04:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Debugging UI</title>
		<link>http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/</link>
		<comments>http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 19:01:09 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/</guid>
		<description><![CDATA[I&#8217;ve talked before about System.Threading.SynchronizationContext, as well as BeginInvoke/InvokedRequired/IsHandleCreated. In a multi-threaded Windows Forms application they can easily be mis-used, introducing difficult to find bugs. One such not-so-subtle bug (application hang) is particularly nasty, and is described fairly well here. Distilled down, the application hangs, usually when the computer comes out of sleep mode, unlocks, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve talked before about <a href="http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/">System.Threading.SynchronizationContext</a>, as well as <a href="http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/">BeginInvoke/InvokedRequired/IsHandleCreated</a>. In a multi-threaded Windows Forms application they can easily be mis-used, introducing difficult to find bugs.</p>
<p>One such not-so-subtle bug (application hang) is particularly nasty, and is <a href="http://ikriv.com:8765/en/prog/info/dotnet/MysteriousHang.html">described fairly well here</a>. Distilled down, the application hangs, usually when the computer comes out of sleep mode, unlocks, or another similar event occurs. The hang happens in the firing of an event handler, called from &#8220;SystemEvents.OnUserPreferenceChanged&#8221;. The cause is that OnUserPreferenceChanged is trying to be super nice, and invoke the event in the appropriate context for each event subscriber. That means that if a Control subscribes to the event, the handler will be called on the UI thread. If user code (on a background thread) subscribes, the handler will be called on an arbitrary thread, etc. The problem occurs when, at some point in the past, a Form or Control was created on a background thread. The creation of the control &#8220;installed&#8221; a WindowsFormsSynchronizationContext as the current SynchronizationContext (this is default behavior). When OnUserPreferenceChanged attempts to Send (Invoke) to the appropriate thread context, it hangs because the WindowsFormsSynchronizationContext is on the wrong thread, and thus has no message pump with which to process messages.</p>
<p>Blah blah blah. Right now you&#8217;re thinking &#8220;Whatever dude, I&#8217;m a web developer, man, I&#8217;m just trying to fix this bug in that <strong>other</strong> jerk&#8217;s code.&#8221; Fair enough, you can read the linked post for more gory details. What you care about is the hard part. Well, hard for <em>web developers</em> anyway. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  By the time the app hangs, it&#8217;s too late to find out where the problem occurred. In a medium-to-large application, how do you find the control that was created on the wrong thread? Here&#8217;s how to do it in a matter of seconds.</p>
<p><strong>1. Name your UI thread.</strong> If you&#8217;re not already doing this, it&#8217;s a good idea in general. I like to call mine &#8220;UI&#8221;, personally. In your &#8220;static void Main()&#8221; add this single line of code:</p>
<pre class="c#" name="code">Thread.CurrentThread.Name = "UI";</pre>
<p><strong>2. Set a breakpoint deep in the bowels of the BCL.</strong> What we want to do is cause our application to break when a WindowsFormsSynchronizationContext gets assigned to the current thread. I cracked open Reflector to look at the constructor for WindowsFormsSynchronizationContext:</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/winforms_synccontext_ctor.png"></p>
<p>And I see that there&#8217;s a call to &#8220;Application.ThreadContext.FromCurrent()&#8221;. Close enough for government work, it&#8217;ll do for what I want. I didn&#8217;t feel like figuring out how to specify a constructor call when setting a breakpoint. (If you know how, leave a comment so we can all learn!) Add a breakpoint to that method call. In Visual Studio, go to the &#8220;Debug&#8221; &gt; &#8220;New Breakpoint&#8221; &gt; &#8220;Break at Function&#8230;&#8221; menu. In the &#8220;Function&#8221; area type the full path to the function: System.Windows.Forms.Application.ThreadContext.FromCurrent()</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/new_breakpoint_threadcontext.png"></p>
<p>When you hit &#8220;OK&#8221; you&#8217;ll get a warning about IntelliSense not finding the specified location. Hit &#8220;Yes&#8221; to set the breakpoint anyway.</p>
<p><strong>3. Run your application.</strong> Depending on what version of Visual Studio you&#8217;re running, and whether you&#8217;ve got source-level debugging for the Framework turned on, you&#8217;ll either get the breakpoint on some code, or you&#8217;ll get this message box:</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/no_source_code_msgbox.png"></p>
<p>It doesn&#8217;t matter, you can press &#8220;OK&#8221; or &#8220;Show Disassembly&#8221;, whatever floats your boat. Go to the &#8220;Call Stack&#8221; debugging window, right-click on the red breakpoint circle located at the top of the stack frame, and select &#8220;Breakpoint&#8221; &gt; &#8220;Filter&#8230;&#8221;</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/breakpoint_filter.png"></p>
<p><strong>4. Add a filter to this breakpoint so that it only breaks when the current threads&#8217; name isn&#8217;t &#8220;UI&#8221;.</strong></p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/breakpoint_filter_non_ui_thread.png"></p>
<p>After you hit &#8220;OK&#8221;, continue running your application in the debugger. The first time a WindowsFormsSynchronizationContext is created and it&#8217;s not on the UI thread, BAM. There&#8217;s your problem, and there&#8217;s your stack trace allowing you to find the bad code.</p>
<p>This worked like a champ for me today, hopefully you have as much success with it too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Windows Forms Globalization</title>
		<link>http://www.aaronlerch.com/blog/2008/01/08/windows-forms-globalization/</link>
		<comments>http://www.aaronlerch.com/blog/2008/01/08/windows-forms-globalization/#comments</comments>
		<pubDate>Tue, 08 Jan 2008 22:21:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/01/08/windows-forms-globalization/</guid>
		<description><![CDATA[It&#8217;s amazing how the process of making an application localizable can be both simple and confusing at the same time. At a basic level, the Visual Studio designer makes it very easy. Set the &#34;Localizable&#34; property on your form to True and you&#8217;re good to go. It&#8217;s very convenient. On the other hand, there are [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s amazing how the process of making an application localizable can be both simple and confusing at the same time. At a basic level, the Visual Studio designer makes it very easy. Set the &quot;Localizable&quot; property on your form to True and you&#8217;re good to go. It&#8217;s very convenient.</p>
<p>On the other hand, there are a lot of challenges like <a href="http://blogs.msdn.com/michkap/archive/2007/01/11/1449754.aspx" mce_href="http://blogs.msdn.com/michkap/archive/2007/01/11/1449754.aspx">poorly named properties</a>, confusing defaults, and possibly unexpected behavior. You really need to understand what&#8217;s going on under the covers.</p>
<p>For instance, if you&#8217;ve looked into .NET <a href="http://blogs.msdn.com/larryosterman/archive/2005/01/26/361015.aspx" mce_href="http://blogs.msdn.com/larryosterman/archive/2005/01/26/361015.aspx">localizability</a> at all, you probably know that by default resources are loaded using the <a href="http://msdn2.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx">CultureInfo</a> retrieved from the <a href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.currentuiculture.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.threading.thread.currentuiculture.aspx">System.Threading.Thread.CurrentThread.CurrentUICulture</a> property. That&#8217;s why most <a href="http://msdn2.microsoft.com/en-us/library/b28bx3bh%28VS.71%29.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/b28bx3bh(VS.71).aspx">guidance</a> for manually changing the default application UI language says to set that property to a value of your choice. And well you should &#8211; it&#8217;s the only way to override the default language settings for your Windows Forms.</p>
<p>See, the Windows Forms designer automatically generates all sorts of useful code that you can&#8217;t (and shouldn&#8217;t) touch. Here&#8217;s an example.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="262" alt="image" src="http://aaronlerch.com.s3.amazonaws.com/images/localizing_windows_forms_code.png" width="520" border="0" mce_src="http://aaronlerch.com.s3.amazonaws.com/images/localizing_windows_forms_code.png" /> </p>
<p>Notice the ComponentResourceManager? It&#8217;s a local variable in the InitializeComponent method. The only way to alter it&#8217;s behavior is to alter the current thread&#8217;s UI culture information.</p>
<p>So that&#8217;s great, and even better it&#8217;s easy. When your application starts, you can load culture/language information from whatever persistence mechanism you prefer, and essentially &quot;set it and forget it&quot;, since all Controls should be created on the <a href="http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/" mce_href="http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/">same</a> <a href="http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/" mce_href="http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/">thread</a>.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="160" alt="image" src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_3.png" width="510" border="0" mce_src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_3.png" /> </p>
<p>But there&#8217;s one problem with this: <b>it only applies to UI elements (Controls).</b></p>
<p>It&#8217;s also common to load objects outside the context of the UI, perhaps with the intention of later presenting them to the user, or persisting to a file, or something else &quot;user visible&quot;. For this, you can add an arbitrary number of resx files that contain images, strings, serialized objects, etc.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="165" alt="image" src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_4.png" width="370" border="0" mce_src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_4.png" /> </p>
<p>With Visual Studio 2005 and higher, these resources are available as strongly-typed properties, giving you compile-time checking and ease of use.</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="40" alt="image" src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_5.png" width="430" border="0" mce_src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_5.png" /> </p>
<p>But here&#8217;s where our problem comes in. Overriding the default UI culture on the main thread applies <i>only to that thread</i>. If you load any resources from a background thread of any kind, they will be the resources for the default windows UI language.</p>
<p>The strongly-typed class (&quot;Resources&quot;, in my example) offers us some relief, however, in the form of a static &quot;Culture&quot; property on the auto generated class. If you never touch the property, resources will be loaded using the current thread value. But if you assign your own value, you can explicitly control which resources are loaded.</p>
<p>Consider this debugging example where I&#8217;m stopped in the execution of a background thread. I&#8217;ve created a global static &quot;Localization&quot; class with a &quot;CurrentCulture&quot; property that I use to maintain the current UI language for my application. You can compare and contrast the values set for the current thread and the auto generated Resource static class, which my application has initialized. (I&#8217;m running the English UI for Windows, by the way.)</p>
<p><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="106" alt="image" src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_6.png" width="520" border="0" mce_src="http://www.aaronlerch.com/files/blog/Localizingwindowsformsapplications_1D07/image_6.png" /> </p>
<p>So, why am I posting this? Because I myself was unsure about how to correctly accomplish the goal of enabling users to select their own UI language until I noticed the auto generated &quot;Culture&quot; property on the Resources class. And <a href="http://www.aaronlerch.com/blog/2008/01/08/on-blogging/" mce_href="http://www.aaronlerch.com/blog/2008/01/08/on-blogging/">it took me embarrassingly long to find it</a>. Hopefully this post keeps somebody else from wasting an evening, or more.</p>
<p>In summary, it&#8217;s actually simple once you understand all the details. To enable a specific &quot;non-default&quot; language in your application:</p>
<ul>
<li>Set the System.Threading.Thread.CurrentThread.CurrentUICulture property to the appropriate culture, and </li>
<li>Initialize all auto generated resource classes (or any custom uses of the ResourceManager class) to the appropriate culture, before loading any resources.      </li>
</ul>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:fd4651f7-d1cf-405f-ad83-99df1c936466" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/Windows%20Forms" rel="tag" mce_href="http://technorati.com/tags/Windows%20Forms">Windows Forms</a>, <a href="http://technorati.com/tags/Localization" rel="tag" mce_href="http://technorati.com/tags/Localization">Localization</a>, <a href="http://technorati.com/tags/Localizable" rel="tag" mce_href="http://technorati.com/tags/Localizable">Localizable</a>, <a href="http://technorati.com/tags/Globalization" rel="tag" mce_href="http://technorati.com/tags/Globalization">Globalization</a>, <a href="http://technorati.com/tags/Internationalization" rel="tag" mce_href<br />
="http://technorati.com/tags/Internationalization">Internationalization</a>, <a href="http://technorati.com/tags/CurrentUICulture" rel="tag" mce_href="http://technorati.com/tags/CurrentUICulture">CurrentUICulture</a>, <a href="http://technorati.com/tags/CultureInfo" rel="tag" mce_href="http://technorati.com/tags/CultureInfo">CultureInfo</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/01/08/windows-forms-globalization/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Watermarked edit controls</title>
		<link>http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/</link>
		<comments>http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/#comments</comments>
		<pubDate>Sat, 01 Dec 2007 21:58:48 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/</guid>
		<description><![CDATA[Recently I wanted to use a WinForms TextBox with some &#8220;watermark text&#8221;, but had some trouble finding anything existing on the web. Which was surprising because of how ubiquitous they are. Turns out the terminology varies: cue, prompt, or watermark. And &#8220;watermark&#8221; is the least used. Once I got my ducks in a row (by [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I wanted to use a WinForms TextBox with some &#8220;watermark text&#8221;, but had some trouble finding anything existing on the web. Which was surprising because of how ubiquitous they are. Turns out the terminology varies: cue, prompt, or watermark. And &#8220;watermark&#8221; is the least used.</p>
<p>Once I got my ducks in a row (by perusing the <a href="http://msdn2.microsoft.com/en-us/library/bb775458.aspx">MSDN documentation on the Win32 edit control</a>, which is the foundation of the .NET TextBox anyway) I found a few resources online, but they either a) didn&#8217;t wrap the exact Win32 edit control behavior, or b) were just a one-off &#8220;send a message to the control like this&#8221;, when I&#8217;d prefer a more polished derived control with designer support, etc.</p>
<p>So I present <a href="http://www.aaronlerch.com/files/blog/CueTextBox.cs">CueTextBox.cs</a>, <a href="http://www.aaronlerch.com/files/blog/CueComboBox.cs">CueComboBox.cs</a>, and <a href="http://www.aaronlerch.com/files/blog/CueToolStripTextBox.cs">CueToolStripTextBox.cs</a>. Here&#8217;s a simple example that hosts all 3 of them:</p>
<p><a href="http://www.aaronlerch.com/files/blog/Watermarkededitcontrols_EEC3/image.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="217" alt="image" src="http://www.aaronlerch.com/files/blog/Watermarkededitcontrols_EEC3/image_thumb.png" width="233" border="0"></a></p>
<p>And, in the interest of making this as easy as possible to get, here is the code. It&#8217;s really a very simple extension &#8211; I&#8217;m not sure why this wasn&#8217;t included in the BCF (but I can guess: this will only work on Windows XP and higher, and only if visual styles are enabled).<br />Note that the downloaded versions have the license text, but I&#8217;ve left it off this page (the license from the downloaded files applies). Why do you care? <a href="http://www.codinghorror.com/blog/archives/000833.html">Let Jeff Atwood tell you.</a></p>
<div class="wlWriterSmartContent" id="scid:C16BAC14-9A3D-4c50-9394-FBFEF7A93539:2e8d23c8-9c84-48bd-85d7-d65507fa38e0" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"><a href="http://www.dotnetkicks.com/kick/?url=http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/" border="0" alt="kick it on DotNetKicks.com" /></a></div>
<p>CueTextbox.cs</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.ComponentModel;
<span class="kwrd">using</span> System.Data;
<span class="kwrd">using</span> System.Drawing;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Windows.Forms;
<span class="kwrd">using</span> System.Runtime.InteropServices;

<span class="kwrd">namespace</span> Lerch.Samples
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> CueTextBox : TextBox
    {
        <span class="preproc">#region</span> PInvoke Helpers

        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> ECM_FIRST = 0x1500;
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> EM_SETCUEBANNER = ECM_FIRST + 1;

        [DllImport(<span class="str">"user32.dll"</span>, CharSet = CharSet.Auto, SetLastError = <span class="kwrd">false</span>)]
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr SendMessage(HandleRef hWnd, <span class="kwrd">uint</span> Msg, IntPtr wParam, String lParam);

        <span class="preproc">#endregion</span> PInvoke Helpers

        <span class="preproc">#region</span> CueText

        <span class="kwrd">private</span> <span class="kwrd">string</span> _cueText = String.Empty;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Gets or sets the text the &lt;see cref="TextBox"/&gt; will display as a cue to the user.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        [Description(<span class="str">"The text value to be displayed as a cue to the user."</span>)]
        [Category(<span class="str">"Appearance"</span>)]
        [DefaultValue(<span class="str">""</span>)]
        [Localizable(<span class="kwrd">true</span>)]
        <span class="kwrd">public</span> <span class="kwrd">string</span> CueText
        {
            get { <span class="kwrd">return</span> _cueText; }
            set
            {
                <span class="kwrd">if</span> (<span class="kwrd">value</span> == <span class="kwrd">null</span>)
                {
                    <span class="kwrd">value</span> = String.Empty;
                }

                <span class="kwrd">if</span> (!_cueText.Equals(<span class="kwrd">value</span>, StringComparison.CurrentCulture))
                {
                    _cueText = <span class="kwrd">value</span>;
                    UpdateCue();
                    OnCueTextChanged(EventArgs.Empty);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Occurs when the &lt;see cref="CueText"/&gt; property value changes.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler CueTextChanged;

        [EditorBrowsable(EditorBrowsableState.Advanced)]
        <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnCueTextChanged(EventArgs e)
        {
            EventHandler handler = CueTextChanged;
            <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)
            {
                handler(<span class="kwrd">this</span>, e);
            }
        }

        <span class="preproc">#endregion</span> CueText

        <span class="preproc">#region</span> ShowCueTextOnFocus

        <span class="kwrd">private</span> <span class="kwrd">bool</span> _showCueTextWithFocus = <span class="kwrd">false</span>;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Gets or sets a value indicating whether the &lt;see cref="TextBox"/&gt; will display the &lt;see cref="CueText"/&gt;</span>
        <span class="rem">/// even when the control has focus.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        [Description(<span class="str">"Indicates whether the CueText will be displayed even when the control has focus."</span>)]
        [Category(<span class="str">"Appearance"</span>)]
        [DefaultValue(<span class="kwrd">false</span>)]
        [Localizable(<span class="kwrd">true</span>)]
        <span class="kwrd">public</span> <span class="kwrd">bool</span> ShowCueTextWithFocus
        {
            get { <span class="kwrd">return</span> _showCueTextWithFocus; }
            set
            {
                <span class="kwrd">if</span> (_showCueTextWithFocus != <span class="kwrd">value</span>)
                {
                    _showCueTextWithFocus = <span class="kwrd">value</span>;
                    UpdateCue();
                    OnShowCueTextWithFocusChanged(EventArgs.Empty);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Occurs when the &lt;see cref="ShowCueTextWithFocus"/&gt; property value changes.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler ShowCueTextWithFocusChanged;

        [EditorBrowsable(EditorBrowsableState.Advanced)]
        <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnShowCueTextWithFocusChanged(EventArgs e)
        {
            EventHandler handler = ShowCueTextWithFocusChanged;
            <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)
            {
                handler(<span class="kwrd">this</span>, e);
            }
        }

        <span class="preproc">#endregion</span> ShowCueTextOnFocus

        <span class="preproc">#region</span> Overrides

        <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnHandleCreated(EventArgs e)
        {
            UpdateCue();

            <span class="kwrd">base</span>.OnHandleCreated(e);
        }

        <span class="preproc">#endregion</span> Overrides

        <span class="kwrd">private</span> <span class="kwrd">void</span> UpdateCue()
        {
            <span class="rem">// If the handle isn't yet created, </span>
            <span class="rem">// this will be called when it is created</span>
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.IsHandleCreated)
            {
                SendMessage(<span class="kwrd">new</span> HandleRef(<span class="kwrd">this</span>, <span class="kwrd">this</span>.Handle), EM_SETCUEBANNER, (_showCueTextWithFocus) ? <span class="kwrd">new</span> IntPtr(1) : IntPtr.Zero, _cueText);
            }
        }
    }
}</pre>
<style type="text/css">.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; }
</style>
<p>CueComboBox.cs</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.ComponentModel;
<span class="kwrd">using</span> System.Data;
<span class="kwrd">using</span> System.Drawing;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Windows.Forms;
<span class="kwrd">using</span> System.Runtime.InteropServices;

<span class="kwrd">namespace</span> Lerch.Samples
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> CueComboBox : ComboBox
    {
        <span class="preproc">#region</span> PInvoke Helpers

        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> CB_SETCUEBANNER = 0x1703;

        [DllImport(<span class="str">"user32.dll"</span>, CharSet = CharSet.Auto, SetLastError = <span class="kwrd">false</span>)]
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr SendMessage(HandleRef hWnd, <span class="kwrd">uint</span> Msg, IntPtr wParam, String lParam);

        <span class="preproc">#endregion</span> PInvoke Helpers

        <span class="preproc">#region</span> CueText

        <span class="kwrd">private</span> <span class="kwrd">string</span> _cueText = String.Empty;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Gets or sets the text the &lt;see cref="ComboBox"/&gt; will display as a cue to the user.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        [Description(<span class="str">"The text value to be displayed as a cue to the user."</span>)]
        [Category(<span class="str">"Appearance"</span>)]
        [DefaultValue(<span class="str">""</span>)]
        [Localizable(<span class="kwrd">true</span>)]
        <span class="kwrd">public</span> <span class="kwrd">string</span> CueText
        {
            get { <span class="kwrd">return</span> _cueText; }
            set
            {
                <span class="kwrd">if</span> (<span class="kwrd">value</span> == <span class="kwrd">null</span>)
                {
                    <span class="kwrd">value</span> = String.Empty;
                }

                <span class="kwrd">if</span> (!_cueText.Equals(<span class="kwrd">value</span>, StringComparison.CurrentCulture))
                {
                    _cueText = <span class="kwrd">value</span>;
                    UpdateCue();
                    OnCueTextChanged(EventArgs.Empty);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Occurs when the &lt;see cref="CueText"/&gt; property value changes.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler CueTextChanged;

        [EditorBrowsable(EditorBrowsableState.Advanced)]
        <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnCueTextChanged(EventArgs e)
        {
            EventHandler handler = CueTextChanged;
            <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)
            {
                handler(<span class="kwrd">this</span>, e);
            }
        }

        <span class="preproc">#endregion</span> CueText

        <span class="preproc">#region</span> Overrides

        <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnHandleCreated(EventArgs e)
        {
            UpdateCue();

            <span class="kwrd">base</span>.OnHandleCreated(e);
        }

        <span class="preproc">#endregion</span> Overrides

        <span class="kwrd">private</span> <span class="kwrd">void</span> UpdateCue()
        {
            <span class="rem">// If the handle isn't yet created, </span>
            <span class="rem">// this will be called when it is created</span>
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.IsHandleCreated)
            {
                SendMessage(<span class="kwrd">new</span> HandleRef(<span class="kwrd">this</span>, <span class="kwrd">this</span>.Handle), CB_SETCUEBANNER, IntPtr.Zero, _cueText);
            }
        }
    }
}</pre>
<style type="text/css">.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; }
</style>
<p>CueToolStripTextBox.cs</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.ComponentModel;
<span class="kwrd">using</span> System.Data;
<span class="kwrd">using</span> System.Drawing;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Windows.Forms;
<span class="kwrd">using</span> System.Runtime.InteropServices;

<span class="kwrd">namespace</span> Lerch.Samples
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> CueToolStripTextBox : ToolStripTextBox
    {
        <span class="kwrd">public</span> CueToolStripTextBox()
            : <span class="kwrd">base</span>()
        {
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.Control != <span class="kwrd">null</span>)
            {
                <span class="kwrd">this</span>.Control.HandleCreated += <span class="kwrd">new</span> EventHandler(OnControlHandleCreated);
            }
        }

        <span class="kwrd">public</span> CueToolStripTextBox(<span class="kwrd">string</span> name)
            : <span class="kwrd">base</span>(name)
        {
            <span class="kwrd">if</span> (<span class="kwrd">this</span>.Control != <span class="kwrd">null</span>)
            {
                <span class="kwrd">this</span>.Control.HandleCreated += <span class="kwrd">new</span> EventHandler(OnControlHandleCreated);
            }
        }

        <span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Dispose(<span class="kwrd">bool</span> disposing)
        {
            <span class="kwrd">if</span> (disposing)
            {
                <span class="kwrd">if</span> (<span class="kwrd">this</span>.Control != <span class="kwrd">null</span>)
                {
                    <span class="kwrd">this</span>.Control.HandleCreated -= <span class="kwrd">new</span> EventHandler(OnControlHandleCreated);
                }
            }

            <span class="kwrd">base</span>.Dispose(disposing);
        }

        <span class="kwrd">void</span> OnControlHandleCreated(<span class="kwrd">object</span> sender, EventArgs e)
        {
            UpdateCue();
        }

        <span class="preproc">#region</span> PInvoke Helpers

        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> ECM_FIRST = 0x1500;
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> EM_SETCUEBANNER = ECM_FIRST + 1;

        [DllImport(<span class="str">"user32.dll"</span>, CharSet = CharSet.Auto, SetLastError = <span class="kwrd">false</span>)]
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr SendMessage(HandleRef hWnd, <span class="kwrd">uint</span> Msg, IntPtr wParam, String lParam);

        <span class="preproc">#endregion</span> PInvoke Helpers

        <span class="preproc">#region</span> CueText

        <span class="kwrd">private</span> <span class="kwrd">string</span> _cueText = String.Empty;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Gets or sets the text the &lt;see cref="TextBox"/&gt; will display as a cue to the user.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        [Description(<span class="str">"The text value to be displayed as a cue to the user."</span>)]
        [Category(<span class="str">"Appearance"</span>)]
        [DefaultValue(<span class="str">""</span>)]
        [Localizable(<span class="kwrd">true</span>)]
        <span class="kwrd">public</span> <span class="kwrd">string</span> CueText
        {
            get { <span class="kwrd">return</span> _cueText; }
            set
            {
                <span class="kwrd">if</span> (<span class="kwrd">value</span> == <span class="kwrd">null</span>)
                {
                    <span class="kwrd">value</span> = String.Empty;
                }

                <span class="kwrd">if</span> (!_cueText.Equals(<span class="kwrd">value</span>, StringComparison.CurrentCulture))
                {
                    _cueText = <span class="kwrd">value</span>;
                    UpdateCue();
                    OnCueTextChanged(EventArgs.Empty);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Occurs when the &lt;see cref="CueText"/&gt; property value changes.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler CueTextChanged;

        [EditorBrowsable(EditorBrowsableState.Advanced)]
        <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnCueTextChanged(EventArgs e)
        {
            EventHandler handler = CueTextChanged;
            <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)
            {
                handler(<span class="kwrd">this</span>, e);
            }
        }

        <span class="preproc">#endregion</span> CueText

        <span class="preproc">#region</span> ShowCueTextOnFocus

        <span class="kwrd">private</span> <span class="kwrd">bool</span> _showCueTextWithFocus = <span class="kwrd">false</span>;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Gets or sets a value indicating whether the &lt;see cref="TextBox"/&gt; will display the &lt;see cref="CueText"/&gt;</span>
        <span class="rem">/// even when the control has focus.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        [Description(<span class="str">"Indicates whether the CueText will be displayed even when the control has focus."</span>)]
        [Category(<span class="str">"Appearance"</span>)]
        [DefaultValue(<span class="kwrd">false</span>)]
        [Localizable(<span class="kwrd">true</span>)]
        <span class="kwrd">public</span> <span class="kwrd">bool</span> ShowCueTextWithFocus
        {
            get { <span class="kwrd">return</span> _showCueTextWithFocus; }
            set
            {
                <span class="kwrd">if</span> (_showCueTextWithFocus != <span class="kwrd">value</span>)
                {
                    _showCueTextWithFocus = <span class="kwrd">value</span>;
                    UpdateCue();
                    OnShowCueTextWithFocusChanged(EventArgs.Empty);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Occurs when the &lt;see cref="ShowCueTextWithFocus"/&gt; property value changes.</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">event</span> EventHandler ShowCueTextWithFocusChanged;

        [EditorBrowsable(EditorBrowsableState.Advanced)]
        <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnShowCueTextWithFocusChanged(EventArgs e)
        {
            EventHandler handler = ShowCueTextWithFocusChanged;
            <span class="kwrd">if</span> (handler != <span class="kwrd">null</span>)
            {
                handler(<span class="kwrd">this</span>, e);
            }
        }

        <span class="preproc">#endregion</span> ShowCueTextOnFocus

        <span class="kwrd">private</span> <span class="kwrd">void</span> UpdateCue()
        {
            <span class="rem">// If the handle isn't yet created, </span>
            <span class="rem">// this will be called when it is created</span>
            <span class="kwrd">if</span> ((<span class="kwrd">this</span>.Control != <span class="kwrd">null</span>) &amp;&amp; (<span class="kwrd">this</span>.Control.IsHandleCreated))
            {
                SendMessage(<span class="kwrd">new</span> HandleRef(<span class="kwrd">this</span>.Control, <span class="kwrd">this</span>.Control.Handle), EM_SETCUEBANNER, (_showCueTextWithFocus) ? <span class="kwrd">new</span> IntPtr(1) : IntPtr.Zero, _cueText);
            }
        }
    }
}</pre>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e2e2dc60-4112-4f74-a361-e496f9980058" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/Windows%20Forms" rel="tag">Windows Forms</a>, <a href="http://technorati.com/tags/UI" rel="tag">UI</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>.NET 2.0 WinForms multithreading and a few long days</title>
		<link>http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/</link>
		<comments>http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/#comments</comments>
		<pubDate>Sat, 19 May 2007 00:37:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/</guid>
		<description><![CDATA[The .NET 2.0 SynchronizationContext class and its prominant children, WindowsFormsSynchronizationContext and AspNetSynchronizationContext (no docs), are used to encapsulate the marshalling of code execution back into an appropriate thread context. In the case of the SynchronizationContext class, it simply posts a job to the ThreadPool because there really isn&#8217;t a specific threading context that requires special [...]]]></description>
			<content:encoded><![CDATA[<p>The .NET 2.0 <a href="http://msdn2.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx">SynchronizationContext</a> class and its prominant children, <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.windowsformssynchronizationcontext.aspx">WindowsFormsSynchronizationContext</a> and AspNetSynchronizationContext (no docs), are used to encapsulate the marshalling of code execution back into an appropriate thread context.  In the case of the SynchronizationContext class, it simply posts a job to the ThreadPool because there really isn&#8217;t a specific threading context that requires special handling.  The WindowsFormsSynchronizationContext contains a reference to the thread it was created on (the UI thread) and the Application&#8217;s MarshalingControl which allow it to do a BeginInvoke onto the control&#8217;s creation thread.  The AspNetSynchronizationContext enables ASP.NET to marshal the callback onto the HttpApplication.ThreadContext which helps provide support for the high-scaling &#8220;<a href="http://msdn.microsoft.com/msdnmag/issues/05/10/WickedCode/">asynchronous pages</a>&#8221; feature.</p>
<p>This stuff is all very cool &#8211; but can also make some bugs seriously hard to find.  Here&#8217;s one I ran across this past week.</p>
<p><a href="http://www.inin.com/">Our</a> <a href="http://community.inin.com/forums/forumdisplay.php?f=74">soon-to-be-public .NET API</a> follows one of the async models recommended by Microsoft, providing two flavors of every synchronous method:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">void</span> Foo();<span class="kwrd">
void</span> FooAsync(AsyncCompletedEventHandler callback, <span class="kwrd">object</span> state);</pre>
<p>Under the covers, we make use of the AsyncOperation and AsyncOperationManager classes found in the System.ComponentModel namespace.  Under one particular circumstance I found that the async operation would complete successfully, but the callback would never get called.  I traced the code to our call to AsyncOperation.PostOperationCompleted, which completed successfully.  Somewhere in frameworkland it just never called the specified callback.  That&#8217;s when I began looking into the AsyncOperation classes and how they interact with the SynchronizationContext (and what the heck the SynchronizationContext even was).  It&#8217;s actually relatively simple. When you construct an AsyncOperation, it keeps a copy of the current SynchronizationContext (which could be &#8220;plain&#8221;, or WindowsForms, or AspNet) and uses the saved copy to post the callback&#8217;s execution onto.  Nothin&#8217; to it, right?</p>
<p>Well, in my case, a background thread was firing an event that caused a lot of these Async calls (don&#8217;t ask <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ), and somewhere in the chain of these many Async calls a subtle bug was causing a Control to be created.  When a control is created, or a message loop started, the current synchronization context will be replaced with a new WindowsFormsSynchronizationContext for the current thread, unless the WindowsFormsSynchronizationContext.AutoInstall static property is set to false (it&#8217;s true by default).  This relies on the fundamental windows rule that all controls must be created on the UI thread.  Everything continued executing successfully, except that the sync context was now referencing a MarshalingControl on the wrong thread (a thread without a message loop) so on all subsequent &#8220;AsyncCompleted&#8221; callbacks, BeginInvoke was being called on the MarshalingControl and would fall into oblivion and never be called.</p>
<p>That itself, aside from my long and boring explanation, wouldn&#8217;t have been so bad (after a little research), except that I couldn&#8217;t find any instance of a control being created!  It ended up that in a relatively recent conversion from the .NET 1.1 ContextMenu to .NET 2.0&#8242;s ContextMenuStrip throughout our applications I hadn&#8217;t taken into account the fact that referencing a ToolStripMenuItem&#8217;s DropDownItems property will create a new DropDown control under the covers automatically if it didn&#8217;t already exist.  Our application&#8217;s &#8220;mini&#8221;-commanding architecture was causing the UI to update itself when new &#8220;actions&#8221; were added, but failed to take into account that actions were being added from a background thread (whoops&#8211;there&#8217;s the root bug).  So a simple call to &#8220;this.DropDownItems.Add(new ToolStripMenuItem(action));&#8221; was creating a control if there were no pre-existing items, and resetting the current SynchronizationContext.  <em>One question I have is why I never saw a System.InvalidOperationException in debug mode like I would&#8217;ve expected for my cross-thread accessing of the DropDownItems property.</em></p>
<p>&lt;sigh&gt;  It&#8217;s times like these that I both feel dumb and feel smart &#8211; dumb because they were rather simple fundamental mistakes, and smart because I learned a lot investigating it.  I was also able to relay some information to the team that they didn&#8217;t know either.</p>
<p>Why do I tell you all this? Let me summarize:</p>
<ul>
<li>ToolStripMenuItem.DropDownItems will create a control if one hasn&#8217;t been created. (And a healthy reminder: only reference methods, properties, and fields of controls on the UI thread!)</li>
<li>An inadvertant change in the current SynchronizationContext (a static thread-specific property) can cause unexpected conditions &#8211; which can be hard to track down because they don&#8217;t appear to &#8220;fail&#8221; explicitly.  And in my case, the buggy code was in no way related to the point where I first saw the problem.</li>
</ul>
<p>Also, if you happen to be so lucky as to be someone writing custom applications using our API, I can assure you that we are <a href="http://www.urbandictionary.com/define.php?term=dogfooding+%28to+dogfood%29">dogfooding</a> it like crazy (unlike our last API), and that does nothing but bring pure benefit to you, the customer. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/05/19/net-20-winforms-multithreading-and-a-few-long-days/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Lock updates for a control</title>
		<link>http://www.aaronlerch.com/blog/2007/02/24/lock-updates-for-a-control/</link>
		<comments>http://www.aaronlerch.com/blog/2007/02/24/lock-updates-for-a-control/#comments</comments>
		<pubDate>Sat, 24 Feb 2007 17:36:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/02/24/lock-updates-for-a-control/</guid>
		<description><![CDATA[Raymond Chen just finished a short series on LockWindowUpdate, including when to use it and when not to. I enjoy reading Raymond&#8217;s blog for a number of reasons. His posts are short, to the point, and well written, and he discusses topics that I, as a .NET developer who is younger (read: showed up after [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blogs.msdn.com/oldnewthing/">Raymond Chen</a> just finished <a href="http://blogs.msdn.com/oldnewthing/archive/2007/02/22/1742084.aspx">a short series on <font face="Courier New">LockWindowUpdate</font></a>, including when to use it and when not to.  I enjoy reading Raymond&#8217;s blog for a number of reasons.  His posts are short, to the point, and well written, and he discusses topics that I, as a .NET developer who is younger (read: showed up after most of the Win32 GUI programming days were long past) am not aware of.  In this case, he had a great impact on me as in a few places I&#8217;ve been very much <em>misusing</em> <font face="Courier New">LockWindowUpdate</font>.  I needed to stop a control from drawing over the course of several operations, to prevent flicker, etc.</p>
<p>After reading his series (which I encourage you to do), I went back and created a class I called <font face="Courier New">ControlRedrawLock</font> which can be used to, well, lock redrawing of a control.</p>
<p>One word of caution, however. I couldn&#8217;t believe something like this hadn&#8217;t been included as a method on <font face="Courier New">Control</font>, so I did some reflectorin&#8217; to look around.  <font face="Courier New">Control.BeginUpdateInternal</font> and <font face="Courier New">Control.EndUpdateInternal</font> do <em>exactly</em> what I was looking for, including ref counting and everything.  But sure enough, as are many useful things, they are marked as <font face="courier new">internal</font>.  On the other hand, I could see that if these were exposed publicly on all controls it could be a potential source of some confusing bugs.  A few select controls do expose this (such as <font face="courier new">ComboBox</font>), probably just where it makes sense.  The word of warning, then, is to be very careful in your use of this class. You might get undesirable results if you combine it&#8217;s usage with parts of controls that internally call <font face="courier new">EndUpdateInternal</font> as my class will re-enable drawing regardless of what&#8217;s going on. That said, enjoy! <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Here&#8217;s how you would use it:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">using</span> (<span class="kwrd">new</span> ControlRedrawLock(<span class="kwrd">this</span>))
{
    <span class="rem">// Do something</span>
}</pre>
<p>And here&#8217;s the code:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">using</span> System;<span class="kwrd">
using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.Text;
<span class="kwrd">using</span> System.Windows.Forms;

<span class="kwrd">namespace</span> Lerch.UI
{
    <span class="kwrd">public</span> <span class="kwrd">class</span> ControlRedrawLock : IDisposable
    {
        [DllImport(<span class="str">"user32.dll"</span>, EntryPoint=<span class="str">"SendMessage"</span>)]
        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">int</span> SendMessage(IntPtr hWnd, <span class="kwrd">uint</span> Msg, <span class="kwrd">int</span> wParam, <span class="kwrd">int</span> lParam);

        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">int</span> WM_SETREDRAW = 0x000B;

        <span class="kwrd">private</span> Control _control;
        <span class="kwrd">private</span> <span class="kwrd">bool</span> _invalidate;
        <span class="kwrd">private</span> <span class="kwrd">bool</span> _disabledRedraw = <span class="kwrd">false</span>;

        <span class="kwrd">public</span> ControlRedrawLock(Control control) : <span class="kwrd">this</span>(control, <span class="kwrd">true</span>)
        {
        }

        <span class="kwrd">public</span> ControlRedrawLock(Control control, <span class="kwrd">bool</span> invalidate)
        {
            <span class="kwrd">try</span>
            {
                _control = control;
                _invalidate = invalidate;

                <span class="kwrd">if</span> (IsValidControl())
                {
                    <span class="rem">// Lock drawing</span>
                    SendMessage(_control.Handle, WM_SETREDRAW, 0, 0);
                    _disabledRedraw = <span class="kwrd">true</span>;
                }
            }
            <span class="kwrd">catch</span>
            { }
        }

        <span class="kwrd">private</span> <span class="kwrd">bool</span> IsValidControl()
        {
            <span class="kwrd">return</span> ((_control != <span class="kwrd">null</span>) &amp;&amp; (_control.IsHandleCreated));
        }

        <span class="preproc">#region</span> IDisposable Members

        <span class="kwrd">public</span> <span class="kwrd">void</span> Dispose()
        {
            <span class="kwrd">try</span>
            {
                <span class="kwrd">if</span> (IsValidControl() &amp;&amp; _disabledRedraw)
                {
                    <span class="rem">// Unlock drawing</span>
                    SendMessage(_control.Handle, WM_SETREDRAW, 1, 0);
                    <span class="kwrd">if</span> (_invalidate)
                    {
                        <span class="rem">// Invalidate the control to trigger a re-paint.
</span>                        _control.Invalidate(<span class="kwrd">true</span>);
                    }
                }
            }
            <span class="kwrd">catch
</span>            { }
        }

        <span class="preproc">#endregion</span>
    }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/02/24/lock-updates-for-a-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Control.Trifecta: InvokeRequired, IsHandleCreated, and IsDisposed</title>
		<link>http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/</link>
		<comments>http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/#comments</comments>
		<pubDate>Fri, 15 Dec 2006 01:10:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/</guid>
		<description><![CDATA[Talking about Control.InvokeRequired seems like something so old, yet as I do a Google blog search for InvokeRequired I see only partial explanations and haphazard examples. I guess that&#8217;s what happens in &#8220;sample code world&#8221;, but the problem is that too many developers live in that world. (I know I&#8217;ve lived there before, and sometimes [...]]]></description>
			<content:encoded><![CDATA[<p>Talking about Control.InvokeRequired seems like something so old, yet as I do a Google blog search for <a href="http://blogsearch.google.com/blogsearch?hl=en&amp;ie=UTF-8&amp;q=invokerequired&amp;btnG=Search+Blogs" title="Google: InvokeRequired">InvokeRequired</a> I see only partial explanations and haphazard examples. I guess that&#8217;s what happens in &#8220;sample code world&#8221;, but the problem is that too many developers <u>live</u> in that world.  (I know I&#8217;ve lived there before, and sometimes I still visit.)  Just read <a href="http://thedailywtf.com/">The Daily WTF</a> for some great examples, and before you ask&#8211;no, none of them are me.  That I know of.</p>
<p>If you don&#8217;t know what InvokeRequired is, or why you want to use it, you should definitely read the <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx">MSDN docs</a> to get up to speed.  In fact, much of what I want to say is available on that page.  It&#8217;s also accompanied by a fairly simple-but-complete <a href="http://msdn2.microsoft.com/en-us/library/3s8xdz5c.aspx">multithreading WinForms example</a>.</p>
<p>Most examples show something like this:</p>
<p class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:14bc2430-2c83-4bd4-9e8b-872e86a6cc4f" contenteditable="false" style="margin: 0px; padding: 0px; display: inline; float: none; width: 400px">&nbsp;</p>
<pre style="background-color: White"><span style="color: #008080">1</span> <span style="color: #0000ff">private</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> UpdateTheUI()</span><span style="color: #008080">
2</span> <span style="color: #000000">{</span><span style="color: #008080">
3</span> <span style="color: #000000">    </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #0000ff">this</span><span style="color: #000000">.InvokeRequired)</span><span style="color: #008080">
4</span> <span style="color: #000000">    {</span><span style="color: #008080">
5</span> <span style="color: #000000">        </span><span style="color: #0000ff">this</span><span style="color: #000000">.BeginInvoke(</span><span style="color: #0000ff">new</span><span style="color: #000000"> MethodInvoker(UpdateTheUI));</span><span style="color: #008080">
6</span> <span style="color: #000000">    }</span><span style="color: #008080">
7</span> <span style="color: #000000">    </span><span style="color: #0000ff">else</span><span style="color: #000000"></span><span style="color: #008080">
8</span> <span style="color: #000000">    {</span><span style="color: #008080">
9</span> <span style="color: #000000">        </span><span style="color: #008000">//</span><span style="color: #008000"> Update the control, etc.
</span><span style="color: #008000"></span><span style="color: #008080">10</span> <span style="color: #008000"></span><span style="color: #000000">    }
</span><span style="color: #008080">11</span> <span style="color: #000000">}</span></pre>
<p>That&#8217;s all fine and good, but there are a few scenarios that can affect this code.  Some of them can be mitigated by your design.  For example, did you know that Control.InvokeRequired can return false even when you&#8217;re calling it from a different thread?  Yep, it&#8217;s true!  From the lips of <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx">MSDN</a>:</p>
<blockquote><p>This means that <strong>InvokeRequired</strong> can return <strong>false</strong> if <strong>Invoke</strong> is not required (the call occurs on the same thread), or if the control was created on a different thread but the control&#8217;s handle has not yet been created.</p></blockquote>
<p>A common scenario where this might occur is if a background process is started from the control&#8217;s constructor (typically considered a no-no, but sometimes it might be necessary). If the background work completes quicker than expected you could be trying to update a UI that hasn&#8217;t even been shown yet.  The solution in this case is to check the IsHandleCreated property if InvokeRequired is false, and defer the update until the control&#8217;s handle has been created.  (Save yourself some time: don&#8217;t check the Handle property for null or IntPtr.Zero&#8211;referencing the property at all will create a handle on the spot&#8211;and likely on the wrong thread, too.)</p>
<p>There&#8217;s one more gotcha I want to mention.  After background processing has elapsed, it&#8217;s entirely possible your control has since been disposed.  <em>It&#8217;s always important to check IsDisposed before updating your UI.</em>  A common problem we ran into at work (one which I took part in) was that we threw in a check for IsDisposed at the top of the method and return if it was true, like this:</p>
<p class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:57b15554-20ef-43fe-bd27-605e7954755f" contenteditable="false" style="margin: 0px; padding: 0px; display: inline; float: none; width: 537px">&nbsp;</p>
<pre style="background-color: White"><span style="color: #008080">1</span> <span style="color: #0000ff">private</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> UpdateTheUI()</span><span style="color: #008080">
2</span> <span style="color: #000000">{</span><span style="color: #008080">
3</span> <span style="color: #000000">    </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #0000ff">this</span><span style="color: #000000">.IsDisposed) </span><span style="color: #0000ff">return</span><span style="color: #000000">;</span><span style="color: #008080">
4</span> <span style="color: #000000"></span><span style="color: #008080">
5</span> <span style="color: #000000">    </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #0000ff">this</span><span style="color: #000000">.InvokeRequired)</span><span style="color: #008080">
6</span> <span style="color: #000000">    {</span><span style="color: #008080">
7</span> <span style="color: #000000">        </span><span style="color: #0000ff">this</span><span style="color: #000000">.BeginInvoke(</span><span style="color: #0000ff">new</span><span style="color: #000000"> MethodInvoker(UpdateTheUI));</span><span style="color: #008080">
8</span> <span style="color: #000000">    }</span><span style="color: #008080">
9</span> <span style="color: #000000">    </span><span style="color: #0000ff">else</span><span style="color: #000000"></span><span style="color: #008080">
10</span> <span style="color: #000000">    {
</span><span style="color: #008080">11</span> <span style="color: #000000">        </span><span style="color: #008000">//</span><span style="color: #008000"> Update the control, etc.
</span><span style="color: #008000"></span><span style="color: #008080">12</span> <span style="color: #008000"></span><span style="color: #000000">    }
</span><span style="color: #008080">13</span> <span style="color: #000000">}</span></pre>
<p>Unfortunately we forgot that besides the InvokeRequired property the only thread-safe methods on the Control class are:  Invoke, BeginInvoke, EndInvoke, and CreateGraphics (all assuming the handle has been created, of course).  Notice that IsDisposed isn&#8217;t in that list?</p>
<p>Here&#8217;s an example that (to my current knowledge) addresses all of these potential issues, at least in one way or another.  At this point you can call UpdateTheUI from almost any context and it won&#8217;t bomb.  That&#8217;s not a promise that it will do exactly what you hope it will do (i.e. update the UI) but that&#8217;s where your control&#8217;s design comes in.</p>
<p class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:7094e6ba-1466-4fab-b272-934d3dc03c06" contenteditable="false" style="margin: 0px; padding: 0px; display: inline; float: none; width: 549px">&nbsp;</p>
<pre style="background-color: White"><span style="color: #008080">1</span> <span style="color: #0000ff">private</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> UpdateTheUI()</span><span style="color: #008080">
2</span> <span style="color: #000000">{</span><span style="color: #008080">
3</span> <span style="color: #000000">    </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #0000ff">this</span><span style="color: #000000">.InvokeRequired)</span><span style="color: #008080">
4</span> <span style="color: #000000">    {</span><span style="color: #008080">
5</span> <span style="color: #000000">        </span><span style="color: #0000ff">this</span><span style="color: #000000">.BeginInvoke(</span><span style="color: #0000ff">new</span><span style="color: #000000"> MethodInvoker(UpdateTheUI));</span><span style="color: #008080">
6</span> <span style="color: #000000">    }</span><span style="color: #008080">
7</span> <span style="color: #000000">    </span><span style="color: #0000ff">else</span><span style="color: #000000"></span><span style="color: #008080">
8</span> <span style="color: #000000">    {</span><span style="color: #008080">
9</span> <span style="color: #000000">        </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #0000ff">this</span><span style="color: #000000">.IsDisposed) </span><span style="color: #0000ff">return</span><span style="color: #000000">;</span><span style="color: #008080">
10</span> <span style="color: #000000"></span><span style="color: #008080">
11</span> <span style="color: #000000">        </span><span style="color: #0000ff">if</span><span style="color: #000000"> (</span><span style="color: #000000">!</span><span style="color: #0000ff">this</span><span style="color: #000000">.IsHandleCreated)</span><span style="color: #008080">
12</span> <span style="color: #000000">        {
</span><span style="color: #008080">13</span> <span style="color: #000000">            </span><span style="color: #008000">//</span><span style="color: #008000"> Background processing completed before the
</span><span style="color: #008080">14</span> <span style="color: #008000">            </span><span style="color: #008000">//</span><span style="color: #008000"> control's handle has been created. Do whatever it takes</span><span style="color: #008080">
15</span> <span style="color: #008000">            </span><span style="color: #008000">//</span><span style="color: #008000"> to indicate that a deferred update must occur (after the handle has
</span><span style="color: #008080">16</span> <span style="color: #008000">            </span><span style="color: #008000">//</span><span style="color: #008000"> been created).</span><span style="color: #008000"></span><span style="color: #008080">
17</span> <span style="color: #008000"></span><span style="color: #000000"></span><span style="color: #008080">
18</span> <span style="color: #000000">            _deferUIUpdate </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">true</span><span style="color: #000000">;
</span><span style="color: #008080">19</span> <span style="color: #000000">            </span><span style="color: #0000ff">return</span><span style="color: #000000">;
</span><span style="color: #008080">20</span> <span style="color: #000000">        }</span><span style="color: #008080">
21</span> <span style="color: #000000"></span><span style="color: #008080">
22</span> <span style="color: #000000">        </span><span style="color: #008000">//</span><span style="color: #008000"> Update the control, etc.
</span><span style="color: #008000"></span><span style="color: #008080">23</span> <span style="color: #008000"></span><span style="color: #000000">    }
</span><span style="color: #008080">24</span> <span style="color: #000000">}</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2006/12/15/controltrifecta-invokerequired-ishandlecreated-and-isdisposed/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Start small and work up</title>
		<link>http://www.aaronlerch.com/blog/2006/09/28/start-small-and-work-up/</link>
		<comments>http://www.aaronlerch.com/blog/2006/09/28/start-small-and-work-up/#comments</comments>
		<pubDate>Thu, 28 Sep 2006 00:20:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2006/09/28/start-small-and-work-up/</guid>
		<description><![CDATA[I re-learned an important lesson tonight: start small and work up from there. I was working on creating a Form that intercepts the WM_MOUSEACTIVATE message to prevent a click from stealing focus from another form (i.e. a menu, or a drop down list). In my experimentation I had a “grand” idea to create a class [...]]]></description>
			<content:encoded><![CDATA[<p>I re-learned an important lesson tonight: start small and work up from there.</p>
<p>I was working on creating a Form that intercepts the <font face="courier new">WM_MOUSEACTIVATE</font> message to prevent a click from stealing focus from another form (i.e. a menu, or a drop down list).  In my experimentation I had a “grand” idea to create a class that implements <font face="courier new"><a href="’s">IMessageFilter</a></font> which would keep a map of the Handle of a form and all its controls (and their controls, etc.) and intercept all <font face="courier new"><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/mouseinput/mouseinputreference/mouseinputmessages/wm_mouseactivate.asp">WM_MOUSEACTIVATE</a></font> messages for the “registered” controls. (Keep in mind I was experimenting, and the intended use of this is a small form that doesn’t have a huge control tree to track.)</p>
<p>I wrote probably about 100 lines of code (fortunately my lesson was learned on a small scale first!) to handle the registering of controls, the watching of controls added to Controls collections, the cleaning up on disposal, and so on.  Finally my masterpiece was complete, I ran it, and … nothing happened. Huh? Debugging showed that the message filter was active and kicking, my controls were registered, but I was never receiving the <font face="courier new">WM_MOUSEACTIVATE</font> message (as I did when I overrode <font face="courier new">WndProc</font>).  A bit of Google searching turned up the answer (below).</p>
<p>So I guess I learned two lessons:</p>
<ol>
<li>Start small and work up from there, and</li>
<li><font face="Courier New">An IMessageFilter</font> only processes windows messages that are posted (PostMessage) and not sent (SendMessage)—and <font face="courier new">WM_MOUSEACTIVATE</font> is sent. Had I tried to intercept this message via the filter <em>before</em> I created all the supporting code, I could’ve saved myself some time.</li>
</ol>
<p>Live and learn! (And pass it on!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2006/09/28/start-small-and-work-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hawkeye</title>
		<link>http://www.aaronlerch.com/blog/2006/08/31/hawkeye/</link>
		<comments>http://www.aaronlerch.com/blog/2006/08/31/hawkeye/#comments</comments>
		<pubDate>Thu, 31 Aug 2006 12:24:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[tools]]></category>
		<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2006/08/31/hawkeye/</guid>
		<description><![CDATA[I just installed Hawkeye, and I&#8217;m pretty impressed! What is Hawkeye? From the website: &#8220;Hawkeye is the only .Net tool that allows you to view, edit, analyze and invoke (almost) any object from a .Net application. Whenever you try to debug, test, change or understand an application, Hawkeye can help.&#8221; I haven&#8217;t put it through [...]]]></description>
			<content:encoded><![CDATA[<p>I just installed <a href="http://acorns.com.au/hawkeye/">Hawkeye</a>, and I&#8217;m pretty impressed!</p>
<p>What is Hawkeye? From the website:</p>
<blockquote><p>&#8220;Hawkeye is the only .Net tool that allows you to view, edit, analyze and invoke (almost) any object from a .Net application. Whenever you try to debug, test, change or understand an application, Hawkeye can help.&#8221;</p></blockquote>
<p>I haven&#8217;t put it through any sort of paces yet, but I was blown away that I was able to attach to my .NET Outlook add-in and change properties in real-time.  I think this will quickly become a valued debugging tool.  Download it and give it a whirl!</p>
<p>(via <a href="http://www.larkware.com/dg6/TheDailyGrind960.aspx">Mike Gunderloy&#8217;s Daily Grind</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2006/08/31/hawkeye/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Metadata Attributes for Custom Controls</title>
		<link>http://www.aaronlerch.com/blog/2006/04/06/metadata-attributes-for-custom-controls/</link>
		<comments>http://www.aaronlerch.com/blog/2006/04/06/metadata-attributes-for-custom-controls/#comments</comments>
		<pubDate>Thu, 06 Apr 2006 10:16:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2006/04/06/metadata-attributes-for-custom-controls/</guid>
		<description><![CDATA[This link (here) may not be exhaustive (but it might be), but it offers a useful list of attributes that can be applied to custom controls to support better design-time interaction. I find it useful to be able to right-click a property in the designer and select &#8220;Reset&#8221; to return it to the control&#8217;s default [...]]]></description>
			<content:encoded><![CDATA[<p>This link (<a href="http://msdn2.microsoft.com/en-US/library/ms178658(VS.80).aspx">here</a>) may not be exhaustive (but it might be), but it offers a useful list of attributes that can be applied to custom controls to support better design-time interaction.</p>
<p>I find it useful to be able to right-click a property in the designer and select &#8220;Reset&#8221; to return it to the control&#8217;s default value.  Much more important is the ability to automatically tag a property as localizable so without any other code it&#8217;s value will be initialized from the resource file.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2006/04/06/metadata-attributes-for-custom-controls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Embedding Flash in C#</title>
		<link>http://www.aaronlerch.com/blog/2006/03/31/embedding-flash-in-c/</link>
		<comments>http://www.aaronlerch.com/blog/2006/03/31/embedding-flash-in-c/#comments</comments>
		<pubDate>Fri, 31 Mar 2006 12:33:00 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[ui]]></category>
		<category><![CDATA[visualization]]></category>
		<category><![CDATA[windows forms]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2006/03/31/embedding-flash-in-c/</guid>
		<description><![CDATA[This is something I think you&#8217;d want to avoid like the plague, but it might have it&#8217;s benefits (as in the article&#8211;cheap charting). Here&#8217;s the article]]></description>
			<content:encoded><![CDATA[<p>This is something I think you&#8217;d want to avoid like the plague, but it might have it&#8217;s benefits (as in the article&#8211;cheap charting).</p>
<p><a href="http://www.macromedia.com/devnet/flash/articles/stock_history.html">Here&#8217;s the article</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2006/03/31/embedding-flash-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
