<?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; programming</title>
	<atom:link href="http://www.aaronlerch.com/blog/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.aaronlerch.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 10 Mar 2010 12:45:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Design Pattern Resources</title>
		<link>http://www.aaronlerch.com/blog/2009/04/02/design-pattern-resources/</link>
		<comments>http://www.aaronlerch.com/blog/2009/04/02/design-pattern-resources/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 00:51:10 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2009/04/02/design-pattern-resources/</guid>
		<description><![CDATA[I’ve had a few people ask me for a recommendation of some resources to learn design patterns. There’s a lot of good stuff “out there”, of course, but my response usually says just three things:
Read pretty much anything this guy writes,    Learn SOLID, and lern it güd. I recommend starting here.  [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve had a few people ask me for a recommendation of some resources to learn design patterns. There’s a lot of good stuff “out there”, of course, but my response usually says just three things:</p>
<p><a href="http://codebetter.com/blogs/jeremy.miller/"><strong>Read pretty much anything this guy writes</strong></a>,    <br /><strong>Learn </strong><a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"><strong>SOLID</strong></a><strong>, and lern it güd. </strong><a href="http://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx"><strong>I recommend starting here.</strong></a>    <br /><em>and</em>    <br /><strong>Let me know if you have any questions and let’s chat.</strong></p>
<p>If you’re anything like me, you’ll find yourself up until 4 AM reading, reading, and reading as you link from post to post and article to article. I swear one of these days I will find <a href="http://www.shibumi.org/eoti.htm">the end of the internet</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2009/04/02/design-pattern-resources/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Are Twitter Clients the new Hello World app?</title>
		<link>http://www.aaronlerch.com/blog/2008/03/13/are-twitter-clients-the-new-hello-world-app/</link>
		<comments>http://www.aaronlerch.com/blog/2008/03/13/are-twitter-clients-the-new-hello-world-app/#comments</comments>
		<pubDate>Thu, 13 Mar 2008 15:48:35 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[misc]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/03/13/are-twitter-clients-the-new-hello-world-app/</guid>
		<description><![CDATA[There&#8217;s been a bit of talk on Twitter recently about the various twitter clients that exist, with more being created practically every day. One view was that everybody is trying to create the ultimate twitter client.

Maybe.
Certainly there are a lot of new twitter client apps being made, some with lofty aspirations, but more importantly I [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a bit of talk on <a href="http://twitter.com/">Twitter</a> recently about the various twitter clients that exist, with more being created practically every day. <a href="http://twitter.com/shanselman/statuses/770579191">One view</a> was that everybody is trying to create the ultimate twitter client.</p>
<p><img src="http://s3.amazonaws.com:80/aaronlerch.com/images/hanselman-tweet-twitter-client.png" /></p>
<p>Maybe.</p>
<p>Certainly there are a lot of new twitter client apps being made, some with lofty aspirations, but more importantly I see a twitter client as the new &quot;<a href="http://en.wikipedia.org/wiki/Hello_world_program">Hello World</a>&quot; for desktop applications. And I think it&#8217;s a great choice. The days of a Hello World application consisting of a Console.WriteLine are long past. To dig in and learn something new, you have to implement something with at least a little substance to it.</p>
<p>A twitter client has the key components one needs when learning a new technology:</p>
<p><strong>Simple</strong></p>
<p>In terms of base functionality, a twitter client has a very simple task. Heck, Twitter itself is built around the simple premise of asking &quot;What are you doing right now?&quot; and letting you answer. A twitter client, at it&#8217;s core, needs to do two things: display your timeline and let you update your &quot;status&quot;. Simple as that.</p>
<p><strong>Easy and intuitive API</strong></p>
<p>Twitter&#8217;s <a href="http://groups.google.com/group/twitter-development-talk/web/api-documentation">API</a> is easy. Really easy. When you&#8217;re writing a real-world Hello World application, you want to focus on what you&#8217;re trying to learn, which is the technology, and not a complex API or other things that simply distract.</p>
<p><strong>Options</strong></p>
<p>Like most applications that have a user interface (and even those that don&#8217;t), there&#8217;s always room for choices. Depending on what you&#8217;re trying to learn (I&#8217;m a UI guy) you have different approaches you can take. If you&#8217;re learning WinForms or WPF, you can play with different presentation models, learning how to accomplish what you want. If you&#8217;re learning deeper back-end programming, you could play with the windows services APIs, or WCF, or whatever. It&#8217;s flexible.</p>
<p><strong>Room for expansion</strong></p>
<p>A twitter client can move beyond the basics I mentioned above and incorporate more features, with the limit practically being your imagination. Just look at <a href="http://twittervision.com/">twittervision</a>.</p>
<p><a href="http://s3.amazonaws.com:80/aaronlerch.com/images/bitter-gray.png"><img height="134" alt="Bitter" src="http://s3.amazonaws.com:80/aaronlerch.com/images/bitter-gray.png" width="72" align="right" /></a>My friend <a href="http://ilikeellipses.com/">Mike</a> has been diving head first into .NET (he&#8217;s an MFC guru), and decided to create a great twitter client (<a href="http://mikehallsite.com/bitter/">Bitter</a>) not to create the ultimate one, but to learn the technology. Which is good, because an ultimate twitter client has already been created. It&#8217;s called <a href="http://iconfactory.com/software/twitterrific">Twitterific</a>. <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/2008/03/13/are-twitter-clients-the-new-hello-world-app/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Confessions of a Software Developer*</title>
		<link>http://www.aaronlerch.com/blog/2008/01/30/confessions-of-a-software-developer/</link>
		<comments>http://www.aaronlerch.com/blog/2008/01/30/confessions-of-a-software-developer/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 15:00:18 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/01/30/confessions-of-a-software-developer/</guid>
		<description><![CDATA[ I&#8217;m ready to confess. It&#8217;s time to lay it all on the table. Ready?
I can&#8217;t keep up!
Wow, that was liberating! I think I should start a taxi service for developers.
There is so much going on in the world of software, how can I keep up with it all, while still making progress in my [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/mdumlao98/976279763/"><img src="http://aaronlerch.com.s3.amazonaws.com/images/tech-taxi.jpg" align="right" /></a> I&#8217;m ready to confess. It&#8217;s time to lay it all on the table. Ready?</p>
<p><strong><font size="4">I can&#8217;t keep up!</font></strong></p>
<p>Wow, that was liberating! I think I should start a <a href="http://www.hbo.com/docs/programs/taxicab10/">taxi service for developers</a>.</p>
<p>There is so much going on in the world of software, how can I keep up with it all, while still making progress in my job? I can&#8217;t shift with the winds of what&#8217;s new or popular&#8211;even if it makes sense&#8211;they just shift too fast, it seems, and there&#8217;s no way I can be productive at work <em>and</em> keep up with all the new stuff. Goodness knows I try.</p>
<p>Here&#8217;s a list of things/buzzwords I really want to learn or use but haven&#8217;t had the time, or more importantly, haven&#8217;t had a real project that I could <em>practice</em> on. Growing in your software development abilities and experience relies on <a href="http://www.codinghorror.com/blog/archives/000446.html">mentoring and apprenticing</a>, after all. I wholeheartedly believe that. That&#8217;s why I work to surround myself with <a href="http://ilikeellipses.com/">incredible</a> <a href="http://www.moserware.com/">people</a>.</p>
<p><strong>1. TDD &#8211; <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test Driven Development</a></strong>     <br />For a while now I&#8217;ve been at the point where I see the great benefits to TDD, and would love to do it, I just don&#8217;t know where to start. I need to really <em>learn</em> it. And by learn, I mean &quot;be mentored&quot;. I can read about it, but implementing it on a project takes it to a &#8216;<a href="http://en.wikipedia.org/wiki/MADtv_(season_12)">hole nutha level</a>&#8216;. And if I don&#8217;t know what I&#8217;m doing, I can&#8217;t implement it on a real project at work.</p>
<p><strong>2. DDD &#8211; <a href="http://domaindrivendesign.org/">Domain Driven Design</a></strong>     <br />This is a tough one, as it&#8217;s not really a technology or methodology, but more of a way of thinking. Which always makes me wonder: am I thinking this way? Should I be, if I&#8217;m not? How can I apply this way of thinking to my projects, considering that in many cases I&#8217;m adding features to existing products that haven&#8217;t necessarily been designed this way?</p>
<p><strong>3. BDD &#8211; <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">Behavior Driven Development</a></strong>     <br />No comment. I think I just need one or two more xDD acronyms to investigate.</p>
<p><strong>4. DI/IoC &#8211; <a href="http://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a>/<a href="http://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a></strong>     <br />This feels pretty basic, and I understand the concepts and at least grok the list of <a href="http://en.wikipedia.org/wiki/Dependency_injection">available frameworks</a>. But in my experience it&#8217;s an architectural decision that if you don&#8217;t make from the start of an enterprise project, well, good luck getting it in later without a significant effort. And doing this right plus learning one of the existing frameworks takes a large investment that frequently I don&#8217;t have. At the moment we&#8217;ve chosen to use <a href="http://msdn2.microsoft.com/en-us/library/aa480450.aspx">CAB</a> (and related technologies) at work for our new projects, and I&#8217;m on the learning curve for it right now. I wish I was more well-rounded.</p>
<p><strong>5. ORM &#8211; <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">Object Relational Mapping</a></strong>     <br />Basic stuff, right? Not for me. I work on a real-time system, not so much a database driven one, although I have done a lot of database-related work in the past. ORM doesn&#8217;t apply to me as much right now, but if you work on anything but a real-time system you&#8217;re probably using one. I&#8217;ve been learning <a href="http://www.hibernate.org/343.html">NHibernate</a> lately with <a href="http://code.google.com/p/codecampserver/">CodeCampServer</a>, and it&#8217;s definitely a stretch for me. I think the real problem is combining the ORM with DDD. ASAP, PDQ. FYI.</p>
<p><strong>6. AOP &#8211; <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">Aspect Oriented Programming</a></strong>     <br />Another &quot;nice to learn&quot; idea, but I have trouble making time to learn it, not to mention how to apply it.</p>
<p><strong>7. A bunch of stuff from </strong><a href="http://msmvps.com/blogs/kathleen/archive/2007/11/13/why-your-development-is-crazy.aspx"><strong>this list</strong></a><strong> (though not nearly everything)</strong>     <br />Stuff like refactoring (specifically how to apply it successfully to large projects), proper and structured integration of LINQ and dynamic languages (if at all), what I&#8217;ll call &quot;reasonable agile&quot; &#8212; non-extreme agile practices, visual modeling/model-driven design, evolving architectures, etc.</p>
<p>You might notice that some of these things on my list aren&#8217;t exactly new or groundbreaking. This <em>is</em> a confession, after all. Would it be confessing to say that I don&#8217;t know much about <a href="http://blogs.msdn.com/pablo/archive/2007/04/30/codename-astoria-data-services-for-the-web.aspx">Astoria</a>? Nah, most people don&#8217;t. So&#8230; does anybody else struggle to learn and incorporate stuff like this? What about those who don&#8217;t? Got any suggestions for me, and people like me? What are some good sources that a random developer on the Internet can find for being mentored in practices like TDD?</p>
<p><strong>* Disclaimer:</strong> I have to limit the term &quot;software developer&quot; to what I am: a non-consultant, full-time developer leading a team of 8 (within a dev organization of 130+) working on a mature and complex product with a release cycle of 12-18 months, and handling escalated support cases&#8211;you can&#8217;t <em>not</em> mention support! Oh, and I have a <a href="http://picasaweb.google.com/aaronlerch">family</a> and a life. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://www.aaronlerch.com/blog/2008/01/30/confessions-of-a-software-developer/"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.aaronlerch.com/blog/2008/01/30/confessions-of-a-software-developer/" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/01/30/confessions-of-a-software-developer/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Refactoring C# with PowerShell</title>
		<link>http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/</link>
		<comments>http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/#comments</comments>
		<pubDate>Fri, 04 Jan 2008 18:06:07 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[.net]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/</guid>
		<description><![CDATA[Visual Studio 2005 and 2008 have built-in support for refactoring code, including renaming namespaces, classes, variables, and more. Add-ins like Resharper also have support for refactoring by renaming. These tools work great, and have good integration into the Visual Studio IDE, for example being able to preview each change and exclude false positive matches. I [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.aaronlerch.com/files/blog/RefactoringCwithPowerShell_E201/image.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="240" alt="image" src="http://aaronlerch.com.s3.amazonaws.com/images/refactoring_with_powershell_screenshot_thumb.png" width="222" align="right" border="0" /></a>Visual Studio 2005 and 2008 have built-in <a href="http://msdn2.microsoft.com/en-us/library/ms379618(VS.80).aspx#vs05_refac_topic8">support for refactoring code</a>, including renaming namespaces, classes, variables, and more. Add-ins like <a href="http://www.jetbrains.com/resharper/">Resharper</a> also have support for <a href="http://www.jetbrains.com/resharper/features/code_refactoring.html#Rename_Symbol_full">refactoring by renaming</a>. These tools work great, and have good integration into the Visual Studio IDE, for example being able to preview each change and exclude false positive matches. I know many people swear by Resharper in particular (for more features than the refactoring alone).</p>
<p>Unfortunately all of these tools are restricted in one normally insignificant way: they only operate on the currently loaded project(s). For most software this really is insignificant. The entire application can be loaded into the IDE all at once. Sometimes, though, it is a problem&#8211;usually when there&#8217;s another problem at play: <a href="http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html">code &quot;bloat&quot;</a> (<a href="http://www.moserware.com/2007/12/how-legacy-of-dead-mathematician-can.html">via Jeff</a>).</p>
<p>If you&#8217;ve ever changed a namespace and wanted to simply push the change into every code file in an entire directory branch, PowerShell comes to our rescue with it&#8217;s search-and-replace capabilities. I wrote the following &quot;Move-Namespace&quot; function to do just that.</p>
<p>Invoke the function like so: &quot;Move-Namespace *.cs &quot;[current namespace]&quot; &quot;[current class name]&quot; &quot;[new namespace]&quot;.</p>
<p>After it completes, any explicit reference will be changed, and any implicit references (using traditional &quot;using [namespace];&quot; statements) will have a new &quot;using [new namespace];&quot; line inserted after the last existing using statement.</p>
<p>Let&#8217;s hope you don&#8217;t have a code base that requires this function. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  But if you do, I hope it helps!</p>
<p><em>Note that this function relies on my &quot;Replace-String&quot; function, </em><a href="http://www.aaronlerch.com/blog/2007/03/28/powershell-replace-string-function/"><em>found here</em></a><em>.</em></p>
<pre class="csharpcode"><span class="kwrd">function</span> Move-Namespace(
    $includes = $(<span class="kwrd">throw</span> <span class="str">'Specify a file filter to use'</span>),
    $oldNamespace = $(<span class="kwrd">throw</span> <span class="str">'The namespace to replace - i.e. MyCompany.Product'</span>),
    $className = $(<span class="kwrd">throw</span> <span class="str">'The class name to search for - i.e. MyClass'</span>),
    $newNamespace = $(<span class="kwrd">throw</span> <span class="str">'The new namespace to add - i.e. MyCompany.Product.Feature'</span>))
{
    <span class="rem"># Look for cases of $className</span>
    <span class="rem"># or $oldNamespace.$className</span>
    <span class="rem"># and replace as necessary</span>

    <span class="rem"># First check for assumed &quot;using&quot; statements, and add the using statement</span>
    $results = @{}
    $files = get-childitem -r -i $includes | select-string <span class="str">&quot;(?&lt;!$oldNamespace\.)\b$className\b&quot;</span> -list |% { $_.Path }
    select-string <span class="str">&quot;^using.*;&quot;</span> -path $files | group-object Path | select-object Name, @{Expression={ ($_.Group | measure-object -property LineNumber -max).Maximum }; Name=<span class="str">&quot;LastUsingStatement&quot;</span> } |% { $results[$_.Name] = $_.LastUsingStatement }
    <span class="kwrd">foreach</span> ($key <span class="kwrd">in</span> $results.keys)
    {
      $processFile = $true
      $lastUsingIndex = $results[$key]
      $fileContents = get-content $key
      <span class="rem"># look for existing using statement and cancel processing this file</span>
      <span class="kwrd">for</span> ($i = 0; $i <span class="preproc">-lt</span> $lastUsingIndex; $i++)
      {
        <span class="kwrd">if</span> ($fileContents[$i] <span class="preproc">-match</span> <span class="str">&quot;using $newNamespace;&quot;</span>)
        {
          <span class="rem"># this file already has the correct using statement, stop processing</span>
          Write-Warning <span class="str">&quot;File $key already has the required using statement, ignoring&quot;</span>
          $processFile = $false
          <span class="kwrd">break</span>;
        }
      }

      <span class="kwrd">if</span> ($processFile)
      {
        $newContents = $fileContents[0..($lastUsingIndex-1)] + <span class="str">&quot;using $newNamespace;&quot;</span> + $fileContents[$lastUsingIndex..$fileContents.Length]
        set-content -path $key -value $newContents
        Write-Host <span class="str">&quot;Successfully updated file $key&quot;</span> -foregroundcolor Green
      }
    }

    <span class="rem"># Next check for explicit references</span>
    replace-string <span class="str">&quot;\b$oldNamespace\.$className\b&quot;</span> <span class="str">&quot;$newNamespace.$className&quot;</span> $includes
}</pre>
<style type="text/css">
<p>.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>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2008/01/04/refactoring-c-with-powershell/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Targeting .NET 2.0 and using C# 3.0 language features</title>
		<link>http://www.aaronlerch.com/blog/2007/12/02/targeting-net-20-and-using-c-30-language-features/</link>
		<comments>http://www.aaronlerch.com/blog/2007/12/02/targeting-net-20-and-using-c-30-language-features/#comments</comments>
		<pubDate>Sun, 02 Dec 2007 21:13:23 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[tips and tricks]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/12/02/targeting-net-20-and-using-c-30-language-features/</guid>
		<description><![CDATA[Did you know you can use most of the new C# 3.0 language features in VS2008 under a project that&#8217;s targeted at .NET 2.0? How cool is that? And it makes sense, too, since there&#8217;s nothing new for the 2.0 runtime, it&#8217;s all compiler magic. I found it by accident &#8211; I found Daniel Moth&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.danielmoth.com/Blog/2007/05/using-c-30-from-net-20.html">Did you know</a> you can use most of the new C# 3.0 language features in VS2008 under a project that&#8217;s targeted at .NET 2.0? How cool is that? And it makes sense, too, since there&#8217;s nothing new for the 2.0 runtime, it&#8217;s all compiler magic. I found it by accident &#8211; I found Daniel Moth&#8217;s post after the fact &#8211; I typed &#8220;prop&#8221; to access the snippet for generating a property. In VS2008, that snippet generates an <a href="http://weblogs.asp.net/scottgu/archive/2007/03/08/new-c-orcas-language-features-automatic-properties-object-initializers-and-collection-initializers.aspx">Automatic Property</a> by default.</p>
<p><a href="http://www.aaronlerch.com/files/blog/Targeting.NET2.0andusi.0languagefeatures_E3D4/image.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="74" alt="image" src="http://www.aaronlerch.com/files/blog/Targeting.NET2.0andusi.0languagefeatures_E3D4/image_thumb.png" width="383" border="0"></a> </p>
<p>I can&#8217;t decide whether this post should be categorized as a tip/trick or a warning, though. It&#8217;s both, probably.</p>
<p>In many development environments you won&#8217;t care &#8211; if you upgrade to Visual Studio 2008 then your build environment is upgraded also. But in some places, such as my company, we have large code bases that span many different technologies, and we have a specially created build system to handle all that. It uses specific compilers &#8211; VS7.1 for C++, for example, and the .NET 2.0 SDK compiler for C#.</p>
<p>You can <a href="http://www.west-wind.com/weblog/posts/122975.aspx">use Visual Studio 2008 for Visual Studio 2005 project files</a>, and with multi-targeting, you can use it in a .NET 2.0 environment. So, back to me as an example, I can transparently use VS2008 as my new IDE of choice &#8211; <em>on my local machine</em>. That means when I build from VS2008 locally, the new C# 3.0 language features will work seamlessly, but will fail when our automated builds pick up my changes.</p>
<p>Thus the warning &#8211; if you&#8217;re not careful (if you&#8217;re on &#8220;autopilot&#8221;) you can write code that will compile in the IDE but not with an SDK.</p>
<p>So, use VS2008, and be careful. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <br />In my case, I always build from the command line anyway &#8211; that way I <em>know</em> that what I check in will build everywhere.</p>
<p>I did have a note to myself to get the .NET 3.5 SDK integrated into our build system, but I see that <a href="http://blogs.msdn.com/windowssdk/archive/2007/06/12/what-is-net-3-5.aspx">a stand-alone version doesn&#8217;t exist</a> &#8211; it&#8217;s being rolled into the Windows SDK which would have far too wide an impact. &lt;sigh&gt;</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:5fa73dbc-5264-40f7-a42e-45ad2b133f22" 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/.NET" rel="tag">.NET</a>, <a href="http://technorati.com/tags/Visual%20Studio" rel="tag">Visual Studio</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/12/02/targeting-net-20-and-using-c-30-language-features/feed/</wfw:commentRss>
		<slash:comments>2</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 perusing [...]]]></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>Cmdlets vs. APIs</title>
		<link>http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/</link>
		<comments>http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/#comments</comments>
		<pubDate>Sun, 25 Nov 2007 02:53:29 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[powershell]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/</guid>
		<description><![CDATA[I&#8217;ve been working on a set of Powershell Cmdlets to fully replace the symstore.exe utility that is included with the Debugging Tools for Windows. (To be released as open source when I&#8217;m done.) When I think about writing Cmdlets, I tend to think that the best approach is to create an API and then wrap [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a set of Powershell Cmdlets to fully replace the symstore.exe utility that is included with the <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">Debugging Tools for Windows</a>. (To be released as open source when I&#8217;m done.) When I think about writing Cmdlets, I tend to think that the best approach is to create an API and then wrap it in a Cmdlet implementation. That enables the best of both worlds&#8211;someone can write an application that uses the API, or people can interact with the Cmdlets via the command line or in an application hosting a Powershell runspace.</p>
<p>But I think I&#8217;ve been very wrong. A while back Jeffrey Snover posted a great &#8220;core dump&#8221; of <a href="http://blogs.msdn.com/powershell/archive/2007/07/03/cmdlets-vs-apis.aspx">cmdlets vs. APIs</a>. He makes some good points, but even after reading it (back when he first posted it) I still thought that API + Cmdlet was the best approach. Experience has changed my mind. Here are, in my opinion, the most important points from his list (paraphrased).</p>
<p><strong>Error handling.</strong> An API can throw exceptions, but a Cmdlet can have terminating and non-terminating errors. With Cmdlets users can easily control the behavior when a non-terminating error occurs as well as get access to the collection of troublemaker objects.</p>
<p><strong>-WhatIf, -Confirm, and -Verbose support.</strong> There simply isn&#8217;t an easy way to have an API support a -WhatIf type of operation, while remaining a good API.</p>
<p><strong>Pipelines and wildcards.</strong> Wildcard support needs to be implemented on a per-API basis, making it a time-consuming (and possibly difficult) task. Working with &#8220;pipelines&#8221; requires specific coding by the user of the API.</p>
<p>The common thread between those three points is that an API simply can&#8217;t provide those services independent of Powershell. You really can&#8217;t create an API and wrap it in a Cmdlet. (If you have a choice.) If my &#8220;Remove-Foo&#8221; Cmdlet simply wraps &#8220;foo.Delete()&#8221;, &#8220;foo.Delete()&#8221; can&#8217;t make use of advanced error handling, or conditional processing (ala &#8220;-WhatIf&#8221; or &#8220;-Confirm&#8221;), or pipeline or wildcard support.</p>
<p>Because applications can host a Powershell runspace, any argument for an API goes away. Your Cmdlets <em>are</em> an API that developers can write code against. The thing that still gets me about this, though, is the verbose code it requires to exercise a Cmdlet&#8217;s &#8220;API&#8221;. Apparently Powershell V2 is going to <a href="http://blogs.msdn.com/powershell/archive/2007/11/06/what-s-new-in-ctp-of-powershell-2-0.aspx">help simplify the runspace hosting story</a>. Maybe that&#8217;s enough to knock the final leg out of my leaning towards an API? Once I finish my work, perhaps I&#8217;ll update the symstore SnapIn for V2 &#8211; in the meantime, I&#8217;d like to release them in a state that people could actually use them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/11/24/cmdlets-vs-apis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Having Fun Writing Software</title>
		<link>http://www.aaronlerch.com/blog/2007/10/23/having-fun-writing-software/</link>
		<comments>http://www.aaronlerch.com/blog/2007/10/23/having-fun-writing-software/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 02:22:46 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[humor]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/10/23/having-fun-writing-software/</guid>
		<description><![CDATA[I was exploring symstore.exe with Depends just now and came across a function in dbghelp that&#8217;s clearly not in the documentation. I got a nice chuckle out of it.  

What sort of &#8220;fun&#8221; (not nasty!) function names do you tend to create? Or do you keep them all boring plain Jane? (Boooo!!) The way [...]]]></description>
			<content:encoded><![CDATA[<p>I was exploring symstore.exe with <a href="http://www.dependencywalker.com/">Depends</a> just now and came across a function in <a href="http://msdn2.microsoft.com/en-us/library/ms679292.aspx">dbghelp</a> that&#8217;s clearly not in the documentation. I got a nice chuckle out of it. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://www.aaronlerch.com/files/blog/HavingFunWritingSoftware_13AB0/image.png"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="208" alt="image" src="http://www.aaronlerch.com/files/blog/HavingFunWritingSoftware_13AB0/image_thumb.png" width="504" border="0"></a></p>
<p>What sort of &#8220;fun&#8221; (not nasty!) function names do you tend to create? Or do you keep them all boring plain Jane? (Boooo!!) The way metadata is exposed in the .NET world, combined with a tool like <a href="http://www.aisto.com/roeder/dotnet/">Reflector</a>, make function names like this more readily &#8220;available&#8221;. But still, we&#8217;ve gotta have some fun somehow!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/10/23/having-fun-writing-software/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Proceed with Caution: Strongly Typed Resources Ahead</title>
		<link>http://www.aaronlerch.com/blog/2007/10/14/proceed-with-caution-strongly-typed-resources-ahead/</link>
		<comments>http://www.aaronlerch.com/blog/2007/10/14/proceed-with-caution-strongly-typed-resources-ahead/#comments</comments>
		<pubDate>Sun, 14 Oct 2007 20:23:08 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[tips and tricks]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/10/14/proceed-with-caution-strongly-typed-resources-ahead/</guid>
		<description><![CDATA[Visual Studio 2005 made using embedded resources a much more integrated experience than it was in Visual Studio 2003. But what I didn&#8217;t know is that there are some important things to be aware of when referencing these resources. A leaky abstraction strikes again!
The Problem
Even though it &#8220;seems&#8221; like a static resource, accessed via a [...]]]></description>
			<content:encoded><![CDATA[<p>Visual Studio 2005 made using embedded resources a much more integrated experience than it was in Visual Studio 2003. But what I didn&#8217;t know is that there are some important things to be aware of when referencing these resources. A <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">leaky abstraction</a> strikes again!</p>
<h4>The Problem</h4>
<p>Even though it &#8220;seems&#8221; like a static resource, accessed via a static property, should create an instance once and only once, it&#8217;s not true. Consider adding and using an image resource &#8211; for example, a &#8220;lock&#8221; image that could be shown in the rows of a <a title="DataGridView Class" href="http://msdn2.microsoft.com/wc5cbb9z.aspx">DataGridView</a> to represent a boolean value:</p>
<p><a href="http://www.aaronlerch.com/files/blog/ProceedwithCautionStronglyTypedResources_7AC/image.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="116" alt="image" src="http://www.aaronlerch.com/files/blog/ProceedwithCautionStronglyTypedResources_7AC/image_thumb.png" width="183" border="0"></a> </p>
<p>One way to translate the data type of a bound object to an &#8220;expected&#8221; data type for a DataGridView column is to handle the CellFormatting event. You might be tempted to write the code to reference your strongly typed &#8220;lock&#8221; image resource like this:</p>
<pre class="code"><span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(43,145,175)">Image</span> _blankIcon = <span style="color: rgb(0,0,255)">new</span> <span style="color: rgb(43,145,175)">Bitmap</span>(16, 16);
<span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">void</span> transactionDataGridView_CellFormatting(<span style="color: rgb(0,0,255)">object</span> sender, <span style="color: rgb(43,145,175)">DataGridViewCellFormattingEventArgs</span> e)
{
    <span style="color: rgb(0,0,255)">if</span> ((e.ColumnIndex == Locked.Index)
        &amp;&amp; (e.DesiredType == <span style="color: rgb(0,0,255)">typeof</span>(<span style="color: rgb(43,145,175)">Image</span>))
        &amp;&amp; (e.Value <span style="color: rgb(0,0,255)">is</span> <span style="color: rgb(0,0,255)">bool</span>))
    {
        <span style="color: rgb(0,0,255)">bool</span> locked = (<span style="color: rgb(0,0,255)">bool</span>)e.Value;
        e.Value = (locked) ? Properties.<span style="color: rgb(43,145,175)">Resources</span>.LockIcon : _blankIcon;
        e.FormattingApplied = <span style="color: rgb(0,0,255)">true</span>;
    }
}</pre>
<p>But you could very easily encounter a <a title="Win32Exception Class" href="http://msdn2.microsoft.com/tac3tbxc.aspx">Win32Exception</a> indicating that you are out of memory. Why? The short answer is that every reference to the property ends up creating a new instance of the resource. With images, movies, or sounds, that can end up using a lot of memory. Notice that the code generated for accessing the resource doesn&#8217;t perform any caching, and in fact two instances of the returned object are logically the same, but are not the same reference. The following is true: &#8220;Properties.Resources.LockIcon != Properties.Resources.LockIcon&#8221;.</p>
<pre class="code"><span style="color: rgb(0,0,255)">internal</span> <span style="color: rgb(0,0,255)">static</span> System.Drawing.<span style="color: rgb(43,145,175)">Bitmap</span> LockIcon {
    <span style="color: rgb(0,0,255)">get</span> {
        <span style="color: rgb(0,0,255)">object</span> obj = ResourceManager.GetObject(<span style="color: rgb(163,21,21)">"LockIcon"</span>, resourceCulture);
        <span style="color: rgb(0,0,255)">return</span> ((System.Drawing.<span style="color: rgb(43,145,175)">Bitmap</span>)(obj));
    }
}</pre>
<h4>The Solution</h4>
<p>It&#8217;s simple, really, but you just have to <em>know</em> to do it. The only real solution is to be intelligent about accessing these resources such that as few instances as possible are created. 99% of the time that means creating a global static variable that is initialized with the resource, and all your code accesses your static variable. This can be time consuming to maintain, if you have a lot of resources, but it&#8217;s definitely worth it. The change to the CellFormatting event handler is a simple one.</p>
<pre class="code"><span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(43,145,175)">Image</span> _lockIcon = Properties.<span style="color: rgb(43,145,175)">Resources</span>.LockIcon;
<span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(43,145,175)">Image</span> _blankIcon = <span style="color: rgb(0,0,255)">new</span> <span style="color: rgb(43,145,175)">Bitmap</span>(16, 16);
<span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">void</span> transactionDataGridView_CellFormatting(<span style="color: rgb(0,0,255)">object</span> sender, <span style="color: rgb(43,145,175)">DataGridViewCellFormattingEventArgs</span> e)
{
    <span style="color: rgb(0,0,255)">if</span> ((e.ColumnIndex == Locked.Index)
        &amp;&amp; (e.DesiredType == <span style="color: rgb(0,0,255)">typeof</span>(<span style="color: rgb(43,145,175)">Image</span>))
        &amp;&amp; (e.Value <span style="color: rgb(0,0,255)">is</span> <span style="color: rgb(0,0,255)">bool</span>))
    {
        <span style="color: rgb(0,0,255)">bool</span> locked = (<span style="color: rgb(0,0,255)">bool</span>)e.Value;
        e.Value = (locked) ? _lockIcon : _blankIcon;
        e.FormattingApplied = <span style="color: rgb(0,0,255)">true</span>;
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>One possibility that could increase maintainability is to write your own Visual Studio custom tool that generates the strongly-typed resource class (the .Designer.cs file). The custom tool could create the standard resource access code but also create a 2nd class that ends in &#8220;Cache&#8221;, for example, and manages a static reference to each resource &#8211; as mentioned in this <a href="https://forums.microsoft.com/msdn/showpost.aspx?postid=616110&amp;siteid=1">MSDN forum post</a>. An <a href="http://www.codeproject.com/dotnet/ResXFileCodeGeneratorEx.asp?df=100">article on The Code Project</a> gives an example implementation of a custom tool. I downloaded it with the intention of doing exactly what I mentioned, but there&#8217;s quite a bit of code there &#8211; and it&#8217;s a lot less trivial than I had hoped. In addition, everybody would have to install this custom tool on their own machine, and would have to manually run it on resource files. Non-optimal. Oh, and I&#8217;m lazy. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e486ce96-1e2d-482e-b530-0fac2255ca9a" 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/Strongly%20Typed%20Resources" rel="tag">Strongly Typed Resources</a>, <a href="http://technorati.com/tags/Visual%20Studio" rel="tag">Visual Studio</a>, <a href="http://technorati.com/tags/Leaky%20Abstraction" rel="tag">Leaky Abstraction</a></div>
<p><a href="http://www.dotnetkicks.com/kick/?url=http://www.aaronlerch.com/blog/2007/10/14/proceed-with-caution-strongly-typed-resources-ahead/"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://www.aaronlerch.com/blog/2007/10/14/proceed-with-caution-strongly-typed-resources-ahead/" border="0" alt="kick it on DotNetKicks.com" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aaronlerch.com/blog/2007/10/14/proceed-with-caution-strongly-typed-resources-ahead/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>TIP: Set breakpoints without source code in Visual Studio 2005</title>
		<link>http://www.aaronlerch.com/blog/2007/08/31/tip-set-breakpoints-without-source-code-in-visual-studio-2005/</link>
		<comments>http://www.aaronlerch.com/blog/2007/08/31/tip-set-breakpoints-without-source-code-in-visual-studio-2005/#comments</comments>
		<pubDate>Fri, 31 Aug 2007 18:15:55 +0000</pubDate>
		<dc:creator>aaron</dc:creator>
				<category><![CDATA[debugging]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tips and tricks]]></category>

		<guid isPermaLink="false">http://www.aaronlerch.com/blog/2007/08/31/tip-set-breakpoints-without-source-code-in-visual-studio-2005/</guid>
		<description><![CDATA[This was probably my favorite Visual Studio 2005 tip I learned in the Mastering .NET Debugging class I recently took. John Robbins is awesome.   This tip lets you set a breakpoint at any arbitrary location &#8211; no source code required! Think framework library, or 3rd party library, or any commonly called code (that [...]]]></description>
			<content:encoded><![CDATA[<p>This was probably my favorite Visual Studio 2005 tip I learned in the Mastering .NET Debugging class <a href="http://www.aaronlerch.com/blog/2007/08/31/mastering-net-debugging-with-john-robbins/">I recently took</a>. <a href="http://www.wintellect.com/cs/blogs/jrobbins/default.aspx">John Robbins is awesome.</a> <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  This tip lets you set a breakpoint at any arbitrary location &#8211; no source code required! Think framework library, or 3rd party library, or any commonly called code (that you don&#8217;t have source for) where you don&#8217;t want to set breakpoints on every single call into the code.</p>
<p>There are a couple of gotchas that have to be configured for this to work. I was scratching my head wondering why this didn&#8217;t work for me immediately, here&#8217;s why.</p>
<p><strong>First</strong>, make sure the &#8220;Just My Code&#8221; setting is turned OFF in the Visual Studio settings (Tools -&gt; Options -&gt; Debugging). In fact, just leave this setting off all the time &#8212; it sucks. <img src='http://www.aaronlerch.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <br /><a href="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/Options_3.png" atomicselection="true"><img height="297" alt="Options" src="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/Options_thumb_3.png" width="500" border="0"></a> </p>
<p><strong>Secondly</strong>, make sure you have a symbol path configured so you can load the appropriate symbols. <em>You must have symbols for the &#8220;source-less&#8221; code!</em> The symbol path/server is specified via an environment variable named &#8220;<a href="http://support.microsoft.com/kb/311503">_NT_SYMBOL_PATH</a>&#8220;. If you don&#8217;t have a symbol server configured (more on that in a later post) your environment variable will probably look like this: (see the previous link for the exact syntax)</p>
<p><code>_NT_SYMBOL_PATH = SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols</code></p>
<p>You can also configure symbols from within Visual Studio in the Tools -&gt; Options -&gt; Debugging -&gt; Symbols configuration:<br /><a href="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/Options2_3.png" atomicselection="true"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="301" alt="Options (2)" src="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/Options2_thumb_3.png" width="500" border="0"></a> </p>
<p>Now, start debugging your application (have it break on the first instruction of the app). This is especially important if Visual Studio hasn&#8217;t yet pulled down the symbols from the symbol server. Bring up the breakpoint window in Visual Studio (CTRL+B) and type in enough detail for the resolver to find the method/property you&#8217;re looking for. If you want to break on a property, be sure to use the method syntax for the property: &#8220;get_[propertyname]&#8221; or &#8220;set_[propertyname]&#8220;.<br /><a href="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/NewBreakpoint_3.png" atomicselection="true"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="New Breakpoint" src="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/NewBreakpoint_thumb_3.png" width="500" border="0"></a> </p>
<p>Hit OK, and, if you had &#8220;Use Intellisense to verify the function name&#8221; selected, press &#8220;Yes&#8221;:<br /><a href="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/MicrosoftVisualStudio_3.png" atomicselection="true"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="183" alt="Microsoft Visual Studio" src="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/MicrosoftVisualStudio_thumb_3.png" width="500" border="0"></a> </p>
<p>At this point, if your code calls the method or property, the debugger will break on it and take you to the Disassembly view. You can use the Call Stack window to traverse up to whatever point you care about. Notice also that in this example, &#8220;child&#8221; breakpoints were automatically set on all the overloaded methods for System.Console.WriteLine, automatically.<br /><a href="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/CropperCapture5_3.png" atomicselection="true"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="203" alt="CropperCapture[5]" src="http://www.aaronlerch.com/files/blog/TIPSetbreakpointswithoutsourcecode_BA97/CropperCapture5_thumb_3.png" width="500" border="0"></a> </p>
<p>This is an awesome trick, one that can save you loads of time! Thanks John! <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/08/31/tip-set-breakpoints-without-source-code-in-visual-studio-2005/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
