<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8076826</id><updated>2012-01-28T16:18:22.163+01:00</updated><title type='text'>tommy.blog</title><subtitle type='html'>Personal weblog of Tommy Carlier.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.tcx.be/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default?start-index=101&amp;max-results=100'/><author><name>Tommy Carlier</name><uri>http://www.blogger.com/profile/10989195508641718599</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>135</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8076826.post-3947571203553449774</id><published>2011-11-17T15:23:00.001+01:00</published><updated>2011-11-17T15:29:43.754+01:00</updated><title type='text'>Removing diacritics from a string</title><content type='html'>Recently I had to write a function that removes all &lt;a href="http://en.wikipedia.org/wiki/Diacritic" target="_blank"&gt;diacritics&lt;/a&gt; from a string (e.g.: turning &lt;code&gt;José&lt;/code&gt; into &lt;code&gt;Jose&lt;/code&gt;). Searching the web, I quickly found the blog post &lt;a href="http://blogs.msdn.com/b/michkap/archive/2007/05/14/2629747.aspx" target="_blank"&gt;“Stripping is an interesting job”&lt;/a&gt; by Michael Kaplan. His code is simple and good, but I saw some opportunities for optimizations (obvious stuff): because we know the approximate length (actually the maximum length) of the resulting string, we could give the StringBuilder-instance an initial capacity equal to the length of the original string. In some simple cases I actually like using a char-array instead of a StringBuilder, because it has even less overhead. Another obvious optimization is to check whether the original string is not empty. Here's my optimized version:&lt;br /&gt;
&lt;pre&gt;public static string RemoveDiacritics(this string value)
{
  if (value == null) throw new ArgumentNullException("value");

  if (value.Length &amp;gt; 0)
  {
    char[] chars = new char[value.Length];
    int charIndex = 0;

    value = value.Normalize(NormalizationForm.FormD);
    for (int i = 0; i &amp;lt; value.Length; i++)
    {
      char c = value[i];
      if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
        chars[charIndex++] = c;
    }

    return new string(chars, 0, charIndex).Normalize(NormalizationForm.FormC);
  }

  return value;
}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-3947571203553449774?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/3947571203553449774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=3947571203553449774' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3947571203553449774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3947571203553449774'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2011/11/recently-i-had-to-write-function-that.html' title='Removing diacritics from a string'/><author><name>Tommy Carlier</name><uri>http://www.blogger.com/profile/10989195508641718599</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-3482297411111010189</id><published>2010-03-04T09:38:00.001+01:00</published><updated>2010-06-03T09:54:26.979+02:00</updated><title type='text'>Google Analytics in ASP.NET</title><content type='html'>&lt;p&gt;Here's a little C# function I occasionally use to insert a &lt;a href="http://www.google.com/analytics/"&gt;Google Analytics&lt;/a&gt;-snippet in an ASP.NET website. It takes a Google Analytics-ID as an argument, which you can leave blank in debug-mode (to not render the snippet). It uses the recently introduced asynchronous loading method (which doesn't block the rendering of your website). It's not literally the same snippet you can find on the Google Analytics site, but it does the same thing (only with a slightly smaller dynamically built JavaScript-snippet).&lt;/p&gt;&lt;pre&gt;public static class SiteUtils
{
  public static string RenderGoogleAnalyticsScript(string googleAnalyticsID)
  {
    return string.IsNullOrEmpty(googleAnalyticsID)
      ? ""
      : "&amp;lt;script&amp;gt;"
      + "var _gaq=_gaq||[];"
      + "_gaq.push(['_setAccount','" + googleAnalyticsID + "']);"
      + "_gaq.push(['_trackPageview']);"
      + "(function(){"
      + "var d=document,s0=d.getElementsByTagName('script')[0],"&lt;br&gt;      + "s=d.createElement('script');"
      + "s.async=true;"
      + "s.type='text/javascript';"
      + "s.src='"
      + (HttpContext.Current.Request.IsSecureConnection
          ? "https://ssl" : "http://www")
      + ".google-analytics.com/ga.js';"
      + "s0.parentNode.insertBefore(s,s0)}())&amp;lt;/script&amp;gt;";
  }
}&lt;/pre&gt;
&lt;p&gt;I usually keep the Google Analytics-ID in my application settings (web.config), which allows me to use a different one for different deployments (or an empty one for debugging). So I have a second function (in the same SiteUtils-class) that doesn't take an argument, but takes the Google Analytics-ID from the settings:&lt;/p&gt;&lt;pre&gt;public static string RenderGoogleAnalyticsScript()
{
  return RenderGoogleAnalyticsScript(Settings.Default.GoogleAnalyticsID);
}&lt;/pre&gt;
&lt;p&gt;In my master-page, I then use the following snippet to insert it into the body of the page (note that you have to use the fully qualified type name, including namespace):&lt;/p&gt;&lt;pre&gt;&amp;lt;%= MyNamespace.SiteUtils.RenderGoogleAnalyticsScript() %&amp;gt;&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;Updated 2010-06-03&lt;/b&gt;: slightly modified the generated JavaScript-code to better match the current official Google Analytics-script.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-3482297411111010189?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/3482297411111010189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=3482297411111010189' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3482297411111010189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3482297411111010189'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2010/03/google-analytics-in-aspnet.html' title='Google Analytics in ASP.NET'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-5677146037898554354</id><published>2010-01-08T08:50:00.001+01:00</published><updated>2010-01-08T12:27:52.138+01:00</updated><title type='text'>if-read-do-while-read part 2</title><content type='html'>&lt;p&gt;I just received a comment on my previous post about the &lt;a href="http://blog.tcx.be/2009/12/if-read-do-while-read.html"&gt;if-read-do-while-read&lt;/a&gt; construction. Tanton suggests that I could create a method that encapsulates this construction, using delegates for the &lt;em&gt;before&lt;/em&gt;, &lt;em&gt;during&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; steps. Here's a quick version of an extension method on IDataReader that does this:&lt;/p&gt;&lt;pre&gt;public static class DataReaderExtensions
{
  public static void ReadAll(
    this IDataReader reader,
    Action before,
    Action&amp;lt;IDataRecord&amp;gt; during,
    Action after)
  {
    if (reader == null) throw new ArgumentNullException("reader");

    if (reader.Read())
    {
      if (before != null)
        before();
      
      do
      {
        if (during != null)
          during(reader);
      }
      while (reader.Read());
      
      if (after != null)
        after();
    }
  }
}&lt;/pre&gt;
&lt;p&gt;And here's a rewrite of the HTML-example, using this extension method:&lt;/p&gt;&lt;pre&gt;StringBuilder html = new StringBuilder();
using (IDataReader reader = command.ExecuteReader())
  reader.ReadAll(
    () =&amp;gt; html.Append("&amp;lt;ul&amp;gt;"),
    record =&amp;gt; html.AppendFormat("&amp;lt;li&amp;gt;{0}", record.GetValue(0)),
    () =&amp;gt; html.Append("&amp;lt;/ul&amp;gt;"));&lt;/pre&gt;
&lt;p&gt;It surely is shorter, but I'm not entirely convinced it's cleaner.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-5677146037898554354?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/5677146037898554354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=5677146037898554354' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5677146037898554354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5677146037898554354'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2010/01/if-read-do-while-read-part-2.html' title='if-read-do-while-read part 2'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-6266039450793416911</id><published>2009-12-29T17:09:00.001+01:00</published><updated>2009-12-29T17:09:27.683+01:00</updated><title type='text'>if-read-do-while-read</title><content type='html'>&lt;p&gt;Here’s a construction I occasionally need when reading items from a IDataReader: to execute some code before and after reading through the IDataReader, but only if there are rows in the IDataReader.&lt;/p&gt; &lt;p&gt;One option is to use a boolean variable that determines whether the collection has items, like this:&lt;/p&gt;&lt;pre&gt;using (IDataReader reader = command.ExecuteReader())
{
  bool hasRows = false;
  while (reader.Read())
  {
    if (!hasRows)
    {
      hasRows = true;
      Before();
    }

    During();
  }

  if (hasRows)
    After();
}&lt;/pre&gt;
&lt;p&gt;But the following construction (which I call the &lt;i&gt;if-read-do-while-read&lt;/i&gt; construction) does not need the boolean variable and is cleaner:&lt;/p&gt;&lt;pre&gt;using (IDataReader reader = command.ExecuteReader())
{
  if (reader.Read())
  {
    Before();

    do
    {
      During();
    }
    while (reader.Read());

    After();
  }
}&lt;/pre&gt;
&lt;p&gt;Here's a practical example: creating HTML-code with a UL-list for the data, but only if there are items:&lt;/p&gt;&lt;pre&gt;StringBuilder html = new StringBuilder();
using (IDataReader reader = command.ExecuteReader())
{
  if (reader.Read())
  {
    html.Append("&amp;lt;ul&amp;gt;");

    do
    {
      html.AppendFormat(
        "&amp;lt;li&amp;gt;{0}",
        reader.GetValue(0));
    }
    while (reader.Read());

    html.Append("&amp;lt;/ul&amp;gt;");
  }
}&lt;/pre&gt;
&lt;p&gt;You could use the same technique on an IEnumerable&amp;lt;T&amp;gt;, but you wouldn't be able to use foreach anymore:&lt;/p&gt;&lt;pre&gt;using (var enumerator = collection.GetEnumerator())
{
  if (enumerator.MoveNext())
  {
    Before();

    do
    {
      var item = enumerator.Current;
      During();
    }
    while (enumerator.MoveNext());

    After();
  }
}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-6266039450793416911?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/6266039450793416911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=6266039450793416911' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6266039450793416911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6266039450793416911'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/12/if-read-do-while-read.html' title='if-read-do-while-read'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-5462265744921489717</id><published>2009-11-12T12:27:00.001+01:00</published><updated>2009-11-12T12:27:53.836+01:00</updated><title type='text'>NDepend</title><content type='html'>&lt;p&gt;A while ago, I received an e-mail from &lt;a href="http://codebetter.com/blogs/patricksmacchia/"&gt;Patrick Smacchia&lt;/a&gt;, offering me a license for &lt;a href="http://www.ndepend.com/"&gt;NDepend&lt;/a&gt; and asking me whether I could try it out, give some feedback and if I liked it, maybe I could blog about my experience with NDepend. Because I was already subscribed to the RSS-feed of Patrick’s blog, I knew about NDepend and how it could help developers write better code. I like trying out stuff like this, but somehow I hadn’t found time to install and properly test it. I was already using Visual Studio’s Code Analysis (&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9aeaa970-f281-4fb0-aba1-d59d7ed09772&amp;amp;DisplayLang=en"&gt;FxCop&lt;/a&gt;) and &lt;a href="http://code.msdn.microsoft.com/sourceanalysis"&gt;StyleCop&lt;/a&gt; to analyze my code and improve its quality, so I never had the right incentives to use additional tools. But it would be rude to just say no to Patrick, so I decided to give it a try.&lt;/p&gt; &lt;p&gt;After installing it (which just means downloading: NDepend is a portable application that doesn’t really have to be “installed”), I started Visual NDepend (the GUI version of NDepend) and was greeted with a start page that looks like the Visual Studio start page. I decided not to just jump in and try stuff, but to first watch some of the &lt;a href="http://www.ndepend.com/GettingStarted.aspx"&gt;screen casts and tutorials on the NDepend website&lt;/a&gt;. And I’m glad I did. After trying to analyze some of my projects, I discovered that NDepend produces a lot of data, reports and graphs that only make sense after you have learnt what it all means. This is a tool that you have to learn how to use and how to interpret its results. The user interface is very flexible, but also a bit overwhelming. But because I don’t really have an idea how I would design a UI for an application like this, I can’t really criticize it.&lt;/p&gt; &lt;p&gt;Comparing it to FxCop and StyleCop is not really fair. There is some overlapping functionality between the 3 tools, but NDepend offers a lot more. First of all, FxCop and StyleCop just analyze your code according to fixed rules and the result is a bunch of errors and warnings. NDepend can also be used like this, but the rules are not fixed and are defined in &lt;a href="http://www.ndepend.com/CQL.htm"&gt;CQL&lt;/a&gt;, a query language that looks and feels like &lt;a href="http://en.wikipedia.org/wiki/SQL"&gt;SQL&lt;/a&gt;, but allows you to query code constructs. The advantage of this approach is that you can write ad-hoc queries to gain insight in your code (or someone else’s assemblies). Here’s an example of a CQL query:&lt;/p&gt;&lt;pre&gt;WARN IF Count &amp;gt; 0 IN SELECT TOP 10 TYPES WHERE NbMethods &amp;gt; 20 ORDER BY NbMethods DESC&lt;/pre&gt;
&lt;p&gt;This query will generate a warning if your code has classes (and structs) with more than 20 methods. All the built-in rules are written as CQL queries, which you can just modify (or you could just create additional rules).&lt;/p&gt;
&lt;p&gt;Another area of analysis that NDepend offers that FxCop and StyleCop do not have is the visual views of your projects. There’s a metrics &lt;a href="http://en.wikipedia.org/wiki/Treemapping"&gt;treemap&lt;/a&gt; that shows the proportions of different metrics of your project (methods, types, fields, …) and there are 2 ways to show dependencies: a &lt;a href="http://en.wikipedia.org/wiki/Dependency_diagram"&gt;dependency graph&lt;/a&gt; and a &lt;a href="http://en.wikipedia.org/wiki/Design_Structure_Matrix"&gt;dependency matrix&lt;/a&gt;. While the dependency graph looks familiar and very graphical, it fails when there are too many elements and dependencies. This is not a failure of NDepend, but just a limitation of dependency graphs in general. Dependency matrices on the other hand are great to understand dependencies, even when there are a lot of elements, but they are less intuitive and you have to learn how to use them and interpret what you see.&lt;/p&gt;
&lt;p&gt;My conclusion is that NDepend is a great tool to analyze your code and improve its quality, but it takes getting used to. You have to learn how to use it and how to interpret the results you get. I feel like I have just seen the tip of the iceberg. NDepend also contains a console-application, and can be automated and integrated in your build process (&lt;a href="http://en.wikipedia.org/wiki/MSBuild"&gt;MSBuild&lt;/a&gt;, &lt;a href="http://nant.sourceforge.net/"&gt;NAnt&lt;/a&gt;, …). It has add-ins for Visual Studio and Reflector, and can be used to compare different versions of a code base (for example: to see if compatibility is broken).&lt;/p&gt;
&lt;p&gt;If you want to try it yourself, I suggest you first &lt;a href="http://www.ndepend.com/GettingStarted.aspx"&gt;watch the screen casts&lt;/a&gt;, &lt;a href="http://www.ndepend.com/NDependDownload.aspx"&gt;download NDepend&lt;/a&gt; and start analyzing some of your projects. Another suggestion I have is to start reading &lt;a href="http://codebetter.com/blogs/patricksmacchia/"&gt;Patrick Smacchia’s blog&lt;/a&gt;, because he has written about some cool things you can do with NDepend. He also explains how he has analyzed some existing .NET applications (&lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2008/10/20/controlling-the-usage-of-libraries.aspx"&gt;Paint.NET&lt;/a&gt;, &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/07/21/nhibernate-2-1-changes-overview.aspx"&gt;NHibernate&lt;/a&gt;, &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/04/26/the-big-picture-of-the-sharpdevelop-code-base.aspx"&gt;SharpDevelop&lt;/a&gt;, …) and even how he uses NDepend to find what has changed between &lt;a href="http://codebetter.com/blogs/patricksmacchia/archive/2009/10/21/interesting-findings-in-the-diff-between-net-fx-v4-beta1-and-beta2.aspx"&gt;different versions of the .NET Framework &lt;abbr title="Base Class Libraries"&gt;BCL&lt;/abbr&gt;&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-5462265744921489717?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/5462265744921489717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=5462265744921489717' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5462265744921489717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5462265744921489717'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/11/ndepend.html' title='NDepend'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-2681698425632753460</id><published>2009-10-03T19:08:00.001+02:00</published><updated>2009-10-03T19:08:59.695+02:00</updated><title type='text'>Awesome videos on Channel 9 this week</title><content type='html'>&lt;p&gt;Channel 9 has always produced nice videos with interviews, or weekly shows (&lt;a href="http://channel9.msdn.com/shows/This+Week+On+Channel+9/"&gt;This Week on Channel 9&lt;/a&gt;, &lt;a href="http://channel9.msdn.com/shows/PingShow/"&gt;Ping&lt;/a&gt;), but this week they have exceeded themselves in quality and awesomeness. I especially liked the following videos:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/shows/Going+Deep/E2E-Erik-Meijer-and-Wes-Dyer-Reactive-Framework-Rx-Under-the-Hood-1-of-2/"&gt;E2E: Erik Meijer and Wes Dyer &amp;ndash; Reactive Framework (Rx) Under the Hood 1 of 2&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/shows/Going+Deep/E2E-Erik-Meijer-and-Wes-Dyer-Reactive-Framework-Rx-Under-the-Hood-2-of-2/"&gt;E2E: Erik Meijer and Wes Dyer &amp;ndash; Reactive Framework (Rx) Under the Hood 2 of 2&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/shows/VisualStudioDocumentary/The-Visual-Studio-Documentary-Part-One/"&gt;The Visual Studio Documentary: Part One&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/shows/VisualStudioDocumentary/The-Visual-Studio-Documentary-Part-Two/"&gt;The Visual Studio Documentary: Part Two&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://channel9.msdn.com/shows/Going+Deep/Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1/"&gt;C9 Lectures: Dr. Erik Meijer &amp;ndash; Functional Programming Fundamentals, Chapter 1 of 13&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Besides being a fan of &lt;a title="This Week on Channel 9" href="http://channel9.msdn.com/shows/This+Week+On+Channel+9/"&gt;TWoC9&lt;/a&gt; and &lt;a href="http://channel9.msdn.com/shows/PingShow/"&gt;Ping&lt;/a&gt;, I also loved the series &amp;ldquo;&lt;a href="http://channel9.msdn.com/shows/History/"&gt;The History of Microsoft&lt;/a&gt;&amp;rdquo; (25 episodes) a while ago. I think Channel 9 is still revolutionary (related to the videos), despite the buggy forum.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-2681698425632753460?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/2681698425632753460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=2681698425632753460' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2681698425632753460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2681698425632753460'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/10/awesome-videos-on-channel-9-this-week.html' title='Awesome videos on Channel 9 this week'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4021376726411390993</id><published>2009-07-28T12:50:00.001+02:00</published><updated>2009-07-28T12:50:09.985+02:00</updated><title type='text'>Calctor 2.1.2</title><content type='html'>&lt;p&gt;This is a small update to &lt;a href="http://blog.tcx.be/2006/09/calctor-calctor-mobile.html"&gt;Calctor&lt;/a&gt;. I added the option to use comma as a decimal separator.&lt;/p&gt; &lt;p&gt;You can download it &lt;a title="Download Calctor" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4021376726411390993?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4021376726411390993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4021376726411390993' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4021376726411390993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4021376726411390993'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/07/calctor-212.html' title='Calctor 2.1.2'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-8815716749037720834</id><published>2009-05-31T12:59:00.001+02:00</published><updated>2009-07-11T17:10:08.059+02:00</updated><title type='text'>for-i-repeat 1.1</title><content type='html'>&lt;img style="margin: 0px 0px 2ex 2em; float: right" alt="for-i-repeat screenshot" src="http://files.myopera.com/TommyCarlier/albums/122489/for-i-repeat-1-1.png"&gt;  &lt;p&gt;I just uploaded a new version of &lt;a href="http://blog.tcx.be/2009/02/for-i-repeat.html"&gt;for-i-repeat&lt;/a&gt;. The only major changes are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The location and size of the window are now remembered (stored in a settings-file)  &lt;li&gt;The visual style has been improved (uses more recent version of the &lt;a href="http://tc.codeplex.com/"&gt;TC Libraries&lt;/a&gt;)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://www.box.net/shared/afyf5kkpsy"&gt;Download for-i-repeat 1.1&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/for-i-repeat" rel="tag"&gt;for-i-repeat&lt;/a&gt;, &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/portable" rel="tag"&gt;portable&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-8815716749037720834?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/8815716749037720834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=8815716749037720834' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8815716749037720834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8815716749037720834'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/05/for-i-repeat-11.html' title='for-i-repeat 1.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1701981119430739583</id><published>2009-04-11T16:18:00.001+02:00</published><updated>2009-04-11T16:18:53.531+02:00</updated><title type='text'>Onebit: cool free icons</title><content type='html'>&lt;p&gt;I just found this little gem in my newsfeeds: &lt;a href="http://www.icojoy.com/articles/44"&gt;Onebit&lt;/a&gt;, a free set of 50 icons (48 by 48 pixels) from &lt;a href="http://www.icojoy.com/"&gt;Icojoy&lt;/a&gt;. The reason I’m blogging about this is because I think it’s a great example of a modern icon set that is not glossy or shiny and still looks very cool.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/free+icons" rel="tag"&gt;free icons&lt;/a&gt;, &lt;a href="http://technorati.com/tags/icojoy" rel="tag"&gt;icojoy&lt;/a&gt;, &lt;a href="http://technorati.com/tags/onebit" rel="tag"&gt;onebit&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1701981119430739583?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1701981119430739583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1701981119430739583' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1701981119430739583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1701981119430739583'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/04/onebit-cool-free-icons.html' title='Onebit: cool free icons'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4381144899609692467</id><published>2009-04-02T07:57:00.001+02:00</published><updated>2009-04-02T07:57:36.103+02:00</updated><title type='text'>Twitter</title><content type='html'>&lt;p&gt;I’ve been trying out &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt; for about a week now. I’m still a bit skeptical about it, but I can see at least 1 advantage: there’s a very close contact between followers and followees. It’s a lot easier to write a quick tweet to someone than it is to comment on their blog. There’s a very convenient bi-directional communication. The 140 character limit is something to get used to, but it also makes you think about what you write. I do like the conventions of replying to someone or mentioning someone via @, or referencing an event via #.&lt;/p&gt; &lt;p&gt;My twitter address: @&lt;a href="http://twitter.com/tommycarlier"&gt;tommycarlier&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/twitter" rel="tag"&gt;twitter&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4381144899609692467?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4381144899609692467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4381144899609692467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4381144899609692467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4381144899609692467'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/04/twitter.html' title='Twitter'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-7917737038536265867</id><published>2009-03-13T11:24:00.001+01:00</published><updated>2009-03-13T11:24:00.759+01:00</updated><title type='text'>Launch of new Transceiver website</title><content type='html'>&lt;p&gt;I haven't had time to write about this yet, but last week our company launched the new website of our flagship technology: &lt;a href="http://www.transceiver.biz/"&gt;Transceiver&lt;/a&gt;. We rewrote the website from scratch, making sure it's fast, accessible and tight. We kept the visual style of the old site, but tweaked it a bit. No more Flash, no more frames, clean XHTML, clean CSS, clean URLs, …&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.transceiver.biz/products/server/client-server.png"&gt;&lt;/p&gt; &lt;p&gt;Transceiver is a technology we've been working on for a few years now that enables users to send and receive files in a very secure and private way. The core functionality is file delivery, but Transceiver also contains additional functionality, like digital signing of files, automation of processes, …&lt;/p&gt; &lt;p&gt;If you're interested, or you want more details, just &lt;a href="http://www.transceiver.biz/"&gt;visit the new website&lt;/a&gt;, check out the Transceiver &lt;a title="An overview of the Transceiver products" href="http://www.transceiver.biz/products"&gt;products&lt;/a&gt; (&lt;a href="http://www.transceiver.biz/products/communicator"&gt;Transceiver Communicator&lt;/a&gt;, &lt;a href="http://www.transceiver.biz/products/automator"&gt;Transceiver Automator&lt;/a&gt;, &lt;a href="http://www.transceiver.biz/products/server"&gt;Transceiver Server&lt;/a&gt;), maybe subscribe to the &lt;a title="The Transceiver News Feed" href="http://www.transceiver.biz/news.rss"&gt;news feed&lt;/a&gt;. If you need more info, or you have questions or suggestions, just use our &lt;a href="http://www.transceiver.biz/contact"&gt;contact form&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Transceiver" rel="tag"&gt;Transceiver&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Transceiver+Communicator" rel="tag"&gt;Transceiver Communicator&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Transceiver+Automator" rel="tag"&gt;Transceiver Automator&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Transceiver+Server" rel="tag"&gt;Transceiver Server&lt;/a&gt;,&lt;a href="http://technorati.com/tags/security" rel="tag"&gt;security&lt;/a&gt;,&lt;a href="http://technorati.com/tags/technology" rel="tag"&gt;technology&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-7917737038536265867?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/7917737038536265867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=7917737038536265867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/7917737038536265867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/7917737038536265867'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/03/launch-of-new-transceiver-website.html' title='Launch of new Transceiver website'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-606073211456021662</id><published>2009-02-15T16:38:00.001+01:00</published><updated>2009-07-11T17:10:51.811+02:00</updated><title type='text'>for-i-repeat</title><content type='html'>&lt;img style="margin: 0px 0px 2ex 2em; float: right" alt="for-i-repeat screenshot" src="http://files.myopera.com/TommyCarlier/albums/122489/for-i-repeat.png"&gt;  &lt;p&gt;&lt;strong&gt;Update 2009-05-31&lt;/strong&gt;: &lt;a href="http://blog.tcx.be/2009/05/for-i-repeat-11.html"&gt;New version 1.1&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I just finished developing a small tool called &lt;em&gt;for-i-repeat&lt;/em&gt; that can duplicate a text-fragment a number of times using a counter. The reason I needed this is for the following scenario: at work we have a machine that has 50 databases that all have the same schema, but different data. If I want to modify the schema of all 50 databases, I create a SQL script that applies the modifications to 1 database, put &lt;code&gt;USE Database01&lt;/code&gt; in front of it, and run it 50 times, each time modifying the USE-statement with the next database number. &lt;em&gt;for-i-repeat&lt;/em&gt; allows me to convert this input:&lt;/p&gt;&lt;pre&gt;USE Database{0:00}
ALTER TABLE ...&lt;/pre&gt;
&lt;p&gt;into this output:&lt;/p&gt;&lt;pre&gt;USE Database01
ALTER TABLE ...
USE Database02
ALTER TABLE ...
USE Database03
ALTER TABLE ...
...
USE Database50
ALTER TABLE ...&lt;/pre&gt;
&lt;p&gt;A real time-saver! To format the counter &lt;code&gt;{0}&lt;/code&gt;, you can use the full range of &lt;a title="Numeric Format Strings" href="http://msdn.microsoft.com/en-us/library/427bttx3.aspx"&gt;.NET numeric formatting&lt;/a&gt; options, including hexadecimal formatting (&lt;code&gt;{0:X}&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;You can download &lt;em&gt;for-i-repeat&lt;/em&gt; &lt;a title="download for-i-repeat" href="http://www.box.net/shared/afyf5kkpsy"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/for-i-repeat" rel="tag"&gt;for-i-repeat&lt;/a&gt;, &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/portable" rel="tag"&gt;portable&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-606073211456021662?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/606073211456021662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=606073211456021662' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/606073211456021662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/606073211456021662'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/02/for-i-repeat.html' title='for-i-repeat'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-93193802742396741</id><published>2009-01-11T17:30:00.001+01:00</published><updated>2009-01-23T20:18:03.646+01:00</updated><title type='text'>Visual Dooby 0.1</title><content type='html'>&lt;p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/122489/1Visual-Dooby.png"&gt;&lt;img style="margin-left: 1em" src="http://files.myopera.com/TommyCarlier/albums/122489/Visual-Dooby-Thumb.png" align="right" border="0"&gt;&lt;/a&gt;I just uploaded an initial version of &lt;a title="Download Visual Dooby" href="http://www.box.net/shared/1ief43febt#blog"&gt;Visual Dooby&lt;/a&gt;, a portable lightweight database client. &lt;/p&gt; &lt;p&gt;This initial release is quite limited. You can currently only connect to a SQL Server database, the database browser only displays tables, views and columns, and you can save the results of a query to an XML-file.&lt;/p&gt; &lt;p&gt;Some nice features are the advanced customizations when saving to XML, the visualization of data types in the result grid and the grid row numbering.&lt;/p&gt; &lt;p&gt;You can download it from &lt;a title="Download Visual Dooby" href="http://www.box.net/shared/1ief43febt#blog"&gt;this page&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;small&gt;Donate: &lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;amp;business=MBYU3Z969WQWS&amp;amp;item_name=Visual%20Dooby&amp;amp;no_shipping=1&amp;amp;currency_code=USD"&gt;USD&lt;/a&gt; – &lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;amp;business=MBYU3Z969WQWS&amp;amp;item_name=Visual%20Dooby&amp;amp;no_shipping=1&amp;amp;currency_code=EUR"&gt;EUR&lt;/a&gt; – &lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;amp;business=MBYU3Z969WQWS&amp;amp;item_name=Visual%20Dooby&amp;amp;no_shipping=1&amp;amp;currency_code=GBP"&gt;GBP&lt;/a&gt; – &lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;amp;business=MBYU3Z969WQWS&amp;amp;item_name=Visual%20Dooby&amp;amp;no_shipping=1&amp;amp;currency_code=AUD"&gt;AUD&lt;/a&gt; – &lt;a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;amp;business=MBYU3Z969WQWS&amp;amp;item_name=Visual%20Dooby&amp;amp;no_shipping=1&amp;amp;currency_code=CAD"&gt;CAD&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Visual+Dooby" rel="tag"&gt;Visual Dooby&lt;/a&gt;, &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/portable" rel="tag"&gt;portable&lt;/a&gt;, &lt;a href="http://technorati.com/tags/database" rel="tag"&gt;database&lt;/a&gt;, &lt;a href="http://technorati.com/tags/database+client" rel="tag"&gt;database client&lt;/a&gt;, &lt;a href="http://technorati.com/tags/SQL+Server" rel="tag"&gt;SQL Server&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-93193802742396741?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/93193802742396741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=93193802742396741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/93193802742396741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/93193802742396741'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2009/01/visual-dooby-01.html' title='Visual Dooby 0.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4239291817952415370</id><published>2008-12-09T22:04:00.001+01:00</published><updated>2009-01-29T15:16:53.884+01:00</updated><title type='text'>.NET BCL proposition: read-only collection interfaces</title><content type='html'>&lt;p&gt;As a result of &lt;a href="http://channel9.msdn.com/forums/TechOff/447651-How-about-some-syntax-sugar-for-IEnumerable/"&gt;this thread on Channel 9&lt;/a&gt;, here's a proposition for a simple enhancement of the .NET &lt;abbr title="Base Class Libraries"&gt;BCL&lt;/abbr&gt;, related to collections.&lt;/p&gt; &lt;p&gt;If a class wants to expose a collection of items, the best thing to do is expose the collection as an abstract interface, so the internal class that is used can be changed without changing the &lt;abbr title="Application Programming Interface"&gt;API&lt;/abbr&gt;. If you want to expose a read-only collection, the options you have are IEnumerable&amp;lt;T&amp;gt;, ICollection&amp;lt;T&amp;gt; or IList&amp;lt;T&amp;gt;. IEnumerable&amp;lt;T&amp;gt; represents a read-only collection that can be enumerated, but you can't ask it how much elements it has. ICollection&amp;lt;T&amp;gt; and IList&amp;lt;T&amp;gt; represent collections that could be read-only, but this can only be checked at runtime and not defined at compile-time.&lt;/p&gt; &lt;p&gt;My proposition is to add 2 additional interfaces IReadOnlyCollection&amp;lt;T&amp;gt; and IReadOnlyList&amp;lt;T&amp;gt; that contain a subset of the members of ICollection&amp;lt;T&amp;gt; and IList&amp;lt;T&amp;gt; that can be performed on read-only collections. ICollection&amp;lt;T&amp;gt; could then implement IReadOnlyCollection&amp;lt;T&amp;gt; and IList&amp;lt;T&amp;gt; could implement IReadOnlyList&amp;lt;T&amp;gt; (and also ICollection&amp;lt;T&amp;gt;, like it does now). Adding these interfaces would not break existing code, they would be fully backward compatible and would not even require changes to the classes that implement ICollection&amp;lt;T&amp;gt; and IList&amp;lt;T&amp;gt;: they would automatically also implement the new interfaces (because ICollection&amp;lt;T&amp;gt; and IList&amp;lt;T&amp;gt; implement IReadOnlyCollection&amp;lt;T&amp;gt; and IReadOnlyList&amp;lt;T&amp;gt;).&lt;/p&gt; &lt;p&gt;The names of the new interfaces could also be ICollectionReader&amp;lt;T&amp;gt; and IListReader&amp;lt;T&amp;gt; or something similar. Here's how the interface hierarchy would look:&lt;/p&gt;&lt;pre&gt;public class IEnumerable&amp;lt;T&amp;gt; : IEnumerable
{
    IEnumerator&amp;lt;T&amp;gt; GetEnumerator();
}

public class IReadOnlyCollection&amp;lt;T&amp;gt; : IEnumerable&amp;lt;T&amp;gt;
{
    int Count { get; }
    bool Contains(T item);
    void CopyTo(T[] array, int arrayIndex);
}

public class IReadOnlyList&amp;lt;T&amp;gt; : IReadOnlyCollection&amp;lt;T&amp;gt;
{
    T this[int index] { get; }
    int IndexOf(T item);
}

public class ICollection&amp;lt;T&amp;gt; : IReadOnlyCollection&amp;lt;T&amp;gt;
{
    void Clear();
    void Add(T item);
    bool Remove(T item);
    bool IsReadOnly { get; }
}

public class IList&amp;lt;T&amp;gt; : ICollection&amp;lt;T&amp;gt;, IReadOnlyList&amp;lt;T&amp;gt;
{
    T this[int index] { get; set; }
    void Insert(int index, T item);
    void RemoveAt(int index);
}&lt;/pre&gt;
&lt;p&gt;Extending this to dictionaries:&lt;/p&gt;&lt;pre&gt;public class IReadOnlyDictionary&amp;lt;TKey, TValue&amp;gt;
     : IReadOnlyCollection&amp;lt;KeyValuePair&amp;lt;TKey, TValue&amp;gt;&amp;gt;
{
    TValue this[TKey key] { get; }
    bool TryGetValue(TKey key, out TValue value);
    bool ContainsKey(TKey key);
    ICollection&amp;lt;TKey&amp;gt; Keys { get; }
    ICollection&amp;lt;TValue&amp;gt; Values { get; }
}

public class IDictionary&amp;lt;TKey, TValue&amp;gt;
     : ICollection&amp;lt;KeyValuePair&amp;lt;TKey, TValue&amp;gt;&amp;gt;, IReadOnlyDictionary&amp;lt;TKey, TValue&amp;gt;
{
    TValue this[TKey key] { get; set; }
    void Add(TKey key, TValue value);
    bool Remove(TKey key);
}&lt;/pre&gt;
&lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/DotNet" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://technorati.com/tags/BCL" rel="tag"&gt;BCL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Collections" rel="tag"&gt;Collections&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4239291817952415370?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4239291817952415370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4239291817952415370' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4239291817952415370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4239291817952415370'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/12/net-bcl-proposition-read-only.html' title='.NET BCL proposition: read-only collection interfaces'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-8884404479993470424</id><published>2008-10-24T20:41:00.001+02:00</published><updated>2008-10-24T20:41:57.957+02:00</updated><title type='text'>Oslo in the open</title><content type='html'>&lt;p&gt;This morning I started &lt;a href="http://channel9.msdn.com/forums/Coffeehouse/435136-Microsoft-DevLabs/"&gt;a thread on Channel 9&lt;/a&gt; about Microsoft's new initiative called &lt;a href="http://msdn.microsoft.com/en-us/devlabs/default.aspx"&gt;DevLabs&lt;/a&gt;. One of the projects is &lt;a href="http://msdn.microsoft.com/en-us/devlabs/cc950524.aspx"&gt;Small Basic&lt;/a&gt;, a simple BASIC-like programming language that is used to teach kids (and adults) to program. The discussion on Channel 9 was primarily focused on Small Basic, and 1 thing lead to the other, so I started checking out the assemblies that were installed with Small Basic using &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I discovered that Small Basic uses Microsoft's mysterious and much anticipated modeling framework code-named &lt;a href="http://www.microsoft.com/soa/products/oslo.aspx"&gt;Oslo&lt;/a&gt;. You can read how I came to this discovery in &lt;a href="http://channel9.msdn.com/forums/Coffeehouse/435136-Microsoft-DevLabs/?CommentID=435230"&gt;this post&lt;/a&gt; on Channel 9.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/DevLabs" rel="tag"&gt;DevLabs&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Small+Basic" rel="tag"&gt;Small Basic&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Microsoft" rel="tag"&gt;Microsoft&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Oslo" rel="tag"&gt;Oslo&lt;/a&gt;, &lt;a href="http://technorati.com/tags/SOA" rel="tag"&gt;SOA&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Modelling+Framework" rel="tag"&gt;Modeling Framework&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-8884404479993470424?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/8884404479993470424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=8884404479993470424' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8884404479993470424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8884404479993470424'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/10/oslo-in-open.html' title='Oslo in the open'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-3546304718161291617</id><published>2008-09-23T07:27:00.001+02:00</published><updated>2008-09-24T18:59:46.517+02:00</updated><title type='text'>Windows 7 calculator looks awesome</title><content type='html'>&lt;p&gt;The title pretty much says it. I've been following the progress of Windows 7 and nothing has made me say wow yet (yeah, Paint and Wordpad get a ribbon, but that doesn't really make sense to me), until I saw a video that demonstrated the new calculator in Windows 7. It has facilities to calculate with dates, convert units and even has templated calculations.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;EDIT 2008-09-24&lt;/strong&gt;: Apparently the video has been removed from YouTube.&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Found via &lt;a href="http://uxevangelist.blogspot.com/2008/09/windows-7-build-6780-new-videos-and.html"&gt;UX Evangelist&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Windows+7" rel="tag"&gt;Windows 7&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-3546304718161291617?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/3546304718161291617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=3546304718161291617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3546304718161291617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3546304718161291617'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/09/windows-7-calculator-looks-awesome.html' title='Windows 7 calculator looks awesome'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4858625829165016291</id><published>2008-09-07T12:02:00.001+02:00</published><updated>2008-09-07T12:02:19.659+02:00</updated><title type='text'>Google Chrome</title><content type='html'>&lt;p&gt;This week the tech news was primarily dominated by the launch of &lt;a href="http://www.google.com/chrome"&gt;Google Chrome&lt;/a&gt;. I was going to write about it earlier, but because EVERYBODY was blogging about it, I didn't think I could add anything useful (I'm not a &lt;em&gt;"me too"&lt;/em&gt;-blogger). But now that the hype is starting to fade a bit, I want to express my opinion about it.&lt;/p&gt; &lt;p&gt;My first impression: I was pleasantly surprised about the smooth installation, the fast startup and the general performance. But the thing I loved the most, was the subtle and minimalist &lt;acronym title="User Interface"&gt;UI&lt;/acronym&gt;. It has very little features, but I think most &lt;em&gt;normal&lt;/em&gt; people (= non-tech) don't need many features.&lt;/p&gt; &lt;p&gt;Of course, the main criticism you hear about Chrome is the fact that it's a Google product. And Google has created it for data mining purposes, to track your every move. I don't believe this. I think they created it because they NEED a healthy web. They NEED browsers that are powerful enough to run Google's web applications (GMail, Google Docs, Google Maps, ...). And I'm not naïve: I know that Chrome is also a new channel to strengthen Google's position on the web.&lt;/p&gt; &lt;p&gt;To counter the paranoia, I'll refer to Matt Cutts' blog post &lt;a href="http://www.mattcutts.com/blog/google-chrome-communication/"&gt;&lt;em&gt;"Preventing paranoia: when does Google Chrome talk to Google.com?"&lt;/em&gt;&lt;/a&gt;. The only thing I'm a bit worried about is the auto-suggest function that sends whatever you type in the omnibar to Google. Luckily, you can turn it off (see Matt's post). Matt goes into great detail about what gets sent to Google and what gets downloaded from Google. His conclusion should silence the paranoids: &lt;em&gt;You can double-check me because the browser is &lt;a href="http://www.chromium.org/"&gt;open-source&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Google" rel="tag"&gt;Google&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Chrome" rel="tag"&gt;Chrome&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Google+Chrome" rel="tag"&gt;Google Chrome&lt;/a&gt;, &lt;a href="http://technorati.com/tags/web+browser" rel="tag"&gt;web browser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/open+source" rel="tag"&gt;open source&lt;/a&gt;, &lt;a href="http://technorati.com/tags/WebKit" rel="tag"&gt;WebKit&lt;/a&gt;, &lt;a href="http://technorati.com/tags/V8" rel="tag"&gt;V8&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4858625829165016291?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4858625829165016291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4858625829165016291' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4858625829165016291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4858625829165016291'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/09/google-chrome.html' title='Google Chrome'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1957198955711820850</id><published>2008-08-21T13:30:00.001+02:00</published><updated>2008-08-21T13:30:48.213+02:00</updated><title type='text'>Microsoft releases Photosynth</title><content type='html'>&lt;p&gt;&lt;a title="Welcome to Photosynth" href="http://blogs.msdn.com/photosynth/archive/2008/08/20/welcome-to-photosynth.aspx"&gt;Yesterday&lt;/a&gt;, Microsoft released the highly anticipated &lt;a href="http://photosynth.net/"&gt;Photosynth&lt;/a&gt; to the public. Now everyone can start synthing (ooh, new verb). Well, everyone running Windows XP or Windows Vista.&lt;/p&gt; &lt;p&gt;Awesome technology!&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tags/Microsoft" rel="tag"&gt;Microsoft&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Photosynth" rel="tag"&gt;Photosynth&lt;/a&gt;, &lt;a href="http://technorati.com/tags/photography" rel="tag"&gt;photography&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Live+Labs" rel="tag"&gt;Live Labs&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Microsoft+Live+Labs" rel="tag"&gt;Microsoft Live Labs&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1957198955711820850?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1957198955711820850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1957198955711820850' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1957198955711820850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1957198955711820850'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/08/microsoft-releases-photosynth.html' title='Microsoft releases Photosynth'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1217008571673339081</id><published>2008-06-26T10:52:00.001+02:00</published><updated>2008-06-26T10:52:52.207+02:00</updated><title type='text'>Free Dutch e-book about Life hacking</title><content type='html'>&lt;p&gt;Yesterday there was a &lt;a href="http://channel9.msdn.com/forums/Coffeehouse/411817-Free-Dutch-Lifehacking-Ebook-Available-for-Download/"&gt;thread on Channel 9&lt;/a&gt; that pointed to a &lt;a href="http://lifehacking.nl/algemeen/download-nu-gratis-het-lifehacking-ebook/"&gt;free eBook about Life hacking&lt;/a&gt;. It's in Dutch and the &lt;a href="http://www.vanduurenmedia.nl/titel.asp?ID=486"&gt;paper version&lt;/a&gt; costs €19.90. Go download it and start &lt;a href="http://en.wikipedia.org/wiki/Life_hack"&gt;life hacking&lt;/a&gt; (if you understand Dutch, of course).&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tags/life+hack" rel="tag"&gt;Life hack&lt;/a&gt;, &lt;a href="http://technorati.com/tags/lifehack" rel="tag"&gt;lifehack&lt;/a&gt;, &lt;a href="http://technorati.com/tags/life+hacking" rel="tag"&gt;life hacking&lt;/a&gt;, &lt;a href="http://technorati.com/tags/lifehacking" rel="tag"&gt;lifehacking&lt;/a&gt;, &lt;a href="http://technorati.com/tags/free+ebook" rel="tag"&gt;free e-book&lt;/a&gt;, &lt;a href="http://technorati.com/tags/information+overload" rel="tag"&gt;information overload&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1217008571673339081?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1217008571673339081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1217008571673339081' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1217008571673339081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1217008571673339081'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/06/free-dutch-e-book-about-life-hacking.html' title='Free Dutch e-book about Life hacking'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-841084789206248285</id><published>2008-04-21T15:24:00.001+02:00</published><updated>2008-04-22T21:03:34.214+02:00</updated><title type='text'>Making your password TextBox more secure</title><content type='html'>&lt;p&gt;If you use a Windows Forms &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.textbox.aspx"&gt;TextBox&lt;/a&gt; to let your users enter a password, you should know it's not very secure: external applications can get the password from the &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.textbox.aspx"&gt;TextBox&lt;/a&gt; by sending it the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms632627(VS.85).aspx"&gt;WM_GETTEXT&lt;/a&gt; message. There are even applications written specifically to do this. If you want to prevent this, you can use the following control that is derived from &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.textbox.aspx"&gt;System.Windows.Forms.TextBox&lt;/a&gt; and that prevents external applications from getting the password via &lt;a href="http://msdn2.microsoft.com/en-us/library/ms632627(VS.85).aspx"&gt;WM_GETTEXT&lt;/a&gt;. Just use it instead of the regular &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.textbox.aspx"&gt;TextBox&lt;/a&gt; for password fields.&lt;/p&gt;&lt;pre&gt;using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace TC.WinForms
{
    /// &amp;lt;summary&amp;gt;Represents a text box control for entering passwords.&amp;lt;/summary&amp;gt;
    [ToolboxItem(true), ToolboxBitmap(typeof(TextBox))]
    public class PasswordTextBox : TextBox
    {
        /// &amp;lt;summary&amp;gt;Initializes a new instance of the &amp;lt;see cref="T:PasswordTextBox" /&amp;gt; class.&amp;lt;/summary&amp;gt;
        public PasswordTextBox()
        {
            base.UseSystemPasswordChar = true;
        }

        bool fAccessText;
        /// &amp;lt;summary&amp;gt;Gets or sets the current text in the &amp;lt;see cref="T:TextBox"/&amp;gt;.&amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;The text displayed in the control.&amp;lt;/returns&amp;gt;
        public override string Text
        {
            get
            {
                fAccessText = true;
                try { return base.Text; }
                finally { fAccessText = false; }
            }
            set
            {
                fAccessText = true;
                try { base.Text = value; }
                finally { fAccessText = false; }
            }
        }

        /// &amp;lt;summary&amp;gt;Gets the length of text in the control.&amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;The number of characters contained in the text of the control.&amp;lt;/returns&amp;gt;
        public override int TextLength
        {
            get
            {
                fAccessText = true;
                try { return base.TextLength; }
                finally { fAccessText = false; }
            }
        }

        /// &amp;lt;summary&amp;gt;Processes Windows message.&amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="m"&amp;gt;The Windows &amp;lt;see cref="T:Message" /&amp;gt; to process.&amp;lt;/param&amp;gt;
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_GETTEXT:
                case WM_GETTEXTLENGTH:
                    if (!fAccessText)
                    {
                        m.Result = IntPtr.Zero;
                        return;
                    }
                    else break;
                case EM_SETPASSWORDCHAR: return;
            }

            base.WndProc(ref m);
        }

        const int WM_GETTEXT = 0x000D, WM_GETTEXTLENGTH = 0x000E, EM_SETPASSWORDCHAR = 0x00CC;
    }
}&lt;/pre&gt;
&lt;p&gt;&lt;small&gt;&lt;b&gt;EDIT&lt;/b&gt;: I added code to also ignore &lt;a href="http://msdn2.microsoft.com/en-us/library/bb761653(VS.85).aspx"&gt;EM_SETPASSWORDCHAR&lt;/a&gt; which can also be used to make the password visible.&lt;br&gt;&lt;b&gt;EDIT 2&lt;/b&gt; (2008-04-22): I fixed the documentation tags in the code.&lt;br&gt;&lt;b&gt;EDIT 3&lt;/b&gt; (2008-04-22): I fixed some bugs that denied access to the password from within your program.&lt;/small&gt;&lt;/p&gt;
&lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Windows+Forms" rel="tag"&gt;Windows Forms&lt;/a&gt;, &lt;a href="http://technorati.com/tags/WinForms" rel="tag"&gt;WinForms&lt;/a&gt;, &lt;a href="http://technorati.com/tags/password" rel="tag"&gt;password&lt;/a&gt;, &lt;a href="http://technorati.com/tags/TextBox" rel="tag"&gt;TextBox&lt;/a&gt;, &lt;a href="http://technorati.com/tags/security" rel="tag"&gt;security&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-841084789206248285?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/841084789206248285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=841084789206248285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/841084789206248285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/841084789206248285'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/04/making-your-password-textbox-more.html' title='Making your password TextBox more secure'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1020177718746544943</id><published>2008-04-01T08:01:00.001+02:00</published><updated>2009-07-11T17:08:43.450+02:00</updated><title type='text'>Silverlight Rehab</title><content type='html'>&lt;p&gt;I previously linked to &lt;a href="http://blog.tcx.be/2008/02/life-at-microsoft.html"&gt;a video made by some Microsoft employees&lt;/a&gt;. Now they created another funny one, this time about &lt;a href="http://www.on10.net/blogs/tina/Silverlight-Rehab/"&gt;Silverlight addicts&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Microsoft" rel="tag"&gt;Microsoft&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Channel+10" rel="tag"&gt;Channel 10&lt;/a&gt;, &lt;a href="http://technorati.com/tags/comedy" rel="tag"&gt;comedy&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Silverlight" rel="tag"&gt;Silverlight&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1020177718746544943?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1020177718746544943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1020177718746544943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1020177718746544943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1020177718746544943'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/04/silverlight-rehab.html' title='Silverlight Rehab'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-5708700770066696108</id><published>2008-03-29T18:57:00.001+01:00</published><updated>2008-03-29T18:57:52.876+01:00</updated><title type='text'>Opera Widget tip: zooming in</title><content type='html'>&lt;p&gt;I just discovered something cool: you can make your &lt;a href="http://widgets.opera.com/"&gt;Opera Widgets&lt;/a&gt; larger by zooming in. I just opened my favorite widget (&lt;a href="http://widgets.opera.com/widget/3903/"&gt;touchTheSky&lt;/a&gt;: a weather forecast widget), and the text was a bit small. Usually, when I'm using Opera and I'm reading a web site with a small font, I press Ctrl and use the mouse wheel to zoom in. I just noticed that I unconsciously did the same with the touchTheSky widget and to my surprise it worked. Cool feature.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Opera" rel="tag"&gt;Opera&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Widgets" rel="tag"&gt;Widgets&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Opera+Widgets" rel="tag"&gt;Opera Widgets&lt;/a&gt;, &lt;a href="http://technorati.com/tags/touchTheSky" rel="tag"&gt;touchTheSky&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-5708700770066696108?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/5708700770066696108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=5708700770066696108' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5708700770066696108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5708700770066696108'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/03/opera-widget-tip-zooming-in.html' title='Opera Widget tip: zooming in'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1877700496132435716</id><published>2008-02-13T07:53:00.001+01:00</published><updated>2008-02-13T07:53:40.778+01:00</updated><title type='text'>Life at Microsoft</title><content type='html'>&lt;p&gt;The guys over at &lt;a href="http://on10.net/"&gt;Channel 10&lt;/a&gt; made an awesome video to show what &lt;a href="http://on10.net/blogs/tina/Life-At-Microsoft/"&gt;life at Microsoft&lt;/a&gt; is &lt;em&gt;really&lt;/em&gt; like. Very funny. &lt;a href="http://on10.net/blogs/tina/Life-At-Microsoft/"&gt;Go watch it&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Microsoft" rel="tag"&gt;Microsoft&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Channel+10" rel="tag"&gt;Channel 10&lt;/a&gt;, &lt;a href="http://technorati.com/tags/comedy" rel="tag"&gt;comedy&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1877700496132435716?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1877700496132435716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1877700496132435716' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1877700496132435716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1877700496132435716'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/02/life-at-microsoft.html' title='Life at Microsoft'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1317988381837360358</id><published>2008-02-07T07:35:00.001+01:00</published><updated>2008-02-07T07:35:10.894+01:00</updated><title type='text'>Video: 12 years of Opera</title><content type='html'>&lt;p&gt;&lt;a href="http://operawatch.com/"&gt;Daniel Goldman&lt;/a&gt; has posted a &lt;a href="http://operawatch.com/news/2008/02/video-opera-browser-12-year-history.html"&gt;cool little video of Opera's 12-year history&lt;/a&gt;. In just 2 minutes it shows the long road &lt;a href="http://www.opera.com/"&gt;Opera&lt;/a&gt; has walked, the many versions of its desktop browser, mobile browser, mini browser and browser for devices.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Opera" rel="tag"&gt;Opera&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Web+Browser" rel="tag"&gt;Web Browser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Opera+Mobile" rel="tag"&gt;Opera Mobile&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Opera+Mini" rel="tag"&gt;Opera Mini&lt;/a&gt;, &lt;a href="http://technorati.com/tags/video" rel="tag"&gt;video&lt;/a&gt;, &lt;a href="http://technorati.com/tags/history" rel="tag"&gt;history&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1317988381837360358?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1317988381837360358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1317988381837360358' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1317988381837360358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1317988381837360358'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/02/video-12-years-of-opera.html' title='Video: 12 years of Opera'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-7381239392117560419</id><published>2008-02-01T13:10:00.000+01:00</published><updated>2008-02-01T13:17:14.450+01:00</updated><title type='text'>PowerShell + Speech API</title><content type='html'>I just read &lt;a href="http://blogs.msdn.com/marcelolr/archive/2008/01/31/say-you-say-me-say-task-complete.aspx"&gt;a blog post about using the Speech API in command-line scripts&lt;/a&gt; on &lt;a href="http://blogs.msdn.com/marcelolr/default.aspx"&gt;Marcelo's Weblog&lt;/a&gt;. So I had to try it but instead of using JScript, I wrote it in &lt;a href="http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx"&gt;PowerShell&lt;/a&gt;. It's so easy and fun:&lt;PRE&gt;$v = New-Object -ComObject SAPI.SpVoice
$v.Speak("Who let the dogs out?")&lt;/PRE&gt;
&lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tag/PowerShell" rel="tag"&gt;PowerShell&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Speech" rel="tag"&gt;Speech&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Speech+API" rel="tag"&gt;Speech API&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-7381239392117560419?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/7381239392117560419/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=7381239392117560419' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/7381239392117560419'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/7381239392117560419'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/02/powershell-speech-api.html' title='PowerShell + Speech API'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-6276626697407628042</id><published>2008-01-27T12:46:00.001+01:00</published><updated>2008-01-27T12:46:38.818+01:00</updated><title type='text'>Garden Gnome Carnage</title><content type='html'>&lt;p&gt;I just watched a video about a game called &lt;a href="http://www.remar.se/daniel/ggc.php"&gt;Garden Gnome Carnage&lt;/a&gt;. I haven't downloaded it yet, but it looks crazy: &lt;a href="http://www.youtube.com/watch?v=o-o1nVjKejg"&gt;the video that explains how to play GGC&lt;/a&gt; is pretty weird. Don't worry if you experience some &lt;acronym title="What the Fuck?"&gt;WTF&lt;/acronym&gt;-moments while watching it.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Garden+Gnome+Carnage" rel="tag"&gt;Garden Gnome Carnage&lt;/a&gt;, &lt;a href="http://technorati.com/tags/GGC" rel="tag"&gt;GGC&lt;/a&gt;, &lt;a href="http://technorati.com/tags/game" rel="tag"&gt;game&lt;/a&gt;, &lt;a href="http://technorati.com/tags/video" rel="tag"&gt;video&lt;/a&gt;, &lt;a href="http://technorati.com/tags/indy+games" rel="tag"&gt;indy games&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-6276626697407628042?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/6276626697407628042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=6276626697407628042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6276626697407628042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6276626697407628042'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2008/01/garden-gnome-carnage.html' title='Garden Gnome Carnage'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1450308485741521165</id><published>2007-11-11T11:46:00.001+01:00</published><updated>2007-11-11T11:46:35.787+01:00</updated><title type='text'>The Making of Peggle</title><content type='html'>&lt;p&gt;&lt;a href="http://www.popcap.com/"&gt;PopCap&lt;/a&gt; released an article, complete with pictures and videos, about how they created their awesome game Peggle (&lt;a title="Download Peggle" href="http://www.popcap.com/games/peggle"&gt;download&lt;/a&gt; or &lt;a title="Play Peggle online" href="http://www.popcap.com/games/free/peggle"&gt;play online&lt;/a&gt;). This cool article clearly explains the entire development process of a great game. Go read &lt;a href="http://www.popcap.com/extras/makingpeggle/big_idea.php"&gt;The Making of Peggle&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/PopCap" rel="tag"&gt;PopCap&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Peggle" rel="tag"&gt;Peggle&lt;/a&gt;, &lt;a href="http://technorati.com/tags/game+development" rel="tag"&gt;game development&lt;/a&gt;, &lt;a href="http://technorati.com/tags/casual+gaming" rel="tag"&gt;casual gaming&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1450308485741521165?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1450308485741521165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1450308485741521165' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1450308485741521165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1450308485741521165'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/11/making-of-peggle.html' title='The Making of Peggle'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4322385451564130469</id><published>2007-11-08T07:45:00.001+01:00</published><updated>2007-11-08T07:45:31.085+01:00</updated><title type='text'>Opera Mini 4 released</title><content type='html'>&lt;p&gt;Opera has released &lt;a href="http://www.operamini.com/"&gt;Opera Mini 4&lt;/a&gt;. New features include &lt;a href="http://link.opera.com/"&gt;Opera Link&lt;/a&gt; (a way of synchronizing the bookmarks on your mobile phone with the bookmarks on your desktop PC), a virtual mouse cursor, enhanced Small Screen Rendering and &lt;a title="Opera Mini features" href="http://www.operamini.com/features/"&gt;much more&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Opera" rel="tag"&gt;Opera&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Opera+Mini" rel="tag"&gt;Opera Mini&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Web+Browser" rel="tag"&gt;Web Browser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Java" rel="tag"&gt;Java&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Mobile+Phone" rel="tag"&gt;Mobile Phone&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4322385451564130469?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4322385451564130469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4322385451564130469' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4322385451564130469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4322385451564130469'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/11/opera-mini-4-released.html' title='Opera Mini 4 released'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-2318703188729435816</id><published>2007-11-01T12:09:00.001+01:00</published><updated>2007-11-01T12:11:26.199+01:00</updated><title type='text'>Cool new Opera skin</title><content type='html'>&lt;p&gt;&lt;a title="Screenshot of new Opera skin: Vista Black and Black" href="http://files.myopera.com/TommyCarlier/albums/122489/NewOperaSkin.png"&gt;&lt;img src="http://files.myopera.com/TommyCarlier/albums/122489/NewOperaSkin_thumb.png" align="right" border="0"&gt;&lt;/a&gt; I just downloaded this cool new &lt;a href="http://www.opera.com"&gt;Opera&lt;/a&gt; &lt;a href="http://my.opera.com/community/customize/skins"&gt;skin&lt;/a&gt; called &lt;a href="http://my.opera.com/community/customize/skins/info/?id=7451"&gt;Vista Black and Black&lt;/a&gt;. It combines elements from Vista, IE7 and Office 2007. There are a lot of skins that emulate the Vista-look or IE7 or Office 2007, but none of them really looked fine for me. But I think this one looks awesome.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Opera" rel="tag"&gt;Opera&lt;/a&gt;, &lt;a href="http://technorati.com/tags/skin" rel="tag"&gt;skin&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Vista" rel="tag"&gt;Vista&lt;/a&gt;, &lt;a href="http://technorati.com/tags/IE7" rel="tag"&gt;IE7&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Office+2007" rel="tag"&gt;Office 2007&lt;/a&gt;.&lt;/div&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-2318703188729435816?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/2318703188729435816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=2318703188729435816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2318703188729435816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2318703188729435816'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/11/cool-new-opera-skin.html' title='Cool new Opera skin'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-809680478544487813</id><published>2007-11-01T11:00:00.001+01:00</published><updated>2007-11-01T11:00:08.853+01:00</updated><title type='text'>TC Animation Library</title><content type='html'>&lt;p&gt;I just released the source code of a Windows Forms animation library I wrote last weekend. I first didn't want to release the source code because the animations looked terrible.&lt;/p&gt; &lt;p&gt;I knew the code I wrote was good and should work, but it ran horribly. The UI would just freeze when 1 animation ran; running multiple animations simultaneously was impossible. This morning I woke up and had a mad idea: to slow down the animation. The reason the UI would freeze was because all the animation steps were performed on the UI-thread and apparently the animation system flooded the UI-thread with work to do, so the normal UI-activities (painting controls, handling input, ...) were severely delayed. By adding 1 line of code (&lt;code&gt;Thread.Sleep(5);&lt;/code&gt;) to the animation loop, I managed to make the animations run fluently while keeping the UI responsive.&lt;/p&gt; &lt;p&gt;You can find the source code in the Channel 9 Sandbox, &lt;a title="Download the TC Animation Library source code" href="http://channel9.msdn.com/ShowPost.aspx?PostID=352665"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Windows+Forms" rel="tag"&gt;Windows Forms&lt;/a&gt;, &lt;a href="http://technorati.com/tags/WinForms" rel="tag"&gt;WinForms&lt;/a&gt;, &lt;a href="http://technorati.com/tags/animation" rel="tag"&gt;animation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/source+code" rel="tag"&gt;source code&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://technorati.com/tags/open+source" rel="tag"&gt;open source&lt;/a&gt;.&lt;/div&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-809680478544487813?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/809680478544487813/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=809680478544487813' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/809680478544487813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/809680478544487813'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/11/tc-animation-library.html' title='TC Animation Library'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1772642672225661422</id><published>2007-10-03T22:34:00.001+02:00</published><updated>2007-10-03T22:34:43.106+02:00</updated><title type='text'>.NET Framework source code released</title><content type='html'>&lt;p&gt;I wasn't going to blog about this, but I just find it remarkable how many people did. The last few hours I received an unusual amount of newsfeed messages about it: &lt;div&gt;&lt;a title=".NET Framework source code released" href="http://files.myopera.com/TommyCarlier/albums/122489/DotNetSourceCode.png"&gt;&lt;img height="480" alt=".NET Framework source code released" src="http://files.myopera.com/TommyCarlier/albums/122489/DotNetSourceCode.png" width="589" border="0"&gt;&lt;/a&gt;&lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/.NET+Framework" rel="tag"&gt;.NET Framework&lt;/a&gt;, &lt;a href="http://technorati.com/tags/source+code" rel="tag"&gt;source code&lt;/a&gt;.&lt;/div&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1772642672225661422?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1772642672225661422/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1772642672225661422' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1772642672225661422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1772642672225661422'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/10/net-framework-source-code-released.html' title='.NET Framework source code released'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1460290772771958534</id><published>2007-09-03T18:55:00.001+02:00</published><updated>2007-09-03T18:55:19.340+02:00</updated><title type='text'>Opera 9.5: preview of new features</title><content type='html'>&lt;p&gt;&lt;a title="Exclusive Opera 9.5 Features &amp;amp; Video" href="http://cybernetnews.com/2007/09/03/cybernotes-exclusive-opera-95-features-video"&gt;CyberNet has just published an article with a video&lt;/a&gt; that shows some of the new features of &lt;a href="http://www.opera.com"&gt;Opera 9.5&lt;/a&gt;. Apparently they made the rendering engine even faster than it already is, while consuming even less memory and at the same time adding a lot of CSS, JavaScript, AJAX and compatibility features. Wow.&lt;/p&gt; &lt;p&gt;Functional new features include an easy way to open the current page in a different browser, restoring closed windows, synchronizing bookmarks with &lt;a href="http://my.opera.com"&gt;My Opera&lt;/a&gt;, full history search, major improvements to the mail client, etc...&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Opera" rel="tag"&gt;Opera&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Web+Browser" rel="tag"&gt;Web Browser&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1460290772771958534?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1460290772771958534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1460290772771958534' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1460290772771958534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1460290772771958534'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/09/opera-95-preview-of-new-features.html' title='Opera 9.5: preview of new features'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4381238119557719070</id><published>2007-08-18T11:27:00.002+02:00</published><updated>2009-03-06T12:43:36.173+01:00</updated><title type='text'>Transceiver</title><content type='html'>&lt;p&gt;For the past 3 years, our company has been developing a new technology for secure file delivery. This week we officially released the technology called &lt;a href="http://www.transceiver.biz/"&gt;Transceiver&lt;/a&gt;. It works a bit like e-mail, but for transmitting files instead of mail messages. Here are some of the features:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Designed to be secure: end-to-end security is the primary goal.  &lt;li&gt;Designed to be private: network sniffing will not reveal who is sending files to who.  &lt;li&gt;Uses a white-list system to avoid the problem of spam: you will only receive files from people you add to your list of &lt;em&gt;Trusted Addresses&lt;/em&gt;.  &lt;li&gt;No file size limitation (of course it's limited to the available disk space).  &lt;li&gt;If you send a file to someone, you can track the entire transmission: you can see exactly where the file is, and when it moves from machine to machine.&lt;li&gt;We're developing different client applications for different scenarios:&lt;ul&gt;&lt;li&gt;&lt;b&gt;&lt;a href="http://www.transceiver.biz/products/communicator"&gt;Transceiver Communicator&lt;/a&gt;&lt;/b&gt;: an interactive Windows application that works like a regular e-mail client. On top of Communicator, we've also developed add-ins for Word 2003, Word 2007, Excel 2003 and Excel 2007 that talk to Communicator. We'll also release a .NET 2.0 library for other developers to integrate with Communicator.&lt;li&gt;&lt;b&gt;&lt;a href="http://www.transceiver.biz/products/automator"&gt;Transceiver Automator&lt;/a&gt;&lt;/b&gt;: an application that runs as a Windows service and that can transmit and receive files automatically. It can be configured to handle incoming files or transmitting files to predefined destinations.&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We encourage people to try out the Transceiver technology for free: we've deployed a server and a website where you can &lt;a href="http://www.transceiver.biz/get-started/request-account"&gt;request an account&lt;/a&gt; (free for 3 months).&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Transceiver" rel="tag"&gt;Transceiver&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Transceiver+Communicator" rel="tag"&gt;Transceiver Communicator&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Transceiver+Automator" rel="tag"&gt;Transceiver Automator&lt;/a&gt;, &lt;a href="http://technorati.com/tags/security" rel="tag"&gt;security&lt;/a&gt;, &lt;a href="http://technorati.com/tags/file+delivery" rel="tag"&gt;file delivery&lt;/a&gt;, &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4381238119557719070?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4381238119557719070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4381238119557719070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4381238119557719070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4381238119557719070'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/08/transceiver.html' title='Transceiver'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-8496390879041761218</id><published>2007-07-01T10:38:00.001+02:00</published><updated>2007-07-01T10:38:52.040+02:00</updated><title type='text'>Calctor 2.1.1</title><content type='html'>&lt;p&gt;This is a small update to Calctor. No additional functionality has been added. I just made some modifications so you can install it on Windows Vista.&lt;/p&gt; &lt;p&gt;You can download it &lt;a title="Calctor 2.1.1 download" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Windows+Vista" rel="tag"&gt;Windows Vista&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-8496390879041761218?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/8496390879041761218/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=8496390879041761218' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8496390879041761218'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8496390879041761218'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/07/calctor-211.html' title='Calctor 2.1.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4005675980313139767</id><published>2007-06-03T12:50:00.001+02:00</published><updated>2007-06-03T12:50:37.527+02:00</updated><title type='text'>New version of Windows Live Writer</title><content type='html'>&lt;p&gt;I just installed the new version of &lt;a href="http://windowslivewriter.spaces.live.com/"&gt;Windows Live Writer&lt;/a&gt;. It's still beta, but it's a lot better than the previous beta version. It seemed for a while that development of WLW had stopped (no updates or news on the WLW blog since November from last year), but I'm glad they're still working on it. This has to be one of the coolest apps Microsoft is currently developing.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Windows+Live+Writer" rel="tag"&gt;Windows Live Writer&lt;/a&gt;, &lt;a href="http://technorati.com/tags/blogging" rel="tag"&gt;blogging&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4005675980313139767?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4005675980313139767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4005675980313139767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4005675980313139767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4005675980313139767'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/06/new-version-of-windows-live-writer.html' title='New version of Windows Live Writer'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1407711363902268077</id><published>2007-05-18T16:18:00.001+02:00</published><updated>2007-05-18T16:18:10.815+02:00</updated><title type='text'>Buzzword screencast</title><content type='html'>I just watched a &lt;a title="Buzzword demo" href="http://www.peapodcast.com/danbcast/buzzworddemo/"&gt;screencast of Buzzword&lt;/a&gt; (recorded by &lt;a href="http://danbricklin.com/log"&gt;Dan Bricklin&lt;/a&gt;), &lt;a href="http://www.virtub.com/"&gt;Virtual Ubiquity&lt;/a&gt;'s&amp;nbsp;not-yet-released word processor for the web that looks very promising. It's a &lt;a href="http://www.adobe.com/products/flash/"&gt;Flash&lt;/a&gt;/&lt;a href="http://www.adobe.com/products/flex/"&gt;Flex&lt;/a&gt; application that looks so much better than any web word processor I've seen before. I'll be keeping an eye on this.  &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Buzzword" rel="tag"&gt;Buzzword&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Virtual+Ubiquity" rel="tag"&gt;Virtual Ubiquity&lt;/a&gt;, &lt;a href="http://technorati.com/tags/word+processor" rel="tag"&gt;word processor&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Flash" rel="tag"&gt;Flash&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Flex" rel="tag"&gt;Flex&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1407711363902268077?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1407711363902268077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1407711363902268077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1407711363902268077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1407711363902268077'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/05/buzzword-screencast.html' title='Buzzword screencast'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-2552352085313423483</id><published>2007-05-06T12:42:00.001+02:00</published><updated>2007-05-06T12:42:25.316+02:00</updated><title type='text'>slimCODE against diabetes</title><content type='html'>I just read on &lt;a title="slimCODE blog" href="http://www.slimcode.com:80/cs/blogs/default.aspx"&gt;Martin Plante's blog&lt;/a&gt; that he's &lt;a href="http://www.slimcode.com:80/cs/blogs/martin/archive/2007/05/06/help-fight-diabetes-buy-slimkeys.aspx"&gt;donating this week's earnings of his slimKEYS application&lt;/a&gt; to &lt;a href="http://www.hanselman.com/blog/TeamHanselmanAndDiabetesWalk2007.aspx"&gt;Team Hanselman&lt;/a&gt; to fight diabetes. slimKEYS is a cool product, and this is a great initiative.  &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/slimCODE" rel="tag"&gt;slimCODE&lt;/a&gt;, &lt;a href="http://technorati.com/tags/slimKEYS" rel="tag"&gt;slimKEYS&lt;/a&gt;, &lt;a href="http://technorati.com/tags/diabetes" rel="tag"&gt;diabetes&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Team+Hanselman" rel="tag"&gt;Team Hanselman&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-2552352085313423483?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/2552352085313423483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=2552352085313423483' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2552352085313423483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2552352085313423483'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/05/slimcode-against-diabetes.html' title='slimCODE against diabetes'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-5935009832946936965</id><published>2007-05-03T22:11:00.001+02:00</published><updated>2009-07-11T17:16:18.127+02:00</updated><title type='text'>Writing a parser: overview</title><content type='html'>Here's a quick overview of the different blog posts in the series &lt;em&gt;Writing a parser&lt;/em&gt;:  &lt;ul&gt; &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser.html"&gt;Introduction&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-basic-terminology.html"&gt;Basic Terminology&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-introduction-to-adl.html"&gt;Introduction to ADL&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-base-vs2005-solution.html"&gt;Base VS2005 solution&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-adl-tokens.html"&gt;ADL tokens&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-adl-tokenizer.html"&gt;ADL Tokenizer&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-adl-tokenizer-correction.html"&gt;ADL Tokenizer correction&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/04/writing-parser-adl-parser-node-types.html"&gt;ADL parser node types&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/05/writing-parser-adl-parser-part-1.html"&gt;ADL Parser - part 1&lt;/a&gt;  &lt;li&gt;&lt;a href="http://blog.tcx.be/2007/05/writing-parser-adl-parser-part-2.html"&gt;ADL Parser - part 2&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Programming+Language" rel="tag"&gt;Programming Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-5935009832946936965?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/5935009832946936965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=5935009832946936965' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5935009832946936965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5935009832946936965'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/05/writing-parser-overview.html' title='Writing a parser: overview'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4219512230675043184</id><published>2007-05-03T22:03:00.001+02:00</published><updated>2009-07-11T17:17:24.465+02:00</updated><title type='text'>Writing a parser: ADL Parser - part 2</title><content type='html'>In &lt;a title="Writing a parse: ADL Parser - part 1" href="http://blog.tcx.be/2007/05/writing-parser-adl-parser-part-1.html"&gt;the previous part&lt;/a&gt; we wrote the first Parser methods, now we'll write the methods for parsing expressions. In the &lt;a href="http://blog.tcx.be/2007/04/writing-parser-introduction-to-adl.html"&gt;introduction to ADL&lt;/a&gt;, I showed the order in which expressions are evaluated. To parse expressions, we'll reverse the order and assume that everything is an AND-expression (lowest precedence): &lt;pre&gt;Expression ParseExpression()
{
    return ParseAndExpression();
}&lt;/pre&gt;An AND-expression consists of one or more OR-expressions, separated by &lt;code&gt;and&lt;/code&gt; operators: &lt;pre&gt;Expression ParseAndExpression()
{
    Expression lNode = ParseOrExpression();

    while (!AtEndOfSource &amp;amp;&amp;amp; fCurrentToken.Equals(TokenType.Word, "and"))
    {
        ReadNextToken(); // skip 'and'
        lNode = new AndExpression(lNode, ParseOrExpression());
    }

    return lNode;
}&lt;/pre&gt;An OR-expression consists of one or more comparisons, separated by &lt;code&gt;or&lt;/code&gt; operators: &lt;pre&gt;Expression ParseOrExpression()
{
    Expression lNode = ParseComparison();

    while (!AtEndOfSource &amp;amp;&amp;amp; fCurrentToken.Equals(TokenType.Word, "or"))
    {
        ReadNextToken(); // skip 'or'
        lNode = new OrExpression(lNode, ParseComparison());
    }

    return lNode;
}&lt;/pre&gt;A comparison is an additive expression, or 2 additive expressions separated by a comparison operator: &lt;pre&gt;Expression ParseComparison()
{
    Expression lNode = ParseAdditiveExpression();

    if (!AtEndOfSource &amp;amp;&amp;amp; fCurrentToken.Type == TokenType.Symbol)
    {
        ComparisonOperator lOperator;
        switch (fCurrentToken.Value)
        {
            case "==": lOperator = ComparisonOperator.Equal; break;
            case "&amp;lt;&amp;gt;": lOperator = ComparisonOperator.NotEquals; break;
            case "&amp;lt;":  lOperator = ComparisonOperator.LessThan; break;
            case "&amp;gt;":  lOperator = ComparisonOperator.GreaterThan; break;
            case "&amp;lt;=": lOperator = ComparisonOperator.LessThanOrEqual; break;
            case "&amp;gt;=": lOperator = ComparisonOperator.GreaterThanOrEqual; break;
            default: return lNode;
        }
        ReadNextToken(); // skip comparison operator
        return new Comparison(lOperator, lNode, ParseAdditiveExpression());
    }
    else return lNode;
}&lt;/pre&gt;An additive expression consists of one or more multiplicative expressions, separated by &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;-&lt;/code&gt; operators: &lt;pre&gt;Expression ParseAdditiveExpression()
{
    Expression lNode = ParseMultiplicativeExpression();

    while (!AtEndOfSource)
    {
        if (fCurrentToken.Equals(TokenType.Symbol, "+"))
        {
            ReadNextToken(); // skip '+'
            lNode = new Addition(lNode, ParseMultiplicativeExpression());
        }
        else if (fCurrentToken.Equals(TokenType.Symbol, "-"))
        {
            ReadNextToken(); // skip '-'
            lNode = new Subtraction(lNode, ParseMultiplicativeExpression());
        }
        else break;
    }

    return lNode;
}&lt;/pre&gt;A multiplicative expression consists of one or more unary expressions, separated by &lt;code&gt;*&lt;/code&gt; or &lt;code&gt;/&lt;/code&gt; operators: &lt;pre&gt;Expression ParseMultiplicativeExpression()
{
    Expression lNode = ParseUnaryExpression();

    while (!AtEndOfSource)
    {
        if (fCurrentToken.Equals(TokenType.Symbol, "*"))
        {
            ReadNextToken(); // skip '*'
            lNode = new Multiplication(lNode, ParseUnaryExpression());
        }
        else if (fCurrentToken.Equals(TokenType.Symbol, "/"))
        {
            ReadNextToken(); // skip '/'
            lNode = new Division(lNode, ParseUnaryExpression());
        }
        else break;
    }

    return lNode;
}&lt;/pre&gt;A unary expression is a base expression, optionally prefixed by a &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;not&lt;/code&gt; operator: &lt;pre&gt;Expression ParseUnaryExpression()
{
    CheckForUnexpectedEndOfSource();

    if (fCurrentToken.Equals(TokenType.Symbol, "-"))
    {
        ReadNextToken(); // skip '-'
        return new Negation(ParseBaseExpression());
    }
    else if (fCurrentToken.Equals(TokenType.Word, "not"))
    {
        ReadNextToken(); // skip 'not'
        return new NotExpression(ParseBaseExpression());
    }
    else if (fCurrentToken.Equals(TokenType.Symbol, "+"))
        ReadNextToken(); // skip '+'

    return ParseBaseExpression();
}&lt;/pre&gt;A base expression is either an integer constant, a string constant, a variable, a function call or a group expression: &lt;pre&gt;Expression ParseBaseExpression()
{
    CheckForUnexpectedEndOfSource();

    switch(fCurrentToken.Type)
    {
        case TokenType.Integer: return ParseIntegerConstant();
        case TokenType.String: return ParseStringConstant();
        case TokenType.Word: return ParseVariableOrFunctionCall();
        default: // TokenType.Symbol
            if (fCurrentToken.Value == "(")
                return ParseGroupExpression();
            else throw new ParserException("Expected an expression.");
    }
}&lt;/pre&gt;A group expression is an expression between parenthesis: &lt;pre&gt;Expression ParseGroupExpression()
{
    ReadNextToken(); // skip '('
    Expression lExpression = ParseExpression();
    SkipExpected(TokenType.Symbol, ")"); // skip ')'
    return lExpression;
}&lt;/pre&gt;A variable and a function call both start with an identifier. To disambiguate, we'll have to read the next token: &lt;pre&gt;Expression ParseVariableOrFunctionCall()
{
    string lName = fCurrentToken.Value;
    ReadNextToken();
    if (!AtEndOfSource &amp;amp;&amp;amp; fCurrentToken.Equals(TokenType.Symbol, "("))
        return ParseFunctionCall(lName);
    else return new Variable(lName);
}&lt;/pre&gt;A string constant is just the read string token: &lt;pre&gt;Expression ParseStringConstant()
{
    string lValue = fCurrentToken.Value;
    ReadNextToken(); // skip string constant
    return new StringConstant(lValue);
}&lt;/pre&gt;An integer constant has to be parsed from the string value: &lt;pre&gt;Expression ParseIntegerConstant()
{
    int lValue;
    if (int.TryParse(fCurrentToken.Value, out lValue))
    {
        ReadNextToken(); // skip integer constant
        return new IntegerConstant(lValue);
    }
    else throw new ParserException("Invalid integer constant " + fCurrentToken.Value);
}&lt;/pre&gt;A function call consists of an identifier, followed by zero or more arguments between parentheses: &lt;pre&gt;FunctionCall ParseFunctionCall(string name)
{
    ReadNextToken(); // skip '('
    CheckForUnexpectedEndOfSource();

    List&lt;expression&gt; lArguments = new List&lt;expression&gt;();
    if (!fCurrentToken.Equals(TokenType.Symbol, ")")
    {
        lArguments.Add(ParseExpression());
        CheckForUnexpectedEndOfSource();

        while (fCurrentToken.Equals(TokenType.Symbol, ","))
        {
            ReadNextToken(); // skip ','
            lArguments.Add(ParseExpression());
            CheckForUnexpectedEndOfSource();
        }

        if (!fCurrentToken.Equals(TokenType.Symbol, ")")
            throw new ParserException("Expected ')'.");
    }

    ReadNextToken(); // skip ')'
    return new FunctionCall(name, lArguments.ToArray());
}&lt;/pre&gt;Now our parser is ready. To test the parser, I've created a test application that reads code from a TextBox, parses it and shows the parse tree in a TreeView. I'm not going to show the source code of the test application in this post, but you can download the complete Visual Studio 2005 solution with both projects (TC.Adl and TC.Adl.Test) &lt;a href="http://my.opera.com/TommyCarlier/blog/writing-a-parser-downloads"&gt;here&lt;/a&gt;. 
&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Programming+Language" rel="tag"&gt;Programming Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4219512230675043184?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4219512230675043184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4219512230675043184' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4219512230675043184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4219512230675043184'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/05/writing-parser-adl-parser-part-2.html' title='Writing a parser: ADL Parser - part 2'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-3031560026365870755</id><published>2007-05-03T21:00:00.001+02:00</published><updated>2007-05-03T21:00:31.491+02:00</updated><title type='text'>Writing a parser: ADL Parser - part 1</title><content type='html'>We'll now write the Parser class: &lt;pre&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using TC.Adl.ParserNodes;

namespace TC.Adl
{
    public class Parser
    {
        Tokenizer fTokenizer;
        Token fCurrentToken;
    }
}&lt;/pre&gt;Our Parser class has only 2 fields: 
&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;fTokenizer&lt;/code&gt; 
&lt;dd&gt;The Tokenizer to read tokens from. 
&lt;dt&gt;&lt;code&gt;fCurrentToken&lt;/code&gt; 
&lt;dd&gt;The current token (most recently read). &lt;/dd&gt;&lt;/dl&gt;The constructor of the Parser class will accept a TextReader argument, create a Tokenizer that uses that TextReader, store it in &lt;code&gt;fTokenizer&lt;/code&gt; and read the first token: &lt;pre&gt;public Parser(TextReader source)
{
    if (source == null) throw new ArgumentNullException("source");

    fTokenizer = new Tokenizer(source);
    ReadNextToken();
}&lt;/pre&gt;
&lt;p&gt;Now we'll add some private helper methods.&lt;/p&gt;Reading a token is simple. just call &lt;code&gt;Tokenizer.ReadNextToken()&lt;/code&gt;, which returns a &lt;code&gt;Token&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt; at the end of the source code. &lt;pre&gt;void ReadNextToken() { fCurrentToken = fTokenizer.ReadNextToken(); }&lt;/pre&gt;To determine if we're at the end of the source, we just have to check the current token for &lt;code&gt;null&lt;/code&gt;: &lt;pre&gt;bool AtEndOfSource { get { return fCurrentToken == null; } }&lt;/pre&gt;We'll need a method that throws an exception when the end of the source has been reached unexpectedly: &lt;pre&gt;void CheckForUnexpectedEndOfSource()
{
    if (AtEndOfSource)
        throw new ParserException("Unexpected end of source.");
}&lt;/pre&gt;We'll also need a method that verifies the current token and skips it: &lt;pre&gt;void SkipExpected(TokenType type, string value)
{
    CheckForUnexpectedEndOfSource();
    if (!fCurrentToken.Equals(type, value))
        throw new ParserException("Expected '" + value + "'.");
    ReadNextToken();
}&lt;/pre&gt;Now that we've written the private helper methods, we can write the only public method: the &lt;code&gt;ReadNextStatement&lt;/code&gt; method. This methods reads a statement and returns it. If we've reached the end of the source, we'll return null, else we'll check the first token to determine the &lt;a href="http://tommycarlier.blogspot.com/2007/04/writing-parser-adl-parser-node-types.html"&gt;type of statement&lt;/a&gt;: 
&lt;ul&gt;
&lt;li&gt;If the current token is the word &lt;code&gt;if&lt;/code&gt;, it's an if-statement. 
&lt;li&gt;If the current token is the word &lt;code&gt;while&lt;/code&gt;, it's a while-statement. 
&lt;li&gt;If the current token is the word &lt;code&gt;for&lt;/code&gt;, it's a for-statement. 
&lt;li&gt;If it's any other word, we assume it's an assignment or a function call. &lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;public Statement ReadNextStatement()
{
    if (AtEndOfSource)
        return null;

    // all the statements start with a word
    if (fCurrentToken.Type != TokenType.Word)
        throw new ParserException("Expected a statement.");

    if (fCurrentToken.Value == "if")
        return ParseIfStatement();

    if (fCurrentToken.Value == "while")
        return ParseWhileStatement();

    if (fCurrentToken.Value == "for")
        return ParseForStatement();

    return ParseAssignmentOrFunctionCallStatement();
}&lt;/pre&gt;An if-statement starts with the word &lt;code&gt;if&lt;/code&gt;, followed by a condition, the word &lt;code&gt;then&lt;/code&gt;, a block of statements, an optional block of statements prefixed with the word &lt;code&gt;else&lt;/code&gt; and the words &lt;code&gt;end if&lt;/code&gt;: &lt;pre&gt;IfStatement ParseIfStatement()
{
    ReadNextToken(); // skip 'if'

    Expression lCondition = ParseExpression();

    SkipExpected(TokenType.Word, "then"); // skip 'then'

    List&lt;statement&gt; lTrueStatements = new List&lt;statement&gt;();
    List&lt;statement&gt; lFalseStatements = new List&lt;statement&gt;();
    List&lt;statement&gt; lStatements = lTrueStatements;
    Statement lStatement;

    CheckForUnexpectedEndOfSource();
    while (!fCurrentToken.Equals(TokenType.Word, "end"))
    {
        if (fCurrentToken.Equals(TokenType.Word, "else"))
        {
            ReadNextToken(); // skip 'else'
            CheckForUnexpectedEndOfSource();
            lStatements = lFalseStatements;
        }

        if ((lStatement = ReadNextStatement()) != null)
            lStatements.Add(lStatement);
        else throw new ParserException("Unexpected end of source.");
    }

    ReadNextToken(); // skip 'end'
    SkipExpected(TokenType.Word, "if"); // skip 'if'

    return new IfStatement(lCondition
        , new StatementCollection(lTrueStatements)
        , new StatementCollection(lFalseStatements));
}&lt;/pre&gt;A while-statement starts with the word &lt;code&gt;while&lt;/code&gt;, followed by a condition, the word &lt;code&gt;do&lt;/code&gt;, a block of statements and the words &lt;code&gt;end while&lt;/code&gt;: &lt;pre&gt;WhileStatement ParseWhileStatement()
{
    ReadNextToken(); // skip 'while'

    Expression lCondition = ParseExpression();

    SkipExpected(TokenType.Word, "do"); // skip 'do'

    List&lt;statement&gt; lStatements = new List&lt;statement&gt;();
    Statement lStatement;
    CheckForUnexpectedEndOfSource();
    while (!fCurrentToken.Equals(TokenType.Word, "end"))
    {
        if ((lStatement = ReadNextStatement()) != null)
            lStatements.Add(lStatement);
        else throw new ParserException("Unexpected end of source.");
    }

    ReadNextToken(); // skip 'end'
    SkipExpected(TokenType.Word, "while"); // skip 'while'

    return new WhileStatement(lCondition, new StatementCollection(lStatements));
}&lt;/pre&gt;A for-statement starts with the word &lt;code&gt;for&lt;/code&gt;, followed by a variable, the symbol &lt;code&gt;:=&lt;/code&gt;, a start-value, the word &lt;code&gt;to&lt;/code&gt;, an end-value, optionally the word &lt;code&gt;by&lt;/code&gt; with a step-size, the word &lt;code&gt;do&lt;/code&gt;, a block of statements and the words &lt;code&gt;end for&lt;/code&gt;: &lt;pre&gt;ForStatement ParseForStatement()
{
    ReadNextToken(); // skip 'for'
    CheckForUnexpectedEndOfSource();

    if (fCurrentToken.Type != TokenType.Word)
        throw new ParserException("Expected a variable.");

    Variable lVariable = new Variable(fCurrentToken.Value);
    ReadNextToken();

    SkipExpected(TokenType.Symbol, ":="); // skip ':='
    Expression lStartValue = ParseExpression();

    SkipExpected(TokenType.Word, "to"); // skip 'to'
    Expression lEndValue = ParseExpression();
    CheckForUnexpectedEndOfSource();

    Expression lStepSize;
    if (fCurrentToken.Equals(TokenType.Word, "by"))
    {
        ReadNextToken(); // skip 'by'
        lStepSize = ParseExpression();
    }
    else lStepSize = new IntegerConstant(1);

    SkipExpected(TokenType.Word, "do");
    List&lt;statement&gt; lStatements = new List&lt;statement&gt;();
    Statement lStatement;
    CheckForUnexpectedEndOfSource();
    while (!fCurrentToken.Equals(TokenType.Word, "end"))
    {
        if ((lStatement = ReadNextStatement()) != null)
            lStatements.Add(lStatement);
        else throw new ParserException("Unexpected end of source.");
    }

    ReadNextToken(); // skip 'end'
    SkipExpected(TokenType.Word, "for"); // skip 'for'

    return new ForStatement(lVariable, lStartValue, lEndValue, lStepSize, new StatementCollection(lStatements));
}&lt;/pre&gt;An assignment and a function call statement both start with an identifier, so we'll have to read the next token to determine if it's an assignment or a function call statement: &lt;pre&gt;Statement ParseAssignmentOrFunctionCallStatement()
{
    Token lToken = fCurrentToken;
    ReadNextToken();
    CheckForUnexpectedEndOfSource();

    if (fCurrentToken.Equals(TokenType.Symbol, ":="))
        return ParseAssignment(new Variable(lToken.Value));

    if (fCurrentToken.Equals(TokenType.Symbol, "("))
        return new FunctionCallStatement(ParseFunctionCall(lToken.Value));

    throw new ParserException("Expected a statement.");
}&lt;/pre&gt;An assignment just has an expression after the &lt;code&gt;:=&lt;/code&gt;: &lt;pre&gt;Assignment ParseAssignment(Variable variable)
{
    ReadNextToken(); // skip ':='
    return new Assignment(variable, ParseExpression());
}&lt;/pre&gt;In the next post, we'll write the methods for parsing expression. 
&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Programming+Language" rel="tag"&gt;Programming Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-3031560026365870755?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/3031560026365870755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=3031560026365870755' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3031560026365870755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3031560026365870755'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/05/writing-parser-adl-parser-part-1.html' title='Writing a parser: ADL Parser - part 1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-1094084785171732698</id><published>2007-04-28T18:28:00.001+02:00</published><updated>2009-07-11T17:18:25.658+02:00</updated><title type='text'>Writing a parser: ADL parser node types</title><content type='html'>&lt;p&gt;In this post, I'll show you the different types of parser nodes. If you remember from &lt;a title="Writing a parser: basic terminology" href="http://blog.tcx.be/2007/04/writing-parser-basic-terminology.html"&gt;one of the first posts I made in this series&lt;/a&gt;, the parser analyzes the tokens it gets from the tokenizer and turns it into structured trees. The nodes in this tree represent the different constructs (additions, multiplications, comparisons, ...).&lt;/p&gt; &lt;p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/248390/ParserNodes.png"&gt;&lt;img border="0" alt="The different types of parser tree nodes" src="http://files.myopera.com/TommyCarlier/albums/248390/ParserNodes.png" width="594" height="117"&gt;&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;em&gt;ParserNode&lt;/em&gt;  &lt;ul&gt; &lt;li&gt;&lt;em&gt;Statement&lt;/em&gt;  &lt;ul&gt; &lt;li&gt;Assignment: &lt;code&gt;x := ...&lt;/code&gt;  &lt;li&gt;IfStatement: &lt;code&gt;if ... then ... else ... end if&lt;/code&gt;  &lt;li&gt;WhileStatement: &lt;code&gt;while ... do ... end while&lt;/code&gt;  &lt;li&gt;ForStatement: &lt;code&gt;for i := ... to ... by ... do ... end for&lt;/code&gt;  &lt;li&gt;FunctionCallStatement: &lt;code&gt;f(...)&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;em&gt;Expression&lt;/em&gt;  &lt;ul&gt; &lt;li&gt;&lt;em&gt;UnaryExpression&lt;/em&gt;  &lt;ul&gt; &lt;li&gt;Negation: &lt;code&gt;-x&lt;/code&gt;  &lt;li&gt;NotExpression: &lt;code&gt;not x&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;&lt;em&gt;BinaryExpression&lt;/em&gt;  &lt;ul&gt; &lt;li&gt;Addition: &lt;code&gt;x + y&lt;/code&gt;  &lt;li&gt;Subtraction: &lt;code&gt;x - y&lt;/code&gt;  &lt;li&gt;Multiplication: &lt;code&gt;x * y&lt;/code&gt;  &lt;li&gt;Division: &lt;code&gt;x / y&lt;/code&gt;  &lt;li&gt;AndExpression: &lt;code&gt;x and y&lt;/code&gt;  &lt;li&gt;OrExpression: &lt;code&gt;x or y&lt;/code&gt;  &lt;li&gt;Comparison: &lt;code&gt;x &amp;lt; y&lt;/code&gt; or &lt;code&gt;x &amp;gt; y&lt;/code&gt; or &lt;code&gt;x == y&lt;/code&gt; or ...&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Variable: &lt;code&gt;x&lt;/code&gt;  &lt;li&gt;IntegerConstant: &lt;code&gt;123&lt;/code&gt;  &lt;li&gt;StringConstant: &lt;code&gt;"abc"&lt;/code&gt;  &lt;li&gt;FunctionCall: &lt;code&gt;f(...)&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;A &lt;strong&gt;statement&lt;/strong&gt; is an instruction that does not return a value. An &lt;strong&gt;expression&lt;/strong&gt; is an instruction that does return a value. A &lt;strong&gt;unary expression&lt;/strong&gt; has an operator and a single child expression. A &lt;strong&gt;binary expression&lt;/strong&gt; has an operator and 2 child expressions.&lt;/p&gt; &lt;p&gt;You might have noticed that I defined both a FunctionCall and a FunctionCallStatement. The difference is that a FunctionCall is an expression that returns the value of the function call, and a FunctionCallStatement is a statement that ignores the value of the function call.&lt;/p&gt;The basic types look like this: &lt;pre&gt;&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; ParserNode
{
}

&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; Statement : ParserNode
{
}

&lt;span class="keyword"&gt;public abstract class&lt;/span&gt; Expression : ParserNode
{
}&lt;/pre&gt;As you can see, they don't contain any code. Because I'm just explaining how parsers work, they don't have to contain code. You should add code if you use these classes to build an interpreter or a compiler. For an interpreter, the &lt;em&gt;Statement&lt;/em&gt; class could have a method &lt;em&gt;Execute&lt;/em&gt; to execute the statement, and the &lt;em&gt;Expression&lt;/em&gt; class could have a method &lt;em&gt;Evaluate&lt;/em&gt; to evaluate the expression and return the result. 
&lt;p&gt;There's no point in showing the source code in this blog post for all the classes, so you can &lt;a href="http://my.opera.com/TommyCarlier/blog/writing-a-parser-downloads"&gt;download them here&lt;/a&gt;. Just create a new folder &lt;em&gt;ParserNodes&lt;/em&gt; in the &lt;em&gt;TC.Adl&lt;/em&gt; project and include the downloaded C# files.&lt;/p&gt;
&lt;p&gt;Next time, we'll write the actual parser and a test application.&lt;/p&gt;
&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Programming+Language" rel="tag"&gt;Programming Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-1094084785171732698?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/1094084785171732698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=1094084785171732698' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1094084785171732698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/1094084785171732698'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-adl-parser-node-types.html' title='Writing a parser: ADL parser node types'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-2532200587876897996</id><published>2007-04-25T07:33:00.001+02:00</published><updated>2009-07-11T17:19:01.030+02:00</updated><title type='text'>Writing a parser: ADL Tokenizer correction</title><content type='html'>&lt;a href="http://www.blogger.com/profile/11160553154275818207"&gt;Sushovan&lt;/a&gt; made a great remark on &lt;a title="Writing a parser: ADL Tokenizer" href="http://blog.tcx.be/2007/04/writing-parser-adl-tokenizer.html"&gt;my last post&lt;/a&gt;. He asked me why I didn't use the method &lt;code&gt;char.IsWhiteSpace()&lt;/code&gt; to test for white-space. The reason I didn't, was ignorance: I had totally forgot about that method. So it's probably a good idea to change the method &lt;code&gt;SkipWhitespace&lt;/code&gt; to this: &lt;pre&gt;&lt;span class="keyword"&gt;void&lt;/span&gt; SkipWhitespace()
{
    &lt;span class="keyword"&gt;while&lt;/span&gt; (&lt;span class="keyword"&gt;char&lt;/span&gt;.IsWhiteSpace(fCurrentChar))
        ReadNextChar();
}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-2532200587876897996?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/2532200587876897996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=2532200587876897996' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2532200587876897996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2532200587876897996'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-adl-tokenizer-correction.html' title='Writing a parser: ADL Tokenizer correction'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-638390542422143928</id><published>2007-04-24T21:30:00.001+02:00</published><updated>2009-07-11T17:21:22.059+02:00</updated><title type='text'>Writing a parser: ADL Tokenizer</title><content type='html'>&lt;p&gt;We'll now start writing the tokenizer.&lt;/p&gt; &lt;p&gt;One thing I haven't explained yet is how we will deal with white-space. The easiest solution is to just skip the white-space between tokens, and that's what we'll do. Usually white-space is defined as one of the following characters: space (&lt;code&gt;' '&lt;/code&gt;), tab (&lt;code&gt;'\t'&lt;/code&gt;), new-line (&lt;code&gt;'\n'&lt;/code&gt;) or carriage-return (&lt;code&gt;'\r'&lt;/code&gt;). But I've noticed that any character below space (&lt;code&gt;' '&lt;/code&gt;) is never used as text. So we can just consider any character &amp;lt;= &lt;code&gt;' '&lt;/code&gt; to be white-space, which makes it easier to test a character.&lt;/p&gt; &lt;p&gt;Because we want our tokenizer to read characters from strings as well as streams, we'll use a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.io.textreader.aspx"&gt;TextReader&lt;/a&gt;. TextReader has 2 derived classes: &lt;a href="http://msdn2.microsoft.com/en-us/library/system.io.stringreader.aspx"&gt;StringReader&lt;/a&gt; (to read text from a string) and &lt;a href="http://msdn2.microsoft.com/en-us/library/system.io.streamreader.aspx"&gt;StreamReader&lt;/a&gt; (to read text from a stream). The only method in TextReader we will use is &lt;a href="http://msdn2.microsoft.com/en-us/library/0w3csw16.aspx"&gt;Read()&lt;/a&gt;, which returns the next character or -1 if the end of the stream or string has been reached.&lt;/p&gt; &lt;p&gt;To extract a token, we read the first character and decide what type of token it will be. For each token, we will have to store the characters it contains. We'll use a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.text.stringbuilder.aspx"&gt;StringBuilder&lt;/a&gt; for this.&lt;/p&gt;&lt;pre&gt;&lt;span class="keyword"&gt;using&lt;/span&gt; System;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Text;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.IO;

&lt;span class="keyword"&gt;namespace&lt;/span&gt; TC.Adl
{
    &lt;span class="keyword"&gt;public class&lt;/span&gt; Tokenizer
    {
        TextReader fSource;
        &lt;span class="keyword"&gt;char&lt;/span&gt; fCurrentChar;
        StringBuilder fTokenValueBuffer;
    }
}&lt;/pre&gt;Our Tokenizer class has only 3 fields: 
&lt;dl&gt;
&lt;dt&gt;&lt;code&gt;fSource&lt;/code&gt; 
&lt;dd&gt;The TextReader to read characters from. 
&lt;dt&gt;&lt;code&gt;fCurrentChar&lt;/code&gt; 
&lt;dd&gt;The current character (most recently read). 
&lt;dt&gt;&lt;code&gt;fTokenValueBuffer&lt;/code&gt; 
&lt;dd&gt;The StringBuilder to store the characters of the current token.&lt;/dd&gt;&lt;/dl&gt;The constructor of the Tokenizer class will accept a TextReader argument, store it in &lt;code&gt;fSource&lt;/code&gt;, initialize &lt;code&gt;fTokenValueBuffer&lt;/code&gt; and read the first character: &lt;pre&gt;&lt;span class="keyword"&gt;public&lt;/span&gt; Tokenizer(TextReader source)
{
    &lt;span class="keyword"&gt;if&lt;/span&gt; (source == &lt;span class="keyword"&gt;null&lt;/span&gt;) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentNullException(&lt;span class="string"&gt;"source"&lt;/span&gt;);

    fSource = source;
    fTokenValueBuffer = &lt;span class="keyword"&gt;new&lt;/span&gt; StringBuilder();
    ReadNextChar();
}&lt;/pre&gt;
&lt;p&gt;Now we'll add some private helper methods.&lt;/p&gt;Reading a character is simple. Just call &lt;code&gt;TextReader.Read()&lt;/code&gt;, which returns an &lt;code&gt;int&lt;/code&gt;. Because a &lt;code&gt;char&lt;/code&gt; cannot be -1 (which is returned by &lt;code&gt;TextReader.Read()&lt;/code&gt; at the end of the stream), we will use character &lt;code&gt;'\0'&lt;/code&gt; as the end-of-stream character. &lt;pre&gt;&lt;span class="keyword"&gt;void&lt;/span&gt; ReadNextChar()
{
    &lt;span class="keyword"&gt;int&lt;/span&gt; lChar = fSource.Read();
    &lt;span class="keyword"&gt;if&lt;/span&gt; (lChar &amp;gt; 0)
        fCurrentChar = (&lt;span class="keyword"&gt;char&lt;/span&gt;)lChar;
    &lt;span class="keyword"&gt;else&lt;/span&gt; fCurrentChar = &lt;span class="string"&gt;'\0'&lt;/span&gt;;
}&lt;/pre&gt;Skipping white-space is also easy: just keep reading characters until we get a character that is not white-space: &lt;pre&gt;&lt;span class="keyword"&gt;void&lt;/span&gt; SkipWhitespace()
{
    &lt;span class="keyword"&gt;while&lt;/span&gt; (fCurrentChar &amp;gt; &lt;span class="string"&gt;'\0'&lt;/span&gt; &amp;amp;&amp;amp; fCurrentChar &amp;lt;= &lt;span class="string"&gt;' '&lt;/span&gt;)
        ReadNextChar();
}&lt;/pre&gt;To determine if we're at the end of the source, we just have to check the current character for &lt;code&gt;'\0'&lt;/code&gt;: &lt;pre&gt;&lt;span class="keyword"&gt;bool&lt;/span&gt;&lt;/span&gt; AtEndOfSource { &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; fCurrentChar == &lt;span class="string"&gt;'\0'&lt;/span&gt;; } }&lt;/pre&gt;We'll also write a simple method to store the current character and read the next: &lt;pre&gt;&lt;span class="keyword"&gt;void&lt;/span&gt; StoreCurrentCharAndReadNext()
{
    fTokenValueBuffer.Append(fCurrentChar);
    ReadNextChar();
}&lt;/pre&gt;And a method to extract the stored characters and clear the buffer: &lt;pre&gt;&lt;span class="keyword"&gt;string&lt;/span&gt; ExtractStoredChars()
{
    &lt;span class="keyword"&gt;string&lt;/span&gt; lValue = fTokenValueBuffer.ToString();
    fTokenValueBuffer.Length = 0;
    &lt;span class="keyword"&gt;return&lt;/span&gt; lValue;
}&lt;/pre&gt;Because the source code can have errors, we'll need some methods that throw exceptions: &lt;pre&gt;&lt;span class="keyword"&gt;void&lt;/span&gt; CheckForUnexpectedEndOfSource()
{
    &lt;span class="keyword"&gt;if&lt;/span&gt; (AtEndOfSource)
        &lt;span class="keyword"&gt;throw new&lt;/span&gt; ParserException(&lt;span class="string"&gt;"Unexpected end of source."&lt;/span&gt;);
}

&lt;span class="keyword"&gt;void&lt;/span&gt; ThrowInvalidCharException()
{
    &lt;span class="keyword"&gt;if&lt;/span&gt; (fTokenValueBuffer.Length == 0)
        &lt;span class="keyword"&gt;throw new&lt;/span&gt; ParserException(&lt;span class="string"&gt;"Invalid character '"&lt;/span&gt; + fCurrentChar.ToString() + &lt;span class="string"&gt;"'."&lt;/span&gt;);
    &lt;span class="keyword"&gt;else&lt;/span&gt;
    {
        &lt;span class="keyword"&gt;throw new&lt;/span&gt; ParserException(&lt;span class="string"&gt;"Invalid character '"&lt;/span&gt; 
                + fCurrentChar.ToString() + &lt;span class="string"&gt;"' after '"&lt;/span&gt; 
                + fTokenValueBuffer.ToString() + &lt;span class="string"&gt;"'."&lt;/span&gt;);
    }
}&lt;/pre&gt;Which introduces our ParserException class (a standard Exception class): &lt;pre&gt;&lt;span class="keyword"&gt;using&lt;/span&gt; System;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Text;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Runtime.Serialization;

&lt;span class="keyword"&gt;namespace&lt;/span&gt; TC.Adl
{
    [Serializable]
    &lt;span class="keyword"&gt;public class&lt;/span&gt; ParserException : Exception
    {
        &lt;span class="keyword"&gt;public&lt;/span&gt; ParserException() { }
        &lt;span class="keyword"&gt;public&lt;/span&gt; ParserException(&lt;span class="keyword"&gt;string&lt;/span&gt; message) : &lt;span class="keyword"&gt;base&lt;/span&gt;(message) { }
        &lt;span class="keyword"&gt;public&lt;/span&gt; ParserException(&lt;span class="keyword"&gt;string&lt;/span&gt; message, Exception innerException) : &lt;span class="keyword"&gt;base&lt;/span&gt;(message, innerException) { }
        &lt;span class="keyword"&gt;protected&lt;/span&gt; ParserException(SerializationInfo info, StreamingContext context) : &lt;span class="keyword"&gt;base&lt;/span&gt;(info, context) { }
    }
}&lt;/pre&gt;Now that we've written the private helper methods, we can write the only public method: the &lt;code&gt;ReadNextToken&lt;/code&gt; method. This method reads a token and returns it. First we skip the initial white-space. If we've reached the end of the source, we'll return null, else we'll check the first character to determine the &lt;a href="http://blog.tcx.be/2007/04/writing-parser-adl-tokens.html"&gt;type of token&lt;/a&gt;: 
&lt;ul&gt;
&lt;li&gt;If the token starts with a letter, it's a word. 
&lt;li&gt;If the token starts with a digit, it's an integer constant. 
&lt;li&gt;If the token starts with a quote, it's a string constant. 
&lt;li&gt;If it's any other character, we assume it's a symbol. &lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;&lt;span class="keyword"&gt;public&lt;/span&gt; Token ReadNextToken()
{
    SkipWhitespace();

    &lt;span class="keyword"&gt;if&lt;/span&gt; (AtEndOfSource)
        &lt;span class="keyword"&gt;return null&lt;/span&gt;;

    &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="keyword"&gt;char&lt;/span&gt;.IsLetter(fCurrentChar))
        &lt;span class="keyword"&gt;return&lt;/span&gt; ReadWord();

    &lt;span class="keyword"&gt;if&lt;/span&gt; (&lt;span class="keyword"&gt;char&lt;/span&gt;.IsDigit(fCurrentChar))
        &lt;span class="keyword"&gt;return&lt;/span&gt; ReadIntegerConstant();

    &lt;span class="keyword"&gt;if&lt;/span&gt; (fCurrentChar == &lt;span class="string"&gt;'"'&lt;/span&gt;)
        &lt;span class="keyword"&gt;return&lt;/span&gt; ReadStringConstant();

    &lt;span class="keyword"&gt;return&lt;/span&gt; ReadSymbol();
}&lt;/pre&gt;A word starts with a letter (already tested in &lt;code&gt;ReadNextToken()&lt;/code&gt;) followed by zero or more letters or digits. So all we have to do is keep reading until we've reached a character that is not a letter or digit: &lt;pre&gt;Token ReadWord()
{
    &lt;span class="keyword"&gt;do&lt;/span&gt;
    {
        StoreCurrentCharAndReadNext();
    }
    &lt;span class="keyword"&gt;while&lt;/span&gt; (&lt;span class="keyword"&gt;char&lt;/span&gt;.IsLetterOrDigit(fCurrentChar));

    &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.Word, ExtractStoredChars());
}&lt;/pre&gt;An integer constant just contains digits: &lt;pre&gt;Token ReadIntegerConstant()
{
    &lt;span class="keyword"&gt;do&lt;/span&gt;
    {
        StoreCurrentCharAndReadNext();
    }
    &lt;span class="keyword"&gt;while&lt;/span&gt; (&lt;span class="keyword"&gt;char&lt;/span&gt;.IsDigit(fCurrentChar));

    &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.Integer, ExtractStoredChars());
}&lt;/pre&gt;A string constant contains a sequence of characters, enclosed in quotes. Because the quote character is used as a delimiter, the characters in between cannot be quotes. But all other characters are allowed. If the end of the source is reached before the closing quote, we throw an exception. We don't want the quotes to be included in the value of the token, so we'll skip them with ReadNextChar. &lt;pre&gt;Token ReadStringConstant()
{
    ReadNextChar();
    &lt;span class="keyword"&gt;while&lt;/span&gt; (!AtEndOfSource &amp;amp;&amp;amp; fCurrentChar != &lt;span class="string"&gt;'"'&lt;/span&gt;)
    {
        StoreCurrentCharAndReadNext();
    }

    CheckForUnexpectedEndOfSource();
    ReadNextChar();

    &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.String, ExtractStoredChars());
}&lt;/pre&gt;Reading a symbol is more complicated. A symbol can be one or two characters, so we'll have to treat each case individually: &lt;pre&gt;Token ReadSymbol()
{
    &lt;span class="keyword"&gt;switch&lt;/span&gt; (fCurrentChar)
    {
        &lt;span class="comment"&gt;// the symbols + - * / ( ) ,&lt;/span&gt;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'+'&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'-'&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'*'&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'/'&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'('&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;')'&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;','&lt;/span&gt;:
            StoreCurrentCharAndReadNext();
            &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.Symbol, ExtractStoredChars());
        &lt;span class="comment"&gt;// the symbols := ==&lt;/span&gt;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;':'&lt;/span&gt;:
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'='&lt;/span&gt;:
            StoreCurrentCharAndReadNext();
            &lt;span class="keyword"&gt;if&lt;/span&gt; (fCurrentChar == &lt;span class="string"&gt;'='&lt;/span&gt;)
            {
                StoreCurrentCharAndReadNext();
                &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.Symbol, ExtractStoredChars());
            }

            CheckForUnexpectedEndOfSource();
            ThrowInvalidCharException();
            &lt;span class="keyword"&gt;break&lt;/span&gt;;
        &lt;span class="comment"&gt;// the symbols &amp;lt; &amp;lt;&amp;gt; &amp;lt;=&lt;/span&gt;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'&amp;lt;'&lt;/span&gt;:
            StoreCurrentCharAndReadNext();
            &lt;span class="keyword"&gt;if&lt;/span&gt; (fCurrentChar == &lt;span class="string"&gt;'&amp;gt;'&lt;/span&gt; || fCurrentChar == &lt;span class="string"&gt;'='&lt;/span&gt;)
            {
                StoreCurrentCharAndReadNext();
            }
            &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.Symbol, ExtractStoredChars());
        &lt;span class="comment"&gt;// the symbols &amp;gt; &amp;gt;=&lt;/span&gt;
        &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="string"&gt;'&amp;gt;'&lt;/span&gt;:
            StoreCurrentCharAndReadNext();
            &lt;span class="keyword"&gt;if&lt;/span&gt; (fCurrentChar == &lt;span class="string"&gt;'='&lt;/span&gt;)
            {
                StoreCurrentCharAndReadNext();
            }
            &lt;span class="keyword"&gt;return new&lt;/span&gt; Token(TokenType.Symbol, ExtractStoredChars());
        &lt;span class="keyword"&gt;default&lt;/span&gt;:
            CheckForUnexpectedEndOfSource();
            ThrowInvalidCharException();
            &lt;span class="keyword"&gt;break&lt;/span&gt;;

    }

    &lt;span class="keyword"&gt;return null&lt;/span&gt;;
}&lt;/pre&gt;That's it, our Tokenizer class is done. To test it, we'll write a small application. Add a new Form to the project TC.Adl.Test, named TokenizerTest. It will have a multiline TextBox where we can type in source code (TextBoxSource), a Button to tokenize the source code (ButtonTokenize), and a ListBox that will display the tokens (ListBoxTokens). It should look like this (follow link to enlarge): 
&lt;p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/248390/TokenizerTest.png"&gt;&lt;img border="0" alt="TokenizerTest designer screenshot" src="http://files.myopera.com/TommyCarlier/albums/248390/TokenizerTest.png" width="533" height="252"&gt;&lt;/a&gt;&lt;/p&gt;The Click event handler of the button creates a new Tokenizer, reads all the tokens, and adds them to the ListBox: &lt;pre&gt;&lt;span class="keyword"&gt;private void&lt;/span&gt; ButtonTokenize_Click(&lt;span class="keyword"&gt;object&lt;/span&gt; sender, EventArgs e)
{
    ListBoxTokens.Items.Clear();
    ListBoxTokens.BeginUpdate();
    &lt;span class="keyword"&gt;try&lt;/span&gt;
    {
        &lt;span class="keyword"&gt;using&lt;/span&gt; (StringReader lSource = &lt;span class="keyword"&gt;new&lt;/span&gt; StringReader(TextBoxSource.Text))
        {
            Tokenizer lTokenizer = &lt;span class="keyword"&gt;new&lt;/span&gt; Tokenizer(lSource);

            Token lToken = lTokenizer.ReadNextToken();
            &lt;span class="keyword"&gt;while&lt;/span&gt; (lToken != &lt;span class="keyword"&gt;null&lt;/span&gt;)
            {
                ListBoxTokens.Items.Add(lToken.Type.ToString() + &lt;span class="string"&gt;":\t"&lt;/span&gt; + lToken.Value);
                lToken = lTokenizer.ReadNextToken();
            }
        }
    }
    &lt;span class="keyword"&gt;catch&lt;/span&gt; (ParserException lException)
    {
        MessageBox.Show(&lt;span class="keyword"&gt;this&lt;/span&gt;, lException.Message, &lt;span class="keyword"&gt;this&lt;/span&gt;.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    &lt;span class="keyword"&gt;finally&lt;/span&gt; { ListBoxTokens.EndUpdate(); }
}&lt;/pre&gt;Now you can start the application, run the TokenizerTest and try out some code to see what tokens are generated. Try out this sample: &lt;pre&gt;&lt;span class="keyword"&gt;for&lt;/span&gt; i := 1 &lt;span class="keyword"&gt;to&lt;/span&gt; 100 &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; i &amp;lt; 50 &lt;span class="keyword"&gt;then&lt;/span&gt;
        print(i, &lt;span class="string"&gt;" &amp;lt; 50"&lt;/span&gt;)
    &lt;span class="keyword"&gt;else&lt;/span&gt;
        print(i, &lt;span class="string"&gt;" &amp;gt;= 50"&lt;/span&gt;)
    &lt;span class="keyword"&gt;end if&lt;/span&gt;
&lt;span class="keyword"&gt;end for&lt;/span&gt;&lt;/pre&gt;As you can see, converting characters to tokens is not very complicated. You just have to get used to it. 
&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Tokenizer" rel="tag"&gt;Tokenizer&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-638390542422143928?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/638390542422143928/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=638390542422143928' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/638390542422143928'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/638390542422143928'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-adl-tokenizer.html' title='Writing a parser: ADL Tokenizer'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-5071925412302393496</id><published>2007-04-22T18:29:00.001+02:00</published><updated>2007-04-22T18:29:20.762+02:00</updated><title type='text'>Writing a parser: ADL tokens</title><content type='html'>&lt;acronym title="Asynchronous Demonstrational Language"&gt;ADL&lt;/acronym&gt; only has 4 different tokens:  &lt;dl&gt; &lt;dt&gt;Word  &lt;dd&gt;A &lt;b&gt;word&lt;/b&gt; starts with a letter, followed by zero or more letters or numbers.  &lt;dd&gt;Examples: &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;abc&lt;/code&gt;, &lt;code&gt;f2&lt;/code&gt;, &lt;code&gt;else&lt;/code&gt;.  &lt;dt&gt;Integer  &lt;dd&gt;An &lt;b&gt;integer&lt;/b&gt; is a sequence of one or more digits.  &lt;dd&gt;Examples: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;42&lt;/code&gt;, &lt;code&gt;3141592654&lt;/code&gt;.  &lt;dt&gt;String  &lt;dd&gt;A &lt;b&gt;string&lt;/b&gt; is a sequence of characters enclosed in quotes.  &lt;dd&gt;Examples: &lt;code&gt;"x"&lt;/code&gt;, &lt;code&gt;"abc"&lt;/code&gt;, &lt;code&gt;"Quid pro quo."&lt;/code&gt;.  &lt;dt&gt;Symbol  &lt;dd&gt;A &lt;b&gt;symbol&lt;/b&gt; is one of the following sequences:  &lt;dd&gt;&lt;code&gt;+ - * / ( ) , := == &amp;lt; &amp;gt; &amp;lt;&amp;gt; &amp;lt;= &amp;gt;=&lt;/code&gt; &lt;/dd&gt;&lt;/dl&gt;To identify tokens, we'll use an enum called &lt;code&gt;TokenType&lt;/code&gt;: &lt;pre&gt;&lt;span class="keyword"&gt;namespace&lt;/span&gt; TC.Adl
{
    &lt;span class="keyword"&gt;public enum&lt;/span&gt; TokenType
    {
        None = 0,
        Word,
        Integer,
        String,
        Symbol
    }
}&lt;/pre&gt;&lt;small&gt;(The value &lt;code&gt;None&lt;/code&gt; is the default value and should not occur.)&lt;/small&gt; 
&lt;p&gt;A token has a type (of type &lt;code&gt;TokenType&lt;/code&gt;) and a value (of type &lt;code&gt;string&lt;/code&gt;). The value is the sequence of characters that represent the token.&lt;/p&gt;&lt;pre&gt;&lt;span class="keyword"&gt;using&lt;/span&gt; System;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span class="keyword"&gt;using&lt;/span&gt; System.Text;

&lt;span class="keyword"&gt;namespace&lt;/span&gt; TC.Adl
{
    &lt;span class="keyword"&gt;public class&lt;/span&gt; Token
    {
        &lt;span class="keyword"&gt;public&lt;/span&gt; Token(TokenType type, &lt;span class="keyword"&gt;string&lt;/span&gt; value)
        {
            fType = type;
            fValue = value;
        }

        &lt;span class="keyword"&gt;readonly&lt;/span&gt; TokenType fType;
        &lt;span class="keyword"&gt;public&lt;/span&gt; TokenType Type { &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; fType; } }

        &lt;span class="keyword"&gt;readonly string&lt;/span&gt; fValue;
        &lt;span class="keyword"&gt;public string&lt;/span&gt; Value { &lt;span class="keyword"&gt;get&lt;/span&gt; { &lt;span class="keyword"&gt;return&lt;/span&gt; fValue; } }

        &lt;span class="keyword"&gt;public bool&lt;/span&gt; Equals(TokenType type, &lt;span class="keyword"&gt;string&lt;/span&gt; value)
        {
            &lt;span class="keyword"&gt;return&lt;/span&gt; fType == type &amp;amp;&amp;amp; fValue == value;
        }
    }
}&lt;/pre&gt;
&lt;p&gt;You may have noticed that there are no comments or argument validation code. This is just to make the code simpler and easier to understand at first sight. The code I'm writing in Visual Studio is fully commented and has all the necessary argument validation code. I'll release the entire library afterwards.&lt;/p&gt;
&lt;p&gt;Next time, we'll write the tokenizer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-5071925412302393496?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/5071925412302393496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=5071925412302393496' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5071925412302393496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/5071925412302393496'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-adl-tokens.html' title='Writing a parser: ADL tokens'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-8881862451468432517</id><published>2007-04-22T10:44:00.001+02:00</published><updated>2007-04-22T10:44:28.846+02:00</updated><title type='text'>Writing a parser: base VS2005 solution</title><content type='html'>&lt;p&gt;I've created an (almost) empty&amp;nbsp;VS2005 solution that will be the base solution to build our parser from. It contains 2 projects: &lt;strong&gt;TC.Adl&lt;/strong&gt; (the ADL Class Library that will contain the parser)&amp;nbsp;and &lt;strong&gt;TC.Adl.Test&lt;/strong&gt; (the WinForms application for testing the library).&lt;/p&gt; &lt;p&gt;The test application has a main form (FormMain) that displays a list of test cases to run. This list is automatically filled with all the classes in TC.Adl.Test that derive from &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.form.aspx"&gt;System.Windows.Forms.Form&lt;/a&gt;. That way, we can add test cases without having to modify FormMain each time.&lt;/p&gt; &lt;p&gt;You can download it &lt;a title="Writing a parser: downloads" href="http://my.opera.com/TommyCarlier/blog/writing-a-parser-downloads"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-8881862451468432517?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/8881862451468432517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=8881862451468432517' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8881862451468432517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/8881862451468432517'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-base-vs2005-solution.html' title='Writing a parser: base VS2005 solution'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-6065466315431701556</id><published>2007-04-21T22:19:00.001+02:00</published><updated>2007-05-03T21:10:50.830+02:00</updated><title type='text'>Writing a parser: introduction to ADL</title><content type='html'>&lt;p&gt;This post will introduce ADL (&lt;em&gt;Acronymic Demonstrational Language&lt;/em&gt;),&amp;nbsp;a language I designed to demonstrate how to write a parser.&lt;/p&gt; &lt;h4&gt;Statements&lt;/h4&gt;ADL has 5 different types of statements:  &lt;ul&gt; &lt;li&gt;if-statement  &lt;li&gt;while-loop  &lt;li&gt;for-loop  &lt;li&gt;assignment  &lt;li&gt;function call&lt;/li&gt;&lt;/ul&gt;An if-statement looks like this: &lt;pre&gt;&lt;b&gt;if&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;then&lt;/b&gt;
    &lt;i&gt;statements&lt;/i&gt;
&lt;b&gt;end if&lt;/b&gt;&lt;/pre&gt;An if-statement can also have an else-clause: &lt;pre&gt;&lt;b&gt;if&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;then&lt;/b&gt;
    &lt;i&gt;statements&lt;/i&gt;
&lt;b&gt;else&lt;/b&gt;
    &lt;i&gt;statements&lt;/i&gt;
&lt;b&gt;end if&lt;/b&gt;&lt;/pre&gt;A while-loop looks like this: &lt;pre&gt;&lt;b&gt;while&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;do&lt;/b&gt;
    &lt;i&gt;statements&lt;/i&gt;
&lt;b&gt;end while&lt;/b&gt;&lt;/pre&gt;A for-loop looks like this: &lt;pre&gt;&lt;b&gt;for&lt;/b&gt; &lt;i&gt;variable&lt;/i&gt; &lt;b&gt;:=&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;to&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;do&lt;/b&gt;
    &lt;i&gt;statements&lt;/i&gt;
&lt;b&gt;end for&lt;/b&gt;&lt;/pre&gt;A for-loop can also have a by-clause that defines the number to add to the variable on each iteration: &lt;pre&gt;&lt;b&gt;for&lt;/b&gt; &lt;i&gt;variable&lt;/i&gt; &lt;b&gt;:=&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;to&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;by&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;do&lt;/b&gt;
    &lt;i&gt;statements&lt;/i&gt;
&lt;b&gt;end for&lt;/b&gt;&lt;/pre&gt;An assignment looks like this: &lt;pre&gt;&lt;i&gt;variable&lt;/i&gt; &lt;b&gt;:=&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt;&lt;/pre&gt;A function call looks like this: &lt;pre&gt;&lt;i&gt;function&lt;/i&gt;&lt;b&gt;()&lt;/b&gt;&lt;/pre&gt;It can also have one or more arguments separated by commas: &lt;pre&gt;&lt;i&gt;function&lt;/i&gt;&lt;b&gt;(&lt;/b&gt;&lt;i&gt;expression&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt;&lt;b&gt;,&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt;&lt;b&gt;)&lt;/b&gt;&lt;/pre&gt;
&lt;h4&gt;Expressions&lt;/h4&gt;
&lt;p&gt;Expressions in ADL consist of variables, constants, function calls, unary expressions, binary expressions and groups.&lt;/p&gt;
&lt;p&gt;Variable names start with a letter, followed by zero or more letters or numbers.&lt;/p&gt;
&lt;p&gt;ADL has 2 types of constants: strings and integer numbers. A string is a sequence of characters, enclosed between 2 quotes. An integer is a sequence of 1 or more digits.&lt;/p&gt;Unary expressions are expressions with an operator that has only 1 operand: 
&lt;ul&gt;
&lt;li&gt;positive operator: &lt;b&gt;+&lt;/b&gt;&lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;negative operator: &lt;b&gt;-&lt;/b&gt;&lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;logical NOT-operator: &lt;b&gt;not&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;Binary expressions are expressions with an operator that has 2 operands: 
&lt;ul&gt;
&lt;li&gt;logical AND-operator: &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;and&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;logical OR-operator: &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;or&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;comparison: &lt;i&gt;expression comparator expression&lt;/i&gt; (&lt;i&gt;comparator&lt;/i&gt; is one of the following: &lt;b&gt;==&lt;/b&gt;, &lt;b&gt;&amp;lt;&amp;gt;&lt;/b&gt;, &lt;b&gt;&amp;lt;&lt;/b&gt;, &lt;b&gt;&amp;gt;&lt;/b&gt;, &lt;b&gt;&amp;lt;=&lt;/b&gt;, &lt;b&gt;&amp;gt;=&lt;/b&gt;) 
&lt;li&gt;addition: &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;+&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;subtraction: &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;-&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;multiplication: &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;*&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; 
&lt;li&gt;division: &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;/&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;A group is an expression between parentheses: &lt;b&gt;(&lt;/b&gt; &lt;i&gt;expression&lt;/i&gt; &lt;b&gt;)&lt;/b&gt; 
&lt;h4&gt;Precedence&lt;/h4&gt;When an expression is built from multiple operators, the expression is evaluated in the following order: 
&lt;ul&gt;
&lt;li&gt;Grouping: &lt;code&gt;( )&lt;/code&gt; 
&lt;li&gt;Unary expression: &lt;code&gt;+ - not&lt;/code&gt; 
&lt;li&gt;Multiplicative expression: &lt;code&gt;* /&lt;/code&gt; 
&lt;li&gt;Additive expression: &lt;code&gt;+ -&lt;/code&gt; 
&lt;li&gt;Comparison: &lt;code&gt;== &amp;lt;&amp;gt; &amp;lt; &amp;gt; &amp;lt;= &amp;gt;=&lt;/code&gt; 
&lt;li&gt;Logical OR: &lt;code&gt;or&lt;/code&gt; 
&lt;li&gt;Logical AND: &lt;code&gt;and&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ADL" rel="tag"&gt;ADL&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Acronymic+Demonstrational+Language" rel="tag"&gt;Acronymic Demonstrational Language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Programming+Language" rel="tag"&gt;Programming Language&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-6065466315431701556?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/6065466315431701556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=6065466315431701556' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6065466315431701556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6065466315431701556'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-introduction-to-adl.html' title='Writing a parser: introduction to ADL'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-2934984288042794315</id><published>2007-04-21T20:47:00.001+02:00</published><updated>2007-04-21T20:47:33.392+02:00</updated><title type='text'>Writing a parser: basic terminology</title><content type='html'>&lt;p&gt;Programming code (or any code that should be parsed) is usually plain text. It's just a sequence of characters. A &lt;strong&gt;tokenizer&lt;/strong&gt; converts this sequence of characters into a sequence of tokens. A token is a group of characters that form a meaningful unit.&lt;/p&gt; &lt;p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/248390/chars_tokens.png"&gt;&lt;img height="75" alt="Converting characters into tokens." src="http://files.myopera.com/TommyCarlier/albums/248390/chars_tokens.png" width="275" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The &lt;strong&gt;parser&lt;/strong&gt; analyzes this sequence of tokens and transforms it into a tree of operators (primitive functions) and operands (the arguments of the operators).&lt;/p&gt; &lt;p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/248390/tokens_tree.png"&gt;&lt;img height="247" alt="Transforming tokens into a tree of operators and operands." src="http://files.myopera.com/TommyCarlier/albums/248390/tokens_tree.png" width="273" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Parser" rel="tag"&gt;Parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Tokenizer" rel="tag"&gt;Tokenizer&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-2934984288042794315?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/2934984288042794315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=2934984288042794315' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2934984288042794315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/2934984288042794315'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser-basic-terminology.html' title='Writing a parser: basic terminology'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-4194010394187996948</id><published>2007-04-21T17:12:00.001+02:00</published><updated>2007-04-21T17:12:57.770+02:00</updated><title type='text'>Writing a parser</title><content type='html'>&lt;p&gt;Inspired by a &lt;a title="Parsers are really, really fun" href="http://channel9.msdn.com/ShowPost.aspx?PostID=301988"&gt;thread about parsers on Channel 9&lt;/a&gt;, I've decided to start a series of blog posts on writing a parser. The parser I (and hopefully some of you) will write, will be able to parse a simple BASIC-like language with enough features to make it interesting, without being too complex.&lt;/p&gt; &lt;p&gt;The name of the language will be ADL, which stands for &lt;em&gt;Acronymic Demonstrational Language&lt;/em&gt;. A pretty lame name but if you have a better name, please leave a comment here. I'll try to show you how easy it is to write a good parser using simple techniques (reading 1 character at a time, no state-machine) without a lot of dry theory. The first introductory post (after this one) will have some theory and some terminology you need to know, but after that the fun will start.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/parser" rel="tag"&gt;parser&lt;/a&gt;, &lt;a href="http://technorati.com/tags/BASIC" rel="tag"&gt;BASIC&lt;/a&gt;, &lt;a href="http://technorati.com/tags/language" rel="tag"&gt;language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Channel+9" rel="tag"&gt;Channel 9&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-4194010394187996948?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/4194010394187996948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=4194010394187996948' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4194010394187996948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/4194010394187996948'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/writing-parser.html' title='Writing a parser'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-6235670272009088979</id><published>2007-04-08T17:13:00.001+02:00</published><updated>2007-04-08T17:13:12.000+02:00</updated><title type='text'>Basic Notation, fourth draft</title><content type='html'>&lt;p&gt;I've just written the fourth draft of the specification for &lt;a href="http://tommycarlier.blogspot.com/2006/11/basic-notation.html"&gt;Basic Notation&lt;/a&gt; 1.0. You can download it in &lt;a title="Basic Notation 1.0 specification" href="http://files.myopera.com/TommyCarlier/bn/Basic%20Notation%201_0.xps"&gt;XPS format&lt;/a&gt; (333 KB), or &lt;a title="Basic Notation 1.0 specification" href="http://files.myopera.com/TommyCarlier/bn/Basic%20Notation%201_0.pdf"&gt;PDF format&lt;/a&gt; (300 KB).&lt;/p&gt; &lt;p&gt;I did not blog about the third draft, in which I added support for namespaces, because I wasn't sure if adding namespaces was a good idea. Namespaces add complexity and make it a bit harder for people to understand the specification. So, in the fourth draft, I've removed namespaces, but I've kept prefixes, because they're easier to understand, don't add much complexity and can be used instead of namespaces.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Basic+Notation" rel="tag"&gt;Basic Notation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/BN" rel="tag"&gt;BN&lt;/a&gt;, &lt;a href="http://technorati.com/tags/notation" rel="tag"&gt;notation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/format" rel="tag"&gt;format&lt;/a&gt;, &lt;a href="http://technorati.com/tags/language" rel="tag"&gt;language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/XML" rel="tag"&gt;XML&lt;/a&gt;, &lt;a href="http://technorati.com/tags/specification" rel="tag"&gt;specification&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-6235670272009088979?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/6235670272009088979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=6235670272009088979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6235670272009088979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/6235670272009088979'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/04/basic-notation-fourth-draft.html' title='Basic Notation, fourth draft'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-3504700577555819786</id><published>2007-03-13T20:39:00.001+01:00</published><updated>2007-04-13T09:45:46.386+02:00</updated><title type='text'>Shawn &amp; Iben Paint 1.0.1</title><content type='html'>I just release a small update to &lt;a href="http://tommycarlier.blogspot.com/2007/03/shawn-iben-paint.html"&gt;Shawn &amp; Iben Paint&lt;/a&gt;. Some bugs are fixed, and I replaced the UpDownControl with a custom control to change the brush size. &lt;p&gt;Download: &lt;a title="Download Shawn and Iben Paint" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;SnIPaint.zip&lt;/a&gt; (11 KB); &lt;a title="Shawn and Iben Paint source code" href="http://channel9.msdn.com/ShowPost.aspx?PostID=289952"&gt;source code&lt;/a&gt; (19 KB).&lt;/p&gt;&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/paint" rel="tag"&gt;paint&lt;/a&gt;, &lt;a href="http://technorati.com/tags/kids" rel="tag"&gt;kids&lt;/a&gt;, &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/C#" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-3504700577555819786?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/3504700577555819786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=3504700577555819786' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3504700577555819786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/3504700577555819786'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/03/shawn-iben-paint-101.html' title='Shawn &amp;amp; Iben Paint 1.0.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-117353316440898551</id><published>2007-03-10T14:26:00.000+01:00</published><updated>2007-04-13T09:46:21.121+02:00</updated><title type='text'>Shawn &amp; Iben Paint</title><content type='html'>&lt;p&gt;I created a small paint&amp;nbsp;application for my nephews Shawn and Iben. You can paint using different brush sizes and colors and clear the painting. No advanced features, no saving and loading files, just painting.&lt;/p&gt; &lt;p&gt;Download: &lt;a title="Download Shawn and Iben Paint" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;SnIPaint.zip&lt;/a&gt; (11 KB); &lt;a title="Shawn and Iben Paint source code" href="http://channel9.msdn.com/ShowPost.aspx?PostID=289952"&gt;source code&lt;/a&gt; (17 KB).&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/paint" rel="tag"&gt;paint&lt;/a&gt;, &lt;a href="http://technorati.com/tags/kids" rel="tag"&gt;kids&lt;/a&gt;, &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/C#" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-117353316440898551?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/117353316440898551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=117353316440898551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/117353316440898551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/117353316440898551'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/03/shawn-iben-paint.html' title='Shawn &amp;amp; Iben Paint'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-117051832008255569</id><published>2007-02-03T16:58:00.000+01:00</published><updated>2007-02-04T18:48:25.603+01:00</updated><title type='text'>5 things you didn't know about me</title><content type='html'>&lt;p&gt;I first didn't want to participate in &lt;a title="Blog-Tag: A Game for a Virtual Cocktail Party" href="http://pulverblog.pulver.com/archives/006087.html"&gt;this blog-tagging game&lt;/a&gt;, but &lt;a title="Martin Plante: 5 things you didn't know about me" href="http://slimcode.com/cs/blogs/martin/archive/2007/02/01/5-things-you-didn-t-know-about-me.aspx"&gt;I got tagged&lt;/a&gt; by &lt;a title="slimCODE Software: simple solutions" href="http://slimcode.com/"&gt;Martin Plante&lt;/a&gt;, and I thought: what the heck, I'll do it.&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;I have 5 brothers&lt;/strong&gt; (3 older and 2 younger&amp;nbsp;than me). There is very little physical resemblance between the 6 of us, and we all have different characters. We do have some things in common, like our broad sense of humor, and our loyalty towards each other. Even though we don't live together anymore, we still stick together.  &lt;li&gt;&lt;strong&gt;I'm missing pieces.&lt;/strong&gt; Years ago, I had this disease called &lt;a href="http://en.wikipedia.org/wiki/Colitis_ulcerosa"&gt;Ulcerative colitis&lt;/a&gt;, which wasn't curable at the time (and I think it still isn't), but they could suppress the symptoms (diarrhea and blood loss) with heavy medication. After trying out all the different kinds of medication without luck, the only option left was to remove my colon. But before they could do that, they first had to remove my spleen, that was damaged by the medication. So I sit before you, an incomplete man. (BTW: after a long and heavy revalidation, I'm better than ever now)  &lt;li&gt;&lt;strong&gt;I have a talent that I can't use as much as I would like to.&lt;/strong&gt; I'm pretty good at drawing cartoonish stuff, but the problem is inspiration. I'm currently missing the inspiration, so if I do draw something, it's usually some meaningless figures on a piece of paper.  &lt;li&gt;&lt;strong&gt;I have a very broad and weird taste in movies.&lt;/strong&gt; I like artistic and alternative movies, good thrillers, but I can also really enjoy&amp;nbsp;science fiction, action movies and &lt;a title="Borat: Cultural Learnings of America for Make Benefit Glorious Nation of Kazakhstan" href="http://www.imdb.com/title/tt0443453/"&gt;cheap comedies&lt;/a&gt; that are considered dumb, and that are frowned upon by intellectuals and so-called educated people. I&amp;nbsp;have no problem with&amp;nbsp;this duality, but because of it, people usually think I'm a weirdo. Most people fit in one category, on one end of the line, and don't understand that I also like the other end.  &lt;li&gt;&lt;strong&gt;After I graduated, it was very hard for me to find a job in IT.&lt;/strong&gt; The dot-com bubble had just burst, and nobody wanted to hire unexperienced youngsters. I spent about 6 months looking for a job, I had&amp;nbsp;sent my resume to dozens of companies, I registered with at least 6 interim bureaus and never got a single call or offer. And then, I got an e-mail from &lt;a title="Weblications" href="http://www.weblications.be/"&gt;a small software company in Harelbeke&lt;/a&gt; that I never even heard of. They were looking for a developer, and had found my resume in a job database. That was and still is my first job as a software developer. I've been working there for more than 4 years, and I couldn't image working somewhere else.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;I'm tagging &lt;a title="Component Factory" href="http://www.componentfactory.com/blog.php"&gt;Phil Wright&lt;/a&gt;, &lt;a href="http://www.cklester.com/"&gt;C.K. Lester&lt;/a&gt;, &lt;a href="http://www.liensberger.it/Christian/MyChannel9.aspx"&gt;Christian Liensberger&lt;/a&gt;, &lt;a href="http://weblogs.asp.net/eporter/"&gt;Erik Porter&lt;/a&gt; and &lt;a href="http://ihatelinux.blogspot.com/"&gt;Brendan Grant&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/five+things" rel="tag"&gt;Five Things&lt;/a&gt;, &lt;a href="http://technorati.com/tags/blog-tagging" rel="tag"&gt;blog-tagging&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ulcerative+colitis" rel="tag"&gt;Ulcerative Colitis&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-117051832008255569?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/117051832008255569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=117051832008255569' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/117051832008255569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/117051832008255569'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/02/5-things-you-didnt-know-about-me.html' title='5 things you didn&apos;t know about me'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-117018176378821096</id><published>2007-01-30T19:29:00.000+01:00</published><updated>2007-01-30T19:29:23.856+01:00</updated><title type='text'>Xceed DataGrid for WPF</title><content type='html'>&lt;p&gt;&lt;a href="http://xceed.com/"&gt;Xceed&lt;/a&gt;, the company that created my favorite &lt;a title="Xceed Grid for .NET" href="http://xceed.com/Grid_WinForms_Intro.html"&gt;Windows Forms grid control&lt;/a&gt;, has just released &lt;a href="http://xceed.com/Grid_WPF_Intro.html"&gt;DataGrid for WPF&lt;/a&gt;. It's a feature-packed DataGrid control that is fully customizable, and the best news is: it's free!&lt;/p&gt; &lt;p&gt;As far as I know, no other company has released an advanced grid control for WPF yet.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Xceed" rel="tag"&gt;Xceed&lt;/a&gt;, &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;, &lt;a href="http://technorati.com/tags/DataGrid" rel="tag"&gt;DataGrid&lt;/a&gt;, &lt;a href="http://technorati.com/tags/GridControl" rel="tag"&gt;GridControl&lt;/a&gt;, &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-117018176378821096?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/117018176378821096/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=117018176378821096' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/117018176378821096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/117018176378821096'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/01/xceed-datagrid-for-wpf.html' title='Xceed DataGrid for WPF'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116818041868402180</id><published>2007-01-07T15:33:00.000+01:00</published><updated>2007-01-07T15:33:38.770+01:00</updated><title type='text'>FileCreationWatcher</title><content type='html'>&lt;p&gt;A few weeks ago, I received an e-mail from someone who asked me if I could give more details about a class I created at work, that is essentially a wrapper around the &lt;a href="http://msdn2.microsoft.com/en-us/system.io.filesystemwatcher.aspx"&gt;FileSystemWatcher&lt;/a&gt; class, and that detects the creation of files more reliably. You can read a discussion about this on &lt;a href="http://channel9.msdn.com/"&gt;Channel 9&lt;/a&gt;, in &lt;a title="FileSystemWatcher for opening files" href="http://channel9.msdn.com/ShowPost.aspx?PostID=251685"&gt;this thread&lt;/a&gt;. I sent him an e-mail back, with a simplified version of the wrapper class, and because I think this could also be useful for other people, I decided to post it here.&lt;/p&gt;&lt;pre&gt;&lt;span class="keyword"&gt;public class&lt;/span&gt; FileCreationWatcher : IDisposable
{
&amp;nbsp;&amp;nbsp;FileSystemWatcher fWatcher;

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public&lt;/span&gt; FileCreationWatcher(&lt;span class="keyword"&gt;string&lt;/span&gt; path, &lt;span class="keyword"&gt;string&lt;/span&gt; filter)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Initialize(path, filter);
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt; Initialize(&lt;span class="keyword"&gt;string&lt;/span&gt; path, &lt;span class="keyword"&gt;string&lt;/span&gt; filter)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fWatcher = &lt;span class="keyword"&gt;new&lt;/span&gt; FileSystemWatcher(path, filter);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fWatcher.Created += OnFileCreated;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fWatcher.Error += OnError;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt; OnFileCreated(&lt;span class="keyword"&gt;object&lt;/span&gt; sender, FileSystemEventArgs e)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FileInfo lFile = &lt;span class="keyword"&gt;new&lt;/span&gt; FileInfo(e.FullPath);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt; (lFile.Exists)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;// schedule the processing on a different thread&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ThreadPool.QueueUserWorkItem(&lt;span class="keyword"&gt;delegate&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;while&lt;/span&gt;(&lt;span class="keyword"&gt;true&lt;/span&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;// wait 100 milliseconds between attempts to read&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Thread.Sleep(TimeSpan.FromMilliseconds(100));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;try&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;// try to open the file&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lFile.OpenRead().Close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;break&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;catch&lt;/span&gt;(IOException)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;// if the file is still locked, keep trying&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;continue&lt;/span&gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;// the file can be opened successfully: raise the event&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt; (Created != &lt;span class="keyword"&gt;null&lt;/span&gt;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Created(&lt;span class="keyword"&gt;this&lt;/span&gt;, e);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;void&lt;/span&gt; OnError(&lt;span class="keyword"&gt;object&lt;/span&gt; sender, ErrorEventArgs e)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="comment"&gt;// when an error occurs, the current FileSystemWatcher is disposed,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// and a new one is created&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;string&lt;/span&gt; lPath = fWatcher.Path;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;string&lt;/span&gt; lFilter = fWatcher.Filter;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fWatcher.Dispose();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Initialize(lPath, lFilter);
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public void&lt;/span&gt; Start() { fWatcher.EnableRaisingEvents = &lt;span class="keyword"&gt;true&lt;/span&gt;; }

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public void&lt;/span&gt; Stop() { fWatcher.EnableRaisingEvents = &lt;span class="keyword"&gt;false&lt;/span&gt;; }

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public event&lt;/span&gt; FileSystemEventHandler Created;

&amp;nbsp;&amp;nbsp;#region IDisposable Members

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;public void&lt;/span&gt; Dispose() { Dispose(&lt;span class="keyword"&gt;true&lt;/span&gt;); GC.SuppressFinalize(&lt;span class="keyword"&gt;this&lt;/span&gt;); }

&amp;nbsp;&amp;nbsp;~FileCreationWatcher() { Dispose(&lt;span class="keyword"&gt;false&lt;/span&gt;); }

&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;protected virtual void&lt;/span&gt; Dispose(&lt;span class="keyword"&gt;bool&lt;/span&gt; disposing)
&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="keyword"&gt;if&lt;/span&gt; (disposing)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fWatcher.Dispose();
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;#endregion
}&lt;/pre&gt;
&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FileSystemWatcher" rel="tag"&gt;FileSystemWatcher&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116818041868402180?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116818041868402180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116818041868402180' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116818041868402180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116818041868402180'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2007/01/filecreationwatcher.html' title='FileCreationWatcher'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116740741461066700</id><published>2006-12-29T16:50:00.000+01:00</published><updated>2007-04-13T09:46:59.995+02:00</updated><title type='text'>Base Converter</title><content type='html'>&lt;p&gt;This post contains all the information about &lt;em&gt;Base Converter&lt;/em&gt;. It's always accessible from the &lt;em&gt;software&lt;/em&gt; category, and will be updated with each new version of &lt;em&gt;Base Converter&lt;/em&gt;. The source code can be downloaded from the &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=269080"&gt;Channel 9 Sandbox&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;/p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/122489/BaseConverter.png"&gt;&lt;img height="75" alt="Base Converter" src="http://files.myopera.com/TommyCarlier/albums/122489/BaseConverter.png" width="250" align="right" border="0"&gt;&lt;/a&gt;  &lt;h3&gt;Base Converter 1.0&lt;/h3&gt; &lt;p&gt;Base Converter is a tool for converting numbers between binary, octal, decimal and hexadecimal notation.&lt;/p&gt; &lt;p&gt;Download: &lt;a title="Base Converter download" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;BaseConverter.zip&lt;/a&gt; (412 KB)&lt;/p&gt; &lt;h4&gt;Version history&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;29 December 2006: &lt;a href="http://tommycarlier.blogspot.com/2006/12/base-converter-10.html"&gt;Base Converter 1.0&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Converter" rel="tag"&gt;Converter&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Base%20Converter" rel="tag"&gt;Base Converter&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/binary" rel="tag"&gt;binary&lt;/a&gt;, &lt;a href="http://technorati.com/tags/octal" rel="tag"&gt;octal&lt;/a&gt;, &lt;a href="http://technorati.com/tags/decimal" rel="tag"&gt;decimal&lt;/a&gt;, &lt;a href="http://technorati.com/tags/hexadecimal" rel="tag"&gt;hexadecimal&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116740741461066700?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116740741461066700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116740741461066700' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116740741461066700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116740741461066700'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/12/base-converter.html' title='Base Converter'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116740698743957291</id><published>2006-12-29T16:43:00.000+01:00</published><updated>2007-04-13T09:47:16.685+02:00</updated><title type='text'>Base Converter 1.0</title><content type='html'>&lt;p&gt;Base Converter is a new tool I created for converting numbers between binary, octal, decimal and hexadecimal notation.&lt;/p&gt; &lt;p&gt;Download: &lt;a title="Base Converter 1.0 download" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;BaseConverter.zip&lt;/a&gt; (412 KB)&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Converter" rel="tag"&gt;Converter&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Base+Converter" rel="tag"&gt;Base Converter&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/binary" rel="tag"&gt;binary&lt;/a&gt;, &lt;a href="http://technorati.com/tags/octal" rel="tag"&gt;octal&lt;/a&gt;, &lt;a href="http://technorati.com/tags/decimal" rel="tag"&gt;decimal&lt;/a&gt;, &lt;a href="http://technorati.com/tags/hexadecimal" rel="tag"&gt;hexadecimal&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116740698743957291?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116740698743957291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116740698743957291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116740698743957291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116740698743957291'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/12/base-converter-10.html' title='Base Converter 1.0'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116739328245075348</id><published>2006-12-29T12:54:00.000+01:00</published><updated>2007-04-13T09:47:33.318+02:00</updated><title type='text'>Calctor Mobile 1.1</title><content type='html'>&lt;p&gt;I've updated &lt;a href="http://tommycarlier.blogspot.com/2006/09/calctor-calctor-mobile.html"&gt;Calctor Mobile&lt;/a&gt; to version 1.1:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Added a notation to enter numbers with commas as separators between thousands, where the commas are ignored. To do this, just put the number between single quotes. Example: &lt;em&gt;'10,000,000'&lt;/em&gt;.  &lt;li&gt;Added documentation inside the application.  &lt;li&gt;Removed unnecessary user-interface elements, like the tabs, and empty menus.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can download it &lt;a title="Calctor Mobile 1.1 download" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Calctor+Mobile" rel="tag"&gt;Calctor Mobile&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Windows+Mobile" rel="tag"&gt;Windows Mobile&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116739328245075348?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116739328245075348/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116739328245075348' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116739328245075348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116739328245075348'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/12/calctor-mobile-11.html' title='Calctor Mobile 1.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116732205834175645</id><published>2006-12-28T17:07:00.000+01:00</published><updated>2007-04-13T09:47:46.631+02:00</updated><title type='text'>Calctor 2.1</title><content type='html'>&lt;p&gt;I've updated my calculator tool to version 2.1:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Fixed some bugs in the snippets.&lt;/li&gt; &lt;li&gt;Added a notation to enter numbers with commas as separators between thousands, where the comma's are ignored. To do this, just put the number between single quotes. Example: &lt;em&gt;'10,000,000'&lt;/em&gt;.&lt;/li&gt; &lt;li&gt;When the output region has focus, and you start typing, the input region gets focus and receives the keystrokes.&lt;/li&gt; &lt;li&gt;Changed the Help-format from RTF to HTML, so it can be shared with the &lt;em&gt;Calctor Mobile&lt;/em&gt;-codebase.&lt;/li&gt; &lt;li&gt;Updated the visual style to&amp;nbsp;use the Office 2007 color schemes. You can chose what color scheme you like (Silver, Black or Blue).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can download it &lt;a title="Calctor 2.1 download" href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116732205834175645?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116732205834175645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116732205834175645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116732205834175645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116732205834175645'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/12/calctor-21.html' title='Calctor 2.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116638365947319560</id><published>2006-12-17T20:27:00.000+01:00</published><updated>2006-12-17T20:27:39.540+01:00</updated><title type='text'>Basic Notation, second draft</title><content type='html'>&lt;p&gt;I've just finished writing a second draft of the specification for &lt;a href="http://tommycarlier.blogspot.com/2006/11/basic-notation.html"&gt;Basic Notation&lt;/a&gt; 1.0. You can download it in &lt;a title="Basic Notation 1.0 specification" href="http://files.myopera.com/TommyCarlier/bn/Basic%20Notation%201_0.xps"&gt;XPS format&lt;/a&gt; (267 KB), or &lt;a title="Basic Notation 1.0 specification" href="http://files.myopera.com/TommyCarlier/bn/Basic%20Notation%201_0.pdf"&gt;PDF format&lt;/a&gt; (237 KB).&lt;/p&gt; &lt;p&gt;The changes since the first draft, are:  &lt;ul&gt; &lt;li&gt;Element names are now optional.  &lt;li&gt;The semicolon ':' is no longer a valid name character, but is used as a separator between the name and the child nodes of an element. Empty elements (elements without child nodes) don't need a semicolon.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I've also started writing a .NET library in C#, for reading, writing and manipulating BN data. It has classes for reading BN data (&lt;em&gt;BNReader&lt;/em&gt;, similar in functionality to &lt;a href="http://msdn2.microsoft.com/en-us/system.xml.xmlreader.aspx"&gt;System.Xml.XmlReader&lt;/a&gt;), writing BN data (&lt;em&gt;BNWriter&lt;/em&gt;, similar in functionality to &lt;a href="http://msdn2.microsoft.com/en-us/system.xml.xmlwriter.aspx"&gt;System.Xml.XmlWriter&lt;/a&gt;),&amp;nbsp;manipulating BN data in-memory (&lt;em&gt;BDocument&lt;/em&gt;, &lt;em&gt;BNode&lt;/em&gt;, &lt;em&gt;BElement&lt;/em&gt;, &lt;em&gt;BText&lt;/em&gt; and&amp;nbsp;&lt;em&gt;BComment&lt;/em&gt;) and serializing objects to BN (&lt;em&gt;BNSerializer&lt;/em&gt;).&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Basic+Notation" rel="tag"&gt;Basic Notation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/BN" rel="tag"&gt;BN&lt;/a&gt;, &lt;a href="http://technorati.com/tags/notation" rel="tag"&gt;notation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/format" rel="tag"&gt;format&lt;/a&gt;, &lt;a href="http://technorati.com/tags/language" rel="tag"&gt;language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/XML" rel="tag"&gt;XML&lt;/a&gt;, &lt;a href="http://technorati.com/tags/specification" rel="tag"&gt;specification&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116638365947319560?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116638365947319560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116638365947319560' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116638365947319560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116638365947319560'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/12/basic-notation-second-draft.html' title='Basic Notation, second draft'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116439522086168425</id><published>2006-11-24T20:07:00.000+01:00</published><updated>2006-11-24T20:07:03.470+01:00</updated><title type='text'>Basic Notation</title><content type='html'>&lt;p&gt;I'm designing a notation that represents structured content in a text-based format. Kind of like a lightweight alternative for XML. The reason I designed this, is because I feel that XML has some problems that a standard format should not have. I started &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=259550"&gt;a discussion on Channel 9&lt;/a&gt;, asking if it was too late for a new format to replace XML. I realize my notation will not be used as much as XML, but I just want to see if I can create something that is technologically better than XML.&lt;/p&gt; &lt;p&gt;I've just finished writing a first version of the specification. You can download it in &lt;a title="Basic Notation 1.0 specification" href="http://files.myopera.com/TommyCarlier/bn/Basic%20Notation%201_0.xps"&gt;XPS format&lt;/a&gt; (195 KB), or &lt;a title="Basic Notation 1.0 specification" href="http://files.myopera.com/TommyCarlier/bn/Basic%20Notation%201_0.pdf"&gt;PDF format&lt;/a&gt; (164 KB).&lt;/p&gt; &lt;p&gt;Because the specification is still in development, you can still provide feedback that&amp;nbsp;can influence the design. To provide feedback, you can post in &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=260510"&gt;this thread on Channel 9&lt;/a&gt;, or just post a comment on this blog post.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Basic%20Notation" rel="tag"&gt;Basic Notation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/BN" rel="tag"&gt;BN&lt;/a&gt;, &lt;a href="http://technorati.com/tags/notation" rel="tag"&gt;notation&lt;/a&gt;, &lt;a href="http://technorati.com/tags/format" rel="tag"&gt;format&lt;/a&gt;, &lt;a href="http://technorati.com/tags/language" rel="tag"&gt;language&lt;/a&gt;, &lt;a href="http://technorati.com/tags/XML" rel="tag"&gt;XML&lt;/a&gt;, &lt;a href="http://technorati.com/tags/specification" rel="tag"&gt;specification&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116439522086168425?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116439522086168425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116439522086168425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116439522086168425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116439522086168425'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/11/basic-notation.html' title='Basic Notation'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116384569879895521</id><published>2006-11-18T11:28:00.000+01:00</published><updated>2006-11-18T11:28:20.866+01:00</updated><title type='text'>The pleasure of peeling peanuts</title><content type='html'>&lt;p&gt;Yesterday, I rediscovered the pleasure of peeling fresh peanuts. It's much easier to just buy peanuts that are already peeled, but they're not as fresh, and they're usually salted. Peeling fresh peanuts requires patience, and you usually spend more time peeling, than eating. But the&amp;nbsp;gratification is so much greater, because you&amp;nbsp;have to &lt;em&gt;work&lt;/em&gt; to get the peanut. In our society of laziness, symbolized by prepackaged peanuts, I think it's important to sometimes take time to peel peanuts yourself, to realize the value of peanuts.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/peanuts" rel="tag"&gt;peanuts&lt;/a&gt;, &lt;a href="http://technorati.com/tags/fresh" rel="tag"&gt;fresh&lt;/a&gt;, &lt;a href="http://technorati.com/tags/peeling" rel="tag"&gt;peeling&lt;/a&gt;, &lt;a href="http://technorati.com/tags/patience" rel="tag"&gt;patience&lt;/a&gt;, &lt;a href="http://technorati.com/tags/laziness" rel="tag"&gt;laziness&lt;/a&gt;, &lt;a href="http://technorati.com/tags/society" rel="tag"&gt;society&lt;/a&gt;, &lt;a href="http://technorati.com/tags/prepackaged" rel="tag"&gt;prepackaged&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116384569879895521?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116384569879895521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116384569879895521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116384569879895521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116384569879895521'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/11/pleasure-of-peeling-peanuts.html' title='The pleasure of peeling peanuts'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116284295447536114</id><published>2006-11-06T20:55:00.000+01:00</published><updated>2006-11-07T13:15:43.373+01:00</updated><title type='text'>New interw3b idea: cross-site bridges</title><content type='html'>&lt;p&gt;Today, I got an idea for a new feature that allows sharing posts&amp;nbsp;between sites. I got the idea from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=253544"&gt;this post I made on Channel 9&amp;nbsp;about Opera's new developer site&lt;/a&gt;. On the Opera dev forum, I also made &lt;a href="http://dev.opera.com/forums/topic/165593"&gt;a post, in which I posted a link to the C9 thread&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Then I started thinking: what if, instead of just linking between threads on separate sites, we could build a &lt;em&gt;bridge&lt;/em&gt; that would connect the threads, and automatically synchronize posts between the 2 sites, each using their own software.&lt;/p&gt;&lt;p&gt;I think this could be easy to implement, via RSS (maybe with some extensions). The bridge could be uni-directional or bi-directional. A uni-directional bridge would be a bridge from a thread on site A to a thread on site B, where A initiates the bridge, and automatically adds the posts of the thread on site B to its own thread, without site B having to know this. A bi-directional bridge would be a bridge between a thread on site A and a thread on site B, where both sites&amp;nbsp;use the bridge-system.&lt;/p&gt;&lt;p&gt;When I use the terms &lt;em&gt;site&lt;/em&gt; and &lt;em&gt;thread&lt;/em&gt;, I don't want to narrow it down to forums only, but also blogs and actually every site that has a concept of logical threads.&lt;/p&gt;&lt;p&gt;This means that members of 2 communities could be connected, each community using its own software, its own community site, but where the posts are shared. And if you create some kind of standard for user profiles, the sites could even create hyperlinks to user profiles on the other site.&lt;/p&gt;&lt;p&gt;&lt;b&gt;EDIT 7 Nov 2006&lt;/b&gt;: I also started &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=254048"&gt;a thread on Channel 9 about cross-site bridges&lt;/a&gt;. Some niners have already made good remarks. &lt;small&gt;Imagine there was a bridge between this blog post and the C9 thread, instead of just a hyperlink...&lt;/small&gt;&lt;/p&gt;&lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/internet" rel="tag"&gt;internet&lt;/a&gt;, &lt;a href="http://technorati.com/tags/www" rel="tag"&gt;www&lt;/a&gt;, &lt;a href="http://technorati.com/tags/bridge" rel="tag"&gt;bridge&lt;/a&gt;, &lt;a href="http://technorati.com/tags/forum" rel="tag"&gt;forum&lt;/a&gt;, &lt;a href="http://technorati.com/tags/blog" rel="tag"&gt;blog&lt;/a&gt;, &lt;a href="http://technorati.com/tags/thread" rel="tag"&gt;thread&lt;/a&gt;, &lt;a href="http://technorati.com/tags/post" rel="tag"&gt;post&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116284295447536114?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116284295447536114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116284295447536114' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116284295447536114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116284295447536114'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/11/new-interw3b-idea-cross-site-bridges.html' title='New interw3b idea: cross-site bridges'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116067183615229008</id><published>2006-10-12T18:50:00.000+02:00</published><updated>2006-10-12T18:50:36.160+02:00</updated><title type='text'>Calctor Mobile requires .NET CF 2.0</title><content type='html'>&lt;p&gt;I've already received 2 comments from people that try to install &lt;a href="http://tommycarlier.blogspot.com/2006/09/calctor-calctor-mobile.html"&gt;Calctor Mobile&lt;/a&gt; on their PocketPC or SmartPhone, and they get an error message &lt;em&gt;"This application requires a more recent version of .NET Compact Framework"&lt;/em&gt;. Calctor Mobile&amp;nbsp;runs on top of&amp;nbsp;.NET Compact Framework 2.0, which you can download &lt;a title=".NET Compact Framework 2.0" href="http://www.microsoft.com/downloads/details.aspx?familyid=0C1B0A88-59E2-4EBA-A70E-4CD851C5FCC4&amp;amp;displaylang=en"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116067183615229008?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116067183615229008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116067183615229008' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116067183615229008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116067183615229008'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/calctor-mobile-requires-net-cf-20.html' title='Calctor Mobile requires .NET CF 2.0'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116030023295706608</id><published>2006-10-08T11:37:00.000+02:00</published><updated>2006-10-08T11:38:04.020+02:00</updated><title type='text'>slimKEYS</title><content type='html'>&lt;p&gt;On &lt;a title="Free tools" href="http://tommycarlier.blogspot.com/2006/10/free-tools.html"&gt;my previous post about free tools I use&lt;/a&gt;, I got &lt;a href="http://tommycarlier.blogspot.com/2006/10/free-tools.html#116026903221076088"&gt;a comment by Martin Plante&lt;/a&gt;, who used to work for &lt;a href="http://www.xceedsoft.com/"&gt;Xceed&lt;/a&gt;, but has started a new company called &lt;a href="http://slimcode.com/"&gt;slimCODE&lt;/a&gt;. He told me about this tool he created called &lt;a href="http://slimcode.com/slimKEYS"&gt;slimKEYS&lt;/a&gt;, which is a universal hotkey manager, that has a plugin that allows you to quickly launch applications and documents.&lt;/p&gt; &lt;p&gt;So I installed it, modified some of the hotkeys (I like Win+Space for launching apps), and tried out some different stuff. And I must say, I like it a lot more than the already great&amp;nbsp;launcher &lt;a href="http://colibri.leetspeak.org/"&gt;Colibri&lt;/a&gt;. One thing I like about &lt;em&gt;slimKEYS&lt;/em&gt; is that it looks and feels like a Windows application. Colibri looks very different, which is not necessarily a bad thing, but I think &lt;em&gt;slimKEYS&lt;/em&gt; integrates better with my environment.&lt;/p&gt; &lt;p&gt;Because it has a plugin system, I think &lt;em&gt;slimKEYS&lt;/em&gt; has a bright future. It's probably easier for Martin to extend &lt;em&gt;slimKEYS&lt;/em&gt; himself with new functionality, but it also allows for external developers to develop cool plugins. This opportunity creates a developer community that will&amp;nbsp;help push &lt;em&gt;slimKEYS&lt;/em&gt; forward.&lt;/p&gt; &lt;p&gt;The most used plugin for me will be &lt;em&gt;slimLAUNCH&lt;/em&gt;, for launching applications and documents. You can fully customize what folders &lt;em&gt;slimLAUNCH&lt;/em&gt; should watch, and (like any plugin) what hotkey to use. I changed the default Win+Z to Win+Space. One thing &lt;em&gt;slimLAUNCH&lt;/em&gt; doesn't do yet that Colibri does, is the ability to quickly launch items from the Control Panel, like &lt;em&gt;'Add or remove programs'&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;The other plugins that are included right now are: &lt;em&gt;slimLAUNCHthis&lt;/em&gt;, for launching a specific application or document by pressing a hotkey; &lt;em&gt;slimSIZE&lt;/em&gt;, for moving and/or resizing the active window to a specific location and size; and &lt;em&gt;slimVOLUME&lt;/em&gt;, for modifying the volume level.&lt;/p&gt; &lt;p&gt;The following plugins are planned: &lt;em&gt;slimSEARCH&lt;/em&gt;, for quickly searching on your favorite search engines; &lt;em&gt;slimMESSAGE&lt;/em&gt;, for sending windows messages to any window; &lt;em&gt;slimSCRIPT&lt;/em&gt;, for executing your own C# or VB.NET code on demand; and &lt;em&gt;slimPASTE&lt;/em&gt;, for pasting the content of the clipboard, after stripping formatting or variants.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/hotkey+manager" rel="tag"&gt;hotkey manager&lt;/a&gt;, &lt;a href="http://technorati.com/tags/launcher" rel="tag"&gt;launcher&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Martin+Plante" rel="tag"&gt;Martin Plante&lt;/a&gt;, &lt;a href="http://technorati.com/tags/slimCODE" rel="tag"&gt;slimCODE&lt;/a&gt;, &lt;a href="http://technorati.com/tags/slimKEYS" rel="tag"&gt;slimKEYS&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116030023295706608?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116030023295706608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116030023295706608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116030023295706608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116030023295706608'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/slimkeys.html' title='slimKEYS'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116021904563767076</id><published>2006-10-07T13:04:00.000+02:00</published><updated>2006-11-25T05:43:19.580+01:00</updated><title type='text'>Free tools</title><content type='html'>&lt;p&gt;The Accessories you get with Windows (Notepad, Calculator, Paint) are small and fast, but sometimes you need more functionality. You have to realize that most of them haven't changed much since Windows 95 (or even earlier). So here are some FREE tools I use instead:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.getpaint.net/index.html"&gt;Paint.NET&lt;/a&gt;: this .NET application is so much better than the regular Paint. It has layers, effects, anti-aliasing, ...  &lt;li&gt;&lt;a href="http://www.pnotepad.org/"&gt;Programmer's Notepad&lt;/a&gt;: has all the features I need, and is still very fast. Great for programmers (syntax highlighting, code folding) or anyone else.  &lt;li&gt;&lt;a href="http://slimcode.com/slimKEYS/"&gt;slimKEYS&lt;/a&gt;: this application is a &amp;lt;quote&amp;gt;&lt;em&gt;Universal Hotkey Manager&lt;/em&gt;&amp;lt;/quote&amp;gt; that allows you to assign hotkeys to simple tasks. It has a plugin-system, and it comes with some nice plugins, including slimLAUNCH, which allows you to quickly launch applications and documents.  &lt;li&gt;&lt;small&gt;&lt;a href="http://colibri.leetspeak.org/"&gt;Colibri&lt;/a&gt;: &lt;strike&gt;this application allows you to launch applications a lot faster and easier than via the Start-menu. The only thing I modified was the hot key to launch Colibri. The default Ctrl+Space I use in Visual Studio, for auto-completion, so I&amp;nbsp;changed it to&amp;nbsp;Win+Space.&lt;/strike&gt;&lt;/small&gt; (I replaced Colibri with slimKEYS, but left the description here)  &lt;li&gt;&lt;a href="http://tommycarlier.blogspot.com/2006/09/calctor-calctor-mobile.html"&gt;Calctor&lt;/a&gt;: this is a calculator I developed myself. It looks very different from traditional calculators. You don't have to press buttons, but you get a text editor interface. Just start typing and Calctor will evaluate your input immediately. I've even developed a mobile version for &lt;em&gt;Windows Mobile&lt;/em&gt; devices.  &lt;li&gt;&lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=165900"&gt;Screen Capture&lt;/a&gt;: another tool I developed myself. It allows you to capture the screen, a part of the screen, or a window, and copy it to the clipboard, or immediately save it to a file.&lt;/li&gt;&lt;/ul&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/freeware" rel="tag"&gt;freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tags/tools" rel="tag"&gt;tools&lt;/a&gt;, &lt;a href="http://technorati.com/tags/accessories" rel="tag"&gt;accessories&lt;/a&gt;, &lt;a href="http://technorati.com/tags/paint" rel="tag"&gt;paint&lt;/a&gt;, &lt;a href="http://technorati.com/tags/notepad" rel="tag"&gt;notepad&lt;/a&gt;, &lt;a href="http://technorati.com/tags/calculator" rel="tag"&gt;calculator&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116021904563767076?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116021904563767076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116021904563767076' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116021904563767076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116021904563767076'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/free-tools.html' title='Free tools'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-116021190672046695</id><published>2006-10-07T11:05:00.000+02:00</published><updated>2006-10-07T11:06:51.700+02:00</updated><title type='text'>C9Park: McCoffeehouse</title><content type='html'>&lt;p&gt;&lt;a href="http://channel9.msdn.com/Niners/jamie"&gt;Jamie&lt;/a&gt; has produced &lt;a title="C9 Park: McCoffeehouse" href="http://c9park.wordpress.com/2006/10/06/c9park-mccoffeehouse/"&gt;another masterpiece&lt;/a&gt;. It must have taken a lot of time and effort to create. I think &lt;a href="http://c9park.wordpress.com/"&gt;C9Park&lt;/a&gt; really catches the spirit of the&amp;nbsp;&lt;a href="http://channel9.msdn.com/"&gt;Channel 9&lt;/a&gt;&amp;nbsp;community. Good one, Jamie. &lt;small&gt;PS: I'm in it!&lt;/small&gt;&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Channel+9" rel="tag"&gt;Channel 9&lt;/a&gt;, &lt;a href="http://technorati.com/tags/C9Park" rel="tag"&gt;C9Park&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-116021190672046695?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/116021190672046695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=116021190672046695' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116021190672046695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/116021190672046695'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/c9park-mccoffeehouse.html' title='C9Park: McCoffeehouse'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115969688454474806</id><published>2006-10-01T12:01:00.000+02:00</published><updated>2007-01-13T10:46:27.023+01:00</updated><title type='text'>The power of Windows Live Writer</title><content type='html'>&lt;p&gt;&lt;a href="http://tommycarlier.blogspot.com/2006/10/windows-live-writer-beta.html"&gt;My previous post&lt;/a&gt; was about the technical side of &lt;a href="http://windowslivewriter.spaces.live.com/"&gt;Windows Live Writer&lt;/a&gt;. This post is about what Windows Live Writer means&amp;nbsp;to me. I downloaded the first beta version, just to try it out, to see what all the fuss was about, not really expecting anything spectacular. And it wasn't very spectacular at first.&lt;/p&gt; &lt;p&gt;But after using it for a while, I've noticed that it makes blogging a lot easier and more fun. No more logging into &lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt;, no more typing in a crappy little editor. No more navigating a web site, clicking links, waiting, previewing slowly. The &lt;em&gt;Web Layout&lt;/em&gt; mode is awesome. Even managing multiple blogs is easy, switching between them is fast, and if you use different styles, the &lt;em&gt;Web Layout&lt;/em&gt; mode makes it very obvious what blog you are posting for.&lt;/p&gt; &lt;p&gt;This application shows that Windows applications will not be replaced by Web applications very soon. On the contrary, this is a Windows application that replaces a Web application. The Web application is not going away, because it's still the most accessible way of blogging when you're not at home. But at home, I'm only logging into Blogger when I need to update the template, or change the options.&lt;/p&gt; &lt;p&gt;Windows Live Writer has encouraged me to blog more often.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Windows+Live+Writer" rel="tag"&gt;Windows Live Writer&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Blogger" rel="tag"&gt;Blogger&lt;/a&gt;, &lt;a href="http://technorati.com/tags/blogging" rel="tag"&gt;blogging&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Windows+versus+Web" rel="tag"&gt;Windows versus Web&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115969688454474806?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115969688454474806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115969688454474806' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115969688454474806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115969688454474806'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/power-of-windows-live-writer.html' title='The power of Windows Live Writer'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115969512751876720</id><published>2006-10-01T11:32:00.000+02:00</published><updated>2006-10-01T11:32:07.523+02:00</updated><title type='text'>Windows Live Writer beta</title><content type='html'>&lt;p&gt;I just installed the latest version of the &lt;a href="http://windowslivewriter.spaces.live.com/"&gt;Windows Live Writer beta&lt;/a&gt;. The first thing you notice is that it starts up a lot faster than the previous version. This speedup was very necessary. Something else I immediately found useful was the function to &lt;em&gt;Insert Tags&lt;/em&gt;. I've always added &lt;a href="http://technorati.com/"&gt;Technorati&lt;/a&gt; tags to my posts, but doing this manually is not really fun. The &lt;em&gt;Insert Tags&lt;/em&gt; function automatically generates the tags and links. It even remembers the tags you've used before, and if you start typing a tag you've used before, it gives you some Intellisense, and autocompletes the tag for you.&lt;/p&gt; &lt;div class="tags"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Windows+Live+Writer" rel="tag"&gt;Windows Live Writer&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115969512751876720?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115969512751876720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115969512751876720' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115969512751876720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115969512751876720'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/windows-live-writer-beta.html' title='Windows Live Writer beta'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115969447835596434</id><published>2006-10-01T11:21:00.000+02:00</published><updated>2006-10-01T11:23:40.690+02:00</updated><title type='text'>Visual Studio Orcas September CTP</title><content type='html'>&lt;p&gt;Microsoft has released the &lt;a title="Visual Studio Orcas, September CTP download" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=82243606-d16d-445c-8949-9ee8c10cda2e&amp;amp;DisplayLang=en"&gt;September CTP of Visual Studio Orcas&lt;/a&gt;, and what I think is fascinating, is the way they deploy it. You don't get an installer, but a Virtual PC image. This means you don't risk losing data or ruining your current configuration. You just download the image, and run it. No need to install anything. Except Virtual PC of course. Once.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tags/Visual+Studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Orcas" rel="tag"&gt;Orcas&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Virtual+PC" rel="tag"&gt;Virtual PC&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115969447835596434?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115969447835596434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115969447835596434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115969447835596434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115969447835596434'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/10/visual-studio-orcas-september-ctp.html' title='Visual Studio Orcas September CTP'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115901005951143270</id><published>2006-09-23T13:14:00.000+02:00</published><updated>2006-09-23T13:14:55.980+02:00</updated><title type='text'>Lang.NET Symposium 2006</title><content type='html'>&lt;p&gt;At &lt;a href="http://www.langnetsymposium.com/"&gt;this website&lt;/a&gt;, you can download videos of the presentations that were held at the Lang.NET Symposium, &lt;em&gt;&amp;lt;quote&amp;gt; a forum for discussion on programming languages, managed execution environments, compilers, multi-language libraries and integrated development environments &amp;lt;/quote&amp;gt;&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;I particularly liked &lt;a href="http://en.wikipedia.org/wiki/Anders_Hejlsberg"&gt;Anders Hejlsberg&lt;/a&gt;'s presentation about &lt;a href="http://download.microsoft.com/download/9/4/1/94138e2a-d9dc-435a-9240-bcd985bf5bd7/AndersH-LINQ_0001.wmv"&gt;LINQ and C# 3.0&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/lang.net" rel="tag"&gt;Lang.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tag/.net" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Programming+Languages" rel="tag"&gt;Programming languages&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115901005951143270?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115901005951143270/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115901005951143270' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115901005951143270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115901005951143270'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/langnet-symposium-2006.html' title='Lang.NET Symposium 2006'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115850699271779026</id><published>2006-09-17T17:29:00.000+02:00</published><updated>2007-04-13T09:48:26.445+02:00</updated><title type='text'>Calctor Mobile 1.0</title><content type='html'>I've created a mobile version of my Calctor application. It runs on Windows Mobile 5, and uses the exact same calculation engine as the desktop version. You can download it &lt;a href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;here&lt;/a&gt;. &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calctor+Mobile" rel="tag"&gt;Calctor Mobile&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Windows+Mobile" rel="tag"&gt;Windows Mobile&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115850699271779026?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115850699271779026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115850699271779026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115850699271779026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115850699271779026'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/calctor-mobile-10.html' title='Calctor Mobile 1.0'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115850653283729960</id><published>2006-09-17T17:22:00.000+02:00</published><updated>2007-04-13T09:48:39.745+02:00</updated><title type='text'>Calctor 2.0</title><content type='html'>&lt;p&gt;I've updated my calculator tool to version 2.0:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Fixed some bugs in the snippets  &lt;li&gt;Refactored the code, so I could extract the calculation engine into a separate library that can be shared with &lt;em&gt;Calctor Mobile&lt;/em&gt;.  &lt;li&gt;Updated the visual style, and the icons  &lt;li&gt;Added&amp;nbsp;a new option: &lt;em&gt;Don't ask to save changes&lt;/em&gt;  &lt;li&gt;Changed the parser: the leading zero is now optional (you can use .75 instead of 0.75)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You can download it &lt;a href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115850653283729960?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115850653283729960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115850653283729960' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115850653283729960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115850653283729960'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/calctor-20.html' title='Calctor 2.0'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115850567518424148</id><published>2006-09-17T17:07:00.000+02:00</published><updated>2009-07-28T12:51:36.418+02:00</updated><title type='text'>Calctor &amp; Calctor Mobile</title><content type='html'>&lt;p&gt;This post contains all the information about &lt;em&gt;Calctor&lt;/em&gt; and &lt;em&gt;Calctor Mobile&lt;/em&gt;. It's always accessible from the &lt;em&gt;software&lt;/em&gt; category, and will be updated with each new version of either &lt;em&gt;Calctor&lt;/em&gt; or &lt;em&gt;Calctor Mobile&lt;/em&gt;. The source code for both version can be downloaded from the &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=235710"&gt;Channel 9 Sandbox&lt;/a&gt;.&lt;/p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/122489/Calctor.png"&gt;&lt;img border="0" alt="Calctor" align="right" src="http://files.myopera.com/TommyCarlier/albums/122489/Calctor.png" width="250" height="181"&gt;&lt;/a&gt;  &lt;h3&gt;Calctor 2.1.2&lt;/h3&gt; &lt;p&gt;Calctor is an advanced calculator with a simple interface. You have an input-region where you enter your calculations, and an output-region where the results of your calculations automatically appear while you're typing.&lt;/p&gt; &lt;p&gt;Download: &lt;a href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;Calctor.zip&lt;/a&gt; (643 KB)&lt;/p&gt; &lt;h4&gt;Version History&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;27 May 2006: &lt;a href="http://blog.tcx.be/2006/05/calctor.html"&gt;Calctor 1.0&lt;/a&gt;  &lt;li&gt;28 May 2006: &lt;a href="http://blog.tcx.be/2006/05/calctor-11.html"&gt;Calctor 1.1&lt;/a&gt;  &lt;li&gt;3 June 2006: &lt;a href="http://blog.tcx.be/2006/06/calctor-12.html"&gt;Calctor 1.2&lt;/a&gt;  &lt;li&gt;10 June 2006: &lt;a href="http://blog.tcx.be/2006/06/calctor-13.html"&gt;Calctor 1.3&lt;/a&gt;  &lt;li&gt;17 September 2006: &lt;a href="http://blog.tcx.be/2006/09/calctor-20.html"&gt;Calctor 2.0&lt;/a&gt;  &lt;li&gt;28 December 2006: &lt;a href="http://blog.tcx.be/2006/12/calctor-21.html"&gt;Calctor 2.1&lt;/a&gt;  &lt;li&gt;1 July 2007: &lt;a href="http://blog.tcx.be/2007/07/calctor-211.html"&gt;Calctor 2.1.1&lt;/a&gt; &lt;li&gt;28 July 2009: &lt;a href="http://blog.tcx.be/2009/07/calctor-212.html"&gt;Calctor 2.1.2&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Calctor Mobile 1.1&lt;/h3&gt; &lt;p&gt;Calctor Mobile is the mobile version of Calctor. It runs on Windows Mobile 5, and uses the exact same calculation engine as the desktop version of Calctor. To run Calctor Mobile, you need to install .NET Compact Framework 2.0, which you can download &lt;a title=".NET Compact Framework 2.0" href="http://www.microsoft.com/downloads/details.aspx?familyid=0C1B0A88-59E2-4EBA-A70E-4CD851C5FCC4&amp;amp;displaylang=en"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Download: &lt;a href="http://my.opera.com/TommyCarlier/blog/downloads"&gt;CalctorMobile.zip&lt;/a&gt; (207 KB)&lt;/p&gt; &lt;h4&gt;Version History&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;17 September 2006: &lt;a href="http://blog.tcx.be/2006/09/calctor-mobile-10.html"&gt;Calctor Mobile 1.0&lt;/a&gt;  &lt;li&gt;29 December 2006: &lt;a href="http://blog.tcx.be/2006/12/calctor-mobile-11.html"&gt;Calctor Mobile 1.1&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calctor+Mobile" rel="tag"&gt;Calctor Mobile&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Windows+Mobile" rel="tag"&gt;Windows Mobile&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115850567518424148?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115850567518424148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115850567518424148' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115850567518424148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115850567518424148'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/calctor-calctor-mobile.html' title='Calctor &amp;amp; Calctor Mobile'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115849329395952045</id><published>2006-09-17T13:41:00.000+02:00</published><updated>2006-10-01T15:06:24.950+02:00</updated><title type='text'>PopCap Games</title><content type='html'>&lt;p&gt;I'm not really into video games. If I do play games, it's usually small and fast games; games you can start up and play for 15 minutes without having to go through a story, or determine long-term strategies. For a while now, I've been playing &lt;a href="http://www.popcap.com/launchpage.php?theGame=bejeweled2"&gt;Bejeweled 2&lt;/a&gt;, the extremely addictive jewel popping game from &lt;a href="http://www.popcap.com/"&gt;PopCap Games&lt;/a&gt;. I think this market has a huge potential. This kind of games have low system requirements, a fairly low price, a small download size, simple rules that are easy to learn, etc... They are not for hardcore gamers, but for everyone else.&lt;/p&gt; &lt;p&gt;Today, I've downloaded the trial version of PopCap's latest game: &lt;a href="http://www.popcap.com/launchpage.php?theGame=talismania"&gt;Talismania&lt;/a&gt;. The demo version lets you play for 60 minutes, and I must admit: those 60 minutes flew by. They managed to produce another awesome game, with nice graphics, great music and simple but addictive gameplay. I suggest you download the trial version (a small&amp;nbsp;12.6 MB download) and try it out.&lt;/p&gt; &lt;p style="font-size: 80%"&gt;PS: I'm not sponsored by PopCap, or in anyway affiliated. I'm just a fan.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Games" rel="tag"&gt;Games&lt;/a&gt;, &lt;a href="http://technorati.com/tag/PopCap" rel="tag"&gt;PopCap&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Talismania" rel="tag"&gt;Talismania&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115849329395952045?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115849329395952045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115849329395952045' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115849329395952045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115849329395952045'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/popcap-games.html' title='PopCap Games'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115834487352148501</id><published>2006-09-15T20:27:00.000+02:00</published><updated>2006-09-15T20:27:53.696+02:00</updated><title type='text'>Rory on open-source</title><content type='html'>&lt;a href="http://neopoleon.com/home/default.aspx"&gt;Rory Blyth&lt;/a&gt; posts &lt;a href="http://neopoleon.com/home/blogs/neo/archive/2006/09/14/21608.aspx"&gt;his opinion on open-source projects&lt;/a&gt;. Like usual, he likes to exaggerate a bit, but he does make a good point: &lt;em&gt;"To get things done, you need to be able to tell Leia to shut up."&lt;/em&gt;  &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/rory+blyth" rel="tag"&gt;Rory Blyth&lt;/a&gt;, &lt;a href="http://technorati.com/tag/open+source" rel="tag"&gt;Open-source&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115834487352148501?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115834487352148501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115834487352148501' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115834487352148501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115834487352148501'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/rory-on-open-source.html' title='Rory on open-source'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115779226554179585</id><published>2006-09-09T10:57:00.000+02:00</published><updated>2006-09-09T11:05:19.573+02:00</updated><title type='text'>Cool introduction to SQL Server Everywhere</title><content type='html'>&lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/bart/default.aspx"&gt;Bart Desmet&lt;/a&gt; has posted a cool article: &lt;a href="http://community.bartdesmet.net/blogs/bart/archive/2006/08/26/4272.aspx"&gt;Getting started with SQL Server 2005 Everywhere Edition&lt;/a&gt;. I think this is a cool technology, that can be used a lot easier than SQL Server Express. It's smaller, needs less memory, doesn't have to be installed as a service, and can run in-process. A cool usage for this would be to use SQL/e as a file format for your application. If you're creating a word processor, or any document-oriented application, you could use SQL/e instead of creating a custom file format.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/SQL+Server" rel="tag"&gt;SQL Server&lt;/a&gt;, &lt;a href="http://technorati.com/tag/SQL+Server+Everywhere" rel="tag"&gt;SQL Server Everywhere&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Portable+database" rel="tag"&gt;Portable database&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115779226554179585?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115779226554179585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115779226554179585' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115779226554179585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115779226554179585'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/09/cool-introduction-to-sql-server.html' title='Cool introduction to SQL Server Everywhere'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115679032432694393</id><published>2006-08-28T20:38:00.000+02:00</published><updated>2006-08-28T20:38:45.213+02:00</updated><title type='text'>Krypton palette continues</title><content type='html'>&lt;p&gt;After my post yesterday, &lt;a href="http://tommycarlier.blogspot.com/2006/08/my-krypton-palette.html"&gt;about the custom Krypton palette I designed&lt;/a&gt;, I got &lt;a href="http://www.componentfactory.com/phpBB2/viewtopic.php?t=95"&gt;some positive comments&lt;/a&gt; on &lt;a href="http://www.componentfactory.com/phpBB2/index.php"&gt;Component Factory's forum&lt;/a&gt;. Phil Wright even suggested to include my palette in the Krypton Toolkit distribution. Of course I'm happy with this! So I first reviewed my palette, to see if I didn't miss anything, and made a few minor adjustments.&lt;/p&gt; &lt;p&gt;You can download it &lt;a href="http://files.myopera.com/TommyCarlier/files/TC_System_Palette.xml"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Windows+Forms" rel="tag"&gt;Windows Forms&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Controls" rel="tag"&gt;Controls&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Component+Factory" rel="tag"&gt;Component Factory&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Krypton+Toolkit" rel="tag"&gt;Krypton Toolkit&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115679032432694393?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115679032432694393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115679032432694393' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115679032432694393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115679032432694393'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/08/krypton-palette-continues.html' title='Krypton palette continues'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115667521789331027</id><published>2006-08-27T12:40:00.000+02:00</published><updated>2006-08-28T06:31:00.700+02:00</updated><title type='text'>My Krypton palette</title><content type='html'>&lt;p&gt;&lt;a href="http://files.myopera.com/TommyCarlier/albums/122489/PackInstaller.png"&gt;&lt;img height="225" alt="Screenshot" src="http://files.myopera.com/TommyCarlier/albums/122489/PackInstaller.png" width="256" align="right" border="0"&gt;&lt;/a&gt;I've been using the free &lt;a href="http://www.componentfactory.com/"&gt;Krypton Toolkit&lt;/a&gt; for a while now, and I like it. I like the fact that you can easily design a custom palette to style your controls. For some of my applications, I've designed a custom palette that looks a bit shiny, a bit Vista-esque, and that uses Windows' system colors.&lt;/p&gt; &lt;p&gt;You can download it &lt;a href="http://files.myopera.com/TommyCarlier/files/TC_System_Palette.xml"&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Windows+Forms" rel="tag"&gt;Windows Forms&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Controls" rel="tag"&gt;Controls&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Component+Factory" rel="tag"&gt;Component Factory&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Krypton+Toolkit" rel="tag"&gt;Krypton Toolkit&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115667521789331027?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115667521789331027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115667521789331027' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115667521789331027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115667521789331027'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/08/my-krypton-palette.html' title='My Krypton palette'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115599133728840845</id><published>2006-08-19T14:42:00.000+02:00</published><updated>2006-08-19T14:43:42.886+02:00</updated><title type='text'>Singularity</title><content type='html'>&lt;p&gt;&lt;a href="http://channel9.msdn.com/"&gt;Channel 9&lt;/a&gt; has 2 new videos about Singularity, an experimental research OS that is (almost) entirely written in Spec#, a superset of C# (only a very small part of the kernel is written in assembly). The technology they're researching is just awesome. Here are some links:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://research.microsoft.com/os/singularity/"&gt;The Singularity website&lt;/a&gt;  &lt;li&gt;&lt;a href="http://research.microsoft.com/specsharp/"&gt;The Spec# website&lt;/a&gt;  &lt;li&gt;Channel 9 video 1: &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=68302"&gt;Singularity: a research OS written in C#&lt;/a&gt;  &lt;li&gt;Channel 9 video 2: &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=141858"&gt;Singularity Revisited&lt;/a&gt;  &lt;li&gt;Channel 9 video 3: &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=227259"&gt;Singularity III: Revenge of the SIP&lt;/a&gt;  &lt;li&gt;Channel 9 video 4: &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=227259"&gt;Singularity IV: Return of the UI&lt;/a&gt;&amp;nbsp;(demo of Singularity!)&lt;/li&gt;&lt;/ul&gt; &lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/microsoft" rel="tag"&gt;Microsoft&lt;/a&gt;, &lt;a href="http://technorati.com/tag/research" rel="tag"&gt;Research&lt;/a&gt;, &lt;a href="http://technorati.com/tag/os" rel="tag"&gt;OS&lt;/a&gt;, &lt;a href="http://technorati.com/tag/singularity" rel="tag"&gt;Singularity&lt;/a&gt;, &lt;a href="http://technorati.com/tag/specsharp" rel="tag"&gt;Spec#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115599133728840845?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115599133728840845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115599133728840845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115599133728840845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115599133728840845'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/08/singularity_19.html' title='Singularity'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115401427297466425</id><published>2006-07-27T17:19:00.000+02:00</published><updated>2006-08-19T14:49:24.876+02:00</updated><title type='text'>New blog layout</title><content type='html'>&lt;p&gt;I created a whole new layout for my blog, while still keeping the existing colors (and some of the fonts). The previous layout was mostly inherited from the standard Blogger template, with some modifications.&lt;/p&gt; &lt;p&gt;But it had some problems. The right column sometimes interfered with the main column, especially on small screens. And it was sometimes too crowded (too much content packed together).&lt;/p&gt; &lt;p&gt;The new layout has only 1 column, pretty large fonts, and a text-width and line-height that are comfortable to read. I moved the right column all the way to the bottom, which gives me the extra advantage that the actual content is loaded BEFORE the less important &lt;i&gt;sidebar&lt;/i&gt;.&lt;/p&gt; &lt;p&gt;I would appreciate some feedback on this. Do you like it? Hate it? Know a way to improve it? Just leave a comment on this post.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115401427297466425?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115401427297466425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115401427297466425' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115401427297466425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115401427297466425'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/07/new-blog-layout.html' title='New blog layout'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115382885222285281</id><published>2006-07-25T14:00:00.000+02:00</published><updated>2007-02-26T18:54:31.980+01:00</updated><title type='text'>Creating a hybrid Class Library</title><content type='html'>&lt;p&gt;This post explains how to create a hybrid Class Library: a Class Library that is used by both a desktop application (regular .NET Framework) and a mobile application (Compact Framework).&lt;/p&gt;
&lt;p&gt;I'm currently working on a mobile version of my &lt;a href="http://tommycarlier.blogspot.com/2006/06/calctor-13.html"&gt;Calctor&lt;/a&gt; application. To make it easier to maintain, I decided to refactor the base functionality into a class library that I could reference in both the desktop version and the mobile version. The refactoring part was easy, but when I tried to add a reference from the device project to the class library, I got an error message that you can't do that. Which actually makes sense: the device project uses the Compact Framework, which contains only a subset of the BCL. &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=219219"&gt;So I asked how to solve this on Channel 9.&lt;/a&gt; As I expected, I soon got a useful answer from &lt;a href="http://www.ookii.org/"&gt;Sven Groot&lt;/a&gt;. After trying out several options, I ended up with the following solution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a Device Class Library: File &amp;gt; New &amp;gt; Project... &amp;gt; Smart Device &amp;gt; &lt;i&gt;[Choose device project type]&lt;/i&gt; &amp;gt; Class Library&lt;/li&gt;
&lt;li&gt;From your Device Application project, add a new reference to the newly created Device Class Library.&lt;/li&gt;
&lt;li&gt;From your Windows Application, add a new reference to the newly created Device Class Library. It will give a warning that unexpected stuff may happen, but you can just continue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This works out great, you can compile and debug just fine. One disadvantage is that you can only use the subset of BCL functionality that is in the Compact Framework, but that is only logical. Another disadvantage: if you have all projects (desktop and mobile) in 1 solution, and you're trying to debug the desktop application, the mobile project(s) will also be built and deployed, which slows down the building considerably. So if you're debugging only one of the application projects, I suggest you unload the other application project(s) that are not referenced. Just right-click the project, and choose &lt;i&gt;Unload project&lt;/i&gt;. Later, you can just reload it by right-clicking the disabled project and choosing &lt;i&gt;Reload project&lt;/i&gt;.&lt;/p&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/visual+studio" rel="tag"&gt;Visual Studio&lt;/a&gt;, &lt;a href="http://technorati.com/tag/compact+framework" rel="tag"&gt;Compact Framework&lt;/a&gt;, &lt;a href="http://technorati.com/tag/windows+mobile" rel="tag"&gt;Windows Mobile&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115382885222285281?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115382885222285281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115382885222285281' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115382885222285281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115382885222285281'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/07/creating-hybrid-class-library.html' title='Creating a hybrid Class Library'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115244907657849457</id><published>2006-07-09T14:25:00.000+02:00</published><updated>2006-07-26T16:53:09.730+02:00</updated><title type='text'>Once upon a time in America</title><content type='html'>On my &lt;a href="http://tommycarlier.blogspot.com/2006/06/world-is-yours.html"&gt;previous post, about the movie &lt;i&gt;Scarface&lt;/i&gt;&lt;/a&gt;, I got a comment from &lt;a href="http://blog.u2u.info/DottextWeb/peter"&gt;Peter Himschoot&lt;/a&gt;, who said I would also like &lt;i&gt;&lt;a href="http://www.imdb.com/title/tt0087843/"&gt;Once upon a time in America&lt;/a&gt;&lt;/i&gt;. So last week I bought the DVD on eBay, and this morning I got up early to watch it. It's a long movie (almost 4 hours), but it never feels long. It's a story that needs a long time to tell properly. It features a great cast (&lt;a href="http://www.imdb.com/name/nm0000134/"&gt;Robert De Niro&lt;/a&gt;, &lt;a href="http://www.imdb.com/name/nm0000249/"&gt;James Woods&lt;/a&gt;, &lt;a href="http://www.imdb.com/name/nm0001235/"&gt;William Forsythe&lt;/a&gt;, ...) and some of the most beautiful music I ever heard in a movie (from the hand of &lt;a href="http://www.imdb.com/name/nm0001553/"&gt;Ennio Morricone&lt;/a&gt;). Truely a masterpiece.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/movies" rel="tag"&gt;movies&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Once+upon+a+time+in+America" rel="tag"&gt;Once upon a time in America&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Sergio+Leone" rel="tag"&gt;Sergio Leone&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Robert+De+Niro" rel="tag"&gt;Robert De Niro&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115244907657849457?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115244907657849457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115244907657849457' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115244907657849457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115244907657849457'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/07/once-upon-time-in-america.html' title='Once upon a time in America'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115144119171939700</id><published>2006-06-27T22:36:00.000+02:00</published><updated>2006-06-29T21:09:38.093+02:00</updated><title type='text'>The world is yours</title><content type='html'>I just finished watching &lt;a href="http://www.imdb.com/title/tt0086250/"&gt;Scarface&lt;/a&gt;, and I'm very impressed. I always thought &lt;a href="http://www.imdb.com/name/nm0000199/"&gt;Al Pacino&lt;/a&gt; was a great actor, but I had never seen any of his earlier work. This just adds a whole new perspective. The movie is strong and violent. It shows the other side of the &lt;i&gt;American dream&lt;/i&gt;, it shows what power and greed can do to a guy.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/movies" rel="tag"&gt;movies&lt;/a&gt;, &lt;a href="http://technorati.com/tag/scarface" rel="tag"&gt;Scarface&lt;/a&gt;, &lt;a href="http://technorati.com/tag/al+pacino" rel="tag"&gt;Al Pacino&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115144119171939700?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115144119171939700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115144119171939700' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115144119171939700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115144119171939700'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/06/world-is-yours.html' title='The world is yours'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115113769131781910</id><published>2006-06-24T10:18:00.000+02:00</published><updated>2006-06-24T10:28:32.370+02:00</updated><title type='text'>Belgian government chooses OpenDocument</title><content type='html'>I've just read that &lt;a href="http://news.com.com/Belgian+government+chooses+OpenDocument/2100-7344_3-6087275.html"&gt;the Belgian government chooses OpenDocument&lt;/a&gt; as the standard format for exchanging documents within the government. They are however leaving the door open for Microsoft's Open XML, waiting for applications that support it. I hope they will accept OpenXML. I think it's a great file format, and it's just as open as ODF.
&lt;div class="tags"&gt;Tags: &lt;a href="http://www.technorati.com/tag/openxml" rel="tag"&gt;OpenXML&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/opendocument" rel="tag"&gt;OpenDocument&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/odf" rel="tag"&gt;ODF&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/open+standards" rel="tag"&gt;Open Standards&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115113769131781910?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115113769131781910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115113769131781910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115113769131781910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115113769131781910'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/06/belgian-government-chooses.html' title='Belgian government chooses OpenDocument'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-115010113224743672</id><published>2006-06-12T10:24:00.000+02:00</published><updated>2006-09-19T07:56:29.920+02:00</updated><title type='text'>Reading an image from a file without locking it</title><content type='html'>When you use &lt;i&gt;Image.FromFile&lt;/i&gt; to read an image from a file, the file is locked. The following method reads an image from a file without locking it:
&lt;pre&gt;&lt;span class="keyword"&gt;public static class&lt;/span&gt; Utils
{
    &lt;span class="keyword"&gt;public static&lt;/span&gt; Image ImageFromFile(&lt;span class="keyword"&gt;string&lt;/span&gt; fileName)
    {
        &lt;span class="keyword"&gt;if&lt;/span&gt; (fileName == &lt;span class="keyword"&gt;null&lt;/span&gt;) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentNullException(&lt;span class="string"&gt;"fileName"&lt;/span&gt;);

        &lt;span class="keyword"&gt;using&lt;/span&gt;(FileStream lStream = &lt;span class="keyword"&gt;new&lt;/span&gt; FileStream(fileName, FileMode.Open, FileAccess.Read))
            &lt;span class="keyword"&gt;return&lt;/span&gt; Image.FromStream(lStream);
    }
}&lt;/pre&gt;
Here's an example how to use it:
&lt;pre&gt;&lt;span class="comment"&gt;// old method that locks the file:&lt;/span&gt;
Image img = Image.FromFile(&lt;span class="string"&gt;"picture.jpg"&lt;/span&gt;);
&lt;span class="comment"&gt;// new method that does not lock the file:&lt;/span&gt;
Image img = Utils.ImageFromFile(&lt;span class="string"&gt;"picture.jpg"&lt;/span&gt;);&lt;/pre&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-115010113224743672?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/115010113224743672/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=115010113224743672' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115010113224743672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/115010113224743672'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/06/reading-image-from-file-without.html' title='Reading an image from a file without locking it'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114995300700351717</id><published>2006-06-10T17:18:00.000+02:00</published><updated>2006-08-11T23:28:48.263+02:00</updated><title type='text'>Calctor 1.3</title><content type='html'>I've updated my calculator tool to version 1.3:
&lt;ul&gt;&lt;li&gt;Fixed some bugs&lt;/li&gt;
&lt;li&gt;Added a &lt;i&gt;Clear&lt;/i&gt;-action, to clear the input region&lt;/li&gt;
&lt;li&gt;Added some functions: &lt;i&gt;arcsecant&lt;/i&gt;, &lt;i&gt;arccosecant&lt;/i&gt;, &lt;i&gt;secanth&lt;/i&gt;, &lt;i&gt;cosecanth&lt;/i&gt;, &lt;i&gt;arcsecanth&lt;/i&gt;, &lt;i&gt;arccosecanth&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Added missing functions to the snippets&lt;/li&gt;
&lt;li&gt;Added some templates&lt;/li&gt;
&lt;li&gt;Added formatters, to format a result: &lt;i&gt;euro&lt;/i&gt;, &lt;i&gt;dollar&lt;/i&gt;, &lt;i&gt;yen&lt;/i&gt;, &lt;i&gt;pound&lt;/i&gt;, &lt;i&gt;percent&lt;/i&gt;, &lt;i&gt;degrees&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;
If you can think of useful templates to put in the &lt;i&gt;Templates&lt;/i&gt; directory, just let me know.&lt;br /&gt;
You can download it from the &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=197792"&gt;Sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114995300700351717?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114995300700351717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114995300700351717' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114995300700351717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114995300700351717'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/06/calctor-13.html' title='Calctor 1.3'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114935834082205423</id><published>2006-06-03T20:12:00.000+02:00</published><updated>2006-06-03T20:12:21.380+02:00</updated><title type='text'>Calctor 1.2</title><content type='html'>I've updated my calculator tool to version 1.2:
&lt;ul&gt;&lt;li&gt;Fixed some bugs, and added some optimizations&lt;/li&gt;
&lt;li&gt;Added some buttons to the header of the input-region&lt;/li&gt;
&lt;li&gt;Added &amp;#xB2; and &amp;#xB3; as synonyms for ^2 and ^3&lt;/li&gt;
&lt;li&gt;Added some functions: &lt;i&gt;gcd&lt;/i&gt;, &lt;i&gt;lcm&lt;/i&gt;, &lt;i&gt;addTimes&lt;/i&gt;, &lt;i&gt;round(x, n)&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Added a new menu to insert snippets&lt;/li&gt;
&lt;li&gt;Added the function &lt;i&gt;New from template&lt;/i&gt;, and a directory with some templates&lt;/li&gt;
&lt;li&gt;Comments on a separate line are now also displayed in the output&lt;/li&gt;
&lt;li&gt;Embedded URLs are converted to hyperlinks in the output&lt;/li&gt;&lt;/ul&gt;
If you can think of useful templates to put in the &lt;i&gt;Templates&lt;/i&gt; directory, just let me know.&lt;br /&gt;
You can download it from the &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=197792"&gt;Sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114935834082205423?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114935834082205423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114935834082205423' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114935834082205423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114935834082205423'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/06/calctor-12.html' title='Calctor 1.2'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114881520349487617</id><published>2006-05-28T13:16:00.000+02:00</published><updated>2006-07-11T20:21:56.216+02:00</updated><title type='text'>Calctor 1.1</title><content type='html'>I've updated my calculator tool to version 1.1:
&lt;ul&gt;
&lt;li&gt;Optimized the parser&lt;/li&gt;
&lt;li&gt;Changed the meaning of the % operator (now percentage instead of modulo)&lt;/li&gt;
&lt;li&gt;Added synonyms for functions (abbreviations)&lt;/li&gt;
&lt;li&gt;Added some functions: modulo, sign, exp, secans, cosecans, arcsinh, arccosh, arctanh, arccotanh&lt;/li&gt;
&lt;li&gt;Added the option to auto scroll the output region&lt;/li&gt;
&lt;li&gt;The output of an invalid expression now looks less threatening&lt;/li&gt;
&lt;li&gt;Added license information to the Info-window&lt;/li&gt;
&lt;li&gt;Calctor is now prejitted after installation, which should improve performance&lt;/li&gt;&lt;/ul&gt;
You can download it from the &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=197792"&gt;Sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114881520349487617?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114881520349487617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114881520349487617' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114881520349487617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114881520349487617'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/calctor-11.html' title='Calctor 1.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114872468712055291</id><published>2006-05-27T12:11:00.000+02:00</published><updated>2006-05-27T12:31:34.713+02:00</updated><title type='text'>Calctor</title><content type='html'>&lt;img src="http://channel9.msdn.com/Photos/197792.jpg" align="right" alt="Calctor" border="0" width="150" height="150"/&gt;
Calctor is a new tool I created. It's an advanced calculator with a simple user interface. It uses the free &lt;a href="http://www.componentfactory.com/product_toolkit.html"&gt;Krypton Toolkit&lt;/a&gt; from &lt;a href="http://www.componentfactory.com/"&gt;Component Factory&lt;/a&gt; for some of the user interface elements. You can download it from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=197792"&gt;the Sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Calctor" rel="tag"&gt;Calctor&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Calculator" rel="tag"&gt;Calculator&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114872468712055291?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114872468712055291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114872468712055291' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114872468712055291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114872468712055291'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/calctor.html' title='Calctor'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114811935039541438</id><published>2006-05-20T11:53:00.000+02:00</published><updated>2010-06-29T19:42:11.446+02:00</updated><title type='text'>Getting a list of all the open windows</title><content type='html'>Here's some code you can use to get a list of all the open windows. Actually, you get a dictionary where each item is a KeyValuePair where the key is the handle (hWnd) of the window and the value is its title. &lt;pre&gt;&lt;span class="keyword"&gt;using&lt;/span&gt; HWND = IntPtr;
&lt;div class="comment"&gt;/// &amp;lt;summary&amp;gt;Contains a method to get all the open windows.&amp;lt;/summary&amp;gt;&lt;/div&gt;
&lt;span class="keyword"&gt;public static class&lt;/span&gt; OpenWindowGetter
{
&lt;div class="comment"&gt;    /// &amp;lt;summary&amp;gt;Returns a dictionary that contains the handle and title of all the open windows.&amp;lt;/summary&amp;gt;
    /// &amp;lt;returns&amp;gt;A dictionary that contains the handle and title of all the open windows.&amp;lt;/returns&amp;gt;&lt;/div&gt;
    &lt;span class="keyword"&gt;public static&lt;/span&gt; IDictionary&amp;lt;HWND, &lt;span class="keyword"&gt;string&lt;/span&gt;&amp;gt; GetOpenWindows()
    {
        HWND lShellWindow = GetShellWindow();
        Dictionary&amp;lt;HWND, &lt;span class="keyword"&gt;string&lt;/span&gt;&amp;gt; lWindows = &lt;span class="keyword"&gt;new&lt;/span&gt; Dictionary&amp;lt;HWND, &lt;span class="keyword"&gt;string&lt;/span&gt;&amp;gt;();

        EnumWindows(&lt;span class="keyword"&gt;delegate&lt;/span&gt;(HWND hWnd, &lt;span class="keyword"&gt;int&lt;/span&gt; lParam)
        {
            &lt;span class="keyword"&gt;if&lt;/span&gt; (hWnd == lShellWindow) &lt;span class="keyword"&gt;return true&lt;/span&gt;;
            &lt;span class="keyword"&gt;if&lt;/span&gt; (!IsWindowVisible(hWnd)) &lt;span class="keyword"&gt;return true&lt;/span&gt;;

            &lt;span class="keyword"&gt;int&lt;/span&gt; lLength = GetWindowTextLength(hWnd);
            &lt;span class="keyword"&gt;if&lt;/span&gt; (lLength == 0) &lt;span class="keyword"&gt;return true&lt;/span&gt;;

            StringBuilder lBuilder = &lt;span class="keyword"&gt;new&lt;/span&gt; StringBuilder(lLength);
            GetWindowText(hWnd, lBuilder, lLength + 1);

            lWindows[hWnd] = lBuilder.ToString();
            &lt;span class="keyword"&gt;return true&lt;/span&gt;;
            
        }, 0);

        &lt;span class="keyword"&gt;return&lt;/span&gt; lWindows;
    }

    &lt;span class="keyword"&gt;delegate bool&lt;/span&gt; EnumWindowsProc(HWND hWnd, &lt;span class="keyword"&gt;int&lt;/span&gt; lParam);

    [DllImport(&lt;span class="string"&gt;"USER32.DLL"&lt;/span&gt;)]
    &lt;span class="keyword"&gt;static extern bool&lt;/span&gt; EnumWindows(EnumWindowsProc enumFunc, &lt;span class="keyword"&gt;int&lt;/span&gt; lParam);

    [DllImport(&lt;span class="string"&gt;"USER32.DLL"&lt;/span&gt;)]
    &lt;span class="keyword"&gt;static extern int&lt;/span&gt; GetWindowText(HWND hWnd, StringBuilder lpString, &lt;span class="keyword"&gt;int&lt;/span&gt; nMaxCount);

    [DllImport(&lt;span class="string"&gt;"USER32.DLL"&lt;/span&gt;)]
    &lt;span class="keyword"&gt;static extern int&lt;/span&gt; GetWindowTextLength(HWND hWnd);

    [DllImport(&lt;span class="string"&gt;"USER32.DLL"&lt;/span&gt;)]
    &lt;span class="keyword"&gt;static extern bool&lt;/span&gt; IsWindowVisible(HWND hWnd);

    [DllImport(&lt;span class="string"&gt;"USER32.DLL"&lt;/span&gt;)]
    &lt;span class="keyword"&gt;static extern&lt;/span&gt; IntPtr GetShellWindow();
}&lt;/pre&gt;And here's some code that uses it: &lt;pre&gt;&lt;span class="keyword"&gt;foreach&lt;/span&gt;(KeyValuePair&amp;lt;IntPtr, &lt;span class="keyword"&gt;string&lt;/span&gt;&amp;gt; lWindow &lt;span class="keyword"&gt;in&lt;/span&gt; OpenWindowGetter.GetOpenWindows())
{
    IntPtr lHandle = lWindow.Key;
    &lt;span class="keyword"&gt;string&lt;/span&gt; lTitle = lWindow.Value;

    Console.WriteLine(&lt;span class="string"&gt;"{0}: {1}"&lt;/span&gt;, lHandle, lTitle);
}&lt;/pre&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://channel9.msdn.com/tags/Windows+Forms" rel="tag"&gt;Windows Forms&lt;/a&gt;.&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114811935039541438?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114811935039541438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114811935039541438' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114811935039541438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114811935039541438'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/getting-list-of-all-open-windows.html' title='Getting a list of all the open windows'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114811275491836548</id><published>2006-05-20T09:48:00.000+02:00</published><updated>2006-05-20T10:12:36.280+02:00</updated><title type='text'>Reading data from an embedded resource</title><content type='html'>Here's some code to read data from an embedded resource:
&lt;pre&gt;&lt;div class="comment"&gt;/// &amp;lt;summary&amp;gt;Contains some methods to read data from an embedded resource.&amp;lt;/summary&amp;gt;&lt;/div&gt;
&lt;span class="keyword"&gt;public static class&lt;/span&gt; EmbeddedResourceReader
{
&lt;div class="comment"&gt;    /// &amp;lt;summary&amp;gt;Returns an embedded resource of the specified assembly as a string.&amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="assembly"&amp;gt;The assembly to read the resource from.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="resourceName"&amp;gt;The name of the resource.&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;A string read from an embedded resource.&amp;lt;/returns&amp;gt;&lt;/div&gt;
    &lt;span class="keyword"&gt;public static string&lt;/span&gt; ReadString(Assembly assembly, &lt;span class="keyword"&gt;string&lt;/span&gt; resourceName)
    {
        &lt;span class="keyword"&gt;if&lt;/span&gt; (assembly == &lt;span class="keyword"&gt;null&lt;/span&gt;) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentNullException(&lt;span class="string"&gt;"assembly"&lt;/span&gt;);
        &lt;span class="keyword"&gt;if&lt;/span&gt; (resourceName == &lt;span class="keyword"&gt;null&lt;/span&gt;) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentNullException(&lt;span class="string"&gt;"resourceName"&lt;/span&gt;);

        &lt;span class="keyword"&gt;using&lt;/span&gt;(Stream lStream = assembly.GetManifestResourceStream(resourceName))
        &lt;span class="keyword"&gt;using&lt;/span&gt;(StreamReader lReader = &lt;span class="keyword"&gt;new&lt;/span&gt; StreamReader(lStream))
            &lt;span class="keyword"&gt;return&lt;/span&gt; lReader.ReadToEnd();
    }

&lt;div class="comment"&gt;    /// &amp;lt;summary&amp;gt;Returns an embedded resource of the specified assembly as an icon.&amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="assembly"&amp;gt;The assembly to read the resource from.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name="resourceName"&amp;gt;The name of the resource.&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;An icon read from an embedded resource.&amp;lt;/returns&amp;gt;&lt;/div&gt;
    &lt;span class="keyword"&gt;public static&lt;/span&gt; Icon ReadIcon(Assembly assembly, &lt;span class="keyword"&gt;string&lt;/span&gt; resourceName)
    {
        &lt;span class="keyword"&gt;if&lt;/span&gt; (assembly == &lt;span class="keyword"&gt;null&lt;/span&gt;) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentNullException(&lt;span class="string"&gt;"assembly"&lt;/span&gt;);
        &lt;span class="keyword"&gt;if&lt;/span&gt; (resourceName == &lt;span class="keyword"&gt;null&lt;/span&gt;) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentNullException(&lt;span class="string"&gt;"resourceName"&lt;/span&gt;);

        &lt;span class="keyword"&gt;using&lt;/span&gt;(Stream lStream = assembly.GetManifestResourceStream(resourceName))
            &lt;span class="keyword"&gt;return new&lt;/span&gt; Icon(lStream);
    }
}&lt;/pre&gt;
Basically, you can read any kind of data from an embedded resource, using the method &lt;i&gt;GetManifestResourceStream&lt;/i&gt;. The resource name you have to pass as an argument should be the default namespace of the assembly, appended with the filename. Here's an example how to use it:
&lt;pre&gt;Assembly assembly = &lt;span class="keyword"&gt;this&lt;/span&gt;.GetType().Assembly;
&lt;span class="keyword"&gt;string&lt;/span&gt; resourceName = &lt;span class="string"&gt;"MyCompany.MyApplication.file.txt"&lt;/span&gt;;
&lt;span class="keyword"&gt;string&lt;/span&gt; content = EmbeddedResourceReader.ReadString(assembly, resourceName);&lt;/pre&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114811275491836548?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114811275491836548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114811275491836548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114811275491836548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114811275491836548'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/reading-data-from-embedded-resource.html' title='Reading data from an embedded resource'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114806779197452286</id><published>2006-05-19T21:40:00.000+02:00</published><updated>2006-05-27T12:32:08.076+02:00</updated><title type='text'>Screen Capture 2.2</title><content type='html'>&lt;img align="right" border="0" alt="Screenshot of 'Screen Capture 2'" src="http://channel9.msdn.com/Photos/165900.jpg" width="135" height="116" /&gt;
I've updated my screen capture tool to version 2.2. I fixed a few bugs, and added these features:&lt;ul&gt;&lt;li&gt;The size of the captured image is displayed in the statusbar.&lt;/li&gt;&lt;li&gt;The captured image is stretched when resizing the window.&lt;/li&gt;&lt;li&gt;A new function is added to capture the content of a selected window.&lt;/li&gt;&lt;/ul&gt;You can download it from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=165900"&gt;the sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://technorati.com/tag/Screen+Capture" rel="tag"&gt;Screen Capture&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114806779197452286?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114806779197452286/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114806779197452286' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114806779197452286'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114806779197452286'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/screen-capture-22.html' title='Screen Capture 2.2'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114681704045533271</id><published>2006-05-05T10:16:00.000+02:00</published><updated>2006-05-05T10:17:20.456+02:00</updated><title type='text'>Format a file size</title><content type='html'>Here you can find a method that creates a human-readable string of a file-size:
&lt;pre&gt;&lt;div class="comment"&gt;/// &amp;lt;summary&amp;gt;Returns a file size as a formatted string with a unit.&amp;lt;/summary&amp;gt;
/// &amp;lt;param name="fileSize"&amp;gt;The file size to format.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;The formatted string.&amp;lt;/returns&amp;gt;&lt;/div&gt;
&lt;span class="keyword"&gt;public static string&lt;/span&gt; FormatFileSize(&lt;span class="keyword"&gt;long&lt;/span&gt; fileSize)
{
 &lt;span class="keyword"&gt;if&lt;/span&gt; (fileSize &amp;lt; 0) &lt;span class="keyword"&gt;throw new&lt;/span&gt; ArgumentOutOfRangeException(&lt;span class="string"&gt;"fileSize"&lt;/span&gt;);

 &lt;span class="keyword"&gt;if&lt;/span&gt; (fileSize &amp;gt;= 1024 * 1024 * 1024) &lt;span class="keyword"&gt;return string&lt;/span&gt;.Format(&lt;span class="string"&gt;"{0:########0.00} GB"&lt;/span&gt;, ((&lt;span class="keyword"&gt;double&lt;/span&gt;)fileSize) / (1024 * 1024 * 1024));
 &lt;span class="keyword"&gt;else if&lt;/span&gt; (fileSize &amp;gt;= 1024 * 1024) &lt;span class="keyword"&gt;return string&lt;/span&gt;.Format(&lt;span class="string"&gt;"{0:####0.00} MB"&lt;/span&gt;, ((&lt;span class="keyword"&gt;double&lt;/span&gt;)fileSize) / (1024 * 1024));
 &lt;span class="keyword"&gt;else if&lt;/span&gt; (fileSize &amp;gt;= 1024) &lt;span class="keyword"&gt;return string&lt;/span&gt;.Format(&lt;span class="string"&gt;"{0:####0.00} KB"&lt;/span&gt;, ((&lt;span class="keyword"&gt;double&lt;/span&gt;)fileSize) / 1024);
 &lt;span class="keyword"&gt;else return string&lt;/span&gt;.Format(&lt;span class="string"&gt;"{0} bytes"&lt;/span&gt;, fileSize);
}&lt;/pre&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114681704045533271?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114681704045533271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114681704045533271' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114681704045533271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114681704045533271'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/format-file-size.html' title='Format a file size'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114681567012394199</id><published>2006-05-05T09:54:00.000+02:00</published><updated>2006-05-05T09:54:30.136+02:00</updated><title type='text'>Filter numbers out of a string</title><content type='html'>Here you find a method that filters the numbers out of a string:
&lt;pre&gt;&lt;span class="keyword"&gt;public static string&lt;/span&gt; FilterNumbers(&lt;span class="keyword"&gt;string&lt;/span&gt; mightContainNumbers)
{
    &lt;span class="keyword"&gt;if&lt;/span&gt; (mightContainNumbers == &lt;span class="keyword"&gt;null&lt;/span&gt; || mightContainNumbers.Length == 0) &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="string"&gt;""&lt;/span&gt;;

    StringBuilder builder = &lt;span class="keyword"&gt;new&lt;/span&gt; StringBuilder(mightContainNumbers.Length);
    &lt;span class="keyword"&gt;foreach&lt;/span&gt; (&lt;span class="keyword"&gt;char&lt;/span&gt; c &lt;span class="keyword"&gt;in&lt;/span&gt; mightContainNumbers)
        &lt;span class="keyword"&gt;if&lt;/span&gt; (Char.IsNumber(c))
            builder.Append(c);

    &lt;span class="keyword"&gt;return&lt;/span&gt; builder.ToString();
}&lt;/pre&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114681567012394199?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114681567012394199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114681567012394199' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114681567012394199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114681567012394199'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/05/filter-numbers-out-of-string.html' title='Filter numbers out of a string'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114478637427408882</id><published>2006-04-11T22:11:00.000+02:00</published><updated>2006-05-27T12:15:47.110+02:00</updated><title type='text'>Screen Capture 2.1.1</title><content type='html'>I've updated my screen capture tool to version 2.1.1. It's just a small update: I added the option to always automatically copy the captured image to the clipboard (saves a click if you have to capture a lot of screenshots to paste in a document). I also added an info-dialog which shows the specific version. You can download it from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=165900"&gt;the sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://www.technorati.com/tag/Screen+Capture" rel="tag"&gt;Screen Capture&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114478637427408882?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114478637427408882/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114478637427408882' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114478637427408882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114478637427408882'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/04/screen-capture-211.html' title='Screen Capture 2.1.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114478229005046979</id><published>2006-04-11T21:00:00.000+02:00</published><updated>2006-04-11T21:04:50.093+02:00</updated><title type='text'>Slam Ball</title><content type='html'>If you thought basketball was a cool sport, then check out &lt;a href="http://www.spikedhumor.com/articles/23255/Slam_Ball.html"&gt;Slam Ball&lt;/a&gt;: a more aggressive form of basketball, but with &lt;b&gt;trampolines&lt;/b&gt;! Looks really cool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114478229005046979?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114478229005046979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114478229005046979' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114478229005046979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114478229005046979'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/04/slam-ball.html' title='Slam Ball'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114147187299823335</id><published>2006-03-04T12:29:00.000+01:00</published><updated>2006-05-27T12:16:05.333+02:00</updated><title type='text'>Screen Capture 2.1</title><content type='html'>I've updated my screen capture tool to version 2.1. You now have the option to &lt;i&gt;Minimize to System Tray&lt;/i&gt;. You can then right-click the system tray icon to access most functionality. You can download it from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=165900"&gt;the sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://www.technorati.com/tag/Screen+Capture" rel="tag"&gt;Screen Capture&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114147187299823335?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114147187299823335/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114147187299823335' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114147187299823335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114147187299823335'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/03/screen-capture-21.html' title='Screen Capture 2.1'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114096722665498947</id><published>2006-02-26T16:17:00.000+01:00</published><updated>2006-05-27T12:16:25.686+02:00</updated><title type='text'>Screen Capture 2</title><content type='html'>&lt;img align="right" border="0" alt="Screenshot of 'Screen Capture 2'" src="http://channel9.msdn.com/Photos/165900.jpg" width="135" height="116"&gt;
I've written a new version of my screen capture tool, from scratch. You can download it from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=165900"&gt;the sandbox at Channel 9&lt;/a&gt;.
&lt;div class="tags"&gt;Tags: &lt;a href="http://www.technorati.com/tag/Screen+Capture" rel="tag"&gt;Screen Capture&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114096722665498947?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114096722665498947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114096722665498947' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114096722665498947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114096722665498947'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/02/screen-capture-2.html' title='Screen Capture 2'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114026881374845006</id><published>2006-02-18T14:10:00.000+01:00</published><updated>2006-08-10T10:09:46.736+02:00</updated><title type='text'>Screen capture tool</title><content type='html'>&lt;img align="right" border="0" alt="Screenshot of 'Screen Capture'" src="http://channel9.msdn.com/Photos/163897.jpg" width="224" height="183"&gt;
I've written a little screen capture tool, for fun. You can download it from &lt;a href="http://channel9.msdn.com/ShowPost.aspx?PostID=163897"&gt;the sandbox at Channel 9&lt;/a&gt;. I did not include the source code, because there isn't a lot of it. Just use &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Reflector&lt;/a&gt; for that. Here's the bit of code that does the actual capturing and copying to the clipboard:
&lt;pre&gt;Rectangle region = ...; &lt;span class="comment"&gt;// the screen region to capture&lt;/span&gt;
&lt;span class="keyword"&gt;using&lt;/span&gt; (Bitmap bitmap =
    &lt;span class="keyword"&gt;new&lt;/span&gt; Bitmap(region.Width, region.Height, PixelFormat.Format32bppArgb))
&lt;span class="keyword"&gt;using&lt;/span&gt; (Graphics bitmapGraphics = Graphics.FromImage(bitmap))
{
    bitmapGraphics.CopyFromScreen(region.Left, region.Top, 0, 0, region.Size);
    Clipboard.SetImage(bitmap);
}&lt;/pre&gt;
&lt;small&gt;&lt;b&gt;EDIT&lt;/b&gt;: I've updated the tool: after capturing, you can now directly save the screenshot too.&lt;/small&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;, &lt;a href="http://channel9.msdn.com/tags/Windows+Forms"&gt;Windows Forms&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/Screen+Capture" rel="tag"&gt;Screen Capture&lt;/a&gt;, &lt;a href="http://www.technorati.com/tag/Freeware" rel="tag"&gt;Freeware&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114026881374845006?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114026881374845006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114026881374845006' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114026881374845006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114026881374845006'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/02/screen-capture-tool.html' title='Screen capture tool'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8076826.post-114017771641196329</id><published>2006-02-17T12:46:00.000+01:00</published><updated>2006-05-05T10:13:24.226+02:00</updated><title type='text'>Years, months and days between 2 dates</title><content type='html'>Here you can find a method that can calculate the years, months and days between 2 dates.
&lt;pre&gt;&lt;div class="comment"&gt;/// &amp;lt;summary&amp;gt;Calculates the difference between 2 dates in years, months and days.&amp;lt;/summary&amp;gt;
/// &amp;lt;param name="startDate"&amp;gt;The start date.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="endDate"&amp;gt;The end date.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="years"&amp;gt;The variable that will contain the years.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="months"&amp;gt;The variable that will contain the months.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="days"&amp;gt;The variable that will contain the days.&amp;lt;/param&amp;gt;&lt;/div&gt;
&lt;span class="keyword"&gt;public static void&lt;/span&gt; DateDifference(DateTime startDate, DateTime endDate, &lt;span class="keyword"&gt;out int&lt;/span&gt; years, &lt;span class="keyword"&gt;out int&lt;/span&gt; months, &lt;span class="keyword"&gt;out int&lt;/span&gt; days)
{
    years = endDate.Year - startDate.Year;
    months = endDate.Month - startDate.Month;
    days = endDate.Day - startDate.Day;

    &lt;span class="keyword"&gt;if&lt;/span&gt; (days &amp;lt; 0) months -= 1;
    &lt;span class="keyword"&gt;while&lt;/span&gt; (months &amp;lt; 0) { months += 12; years -= 1; }

    TimeSpan timeSpan = endDate - startDate.AddYears(years).AddMonths(months);
    days = (&lt;span class="keyword"&gt;int&lt;/span&gt;)Math.Round(timeSpan.TotalDays);
}&lt;/pre&gt;
And here is a method that uses the previous method and returns a string representation of the difference:
&lt;pre&gt;&lt;div class="comment"&gt;/// &amp;lt;summary&amp;gt;Calculates the difference between 2 dates, and returns it as a formatted string.&amp;lt;/summary&amp;gt;
/// &amp;lt;param name="startDate"&amp;gt;The start date.&amp;lt;/param&amp;gt;
/// &amp;lt;param name="endDate"&amp;gt;The end date.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;The formatted string that represents the calculated difference.&amp;lt;/returns&amp;gt;&lt;/div&gt;
&lt;span class="keyword"&gt;public static string&lt;/span&gt; DateDifference(DateTime startDate, DateTime endDate)
{
    &lt;span class="keyword"&gt;int&lt;/span&gt; years, months, days;
    DateDifference(startDate, endDate, &lt;span class="keyword"&gt;out&lt;/span&gt; years, &lt;span class="keyword"&gt;out&lt;/span&gt; months, &lt;span class="keyword"&gt;out&lt;/span&gt; days);
    &lt;span class="keyword"&gt;return&lt;/span&gt; 
        ((years != 0 ? years.ToString() + &lt;span class="string"&gt;"y "&lt;/span&gt; : &lt;span class="string"&gt;""&lt;/span&gt;) +
        (months != 0 ? months.ToString() + &lt;span class="string"&gt;"m "&lt;/span&gt; : &lt;span class="string"&gt;""&lt;/span&gt;) +
        (days != 0 ? days.ToString() + &lt;span class="string"&gt;"d"&lt;/span&gt; : &lt;span class="string"&gt;""&lt;/span&gt;)).TrimEnd();
}&lt;/pre&gt;
&lt;div class="tags"&gt;Tags: &lt;a href="http://channel9.msdn.com/tags/CSharp" rel="tag"&gt;C#&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8076826-114017771641196329?l=blog.tcx.be' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.tcx.be/feeds/114017771641196329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8076826&amp;postID=114017771641196329' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114017771641196329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8076826/posts/default/114017771641196329'/><link rel='alternate' type='text/html' href='http://blog.tcx.be/2006/02/years-months-and-days-between-2-dates.html' title='Years, months and days between 2 dates'/><author><name>Tommy Carlier</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_xdtwGgCD_oI/Styx8nacP-I/AAAAAAAAABs/8nx-9wszXdQ/S220/avatar-20091019.jpg'/></author><thr:total>4</thr:total></entry></feed>
