<?xml version="1.0" encoding="utf-8"?>
<feed xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
  <title>Francesco's blog</title>
  <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/" />
  <link rel="self" href="http://www.dotnet2themax.com/blogs/fbalena/SyndicationService.asmx/GetAtom" />
  <icon>favicon.ico</icon>
  <updated>2008-01-11T15:03:27.6875000-08:00</updated>
  <author>
    <name>Francesco Balena</name>
  </author>
  <subtitle />
  <id>http://www.dotnet2themax.com/blogs/fbalena/</id>
  <generator uri="http://www.dasblog.net" version="1.8.5223.1">DasBlog</generator>
  <entry>
    <title>Introducing VB Migration Partner</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,2dfe27ee-fe6a-49c5-8e4b-6fa4caa47bc9.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,2dfe27ee-fe6a-49c5-8e4b-6fa4caa47bc9.aspx</id>
    <published>2008-01-11T15:00:33.2180000-08:00</published>
    <updated>2008-01-11T15:03:27.6875000-08:00</updated>
    <category term="Migrating from VB6" label="Migrating from VB6" scheme="dasBlog" />
    <category term="Tools" label="Tools" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <table>
            <tbody>
              <tr>
                <td width="200">
                  <font size="2">
                    <a href="http://www.dotnet2themax.com/blogs/fbalena/www.vbmigration.com">
                      <img height="84" src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/vbmp_logo.jpg" width="142" border="0" />
                    </a>
                  </font>
                </td>
                <td>
                  <font size="2">Many readers asked whether I was about to release a book about VB 2008
                  and, more in general, how come I have reduced my writing activity so dramatically.
                  The answer is in this post.</font>
                  <p>
                    <font size="2">Immediately after publishing my C# 2005 book I started working on a
                     very ambitious software project. Now, after exactly two years of hard work, </font>
                    <a href="http://www.vbmigration.com/">
                      <strong>
                        <font size="2">VB
                     Migration Partner </font>
                      </strong>
                    </a>
                    <font size="2">is in beta test stage and is
                     quickly approaching the public release.</font>
                  </p>
                </td>
              </tr>
              <p>
              </p>
              <p>
              </p>
              <p>
              </p>
            </tbody>
          </table>
        </p>
        <p>
      The name of this tool says it all: in a nutshell, <strong>it is a converter of VB6
      applications to VB.NET</strong>. I won’t waste your time trying to emphasize how weak
      the Upgrade Wizard that comes with Visual Studio is: if you’ve never tried it out,
      just google for “vb6 migration” and read what developers and bloggers have to say
      about it. Our goal at Code Architects was to build a better mouse trap than that.
   </p>
        <p>
          <strong>A word on the migration-vs-rewriting debate:</strong> Many industry experts
      suggest that you should rewrite your VB6 from scratch rather than trying to port it
      to .NET automatically using a conversion tool, because the two environments are just
      too different. In theory this argument makes a lot of sense; in practice, however,
      when you have a real-world business app with some hundreds thousands lines of code
      – or even millions of lines! – a rewrite from scratch is simply too expensive, especially
      when the developers who wrote it originally aren’t working with the company any longer,
      the documentation is poor, remarks are scarce, etc. When facing the perspective of
      investing many years/man in this daunting task, it’s no surprise that many companies
      have postponed the migration to “some other time.” Now they are realizing, however,
      that the migration step can’t be postponed any longer, either because a few VB6 apps
      don’t work under Microsoft Vista – possibly because they use 3rd-party controls that
      are incompatible with the new Microsoft operating system – or, above all, because <a href="http://msdn2.microsoft.com/en-us/vbrun/ms788707.aspx">Microsoft
      declared that VB6 support ends on March 2008</a>.
   </p>
        <p>
      The problem is, automatic code converters don’t have a good reputation and rarely
      keep their promises, regardless of the language you are migrating from/to. In most
      cases, they manage to convert 95% of existing code, or less. With a 100,000 line application
      – a medium-size application of average complexity, then – having to manually fix the
      remaining 5% means that you have to fix about five thousand lines. It doesn’t sound
      too bad, until you realize that most of these “fixes” might take hours or even days.
      For example, consider that VB6 and VB.NET have two vastly different (and incompatible)
      programming models for drag-and-drop. Therefore one OLEDrag method counts as an individual
      problematic statement, yet it forces you to rewrite a large portion of your code.
      Drag-and-drop isn’t the only example, because the same concept applies to graphic
      statements, printing, data-binding, object finalization, component initialization,
      and many others.
   </p>
        <p>
      We tested our VB Migration Partner on hundreds of VB6 apps – for well over one million
      lines – and found out that it delivers code that compiles and runs correctly most
      of the times, with an average of <strong>one compilation error every 1,100 lines of
      code</strong>. This corresponds to an accuracy higher than 99.9%. Not bad, uh? Of
      course the actual accuracy depends on how well the VB6 code is and on the features
      that the application uses, thus you can get a better idea of how good our tool
      is by having a look at the VB6 features that itsupports ...and that are out of reach
      for most other conversion tool on the market:
   </p>
        <ul>
          <li>
         arrays with nonzero LBound 
      </li>
          <li>
         Gosub, On...Goto, and On ...Gosub 
      </li>
          <li>
         auto-instancing variables (Dim x As New Person), which keep their lazy-instantiation
         feature even under VB.NET 
      </li>
          <li>
         As Any parameters and callback addresses in Declare parameters (e.g. EnumWindows) 
      </li>
          <li>
         default properties resolved correctly even for late-bound variables 
      </li>
          <li>
         deterministic finalization for objects such as Connection and Recordset, to ensure
         that the connection is correctly closed when the variable is set to Nothing or the
         current scope is exited 
      </li>
          <li>
         (limited) support for Variant variable and null propagation in expressions 
      </li>
          <li>
         all 60+ controls in the VB6 toolbox, with the only exceptions of OLE container and
         Repeater, plus the support for common ActiveX controls and components such as WebBrowser,
         ScriptControl, Scripting runtime, and the MSWLess library 
      </li>
          <li>
         control arrays, including arrays of 3-rd party controls 
      </li>
          <li>
         popup menus 
      </li>
          <li>
         the Controls.Add method and the VBControlExtender object, to dynamically create data-entry
         forms 
      </li>
          <li>
         graphic methods (Line, Circle, PSet, PaintPicture, etc.), with support for any ScaleMode,
         including custom user modes 
      </li>
          <li>
         the Printer object and the Printers collection 
      </li>
          <li>
         OLE drag-and-drop 
      </li>
          <li>
         UserControl classes, with support for advanced features such as the Ambient and Extender
         objects 
      </li>
          <li>
         data-binding to DAO, RDO, and ADO Data controls, ADO recordsets, DataEnvironment objects 
      </li>
          <li>
         non-hierarchical DataEnvironment objects 
      </li>
          <li>
         ADO data source and simple data consumer classes and user controls (e.g. custom ADO
         Data controls) 
      </li>
          <li>
         MultiUse, PublicNotCreatable, GlobalMultiUse classes 
      </li>
          <li>
         persistable classes, MTS/COM+ classes</li>
        </ul>
        <p>
      The number of supported features is so high that it is simpler to list the features
      that are not supported: UserDocument, PropertyPage, WebClass and DHTML Page components;
      undocumented methods (VarPtr, ObjPtr, StrPtr); “classic” drag-and-drop, and little
      else.
   </p>
        <p>
      VB Migration Partner can convert <strong>an entire VB6 project group in one operation</strong>,
      in which case it typically delivers better quality code because it can see “inside”
      a DLL that belongs to the group. The tool also includes a very sophisticated <strong>code
      analyzer </strong>that can spot unused members: a large project that has evolved over
      many years can easily include 5-10% of “dead code”, thus this feature alone can save
      you a lot of precious time because it allows you to focus on just the code that is
      really important.
   </p>
        <p>
      One of the secrets for such high error-free conversion factor is the support for <strong>migration
      pragmas</strong>. A migration pragma is a special remark that you can add to the original
      VB6 code and that teaches VB Migration Partner how a given portion of code must be
      translated, if many alternatives exist. For example, the following ArrayBounds pragma
      tells VB Migration Partner that all the arrays in the current projects must have their
      lower bound index forced to zero:<br /><font face="Courier New">          '##project:ArrayBounds
      ForceZero</font><br />
      Pragmas can have project, class, method, or variable scope. A pragma scoped at the
      variable- or method-level always have higher priority than pragmas scoped at the project-
      or class-level. For example, you can override the previous pragma inside a method,
      and then override this latter pragma for a given array variable:<br /><font face="Courier New">          Sub
      Test()<br />
                   '## ArrayBounds
      Shift<br />
                   '## arr.ArrayBounds
      ForceZero<br />
                   '## names.ShiftIndexes
      1<br />
                   Dim names(1
      To 10) As String<br />
                   Dim values(1
      To 10) As Long<br />
                   Dim arr(1
      To 10) As Integer<br />
                   names(1)
      = "John": names(2) = "Ann"<br />
                   '...<br />
                End Sub</font><br />
      The Shift option tells VB Migration Partner that the LBound and UBound indexes must
      be shifted towards zero, so that the total number of elements in the array is preserved.
      The ShiftIndexes pragma –applied only to the names array – ensures that constant indexes
      are correctly shifted too:<br /><font face="Courier New">          Sub
      Test()<br />
                   Dim names(9)
      As String<br />
                   Dim values(9)
      As Integer<br />
                   Dim arr(0
      To 10) As Short<br />
                   names(0)
      = "John": names(1) = "Ann"<br />
                End Sub</font><br />
      VB Migration Partner supports over 50 pragmas. For example, the SetName pragma changes
      the name of a control or variable during the migration, SetType changes its type,
      AutoNew implements the auto-instancing behavior of As New variables, AutoDispose implements
      the deterministic finalization when the variable is set to Nothing or the current
      scope is exited, and so forth.
   </p>
        <p>
      One of the main defects of a “traditional” conversion tool is that – after the first
      migration – there is no relationship between the original VB6 project and the new
      VB.NET project. If the migration process takes weeks or months – which is common for
      large projects – and if the VB6 application must evolve in the meantime with new features
      and bug fixing, then at the end of the migration process the VB.NET code is already
      outdated and must be manually patched. The margin for mistakes in this phase is very
      high.
   </p>
        <p>
      VB Migration Partner allows you to work around this issue, by means of pragmas and
      what we call <strong>the convert-text-fix cycle methodology</strong>. In a nutshell,
      you can iteratively migrate a given VB6 project by reaching the zero compilation errors
      stage and then the zero runtime error stage by simply inserting pragmas in the original
      project, but without modifying any VB6 executable statement. Thanks to the convert-test-fix
      cycle you can face complex migration tasks and keep the VB6 and VB.NET versions of
      your app always in sync.
   </p>
        <p>
      I am especially proud of VB Migration Partner’s refactoring engine, which is able
      to apply many optimization techniques the result of the “raw” conversion. For example,
      it can merge variable declarations and the initializations, to generate Return statements,
      and to leverage the compound assignment operators (e.g. +=), and more:
   </p>
        <p>
          <font face="Courier New">    Function GetValue() As Long    
      =&gt;     Function GetValue() As Integer<br />
             Dim x As Long                         
      Dim x As Integer = 123<br />
             x = 123                               
      ...<br />
             ...                                   
      If x &gt; 0 Then<br />
             If x &gt; 0 Then                            
      Return x<br />
                GetValue = x                       
      ElseIf x = 0 Then<br />
                Exit Function                         
      Return -1<br />
             ElseIf x = 0 Then                     
      End If<br />
                GetValue = -1                      
      ...<br />
                Exit Function                      
      x += 1<br />
             End If                                
      ...<br />
             ...                                
      End Function<br />
             x = x + 1<br />
             ...<br />
          End Function</font>
        </p>
        <p>
      Other refactoring techniques can be achieved by means of pragmas. For example, you
      can move the declaration of a variable inside a For or For Each method, as in this
      example:
   </p>
        <p>
          <font face="Courier New">    Dim i As Integer               
      =&gt;     For i As Integer = 1 To 100<br />
          For i = 1 To 100                         
      ...<br />
             ...                                
      Next<br />
          Next</font>
        </p>
        <p>
      On top of the cake: in spite of all these features, VB Migration Partner is <strong>up
      to 8 times faster </strong>than the Upgrade Wizard that comes with Visual Studio! 
   </p>
        <p>
      You can learn all about VB Migration Partner on our new site <a href="http://www.vbmigration.com/">www.vbmigration.com</a>.
      The web site hosts a Resource section where we dissect each and every difference between
      VB6 and VB.NET – most of which have never been documented anywhere – thus you can
      find many useful tips even if you don’t plan to use our tool. I also opened a <a href="http://www.vbmigration.com/blog">new
      blog</a>, entirely devoted to migration techniques. 
   </p>
        <p>
      That's it for now. Stay tuned!<br /></p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=2dfe27ee-fe6a-49c5-8e4b-6fa4caa47bc9" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Speed up string concatenation in VB.NET apps migrated from VB6</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,ce96d1dc-838b-424d-b571-282e028e9e32.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,ce96d1dc-838b-424d-b571-282e028e9e32.aspx</id>
    <published>2007-12-22T03:40:06.9175000-08:00</published>
    <updated>2007-12-22T03:40:06.9175000-08:00</updated>
    <category term="Migrating from VB6" label="Migrating from VB6" scheme="dasBlog" />
    <category term="Optimization" label="Optimization" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      When you migrate code from VB6 - regardless of whether you are using an automatic
      conversion tool - chances are that string-intensive code will actually run slower
      under VB.NET, if it uses a lot of string concatenation operations. For example, this
      code takes 2.8 seconds when it runs in VB6 and 27 seconds after its conversion to
      VB.NET on my 3GHz system:
   </p>
        <p>
          <font color="#0000ff">Dim</font> s <font color="#0000ff">As</font> <font color="#0000ff">String</font> = <font color="#800000">""<br /></font><font color="#0000ff">For</font> i <font color="#0000ff">As</font><font color="#0000ff">Integer</font> =
      1 <font color="#0000ff">To</font> 100000<br />
          s = s + <font color="#800000">"*"<br /></font><font color="#0000ff">Next<br /></font></p>
        <p>
      The solution is of course trivial: just replace the string variable with a <strong>StringBuilder </strong>object.
      Alas, this fix requires that you completely revise your source code, because you need
      to replace all + and &amp; operators with the Append method, not to mention cases
      where the StringBuilder is used as an argument to string functions such as Trim or
      Len.
   </p>
        <p>
      Is there a way to speed up the previous code with a minimal impact on the code itself?
      The answer is yes and the solution is actually very simple: you just need to create
      a VB.NET class that is based on the System.Text.StringBuilder object, that redifines
      the + and &amp; operators, and that supports the implicit conversion to and from the
      System.String type. Authoring such a <strong>StringBuilder6 </strong>class is a matter
      of minutes:
   </p>
        <font color="#008000">
          <p>
      ' a wrapper for the StringBuilder object, with support for + and &amp; operators
   </p>
        </font>
        <font color="#0000ff">
          <p>
      Public
   </p>
        </font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Class</font>
        <font color="#000000"> StringBuilder6</font>
        <p>
          <font color="#0000ff">    Private</font> buffer <font color="#0000ff">As</font><font color="#0000ff">New</font><font color="#000000">System.Text.</font>StringBuilder
   </p>
        <p>
          <font color="#008000">
            <font color="#0000ff">    </font>' return the
      inner string
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Overrides</font>
          <font color="#0000ff">Function</font> ToString() <font color="#0000ff">As</font><font color="#0000ff">String<br />
              </font><font color="#0000ff">Return</font> buffer.ToString()<br /><font color="#0000ff">    End</font><font color="#0000ff">Function
      </font></p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#000000">
          </font>
          <font color="#0000ff">Shared</font>
          <font color="#000000">
          </font>
          <font color="#0000ff">Operator</font>
          <font color="#000000"> +(</font>
          <font color="#0000ff">ByVal</font>
          <font color="#000000"> op1 </font>
          <font color="#0000ff">As</font>
          <font color="#000000"> StringBuilder6, </font>
          <font color="#0000ff">ByVal</font>
          <font color="#000000"> op2 </font>
          <font color="#0000ff">As</font>
          <font color="#000000">
          </font>
          <font color="#0000ff">String</font>
          <font color="#000000">) </font>
          <font color="#0000ff">As</font>
          <font color="#000000"> StringBuilder6<br />
              op1.buffer.Append(op2)<br />
              </font>
          <font color="#0000ff">Return</font>
          <font color="#000000"> op1<br /></font>
          <font color="#0000ff">    End</font>
          <font color="#000000">
          </font>
          <font color="#0000ff">Operator
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Operator</font> &amp;(<font color="#0000ff">ByVal</font> op1 <font color="#0000ff">As</font> StringBuilder6, <font color="#0000ff">ByVal</font> op2 <font color="#0000ff">As</font><font color="#0000ff">String</font>) <font color="#0000ff">As</font> StringBuilder6<br />
              op1.buffer.Append(op2)<br />
              <font color="#0000ff">Return</font> op1<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
          <font color="#008000">    ' convert to string
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Widening</font>
          <font color="#0000ff">Operator</font>
          <font color="#0000ff">CType</font>(<font color="#0000ff">ByVal</font> op <font color="#0000ff">As</font> StringBuilder6) <font color="#0000ff">As</font><font color="#0000ff">String<br />
              </font><font color="#0000ff">Return</font> op.ToString()<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
          <font color="#008000">    ' convert from string 
      </font>
        </p>
        <p>
          <font color="#0000ff">    Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">Widening</font>
          <font color="#0000ff">Operator</font>
          <font color="#0000ff">CType</font>(<font color="#0000ff">ByVal</font> str <font color="#0000ff">As</font><font color="#0000ff">String</font>) <font color="#0000ff">As</font> StringBuilder6<br />
              <font color="#0000ff">Dim</font> op <font color="#0000ff">As</font><font color="#0000ff">New</font> StringBuilder6()<br />
              op.buffer.Append(str)<br />
              <font color="#0000ff">Return</font> op<br /><font color="#0000ff">    End</font><font color="#0000ff">Operator
      </font></p>
        <p>
      End<font color="#000000"></font><font color="#0000ff">Class</font></p>
        <p>
      Once the StringBuilder6 class is in place, you just need to replace the type of the
      String variable:
   </p>
        <p>
          <font color="#0000ff">Dim</font> s <font color="#0000ff">As</font> StringBuilder6
      = <font color="#800000">""<br /></font></p>
        <font color="#000000">
          <p>
      After this edit, the loop runs in <strong>0.008 seconds</strong>, that is <strong><font color="#ff0000">about
      2000 times faster</font></strong>!!! Not bad, for such a simple fix :-)
   </p>
          <p>
      Regardless of whether you are migrating code from VB6 or you've written VB.NET or
      C# code from scratch, the StringBuilder class gives you a quick and simple way to
      check whether your string concatenations can be optimized by resorting to a StringBuilder.
   </p>
          <p>
       
   </p>
        </font>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=ce96d1dc-838b-424d-b571-282e028e9e32" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Compressing and hiding DLLs</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,60e09b96-7033-4883-95b0-8ddb0b205ad3.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,60e09b96-7033-4883-95b0-8ddb0b205ad3.aspx</id>
    <published>2007-04-11T09:07:41.4248750-07:00</published>
    <updated>2007-04-11T09:07:41.4248750-07:00</updated>
    <category term=".NET Framework" label=".NET Framework" scheme="dasBlog" />
    <category term="C#" label="C#" scheme="dasBlog" />
    <category term="Optimization" label="Optimization" scheme="dasBlog" />
    <category term="Tools" label="Tools" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <category term="Windows Forms" label="Windows Forms" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I like the ability to extend the power of my applications by simply adding a reference
      to an assembly that contains the functions or the controls that I need. I like much
      less, however, the need to distribute and deploy many DLLs together with my executables.
      In this post I show a technique that I use to compress (nearly) all the DLLs of a
      Windows Forms application and "merge" them with the main EXE.
   </p>
        <p>
      All the files you need are in <a href="http://www.dotnet2themax.com/blogs/fbalena/content/binary/asmzip.zip">this
      ZIP archive</a>, which contains the AsmZip.exe utility (which you run from the command
      prompt) and two source files, Unzipper.cs and Unzipper.vb. I suggest that you copy
      the AsmZip utility in a directory listed on the system path, to run it easily.
   </p>
        <p>
          <strong>
            <font size="4">Step-by-step</font>
          </strong>
          <br />
      These are the steps you must follow to implement the technique.
   </p>
        <p>
          <strong>1)</strong> Add either the Unzipper.vb or the Unzipper.cs file to the main
      project of your application, depending on the language you've used.
   </p>
        <p>
          <strong>2)</strong> In the Main method, add a statement that initializes the AssemblyUnzipper
      class (which is defined in the Unzipper file you added in step 1).<br />
             ' (Visual Basic 2005)<br />
             CodeArchitects.AssemblyUnzipper.Initialize()<br />
             // Visual C# 2005<br />
             CodeArchitects.AssemblyUnzipper.Initialize();<br />
      It is essential that this statement runs before any other statement in the application,
      particularly before showing a form that contains a control implemented in one of the
      DLLs you want to compress. If you are working with VB and the application has a startup
      form (and therefore you don't have a Sub Main method), you should initialize the AssemblyUnzipper
      class from inside the startup form's static constructor:<br />
            Shared Sub New()<br />
               CodeArchitects.AssemblyUnzipper.Initialize()<br />
            End Sub
   </p>
        <p>
          <strong>3)</strong> compile the project, obviously in Release mode. (You should use
      this technique just before delivering the executable to your customer(s).
   </p>
        <p>
          <strong>4)</strong> open a command prompt window from inside the application's \bin
      directory, and run the AsmZip utility as follows:<br />
                   AsmZip main.exe
      *.dll<br />
      where main.exe is the name of the main executable. The above command compresses *all*
      the DLLs in the directory and appends the compressed data to the main.exe file. If
      you want to compress just a subset of the DLLs that the application uses, you should
      specify their names, as in this example:<br />
                   AsmZip main.exe
      CodeArchitects*.dll Microsoft*.dll<br />
      There can be a few good reasons not to compress some of the DLLs used by the applications,
      as I'll explain shortly.
   </p>
        <p>
          <strong>5)</strong> You can now delete all the DLLs that you have compressed, because
      the application - thanks to the AssemblyUnzipper class - is able to find them at the
      end of its executable file, to decompress them, and to load them in memory.
   </p>
        <p>
          <strong>
            <font size="4">Pros</font>
          </strong>
          <br />
      Before proceeding with an explaination of the technique's inner details, let's summarize
      its advantages:
   </p>
        <p>
      a) simpliefied deployment: you need to distribute fewer files (often just the main
      EXE)<br />
      b) more robust applications: end users can't break the application by accidentally
      deleting one of its DLLs<br />
      c) fewer bytes on disk: all DLLs are compressed and appended to the main EXE file<br />
      d) the ability to "hide" some of your trade secrets, for example which 3rd party controls
      you've used<br />
      e) a slightly better protection of your intellectual property: compressed DLLs can't
      be decompiled, at least not as easily as uncompressed DLLs .
   </p>
        <p>
      The last two points aren't a real protection against even unexperienced malicious
      hackers, if he or she is determined to peek into your application. To do so he would
      just need to decompile the main EXE, understand how the AssemblyZipper class works,
      and write a short programma that works similarly but saves the uncompressed assemblies
      to disk. In other words, don't rely on this technique to protect your code from reverse
      engineering.
   </p>
        <p>
      The AsmZip tool relies on the GZipStream class to compress the original DLLs, therefore
      the compression factor that you achieve with this technique is lower than the one
      you can obtain with WinZip or WinRar, but it is usually more than adequate, as the
      following figure shows.
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/AsmZip.gif" border="0" />
        </p>
        <p>
          <br />
          <strong>
            <font size="4">How it works</font>
          </strong>
          <br />
      This technique relies on the AssemblyResolve event of the AppDomain object. This event
      fires when the CLR loads an assembly referenced by the running application. By handling
      this event you can perform some nice tricks that wouldn't be possible otherwise. For
      example, you might load satellite assemblies from a network share or from a binary
      field in a database.
   </p>
        <p>
      The AssemblyUnzippere class uses this event to search the required assembly from a
      compressed stream that has been appended to the application's main EXE file:<br />
            // the handler for AssemblyResolve event<br />
            static Assembly CurrentDomain_AssemblyResolve(object
      sender, ResolveEventArgs e)<br />
            {<br />
               // find the assembly with given name,
      cause error if not found<br />
               AssemblyInfo info = null;<br />
               if ( AsmInfos.TryGetValue(e.Name,
      out info) )<br />
                  return ExtractAssembly(info);<br />
               // signal error<br />
               Debug.WriteLine("Failed to uncompress
      assembly " + info.Name);<br />
               return null;<br />
            }<br />
      Each AssemblyInfo object keeps track of where, in the main EXE file, the compressed
      data for each DLL is located. The AsmInfos dictionary enables the code to quickly
      locate the information associated with a DLL with given name. This dictionary is created
      inside the Initialize method, when the application is launched, and is then used each
      time the application attempts to load an assembly. For more details, see comments
      in either the VB or the C# source code.
   </p>
        <p>
          <strong>
            <font size="4">Limitations</font>
          </strong>
          <br />
      I tried this technique with several Windows Forms apps, without any problem. The main
      issue is that compressed assemblies loaded programmatically have their Location property
      set to null/Nothing, but if you don't use reflection to explore the assembly's feature
      you might never realize that the assembly was loaded in a nonstandard way. For example,
      if your app dynamically loads all the assemblies in a given directory, for example
      to explore their attributes, it is evident that it won't work as intended if these
      DLLs have been compressed and then deleted. In such cases, you should exclude these
      DLLs from compression.
   </p>
        <p>
      The AssemblyZipper class works only with Windows Forms applications. For what I know,
      it is possible to use the AssemblyResolve event inside ASP.NET applications, but it
      isn't possible to use the AssemblyUnzipper in that context. However, the problems
      that this technique solves aren't considered as real issues under ASP.NET, therefore
      I don't think it makes sense to use it in web applications.
   </p>
        <p>
      The only other limitation is that this technique works with DLLs but not with the
      main EXE. If you have a large EXE that uses some small DLLs, you won't achieve an
      interesting compression factor. In such a case, you might want to move your forms
      from the main EXE into a DLL and then compress the DLL with AsmZip. Even better, the
      main EXE might contain only the splash screen (if you have one) and it should load
      the startup form from the DLL that contains the actual application. Using this approach
      it is often possible to achieve an overall compression factor near or above 60 percent.
   </p>
        <p>
          <strong>Note:</strong> in the first implementation of this technique I managed to
      successfully compress even the main EXE and used a small “stub” executable whose only
      job was to decompress and launch the actual EXE. After some tests, however, I found
      that the technique wasn’t very stable and I fell back to the technique described in
      this article.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=60e09b96-7033-4883-95b0-8ddb0b205ad3" />
      </div>
    </content>
  </entry>
  <entry>
    <title>YART - Yet Another Regex Tester</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,13bce26d-7755-441e-92b3-1eb5f9e859f9.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,13bce26d-7755-441e-92b3-1eb5f9e859f9.aspx</id>
    <published>2006-08-29T12:00:02.6620000-07:00</published>
    <updated>2008-01-11T04:07:58.9062500-08:00</updated>
    <category term="C#" label="C#" scheme="dasBlog" />
    <category term="Regex" label="Regex" scheme="dasBlog" />
    <category term="Tools" label="Tools" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I know, I know, there are soooo many regular expression tester tools available on
      the 'Net, but I couldn't help creating my own. It's very simple, yet it supports all
      the basic features you'd espect from a tool of its kind, including code generation
      (VB and C#) and compilation to stand-alone assemblies. Best of all, <strong>it comes
      with source code</strong>. You can download it from the <a href="http://www.dotnet2themax.com/ProgrammingVB2005.aspx">home
      page</a> of my Visual Basic 2005 book (together with all other code samples in the
      book) or directly from here:
   </p>
        <p>
      Executable (requires .NET Framework 2.0): <a href="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester.zip">RegexTester.zip
      (75.57 KB)</a><br />
      Source code (VB2005): <a href="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester%20source.zip">RegexTester
      source.zip (88.15 KB)</a></p>
        <p>
      Using the tool is quite simple. The main window is divided in three panes: (a) the
      pane where you enter the regex, (b) the pane where you load the text the regex must
      be applied to, (c) the result pane. A fourth pane appears when you select the Replace
      item from the Commands menu, and it's where you enter the replace pattern. As you
      can see in the image below, you can enter most regex patterns by selecting them from
      the context menu:
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester1.gif" border="0" />
        </p>
        <p>
      You select the kind of command (Find, replace, Split) from the Commands menu and you
      select one or more regex options from the Options menu:
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester2.gif" border="0" />
        </p>
        <p>
      After selecting the proper options, you press the F5 key (the Run item in the Commands
      menu) to execute the regex. Results are displayed in the bottom pane in a variety
      of formats and sort orders, which you can select from the Results menu, and the status
      bar displays the number of matches, the execution time, and the properties of the
      result currently highlighted in the result pane:
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester3.gif" border="0" />
        </p>
        <p>
      Alternatively, you can set all these options from the Properties dialog box (the Properties
      command in the File menu, or just press the F4 key):
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester4.gif" border="0" />
        </p>
        <p>
      Assigning a name to the current regex is important because you can save it on disk
      in a file with .regex extension, for later retrieval. 
   </p>
        <p>
      The Commands menu contains a couple of other interesting items. First, you can generate
      the C# or VB code for the current regular expression and copy it to the Clipboard:
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester5.gif" border="0" />
        </p>
        <p>
      Second, and more interesting, you can compile one or more regular expressions (including
      saved .regex projects) into a compiled assembly, which you can later reference from
      any .NET application. Using such compiled regexes is obviously faster than defining
      them in code, because you skip the parsing step:
   </p>
        <p>
       
   </p>
        <p>
          <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/RegexTester6.gif" border="0" />
        </p>
        <p>
      That's it. You can use the YART tool for your own use, study its source code, modify
      and expands it as you like. If you find any major problems or add some noteworthy
      feature, just let me know.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=13bce26d-7755-441e-92b3-1eb5f9e859f9" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Two sample chapters from "Programming Microsoft Visual C# 2005: The Base Class Library"</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,fc6a58f2-9682-4e6c-97a4-20ad0facb5e6.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,fc6a58f2-9682-4e6c-97a4-20ad0facb5e6.aspx</id>
    <published>2006-07-01T02:35:25.9687500-07:00</published>
    <updated>2006-07-01T02:35:25.9687500-07:00</updated>
    <category term="Books" label="Books" scheme="dasBlog" />
    <category term="C#" label="C#" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      My new C# book has been released a few months ago, but I was so busy with my everyday
      activities that I didn't even blogged about it. Instead of going to the beach, today
      I sat down a prepare a <a href="http://www.dotnet2themax.com/ProgrammingCSharp2005.aspx">home
      page</a> for the book, from where you can download two sample chapters: Chapter 5 <strong>"Arrays
      and Collection"</strong> and Chapter 10, <strong>"Custom Attributes", </strong>as
      well as all the code samples and the errata doc.
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=fc6a58f2-9682-4e6c-97a4-20ad0facb5e6" />
      </div>
    </content>
  </entry>
  <entry>
    <title>New errata document for "Programming Microsoft Visual Basic 2005: The Language"</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,f604c9a6-7804-4736-b7f6-6e445a097113.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,f604c9a6-7804-4736-b7f6-6e445a097113.aspx</id>
    <published>2006-07-01T01:01:26.7343750-07:00</published>
    <updated>2006-07-01T01:01:26.7343750-07:00</updated>
    <category term="Books" label="Books" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      At last I found the time to sort all the notes from readers, pointing at typos and
      mistakes in my VB2005 book, and to update the errata document that you can download
      from the <a href="http://www.dotnet2themax.com/ProgrammingVB2005.aspx">book's home
      page</a>. I have clearly marked the additions with a "New" marker. Most of these notes
      are typos that don't affect how code works, with the notable exception of the fix
      to the Evaluate function in Chapter 16 (regular expression).
   </p>
        <p>
      My grat thanks to all the readers who took the time to write me to inform of the mistakes
      they found, with a special mention to <strong>Dan Karmann</strong>, who actually methodically
      proof-read the book and found about twenty of them. 
   </p>
        <p>
       
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=f604c9a6-7804-4736-b7f6-6e445a097113" />
      </div>
    </content>
  </entry>
  <entry>
    <title>How many instances are running?</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,669b012d-46d6-402f-b8d9-b7553b44451c.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,669b012d-46d6-402f-b8d9-b7553b44451c.aspx</id>
    <published>2006-05-31T02:10:12.0600000-07:00</published>
    <updated>2007-04-15T22:30:36.9873750-07:00</updated>
    <category term=".NET Framework" label=".NET Framework" scheme="dasBlog" />
    <category term="C#" label="C#" scheme="dasBlog" />
    <category term="Code Snippets" label="Code Snippets" scheme="dasBlog" />
    <category term="Migrating from VB6" label="Migrating from VB6" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <category term="Windows Forms" label="Windows Forms" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Visual Basic 6's App object exposes a useful property named PrevInstance, which allows
      you to determine whether there are other instances of the same application running.
      This property has never been implemented in VB.NET, even though a VB2005 application
      can use the StartupNextInstance event for this purpose.
   </p>
        <font color="#0000ff">
          <font color="#008000">
            <p>
      ' to display this code, open the Application page of the My Project designer and click
      the Application Events button<br /></p>
          </font>Namespace</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">My<br />
      </font>
        <font color="#0000ff">Partial</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Friend</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Class</font>
        <font color="#000000"> MyApplication<br />
         </font>
        <font color="#0000ff">Private</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Sub</font>
        <font color="#000000"> MyApplication_StartupNextInstance(</font>
        <font color="#0000ff">ByVal</font>
        <font color="#000000"> sender </font>
        <font color="#0000ff">As</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Object</font>
        <font color="#000000">, </font>
        <font color="#0000ff">ByVal</font>
        <font color="#000000"> e </font>
        <font color="#0000ff">As</font>
        <font color="#000000"> Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) </font>
        <font color="#0000ff">Handles</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Me</font>
        <font color="#000000">.StartupNextInstance<br /></font>
        <font color="#008000">         ' another
   instance of this application has been launched<br /></font>
        <font color="#0000ff">      End</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Sub<br />
      </font>
        <font color="#0000ff">End</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Class<br />
   End</font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Namespace</font>
        <font color="#000000">
          <p>
      The problem of this approach is that the event is raised in the first instance of
      the application, not in the new instance, therefore when the VB.NET application starts
      you can't determine for sure whether it is the only instance in the system. In other
      words, you can learn only whether and when <em>another </em>application is launched,
      not if the current applicatin is the first and only running instance.
   </p>
          <p>
      .NET developers have solved this problem in a variety of ways, for example using Mutexes
      or by iterating over the collection returned by the Process.GetProcesses method. In
      .NET we have a new and more elegant alternative, based on the System.Threading.Semaphore
      type. A semaphore is a counter which can be incremented and decremented. If its value
      becomes zero, a thread can't decrement it and must wait for another thread to increment
      it to a value &gt;0. Interestingly, if the semaphore has a name it becomes a system-wid
      object which can be shared by all the applications that ask for a reference to a semaphore
      with that specific name. It is therefore sufficient that the app creates a semaphore
      with a unique name just after its launch (e.g. it can be a name that includes the
      executable's path) to have all the instances of a given app share the same semaphore
      and therefore the same counter. The only problem left to solve is ensure that the
      semaphore's counter be correctly resotred when the application terminates, but this
      is easy to achieve by means of a Finalize method.
   </p>
          <p>
      In addition to the PrevInstance property - which returns False if the application
      was the only running instance <em>when the application was launched </em>- the following
      VB6App class exposes also the InstanceCount property, which returns the total number
      of instances <em>in that moment </em>(the current app is included in the count). Here's
      the VB2005 version of this class:
   </p>
          <font color="#0000ff">
            <p>
      Class
   </p>
          </font> VB6App<br />
      <font color="#008000">' the default instance 
   <br />
      </font><font color="#0000ff">Private</font><font color="#0000ff">Shared</font> DefValue <font color="#0000ff">As</font><font color="#0000ff">New</font> VB6App
   <p><font color="#008000">   ' the system-wide semaphore<br />
         </font><font color="#0000ff">Private</font> semaphore <font color="#0000ff">As</font> System.Threading.Semaphore<br /><font color="#008000">   ' initial count for the semaphore (very high value)<br />
         </font><font color="#0000ff">Private</font><font color="#0000ff">Const</font> MAXCOUNT <font color="#0000ff">As</font><font color="#0000ff">Integer</font> =
      10000
   </p><p><font color="#008000">   </font><font color="#0000ff">Private</font><font color="#0000ff">Sub</font><font color="#0000ff">New</font>()<br />
            <font color="#008000"><font color="#0000ff">Dim</font><font color="#000000">ownership</font><font color="#0000ff">As</font><font color="#0000ff">Boolean</font> = <font color="#0000ff">False<br /></font><font color="#000000">      <font color="#008000">' create
      a unique name, but strip invalid characters<br /></font>      </font><font color="#0000ff">Dim</font><font color="#000000">name</font><font color="#0000ff">As</font><font color="#0000ff">String</font> = <font color="#800000">"VB6App_"</font> &amp; <font color="#000000">System.Reflection.Assembly.GetExecutingAssembly().Location.Replace(</font><font color="#800000">":"</font><font color="#000000">,</font><font color="#800000">""</font>)<font color="#000000">.Replace(</font><font color="#800000">"\"</font>, <font color="#800000">""</font><font color="#000000">)</font><br /><font color="#000000">      </font><font color="#000000">semaphore</font> = <font color="#0000ff">New</font><font color="#000000">System.Threading.Semaphore(MAXCOUNT,
      MAXCOUNT, name, ownership)<br /></font><font color="#000000">      </font><font color="#008000">'
      decrement its value <br /></font><font color="#000000">      </font><font color="#000000">semaphore.WaitOne()</font><br /><font color="#000000">      </font><font color="#008000">'
      if we got ownership, this app has no previous instances<br /></font><font color="#000000">      </font><font color="#000000">m_PrevInstance </font>= <font color="#0000ff">Not</font><font color="#000000">ownership</font><br /></font><font color="#008000">   </font><font color="#0000ff">End</font><font color="#0000ff">Sub
      </font></p></font>
        <p>
          <font color="#008000">   ' the PrevInstance property returns True if there
      was a previous instance running <br />
         </font>
          <font color="#008000">' when the default instance was created<br />
         </font>
          <font color="#0000ff">Private</font>
          <font color="#0000ff">Shared</font> m_PrevInstance <font color="#0000ff">As</font> <font color="#0000ff">Boolean</font></p>
        <p>
          <font color="#0000ff">
            <font color="#008000">   </font>Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">ReadOnly</font>
          <font color="#0000ff">Property</font> PrevInstance() <font color="#0000ff">As</font><font color="#0000ff">Boolean<br /></font><font color="#008000">      </font><font color="#0000ff">Get<br /></font><font color="#008000">         </font><font color="#0000ff">Return</font> m_PrevInstance <br /><font color="#008000">      </font><font color="#0000ff">End</font><font color="#0000ff">Get<br /></font><font color="#008000">   </font><font color="#0000ff">End</font><font color="#0000ff">Property
      </font></p>
        <p>
          <font color="#008000">   ' return the total number of instances of the same
      application that are currently running <br />
         </font>
          <font color="#0000ff">Public</font>
          <font color="#0000ff">Shared</font>
          <font color="#0000ff">ReadOnly</font>
          <font color="#0000ff">Property</font> InstanceCount() <font color="#0000ff">As</font><font color="#0000ff">Integer<br /></font><font color="#008000">      </font><font color="#0000ff">Get<br /></font><font color="#008000">         ' release
      the semaphore and grab the previous count <br />
               </font><font color="#0000ff">Dim</font> prevCount <font color="#0000ff">As</font><font color="#0000ff">Integer</font> =
      DefValue.semaphore.Release()<br /><font color="#008000">         ' acquire the
      semaphore again<br />
               </font>DefValue.semaphore.WaitOne()<br /><font color="#008000">         ' eval the
      number of other instances that are currently running <br />
               </font><font color="#0000ff">Return</font> MAXCOUNT
      - prevCount<br /><font color="#008000">      </font><font color="#0000ff">End</font><font color="#0000ff">Get<br /></font><font color="#008000">   </font><font color="#0000ff">End</font><font color="#0000ff">Property
      </font></p>
        <p>
          <font color="#0000ff">
            <font color="#008000">   </font>Protected</font>
          <font color="#0000ff">Overrides</font>
          <font color="#0000ff">Sub</font> Finalize()<br /><font color="#008000">      ' increment the semaphore when
      the application terminates<br />
            </font>semaphore.Release()<br /><font color="#008000">   </font><font color="#0000ff">End</font><font color="#0000ff">Sub
      </font></p>
        <p>
      End <font color="#0000ff">Class
      </font></p>
        <p>
      Notice that this class has a Finalize method without implementing IDisposable. It
      is one of those special cases when it is OK to violate the Dispose-Finalize pattern.
   </p>
        <p>
      To understand how the class works, just keep in mind that the Semaphore.Release method
      increments the internal counter, whereas the WaitOne method decrements it. You must
      test the VB6App.PrevInstance property as soon as the application starts, for example
      in the Sub Main method or in the Load event hander for the main form, as to let the
      VB6App class store the boolean value internally. The same form might then test the
      value of the InstanceCount property on exit, for example if you need to run some cleanup
      code when the last application instance is about to terminate:
   </p>
        <p>
          <font color="#0000ff">Private</font>
          <font color="#0000ff">Sub</font> Form1_Load(<font color="#0000ff">ByVal</font> sender <font color="#0000ff">As</font><font color="#0000ff">Object</font>, <font color="#0000ff">ByVal</font> e <font color="#0000ff">As</font> System.EventArgs) <font color="#0000ff">Handles</font><font color="#0000ff">Me</font>.Load<br /><font color="#008000">   </font><font color="#0000ff">If</font> <font color="#0000ff">Not</font> VB6App.PrevInstance <font color="#0000ff">Then</font> <br /><font color="#0000ff">      <font color="#008000">' open
      the common log file<br /><font color="#0000ff">      </font><font color="#008000">' ...<br /></font></font>   End</font><font color="#0000ff">If<br /></font><font color="#0000ff">End</font><font color="#0000ff">Sub 
      <p></p></font></p>
        <p>
          <font color="#0000ff">Private</font>
          <font color="#0000ff">Sub</font> Form1_FormClosing(<font color="#0000ff">ByVal</font> sender <font color="#0000ff">As</font><font color="#0000ff">Object</font>, <font color="#0000ff">ByVal</font> e <font color="#0000ff">As</font> System.Windows.Forms.FormClosingEventArgs) <font color="#0000ff">Handles</font><font color="#0000ff">Me</font>.FormClosing<br />
         <font color="#0000ff">If</font> VB6App.InstanceCount = 1 <font color="#0000ff">Then<br />
            </font><font color="#008000">' close the common log
      file.<br /><font color="#0000ff">      </font><font color="#008000">' ...<br /></font>   </font><font color="#0000ff">End</font><font color="#0000ff">If<br /></font><font color="#0000ff">End</font><font color="#0000ff">Sub
      </font></p>
        <p>
      Here's the C# version of the class. <em>(I fixed the original version to fix two syntax
      errors mentioned in one of the comments below.)</em></p>
        <p>
          <font color="#0000ff">public</font>
          <font color="#0000ff">class</font>
          <font color="#008080">VB6App</font>
          <br />
      { 
      <br />
         <font color="#008000">// the default instance <br /></font><font color="#000000">   </font><font color="#0000ff">private</font><font color="#0000ff">static</font><font color="#008080">VB6App</font> DefValue
      = <font color="#0000ff">new</font><font color="#008080">VB6App</font>(); <br />
         <font color="#008000">// the system-wide semaphore<br /></font><font color="#000000">   </font><font color="#0000ff">private</font> System.Threading.<font color="#008080">Semaphore</font> semaphore; <br />
         <font color="#008000">// initial count for the semaphore (very high value)<br /></font><font color="#000000">   </font><font color="#0000ff">private</font><font color="#0000ff">const</font><font color="#0000ff">int</font> MAXCOUNT
      = 10000; 
   </p>
        <p>
        </p>
        <p>
          <font color="#0000ff">
            <font color="#000000">   </font>private</font> VB6App() <br />
         { <br />
            <font color="#008000">// create a named (system-wide
      semaphore)<br /></font><font color="#000000">      </font><font color="#0000ff">bool</font> ownership
      = <font color="#0000ff">false</font>; <br />
            <font color="#008000">// create the semaphore or get
      a reference to an existing semaphore</font></p>
        <p>
          <font color="#008000">
            <font color="#0000ff">      string</font>
            <font color="#000000">name</font> = <font color="#800000">"VB6App_"</font> <font color="#0000ff">+</font><font color="#000000">System.Reflection.Assembly.GetExecutingAssembly().Location.Replace(<font color="#800000">":"</font><font color="#000000">,</font><font color="#008000"></font><font color="#800000">""</font><font color="#008000">)</font><font color="#000000">.Replace(</font><font color="#800000">"\\"</font><font color="#008000">, </font><font color="#800000">""</font><font color="#000000">);</font><br /></font></font>      semaphore = <font color="#0000ff">new</font> System.Threading.<font color="#008080">Semaphore</font>(
      MAXCOUNT, MAXCOUNT, name, <font color="#0000ff">out </font>ownership); <br />
            <font color="#008000">// decrement its value 
      <br />
            </font>semaphore.WaitOne(); <br /><font color="#008000"><font color="#000000">      </font><font color="#008000">//
      if we got ownership, this app has no previous instances<br /></font><font color="#000000">      </font><font color="#000000">m_PrevInstance </font>= <font color="#0000ff">!</font><font color="#000000">ownership;</font></font><br />
         } 
   </p>
        <p>
        </p>
        <p>
          <font color="#008000">   // the PrevInstance property returns True if there
      was a previous instance running 
      <br />
         </font>
          <font color="#008000">// when the default instance was created
      </font>
        </p>
        <p>
        </p>
        <p>
          <font color="#0000ff">
            <font color="#008000">   </font>private</font>
          <font color="#0000ff">static</font>
          <font color="#0000ff">bool </font>m_PrevInstance
      ; 
   </p>
        <p>
        </p>
        <p>
          <font color="#0000ff">
            <font color="#008000">   </font>public</font>
          <font color="#0000ff">static</font>
          <font color="#0000ff">bool</font> PrevInstance <br /><font color="#008000">   </font>{ <br /><font color="#008000">      </font><font color="#0000ff">get</font> <br /><font color="#008000">      </font>{ <br /><font color="#008000">         </font><font color="#0000ff">return</font> m_PrevInstance ; <br /><font color="#008000">      </font>} <br /><font color="#008000">   </font>} 
   </p>
        <p>
        </p>
        <p>
          <font color="#008000">   // return the total number of instances of the
      same application that are currently running 
      </font>
        </p>
        <p>
        </p>
        <p>
          <font color="#0000ff">
            <font color="#008000">   </font>public</font>
          <font color="#0000ff">static</font>
          <font color="#0000ff">int</font> InstanceCount <br /><font color="#008000">   </font>{ <br /><font color="#008000">      </font><font color="#0000ff">get</font> <br /><font color="#008000">      </font>{ <br /><font color="#008000">         // release
      the semaphore and grab the previous count <br />
               </font><font color="#0000ff">int</font> prevCount
      = DefValue.semaphore.Release(); <br /><font color="#008000">         // acquire
      the semaphore again<br />
               </font>DefValue.semaphore.WaitOne(); <br /><font color="#008000">         // eval the
      number of other instances that are currently running <br />
               </font><font color="#0000ff">return</font> MAXCOUNT
      - prevCount; <br /><font color="#008000">      </font>} <br /><font color="#008000">   </font>} 
   </p>
        <p>
        </p>
        <p>
          <font color="#008000">   </font>~VB6App() <br /><font color="#008000">   </font>{ <br /><font color="#008000">      // increment the semaphore when
      the application terminates<br />
            </font>semaphore.Release(); <br /><font color="#008000">   </font>} 
      <br />
      } 
   </p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=669b012d-46d6-402f-b8d9-b7553b44451c" />
      </div>
    </content>
  </entry>
  <entry>
    <title>"Programming Microsoft Visual C# 2005 : The Base Class Library" is here</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,6d4703fa-edb4-441d-ae2a-dd9bc1303689.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,6d4703fa-edb4-441d-ae2a-dd9bc1303689.aspx</id>
    <published>2006-05-29T00:50:45.5135000-07:00</published>
    <updated>2006-05-29T00:50:45.5135000-07:00</updated>
    <category term=".NET Framework" label=".NET Framework" scheme="dasBlog" />
    <category term="Books" label="Books" scheme="dasBlog" />
    <category term="C#" label="C#" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <table>
          <tbody>
            <tr>
              <td valign="top" width="200">
                <p>
                  <img src="http://www.dotnet2themax.com/blogs/fbalena/content/binary/ProgrammingCSharp2005_Cover.gif" border="0" />
                </p>
              </td>
              <td>
                <p>
                  I have been so busy in May that I couldn't update the blog, not even to mention that
                  my latest Microsoft Press book had been released and is now available on all major
                  US bookstores. With fewer than 600 pages, Programming Microsoft Visual C# 2005: The
                  Base Class Library is surely the shortest book I wrote. Not only that: it's also the
                  book that took me less time to wrote. In fact, this book is basically the translation
                  to C# of the second half of my <a href="http://www.dotnet2themax.com/ProgrammingVB2005.aspx">VB
                  2005 book</a>, more precisely of the chapters that have to do more with the .NET Framework
                  and less with the C# language itself. Here's the Table of Contents:
               </p>
                <p>
                  1. .NET Framework Basic Types<br />
                  2. Object Lifetime<br />
                  3. Interfaces<br />
                  4. Generics<br />
                  5. Arrays and Collections<br />
                  6. Regular expressions<br />
                  7. Files, directories, and streams<br />
                  8. Assemblies and resources<br />
                  9. Reflection<br />
                  10. Custom attributes<br />
                  11. Threads<br />
                  12. Object serialization<br />
                  13. PInvoke and COM interop
               </p>
              </td>
            </tr>
            <tr>
            </tr>
          </tbody>
        </table>
        <p>
          <font size="3">Even though the book isn't specifically on the C# language, it adequately
      covers most of the new features of C# 2.0, such as generics, iterators, and anonymous
      methods. </font>
        </p>
        <p>
          <font size="3">Why a book on the BCL? Well, in these years I realized that far too
      many developers focus solely on high-level features - such as Windows Forms, ADO.NET,
      and ASP.NET - and often fail to leverage the full potential from other portions of
      the .NET Framework. For example, I have seen many apps that use verbose and unefficient
      validation rules that might be replaced by a single regular expression. Or apps that
      could be written in a fraction of time (and lines of code) if the author had been
      conscious of the full potential of reflection and custom attributes. Not to mention
      the fact that new .NET 2.0 features, such as generics, could make things only worse.</font>
        </p>
        <p>
          <font size="3">In general I find that most books that are "translated" from a different
      programming language are disappointing, so you might wonder why this book should be
      different. First, when I signed the contract for my VB 2005 book I already knew that
      the book would have been translated to C#, thus I planned the book so that its structure
      wouldn't be too VB-centric. Secoond, in the last four years I have been using C# in
      virtually all my programming projects - in fact I have surely written more C# code
      than VB code. For this reason, you'll find that the C# code is carefully optimized
      to use all the usual C#-specific techniques, such as iterators and anonymous delegates.</font>
        </p>
        <p>
          <font size="3">Shortly I will prepare a home page for the book on this site, with
      a couple of sample chapters. In the meantime, you can read more about the book (and
      hopefully order it) on <a href="http://www.amazon.com/gp/product/0735623082/ref=pe_snp_082/102-4059606-6476126">Amazon's
      home page</a>.</font>
        </p>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=6d4703fa-edb4-441d-ae2a-dd9bc1303689" />
      </div>
    </content>
  </entry>
  <entry>
    <title>Frozen forms for flickering-free updates</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,6336502b-57c5-430d-9d37-7f9be484f6b3.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,6336502b-57c5-430d-9d37-7f9be484f6b3.aspx</id>
    <published>2006-05-03T04:16:30.2790000-07:00</published>
    <updated>2006-05-03T04:17:12.4041250-07:00</updated>
    <category term="C#" label="C#" scheme="dasBlog" />
    <category term="Code Snippets" label="Code Snippets" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <category term="Windows Forms" label="Windows Forms" scheme="dasBlog" />
    <content type="html">&lt;p&gt;
   Yesterday I got an email from reader Claudio Fontana, with the following, deceiptively
   simple request: how can you avoid flickering while updating many controls on a form?
   The problem is especially serious when you need to add thousands of items to a ListView
   or a TreeView.
&lt;/p&gt;
&lt;p&gt;
   In VB6 this problem can be solved quite simply by temporarily setting the Visible
   (or Enabled) property to False for all the controls about to be updated: the control
   isn't actually hidden, yet the result of the update operation appears istantaneously
   when the property is reset to True. Just as interesting: the update operation is carried
   out much faster if the control is invisible, often twice as faster. Alas, this trick
   doesn't work in .NET, because as soon as you set the Visible property to False the
   control is immediately hidden. It's necessary to find another solution.
&lt;/p&gt;
&lt;p&gt;
   A few Windows Forms controls - namely the ListBox, ComboBox, ListView, and TreeView
   controls - do expose the &lt;strong&gt;BeginUpdate &lt;/strong&gt;and &lt;strong&gt;EndUpdate &lt;/strong&gt;methods,
   which allow you to "freeze" the control while you add items to it. Not only do they
   solve the flickering problem, they also speed up the update operation, tipically by
   a factor of 2.5x. However, if your form contains many controls that do NOT expose
   these methods, you must devise something else, and this was exactly the problem that
   Claudio submitted, after he unsuccessfully googled around on the 'Net looking for
   a solution.
&lt;/p&gt;
&lt;p&gt;
   The problem is quite intriguing, thus I decided to spend some time on it, until I
   came to the following solution. The idea is simple, and can be split in the following
   steps: (1) take a snapshot of the current form's appearance, by making a pixel-by-pixel
   copy into a bitmap, (2) create a PictureBox control as large as the form, and load
   the bitmap into the PictureBox, (3) add the PictureBox to the form's Controls collection
   and bring the PictureBox in front of all other controls, (4) while the user looks
   at the "frozen" image of the form, update your controls, using the BeginUpdate/EndUpdate
   mthods if possible to speed up execution, (5) when the update operation is completed,
   remove the PictureBox from the Controls collection, so that the user can now see the
   real form.
&lt;/p&gt;
&lt;p&gt;
   You just need one dozen statements to implement this algorithim, but I prepared a
   class to make the code more reusable and to ensure that it releases all resources
   correctly:
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#0000ff&gt;Public&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;Class&lt;/font&gt;&lt;font color=#000000&gt; FormFreezer&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Implements&lt;/font&gt;&lt;font color=#000000&gt; IDisposable&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' The form being frozen&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; Form &lt;font color=#0000ff&gt;As&lt;/font&gt; Form&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' the auxiliary PictureBox
   that will cover the form&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; PictureBox &lt;font color=#0000ff&gt;As&lt;/font&gt; PictureBox&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' the number of times
   the Freeze method has been called&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; FreezeCount &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;Integer&lt;/font&gt; =
   0
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' create an instance associated
   with a given form&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' and optionally
   freeze the form right away&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Public&lt;/font&gt; &lt;font color=#0000ff&gt;Sub&lt;/font&gt; &lt;font color=#0000ff&gt;New&lt;/font&gt;(&lt;font color=#0000ff&gt;ByVal&lt;/font&gt; form &lt;font color=#0000ff&gt;As&lt;/font&gt; Form, &lt;font color=#0000ff&gt;Optional&lt;/font&gt; &lt;font color=#0000ff&gt;ByVal&lt;/font&gt; freezeIt &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;Boolean&lt;/font&gt; = &lt;font color=#0000ff&gt;False&lt;/font&gt;)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Me&lt;/font&gt;.Form
   = form&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;If&lt;/font&gt; freezeIt &lt;font color=#0000ff&gt;Then&lt;/font&gt; &lt;font color=#0000ff&gt;Me&lt;/font&gt;.Freeze()&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Sub
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' freeze the form&amp;nbsp;&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Public&lt;/font&gt; &lt;font color=#0000ff&gt;Sub&lt;/font&gt; Freeze()&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' Remember
   we have frozen the form once more&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;FreezeCount += 1&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' Do
   nothing if it was already frozen&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;If&lt;/font&gt; FreezeCount
   &amp;gt; 1 &lt;font color=#0000ff&gt;Then&lt;/font&gt; &lt;font color=#0000ff&gt;Exit&lt;/font&gt; &lt;font color=#0000ff&gt;Sub
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' Create
   a PictureBox that resizes with its contents&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;PictureBox = &lt;font color=#0000ff&gt;New&lt;/font&gt; PictureBox()&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;PictureBox.SizeMode = PictureBoxSizeMode.AutoSize&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' create
   a bitmap as large as the form's client area and with same color depth&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; frmGraphics &lt;font color=#0000ff&gt;As&lt;/font&gt; Graphics
   = Form.CreateGraphics()&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; rect &lt;font color=#0000ff&gt;As&lt;/font&gt; Rectangle
   = Form.ClientRectangle&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;PictureBox.Image = &lt;font color=#0000ff&gt;New&lt;/font&gt; Bitmap(rect.Width,
   rect.Height, frmGraphics)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;frmGraphics.Dispose()
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' copy
   the screen contents, from the form's client area to the hidden bitmap&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; picGraphics &lt;font color=#0000ff&gt;As&lt;/font&gt; Graphics
   = Graphics.FromImage(PictureBox.Image)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;picGraphics.CopyFromScreen(Form.PointToScreen(&lt;font color=#0000ff&gt;New&lt;/font&gt; Point(rect.Left,
   rect.Top)), &lt;font color=#0000ff&gt;New&lt;/font&gt; Point(0, 0), &lt;font color=#0000ff&gt;New&lt;/font&gt; Size(rect.Width,
   rect.Height))&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;picGraphics.Dispose()
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' Display
   the bitmap in the picture box, and show the picture box in front of all other controls&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;Form.Controls.Add(PictureBox)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;PictureBox.BringToFront()&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Sub
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' unfreeze the form&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' Note: calls to
   Freeze and Unfreeze must be balanced, unless force=true&amp;nbsp;&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Public&lt;/font&gt; &lt;font color=#0000ff&gt;Sub&lt;/font&gt; Unfreeze(&lt;font color=#0000ff&gt;Optional&lt;/font&gt; &lt;font color=#0000ff&gt;ByVal&lt;/font&gt; force &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;Boolean&lt;/font&gt; = &lt;font color=#0000ff&gt;False&lt;/font&gt;)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' exit
   if nothing to unfreeze&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;If&lt;/font&gt; FreezeCount
   = 0 &lt;font color=#0000ff&gt;Then&lt;/font&gt; &lt;font color=#0000ff&gt;Exit&lt;/font&gt; &lt;font color=#0000ff&gt;Sub&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;'
   remember we've unfrozen the form, but exit if it is still frozen&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;FreezeCount -= 1&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' force
   the unfreeze if so required&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;If&lt;/font&gt; force &lt;font color=#0000ff&gt;Then&lt;/font&gt; FreezeCount
   = 0&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;If&lt;/font&gt; FreezeCount
   &amp;gt; 0 &lt;font color=#0000ff&gt;Then&lt;/font&gt; &lt;font color=#0000ff&gt;Exit&lt;/font&gt; &lt;font color=#0000ff&gt;Sub
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' remove
   the picture box control and clean up&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;Form.Controls.Remove(PictureBox)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;PictureBox.Dispose()&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;PictureBox = &lt;font color=#0000ff&gt;Nothing&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Sub
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' return true if the form
   is currently frozen&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Public&lt;/font&gt; &lt;font color=#0000ff&gt;ReadOnly&lt;/font&gt; &lt;font color=#0000ff&gt;Property&lt;/font&gt; IsFrozen() &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;Boolean&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Get&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Return&lt;/font&gt; FreezeCount
   &amp;gt; 0&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Get&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Property
&lt;/p&gt;
&gt; 
&lt;p&gt;
   &lt;font color=#008000&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;' ensure that resources
   are cleaned up correctly&lt;br&gt;
   &lt;/font&gt;&lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Public&lt;/font&gt; &lt;font color=#0000ff&gt;Overridable&lt;/font&gt; &lt;font color=#0000ff&gt;Sub&lt;/font&gt; Dispose() &lt;font color=#0000ff&gt;Implements&lt;/font&gt; IDisposable.Dispose&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;Me&lt;/font&gt;.Unfreeze(&lt;font color=#0000ff&gt;True&lt;/font&gt;)&lt;br&gt;
   &lt;font color=#000000&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Sub&lt;br&gt;
   End&lt;/font&gt;&lt;font color=#000000&gt; &lt;/font&gt;&lt;font color=#0000ff&gt;Class&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#0000ff&gt;&lt;font color=#003300&gt;This is the C# version, translated from VB
   by Claudio:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font color=#0000ff&gt;&lt;font color=#003300&gt; 
&lt;div&gt;&lt;span class=797585908-03052006&gt; 
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; COLOR: blue; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;public
      class&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt; &lt;span style="COLOR: teal"&gt;FormFreezer&lt;/span&gt;: &lt;span style="COLOR: teal"&gt;IDisposable&lt;br&gt;
      &lt;/span&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;{&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&lt;/span&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="COLOR: green"&gt;&amp;nbsp;&amp;nbsp;
      // The form being frozen&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Form&lt;/span&gt; form;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      the auxiliary PictureBox that will cover the form&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;PictureBox&lt;/span&gt; pictureBox;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      the number of times the Freeze method has been called&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;int&lt;/span&gt; FreezeCount
      = 0;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      create an instance associated with a given form&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      and freeze the form in base of flag freezeIt&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt; FormFreezer(&lt;span style="COLOR: teal"&gt;Form&lt;/span&gt; form, &lt;span style="COLOR: blue"&gt;bool&lt;/span&gt; freezeIt)&lt;br&gt;
      &amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;this&lt;/span&gt;.form
      = form;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (freezeIt) &lt;span style="COLOR: blue"&gt;this&lt;/span&gt;.Freeze();&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      freeze the form&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; Freeze()&lt;br&gt;
      &amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      Remember we have frozen the form once more&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      Do nothing if it was already frozen&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (++FreezeCount
      &amp;gt; 1)&amp;nbsp;&lt;br&gt;
      &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt;;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      Create a PictureBox that resizes with its contents&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pictureBox
      = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: teal"&gt;PictureBox&lt;/span&gt;();&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pictureBox.SizeMode
      = &lt;span style="COLOR: teal"&gt;PictureBoxSizeMode&lt;/span&gt;.AutoSize;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      create a bitmap as large as the form's client area and with same color depth&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Graphics&lt;/span&gt; frmGraphics
      = form.CreateGraphics();&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span lang=FR style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;Rectangle&lt;/span&gt;&lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt; rect
      = form.ClientRectangle;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;pictureBox.Image
      = &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: teal"&gt;Bitmap&lt;/span&gt;(rect.Width,
      rect.Height, frmGraphics);&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;frmGraphics.Dispose();&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      copy the screen contents, from the form's client area to the hidden bitmap&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: teal"&gt;Graphics&lt;/span&gt; picGraphics
      = &lt;span style="COLOR: teal"&gt;Graphics&lt;/span&gt;.FromImage(pictureBox.Image);&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;picGraphics.CopyFromScreen(form.PointToScreen(&lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: teal"&gt;Point&lt;/span&gt;(rect.Left,
      rect.Top)), &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: teal"&gt;Point&lt;/span&gt;(0,
      0), &lt;span style="COLOR: blue"&gt;new&lt;/span&gt; &lt;span style="COLOR: teal"&gt;Size&lt;/span&gt;(rect.Width,
      rect.Height));&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;picGraphics.Dispose();&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&amp;nbsp;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      Display the bitmap in the picture box, and show the picture box in front of all other
      controls&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;form.Controls.Add(pictureBox);&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pictureBox.BringToFront();&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/span&gt;
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      unfreeze the form&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      Note: calls to Freeze and Unfreeze must be balanced, unless force=true 
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;void&lt;/span&gt; Unfreeze(&lt;span style="COLOR: blue"&gt;bool&lt;/span&gt; force)&lt;br&gt;
      &amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      exit if nothing to unfreeze&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (
      FreezeCount == 0 )&amp;nbsp;&lt;br&gt;
      &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt; ;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      remember we've unfrozen the form, but exit if it is still frozen&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;FreezeCount
      -= 1;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      force the unfreeze if so required&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (force)&amp;nbsp;&lt;br&gt;
      &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FreezeCount = 0;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;if&lt;/span&gt; (FreezeCount
      &amp;gt; 0)&amp;nbsp;&lt;br&gt;
      &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR: blue"&gt;return&lt;/span&gt;; 
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      remove the picture box control and clean up&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pictureBox.Controls.Remove(pictureBox);&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pictureBox.Dispose();&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;pictureBox
      = &lt;span style="COLOR: blue"&gt;null&lt;/span&gt;;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: green"&gt;//
      return true if the form is currently frozen 
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;&lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;public&lt;/span&gt; &lt;span style="COLOR: blue"&gt;bool&lt;/span&gt; IsFrozen&lt;br&gt;
      &amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;get &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt; &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="COLOR: blue"&gt;return&lt;/span&gt; (FreezeCount
      &amp;gt; 0);&amp;nbsp;&lt;/span&gt;&lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;} 
      &lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: blue"&gt;void&lt;/span&gt; &lt;span style="COLOR: teal"&gt;IDisposable&lt;/span&gt;.Dispose()&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=FR style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: FR"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;{&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="COLOR: blue"&gt;this&lt;/span&gt;.Unfreeze(&lt;span style="COLOR: blue"&gt;true&lt;/span&gt;);&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span lang=EN-US style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-ansi-language: EN-US"&gt;&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;
      &lt;/span&gt;
   &lt;/p&gt;
   &lt;p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none"&gt;
      &lt;span style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;/span&gt;
   &lt;/p&gt;
   &lt;/span&gt;
&lt;/div&gt;
&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&lt;font color=#003300&gt;Using the FormFreezer class is quite simple.
   Here's a code sample, which assumes that it is located inside a form class so that
   the Me keyword points to the current form:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color=#0000ff&gt;Dim&lt;/font&gt; ff &lt;font color=#0000ff&gt;As&lt;/font&gt; &lt;font color=#0000ff&gt;New&lt;/font&gt; FormFreezer(&lt;font color=#0000ff&gt;Me&lt;/font&gt;, &lt;font color=#0000ff&gt;True&lt;/font&gt;)&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;' update controls here&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' ...&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &lt;/font&gt;ff.Unfreeze()&lt;/font&gt;
&lt;/p&gt;
&lt;font color=#0000ff&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&lt;font color=#003300&gt;The class implements IDisposable, thus you
   can bracket the update code in a Using block, either in C# or in VB2005, and avoid
   an explicit call to Unfreeze:&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;font color=#003300&gt; 
&lt;p&gt;
   &lt;font color=#0000ff&gt;&amp;nbsp;&amp;nbsp; Using&lt;/font&gt; &lt;font color=#0000ff&gt;New&lt;/font&gt; FormFreezer(&lt;font color=#0000ff&gt;Me&lt;/font&gt;, &lt;font color=#0000ff&gt;True&lt;/font&gt;)&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;font color=#008000&gt;' Update controls here&lt;br&gt;
   &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#008000&gt;' ...&lt;br&gt;
   &amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color=#0000ff&gt;End&lt;/font&gt; &lt;font color=#0000ff&gt;Using
&lt;/p&gt;
&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;
   &lt;font color=#003300&gt;Notice that calls to Freeze and Unfreeze must be balanced. If
   you call Freeze twice you then need two calls to Unfreeze to actually restore the
   updated form. This behavior allows you to call Freeze and then invoke a method that
   calls Freeze again and still have the code work correctly (provided that all methods
   use the same instance of the FormFreeze class).&lt;/font&gt;
&lt;/p&gt;
&gt;&lt;img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=6336502b-57c5-430d-9d37-7f9be484f6b3" /&gt;</content>
  </entry>
  <entry>
    <title>Avoiding API calls in Windows Forms controls</title>
    <link rel="alternate" type="text/html" href="http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,78ac96c7-477a-42d9-bc64-8c38dddbdbe1.aspx" />
    <id>http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,78ac96c7-477a-42d9-bc64-8c38dddbdbe1.aspx</id>
    <published>2006-05-01T01:48:39.4350000-07:00</published>
    <updated>2006-05-03T04:17:47.2791250-07:00</updated>
    <category term="Code Snippets" label="Code Snippets" scheme="dasBlog" />
    <category term="Migrating from VB6" label="Migrating from VB6" scheme="dasBlog" />
    <category term="Visual Basic" label="Visual Basic" scheme="dasBlog" />
    <category term="Windows Forms" label="Windows Forms" scheme="dasBlog" />
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Many, if not most, Windows Forms samples you can find on the 'net include one or more
      calls to unmanaged code in Windows DLLs, often in the form of calls to the SendMessage
      API methods to fix some of the (very few) missing features of .NET controls. The problem
      is, such a call to unmanaged code creates a problem when the program runs as a ClickOnce
      application, because it requires higher CAS privileges.
   </p>
        <p>
      Even though this problem doesn't have a generic solution, when you just need to send
      a message to the control you are inheriting from, you can avoid an explicit call to
      SendMessage by invoking the protected <strong>DefWndProc </strong>method instead.
      For example, let's say that you are writing an enhanced ComboBox that exposes the
      TopIndex property, which can set or return the index of the first visible item in
      the list area. These two operations can be implemented by sending the control the
      CB_SETTOPINDEX or CB_GETTOPINDEX message, respectively. Here's how you can use
      the DefWndProc method instead of SendMessage:
   </p>
        <font color="#0000ff">
          <p>
      Public
   </p>
        </font>
        <font color="#000000">
        </font>
        <font color="#0000ff">Class</font>
        <font color="#000000"> ComboBoxEx<br />
      </font>
        <font color="#0000ff">Inherits</font>
        <font color="#000000"> System.Windows.Forms.ComboBox</font>
        <p>
          <font color="#0000ff">
            <font color="#000000">   </font>Public</font>
          <font color="#0000ff">Property</font> TopIndex() <font color="#0000ff">As</font><font color="#0000ff">Integer<br /></font><font color="#000000">      </font><font color="#0000ff">Get<br /></font><font color="#000000">         </font><font color="#0000ff">Const</font> CB_GETTOPINDEX <font color="#0000ff">As</font> Int32
      = &amp;H15B<br /><font color="#000000">         </font><font color="#0000ff">Dim</font> m <font color="#0000ff">As</font><font color="#0000ff">New</font> Message()<br /><font color="#000000">         </font>m.HWnd
      = <font color="#0000ff">Me</font>.Handle<br /><font color="#000000">         </font>m.Msg
      = CB_GETTOPINDEX<br /><font color="#000000">         </font><font color="#0000ff">Me</font>.DefWndProc(m)<br /><font color="#000000">         </font><font color="#0000ff">Return</font> m.Result.ToInt32()<br /><font color="#000000">      </font><font color="#0000ff">End</font><font color="#0000ff">Get<br /></font><font color="#000000">      </font><font color="#0000ff">Set</font>(<font color="#0000ff">ByVal</font> value <font color="#0000ff">As</font><font color="#0000ff">Integer</font>)<br /><font color="#000000">         </font><font color="#0000ff">Const</font> CB_SETTOPINDEX <font color="#0000ff">As</font> Int32
      = &amp;H15C<br /><font color="#000000">         </font><font color="#0000ff">Dim</font> m <font color="#0000ff">As</font><font color="#0000ff">New</font> Message()<br /><font color="#000000">         </font>m.HWnd
      = <font color="#0000ff">Me</font>.Handle<br /><font color="#000000">         </font>m.Msg
      = CB_SETTOPINDEX<br /><font color="#000000">         </font>m.WParam
      = <font color="#0000ff">New</font> IntPtr(value)<br /><font color="#000000">         </font><font color="#0000ff">Me</font>.DefWndProc(m)<br /><font color="#000000">      </font><font color="#0000ff">End</font><font color="#0000ff">Set<br /></font><font color="#000000">   </font><font color="#0000ff">End</font><font color="#0000ff">Property</font></p>
        <p>
          <font color="#0000ff">End Class</font>
        </p>
        <font color="#000000">
          <p>
      By the way, such an enhanced ComboBox can be useful when migrating a VB6 app to VB.NET.
      In fact, the VB6 ComboBox and ListBox controls expopse the TopIndex property, whereas
      under .NET only the ListBox control exposes this property. If you have any VB6 code
      that takes advantage of the ComboBox's TopIndex, the simplest approach is replacing
      the standard ComboBox with a ComboBoxEx instance.
   </p>
        </font>
        <img width="0" height="0" src="http://www.dotnet2themax.com/blogs/fbalena/aggbug.ashx?id=78ac96c7-477a-42d9-bc64-8c38dddbdbe1" />
      </div>
    </content>
  </entry>
</feed>