<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://zerosandtheone.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>VB.NET For Everyone!</title><link>http://zerosandtheone.com/blogs/vb/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008 (Build: 30417.1769)</generator><item><title>.NET : Install your app and the .NET framework using INNO Setup</title><link>http://zerosandtheone.com/blogs/vb/archive/2008/06/23/vb-net-install-your-app-and-the-net-framework-using-inno-setup.aspx</link><pubDate>Mon, 23 Jun 2008 19:53:00 GMT</pubDate><guid isPermaLink="false">25aead6d-839f-4a6e-811a-c90be434890b:167</guid><dc:creator>Matthew Kleinwaks</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://zerosandtheone.com/blogs/vb/rsscomments.aspx?PostID=167</wfw:commentRss><comments>http://zerosandtheone.com/blogs/vb/archive/2008/06/23/vb-net-install-your-app-and-the-net-framework-using-inno-setup.aspx#comments</comments><description>&lt;p&gt;Today we are going to look at an alternative to using ClickOnce or
Windows Installer MSI to install an application written in .NET.&lt;/p&gt;
&lt;p&gt;This article is written for installing an application written in Microsoft .NET 2.0 (does not have to be VB specifically) and including the .NET Framework as part of your installation.&amp;nbsp; The concepts here can be applied to do the same for a .NET 1.1 or .NET 3.x installation, however some specific values will change, and some logic will change (like the fact that .NET 3.x will not run on any Windows below XP SP2, and .NET 2.0 does).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Some History&lt;br /&gt;&lt;/b&gt;One of the biggest problems with using an MSI
based installer, or ClickOnce to deploy your .NET application, is the
need to have multiple installation files. At the least, you generally
need 2, a setup.exe bootstrapper to kick things off, and the MSI file
which contains the actual files to install. This can be fine when
dealing with a CD based installation, but how about internet downloads?
Some make use of self extracting zip type files to extract the setup
files and launch the bootstrapper, others simply zip the files up and
expect you to unzip them and run the setup.exe. There are also 3rd
party apps like InstallShield and Wise, however I was looking for a
&amp;quot;free&amp;quot; approach to his.&lt;/p&gt;
&lt;p&gt;Depending on your target audience, you may want to have a nice, easy
to use, single setup.exe that people can download and run without any
extra hoops to jump through. &lt;/p&gt;
&lt;p&gt;INNO Setup is a free open source installer program written and
maintained by Jordan Russell. It has the ability to package everything
into a single setup.exe for easy deployment.&lt;/p&gt;
&lt;p&gt;Here are some links of importance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a target="_blank" title="Jordan Russell Homepage" href="http://www.jrsoftware.org/"&gt;JR Software Homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" title="INNO Setup 5.1.9" href="http://files.jrsoftware.org/ispack/ispack-5.1.9.exe"&gt;INNO Version used in this article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" title="Newest Inno Setup Download" href="http://www.jrsoftware.org/isdl.php#qsp"&gt;Newest INNO Version Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" title=".NET 2.0 Redist Download" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0856EACB-4362-4B0D-8EDD-AAB15C5E04F5&amp;amp;displaylang=en"&gt;.NET 2.0 Redist File Download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a target="_blank" title=".NET 2.0 (SP1) Redist Download" href="http://www.microsoft.com/downloads/details.aspx?familyid=79BC3B77-E02C-4AD3-AACF-A7633F706BA5&amp;amp;displaylang=en"&gt;.NET 2.0 (sp1) Redist File Download&lt;/a&gt; (&lt;i&gt;Note: This is a full version of .NET Framework, you don&amp;#39;t need the above link if you use this one.&lt;/i&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Make sure you always download and install the QuickStart pack
installation of Inno versus just the standard one, as it includes a
preprocessor &lt;br /&gt;(similar to conditional compiler statements in VB with the # sign). More on this later.&lt;/p&gt;
&lt;p&gt;One thing to keep in mind as you start to use INNO Setup, is that it
is NOT a .NET installer. It is a generic installer for installing
anything from a full blown app, to possibly just a directory of
pictures. It is very flexible, albeit with a slight learning curve if
you are used to VB programming. I use VB for 95% of my programming, and
I found INNO&amp;#39;s Pascal Scripting to be pretty easy to pickup, and not
required in all cases of use.&lt;/p&gt;
&lt;p&gt;Inno setup files have .iss (Inno Setup Script) extensions, and they
are nothing more than plain text files. You can write them in notepad
if you wish, however using the INNO program gives you syntax
highlighting (plus it is free, and we need it to compile the script
when we are done).&lt;/p&gt;
&lt;p&gt;This article does not require you have existing knowledge of INNO Setup, however if you do, you will likely understand much of this article a bit better than those who do not. For those of you who are new to INNO Setup, this is not going to teach you everything you will want to know about it, so I suggest you visit the INNO website and look over some of the docs, tutorials, and newsgroups there. That being said, you can take this script and mostly change around values of the fields to fit your own application and have a working installer.&lt;/p&gt;
&lt;p&gt;This article is also not a tutorial on how to use INNO Setup. It is an article on how to use INNO Setup to install the .NET Framework. Yes there is a difference, and that difference is I am not going to go into great detail about what each property and method of the setup does. That would take a book, not a blog posting. &lt;img src="http://zerosandtheone.com/emoticons/emotion-5.gif" alt="Wink" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Time to get down to business&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Ok, so now that we have gotten those facts out of the way, and you
have downloaded and installed either the specific version I used for
this example (5.1.9), or the newest version.&lt;br /&gt;&lt;i&gt;(Important note as of this article, the newest version of INNO 5.2.3 works fine with this script)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;So we are going to go through the entire setup file, section by section, and talk about what is going on.&lt;/p&gt;
&lt;ol&gt;&lt;/ol&gt;
&lt;p&gt;So open up INNO setup, and select &amp;quot;Create a new empty script file&amp;quot;,
or just click cancel on the welcome dialog. You will be at the script
editor window, which looks similar to a standard text editor like
notepad.&lt;/p&gt;
&lt;p&gt;Lets add some comments to the top of the script:&lt;/p&gt;
&lt;p&gt;
&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;;Example
.NET Setup Script&lt;br /&gt;;written
in Inno Setup 5.1.9 (ISPP 5.1.8.0)&lt;br /&gt;;2008
Matthew Kleinwaks&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;;www.ZerosAndTheOne.com&lt;br /&gt;;change these comments as needed for your own app&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Now we will define some preprocessor variables&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;#define
SourceFileDir &amp;quot;c:\work\myapp&amp;quot;&lt;br /&gt;#define
IncludeFramework true&lt;br /&gt;#define IsExternal &amp;quot;&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;Basically, these preprocessor variables are generated BEFORE the script is compiled. This is useful to do things like set options. Perhaps you want to have a demo version as well as the full version of your product. You could use a preprocessor directive to indicate if its the demo or not, which can allow for boolean logic (if statements) to include one file or another based on if its a demo or not. That is just one example, but you get the idea.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;SourceFileDir &lt;/b&gt;is a directory on my machine where the release version
files of my actual application are. This would be the exe, dll files,
any support files that are part of the application itself, like
pictures, data files, eula, readme, etc.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IncludeFramework &lt;/b&gt;is simply a boolean to indicate if you want the framework packaged and installed. Sometimes it can be convenient to NOT include it.&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IsExternal&lt;/b&gt; is also a directive that we will use to determine if in fact we want to package the app files with the setup.exe, or keep them separate. Obviously for a download we want them all to be part of one setup.exe file, however sometimes for distribution on CD, it is better to package the files loosely instead of all packed into one file. If you do want the files external, you should replace the &amp;quot;&amp;quot; in this line with &amp;quot;external&amp;quot; (including the quotes). More on why it works like that further down in the &lt;b&gt;[files]&lt;/b&gt; section.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;i&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;So now lets write out the sections of the setup file. After that, we will create the code section to do all of our custom .NET installer coding.&lt;/p&gt;
&lt;p&gt;The first section is &lt;b&gt;[Setup]&lt;/b&gt;. It defines many of the properties that make up the installer&amp;#39;s look, feel, and many textual attributes.&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;[setup]&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;;name
of your application&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt; &lt;br /&gt;
AppName&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=MyApp&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;;repeat
name of application. (otherwise you get &lt;br /&gt;
;multiple entries in add/remove programs)&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;AppVerName&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=MyApp&lt;br /&gt;
&lt;span style="color:#339966;"&gt;;app publisher name&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;AppPublisher&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=zerosandtheone.com&lt;br /&gt;
&lt;span style="color:#339966;"&gt;;app publisher website URL&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;AppPublisherURL&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=http://www.zerosandtheone.com&lt;br /&gt;
&lt;span style="color:#339966;"&gt;;app publisher support URL&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;AppSupportURL&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=http://www.zerosandtheone.com/support&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;app
publisher updates URL&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;AppUpdatesURL&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=http://www.zerosandtheone.com&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;default
directory {pf} is a constant for&lt;br /&gt;;program
files. See INNO help for all constants&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;DefaultDirName&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={pf}\zerosandtheone\MyApp&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;default
group name in the programs &lt;br /&gt;; section
of the start menu&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;DefaultGroupName&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=MyApp&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;Boolean
to disable allowing user to customize &lt;br /&gt;;start
menu entry during installation&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;DisableProgramGroupPage&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=yes&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;Boolean
to warn if directory user picks&lt;br /&gt;;already
exists&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;DirExistsWarning&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=no&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;directory
where uninstaller exe will be&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;this will
be where our app is&lt;br /&gt;;the
constant we use is {app}&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;UninstallFilesDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={app}&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;Location
of the license file&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;LicenseFile&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={#SourceFileDir}\eula.rtf&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;file
to show before install (I show sys requirements)&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;InfoBeforeFile&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={#&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;SourceFileDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;}\sysreq.rtf&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;file
to show after install (I show readme)&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;InfoAfterFile&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={#&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;SourceFileDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;}
eadme.txt&lt;span style="color:red;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;Custom
image to show on left side of installer&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;WizardImageFile&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={#&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;SourceFileDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;}installlogo.bmp&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;;Icon
for uninstall in add/remove programs&lt;br /&gt;;I use
whatever my apps icon is&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;UninstallDisplayIcon&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={app}\MyApp.exe&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;Version
number of your installer (not your app)&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;VersionInfoVersion&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=1.0.0.0&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;If
IncludeFramework, append _FW to end of compiled setup&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;;&lt;br /&gt;I do
this to make it easy to compile a version with and&lt;br /&gt;;without
the framework included&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;br /&gt;#if
IncludeFramework&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;&amp;nbsp; OutputBaseFilename&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=setup_FW&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;br /&gt;#else&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;&amp;nbsp; OutputBaseFilename&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;=Setup&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;br /&gt;#endif&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;;Directory
where setup.exe will be compiled to&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;OutputDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;={#&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;SourceFileDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;}\setup&lt;span style="color:red;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So there you have it. The comments should explain what is going on for you. Some of these fields are optional and can be removed if not needed. Likewise there are some others that I do not use. See the INNO help file for a full list of what is available to the &lt;b&gt;[setup]&lt;/b&gt; section.&lt;/p&gt;
&lt;p&gt;The next section is the &lt;b&gt;[files]&lt;/b&gt; section. This section defines what files should be compiled into the setup.exe file. Our example will simply consist of an exe, a readme.txt and the .NET framework redistributable file.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;[files]&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;Source&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {#SourceFileDir}\MyApp.exe; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DestDir&lt;/span&gt;:
{app};&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;Flags&lt;/span&gt;:
ignoreversion {#IsExternal}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;source&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {#&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;SourceFileDir&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;}readme.txt; &amp;nbsp;&amp;nbsp; &lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;nbsp; DestDir&lt;/span&gt;:
{app};&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;Flags&lt;/span&gt;:
ignoreversion &lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;{#IsExternal}&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;br /&gt;#if
IncludeFramework&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;&lt;br /&gt;&amp;nbsp; Source&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {#SourceFileDir}\dotnetfx.exe;&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;DestDir&lt;/span&gt;:
{tmp};&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;Flags&lt;/span&gt;:
ignoreversion &lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;{#IsExternal}&lt;/span&gt;
&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;; &lt;span style="color:#3366ff;"&gt;Check&lt;/span&gt;: NeedsFramework&lt;/span&gt;
&lt;br /&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;#endif&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;So what we have here are 3 lines indicating our source files, where they will go on the target machine, and any flags we need to associate. Again see INNO help for all possible flags and properties here. (I will mention to refer to INNO Help a lot because it is too robust to cover every aspect in one article, however you will end up with a fully working script by the end of this one). Notice that while we install myapp.exe and readme.txt to the {app} directory, we unpack the dotnetfx.exe (framework redist file) to a temp directory. The constant {app} actually translates at install time to whatever directory the user selects for installation. While we always like to assume they will install to c:\program files\ that will never be the case 100% of the time. IgnoreVersion just means we are going to copy the file no matter what, you can put restrictions here to only copy the file if its a newer version, etc. Also notice our {#IsExternal} directive here. I mentioned earlier that its value should be either &amp;quot;&amp;quot; or &amp;quot;external&amp;quot;. That is because these preprocessor directives are compiled into literal strings for use when the setup is compiled. What that means is, when the value of #IsExternal is &amp;quot;&amp;quot; the line looks like this once compiled:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp; &lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;Source&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {#SourceFileDir}\MyApp.exe; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DestDir&lt;/span&gt;:
{app};&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;Flags&lt;/span&gt;:
ignoreversion &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;however if the value is &amp;quot;external&amp;quot; then the line compiles like this:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp; &lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:blue;"&gt;Source&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {#SourceFileDir}\MyApp.exe; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;DestDir&lt;/span&gt;:
{app};&lt;span&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;Flags&lt;/span&gt;:
ignoreversion external&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Which adds the external flag to this file. The external flag tells the setup that the file to install is actually not packed into the installer, but a loose file included along with it. This makes preprocessor directives very powerful to customize your installer when used in this way. The &lt;b&gt;Check: NeedsFramework&lt;/b&gt; line for the .NET redist file will call up a custom function to check and see if the machine even needs the .NET framework or not. We will define that function when we get to the code section of the script.&lt;/p&gt;
&lt;p&gt;Now lets specify the shortcuts we want made.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;[icons]&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;Name&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {group}\MyApp;&lt;span style="color:red;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;Filename&lt;/span&gt;:
{app}\MyApp.exe;&lt;span style="color:red;"&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;WorkingDir&lt;/span&gt;: {app}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;Name&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {group}\&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;Remove &lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;MyApp;&lt;span style="color:red;"&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;Filename&lt;/span&gt;: &lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;{uninstallexe};&lt;span style="color:red;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;WorkingDir&lt;/span&gt;: {app}&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;Name&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {userdesktop}\MyApp;&lt;span style="color:red;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;Filename&lt;/span&gt;: &lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;{app}\MyApp.exe&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;span style="color:red;"&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;WorkingDir&lt;/span&gt;: {app}&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;So we are putting a shortcut in the programs section of the start menu, as well as the desktop. We also put an uninstall shortcut in the start menu folder. Everything that is in curly braces { } is a constant that INNO translates at install time into a real string value. Where can you find all these constants? Yup, you guessed it, in the INNO Help file.&lt;/p&gt;
&lt;p&gt;On to the &lt;b&gt;[Run]&lt;/b&gt; section. This section defines what processed should be run as part of the installation. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;[Run]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;#if
IncludeFramework&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;&amp;nbsp; Filename&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;: {tmp}\dotnetfx.exe;&lt;span&gt; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;Parameters&lt;/span&gt;: &amp;quot;/q:a /c:&amp;quot;&amp;quot;install /l
/q&amp;quot;&amp;quot;&amp;quot;;&lt;span&gt; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;WorkingDir&lt;/span&gt;: {tmp};&lt;span&gt; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;Flags&lt;/span&gt;:
skipifdoesntexist; &lt;span style="color:#3366ff;"&gt;StatusMsg&lt;/span&gt;:
&amp;quot;Installing .NET Framework if needed&amp;quot;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:red;"&gt;&lt;br /&gt;#endif&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;Filename&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;:
{win}\Microsoft.NET\Framework\v2.0.50727\CasPol.exe; &lt;span style="color:#3366ff;"&gt;Parameters&lt;/span&gt;:
&amp;quot;-q -machine -remgroup &amp;quot;&amp;quot;MyApp&amp;quot;&amp;quot;&amp;quot;;&lt;span&gt; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;WorkingDir&lt;/span&gt;: {tmp}; &lt;span style="color:#3366ff;"&gt;Flags&lt;/span&gt;:
skipifdoesntexist runhidden; &lt;span style="color:#3366ff;"&gt;StatusMsg&lt;/span&gt;:
&amp;quot;Setting Program Access Permissions...&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;Filename&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;:
{win}\Microsoft.NET\Framework\v2.0.50727\CasPol.exe; &lt;span style="color:#3366ff;"&gt;Parameters&lt;/span&gt;:
&amp;quot;-q -machine -addgroup 1.2 -url &amp;quot;&amp;quot;file://{app}/*&amp;quot;&amp;quot;
FullTrust -name &amp;quot;&amp;quot;MyApp&amp;quot;&amp;quot;&amp;quot;; &lt;span&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;WorkingDir&lt;/span&gt;:
{tmp}; &lt;span style="color:#3366ff;"&gt;Flags&lt;/span&gt;:
skipifdoesntexist runhidden; &lt;span style="color:#3366ff;"&gt;StatusMsg&lt;/span&gt;:
&amp;quot;Setting Program Access Permissions...&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Lets go over each of these 3 lines here. The first one installs the .NET framework. The Parameters we pass along with this file are simply those to make the installation silent (show no UI while installing). You may or may not want this, it is up to you. For full details on the exact meaning of the command line switch used for the framework installation, visit this &lt;a target="_blank" title="MSDN: .NET Framework Redist Command Line Switches"&gt;MSDN Page&lt;/a&gt; on the subject. The StatusMsg field lets you specify a message that INNO displays while this process is running. I left it off for space saving here, but I often also put &amp;quot;this will take several minutes...&amp;quot; because lets face it, installing the .NET framework on an average computer does take a few minutes. The skipifdcoesntexist flag is important because remember that we only extracted the framework to the temp directory if the system didn&amp;#39;t have the framework installed, so if it doesn&amp;#39;t exist, then chances are the user already had the framework (or is out of disk space!).&lt;/p&gt;
&lt;p&gt;The other 2 lines simply run caspol.exe to set permissions using a little &amp;quot;url&amp;quot; trick. If you are not familiar with CasPol, it is the Code Access Security Policy utility. .NET code has an extra layer of code security hooked into the runtime, and by default your local drives run with full trust, and your network drives run with partial trust. Long story short, if your customer installs your program to a network mapped drive, there is a good chance they will start getting weird security exceptions because you did not design your app to run at partial trust (or your app simply NEEDS full trust to do whatever it is your app does). So we have INNO set permissions to give full trust to wherever the user installed the app. If its the local drive, they already had the permissions, and if its a network drive, this will give them the permissions to the installation folder. Its a win/win scenario. You may wonder why there are 2 entries though, and that is because we first try to remove an existing entry if it is there, to avoid duplicate entries in caspol. If there was no entry to begin with, the method simply completes without doing anything.&lt;/p&gt;
&lt;p&gt;The skipifdoesntexist flag just tells INNO that if the file we are working with doesn&amp;#39;t exist for some reason, don&amp;#39;t try to launch it. The only time it won&amp;#39;t exist is in weird scenarios of framework installation failure, etc.&lt;/p&gt;
&lt;p&gt;Like the &lt;b&gt;[run]&lt;/b&gt; section, there is also an &lt;b&gt;[uninstallrun]&lt;/b&gt; section. This section defines what will run when the program is uninstalled. The only thing I put here, is to remove the caspol entry, just like we did in the run section. It is better to do it here, the entry in the run section is just a backup.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;[UninstallRun]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;Filename&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;:
{win}\Microsoft.NET\Framework\v2.0.50727\CasPol.exe; &lt;span style="color:#3366ff;"&gt;Parameters&lt;/span&gt;:
&amp;quot;-q -machine -remgroup &amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;MyApp&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&amp;quot;&amp;quot;&amp;quot;; &lt;span style="color:#3366ff;"&gt;Flags&lt;/span&gt;: skipifdoesntexist runhidden;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So up to this point, we have finished our entire INNO script file, with the exception of the code section. INNO implemented a pascal scripting code section at some point in its life to allow you to extend and customize the installation experience. There is little you can not do, but this flexibility comes at the cost of knowing how to write the code. The Inno Setup IDE is not nearly as advanced as the Visual Studio IDE, so writing code can be a bit difficult at times, however I am going to take you through my standard setup code, and explain what it does.&lt;/p&gt;
&lt;p&gt;The code section starts with, yes you guessed it, a &lt;b&gt;[code]&lt;/b&gt; heading.&lt;/p&gt;
&lt;p&gt;First we are going to define some functions that we will use to aid our setup process.&lt;/p&gt;
&lt;p&gt;I am not going to go over every single line here in detail. The functions are pretty short, and do specifically only what they say. Most of them are just checking the state of the system for a given value, like if the framework exists, if a service pack is installed, etc. Most of them query a registry key, check a file version, or something similar to see what is already on the system.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;[code]&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//
Indicates whether .NET Framework 2.0 is installed.&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; IsDotNET20Detected(): boolean;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;var&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;success: boolean;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;install: cardinal;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;begin&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;success := RegQueryDWordValue(HKLM,
&amp;#39;SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727&amp;#39;, &amp;#39;Install&amp;#39;, install);&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Result := success &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;
(install = 1);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//RETURNS
OPPOSITE OF IsDotNet20Detected FUNCTION&lt;br /&gt;//Remember
this method from the Files section above&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; NeedsFramework(): Boolean;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;Result := (IsDotNET20Detected = false);&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//CHECKS
TO SEE IF CLIENT MACHINE IS WINDOWS 95&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; IsWin95 : boolean;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;Result := (InstallOnThisVersion(&amp;#39;4.0,0&amp;#39;,
&amp;#39;4.1.1998,0&amp;#39;) = irInstall);&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//CHECKS
TO SEE IF CLIENT MACHINE IS WINDOWS NT4&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; IsWinNT : boolean;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;Result := (InstallOnThisVersion(&amp;#39;0,4.0.1381&amp;#39;,
&amp;#39;0,4.0.1381&amp;#39;) = irInstall);&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//GETS
VERSION OF IE INSTALLED ON CLIENT MACHINE&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; GetIEVersion : &lt;span style="color:#3366ff;"&gt;String&lt;/span&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;var&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;IE_VER: &lt;span style="color:#3366ff;"&gt;String&lt;/span&gt;;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span style="color:#339966;"&gt;{First check if Internet
Explorer is installed}&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;&amp;nbsp; if&lt;/span&gt;
RegQueryStringValue(HKLM,&amp;#39;SOFTWARE\Microsoft\Internet
Explorer&amp;#39;,&amp;#39;Version&amp;#39;,IE_VER) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;/span&gt;Result := IE_VER&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#3366ff;"&gt;else&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;{No Internet
Explorer at all}&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result := &amp;#39;&amp;#39;;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//GETS
THE VERSION OF WINDOWS INSTALLER DLL&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; GetMSIVersion(): &lt;span style="color:#3366ff;"&gt;String&lt;/span&gt;;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;/span&gt;GetVersionNumbersString(GetSystemDir+&amp;#39;\msi.dll&amp;#39;, Result);&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//LAUNCH
DEFAULT BROWSER TO WINDOWS UPDATE WEBSITE&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;procedure&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; GoToWindowsUpdate;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;var&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;ErrorCode: Integer;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
(MsgBox(&amp;#39;Would you like to go to the Windows Update site now?&amp;#39; + chr(13) +
chr(13) + &amp;#39;(Requires Internet Connection)&amp;#39;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;, mbConfirmation, MB_YESNO) =
IDYES) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ShellExec(&amp;#39;open&amp;#39;,
&amp;#39;http://windowsupdate.microsoft.com&amp;#39;,&amp;#39;&amp;#39;, &amp;#39;&amp;#39;, SW_SHOW, ewNoWait, ErrorCode);&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Those are all of our helper functions. Now lets define a few functions that are built into INNO setup. When I say built in, I mean these are functions that INNO already knows the name of, and will run at a certain point if you define them.&lt;/p&gt;
&lt;p&gt;There are many, but the ones we are going to use are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;InitializeSetup()&lt;/li&gt;
&lt;li&gt;GetCustomSetupExitCode()&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;InitializeSetup() is the first thing that runs when the installer starts up, so we will add in our custom logic to this routine to make the installer do the checks we want to perform.&lt;/p&gt;
&lt;p&gt;GetCustomSetupExitCode() is something that runs when setup is complete. We use this method to check for the .NET Framework (because at this point it should be installed) and give an error message if we don&amp;#39;t find it. There are any number of reasons why the installation could fail, so all we really do here is check and alert the user if it did fail.&lt;/p&gt;
&lt;p&gt;I will define GetCustomSetupExitCode() first because it is shorter and self explanatory.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;//IF
SETUP FINISHES WITH EXIT CODE OF 0, MEANING ALL WENT WELL&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#339966;"&gt;&lt;br /&gt;//THEN
CHECK FOR THE PRESENCE OF THE REGISTRY FLAG TO INDICATE THE&lt;br /&gt;//.NET
FRAMEWORK WAS INSTALLED CORRECTLY&lt;br /&gt;//IT
CAN FAIL WHEN CUST DOESN&amp;#39;T HAVE CORRECT WINDOWS INSTALLER VERSION&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; &lt;b&gt;GetCustomSetupExitCode&lt;/b&gt;():
Integer;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
(IsDotNET20Detected = false) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;MsgBox(&amp;#39;.NET Framework was NOT installed successfully!&amp;#39;,mbError, MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result := -1&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now on to the InitializeSetup. This routine is pretty long, because it contains all the checks we want to do before allowing the user to install. Returning False from this routine aborts the setup.&lt;/p&gt;
&lt;p&gt;We perform the following checks&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If Windows 2000, require at least SP3&lt;/li&gt;
&lt;li&gt;If WIndows XP, require at least SP2&lt;/li&gt;
&lt;li&gt;If Windows 95 or NT, don&amp;#39;t install at all&lt;/li&gt;
&lt;li&gt;If NT based (2000, XP, 2003, Vista), require MSI Installer 3 or higher&lt;/li&gt;
&lt;li&gt;If 9x based (98, ME), require MSI Installer 2 or higher&lt;/li&gt;
&lt;li&gt;If IE version is less than version 5.01, don&amp;#39;t install&lt;/li&gt;
&lt;li&gt;If admin is not logged on, don&amp;#39;t install (.NET Framework install requires admin rights)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So lets get to the code shall we:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;function&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt; &lt;b&gt;InitializeSetup&lt;/b&gt;:
Boolean;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;var&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;Version: TWindowsVersion;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;IE_VER: &lt;span style="color:#3366ff;"&gt;String&lt;/span&gt;;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;MSI_VER: &lt;span style="color:#3366ff;"&gt;String&lt;/span&gt;;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;NL: Char;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;NL2: &lt;span style="color:#3366ff;"&gt;String&lt;/span&gt;;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;begin&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;NL := Chr(13);&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;NL2 := NL + NL;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;// Get Version of
Windows from API Call&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;GetWindowsVersionEx(Version); &lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;// On Windows
2000, check for SP3&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
Version.NTPlatform &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(Version.Major = 5) &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(Version.Minor = 0) &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(Version.ServicePackMajor &amp;lt; 3) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;SuppressibleMsgBox(&amp;#39;When running on Windows
2000, Service Pack 3 is required.&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;Visit&amp;#39; + NL2 +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39; ***
http://windowsupdate.microsoft.com ***&amp;#39; + NL2 +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;to get the needed Windows
Updates,&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;and then reinstall this
program&amp;#39;,&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mbCriticalError, MB_OK,
MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;GoToWindowsUpdate;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Result := False;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Exit;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;// On Windows XP,
check for SP2&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
Version.NTPlatform &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(Version.Major = 5) &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(Version.Minor = 1) &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(Version.ServicePackMajor &amp;lt; 2) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;SuppressibleMsgBox(&amp;#39;When running on Windows
XP, Service Pack 2 is required.&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;Visit&amp;#39; + NL2 + &amp;#39; ***
http://windowsupdate.microsoft.com ***&amp;#39; + NL2 +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;to get the needed
Windows Updates,&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;and then reinstall this
program&amp;#39;,&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mbCriticalError, MB_OK,
MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;GoToWindowsUpdate;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Result := False;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Exit;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;//IF WINDOWS 95
OR NT DON&amp;#39;T INSTALL&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
(IsWin95) &lt;span style="color:#3366ff;"&gt;or&lt;/span&gt; (IsWinNT) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;SuppressibleMsgBox(&amp;#39;This program can not
run on Windows 95 or Windows NT.&amp;#39;,&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mbCriticalError, MB_OK, MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Result := False;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Exit;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;//CHECK MSI VER,
NEEDS TO BE 3.0 ON ALL SUPPORTED SYSTEM EXCEPT 95/ME, WHICH NEEDS 2.0)&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;MSI_VER := GetMSIVersion&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
((Version.NTPlatform) &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt; (MSI_VER &amp;lt;
&amp;#39;3&amp;#39;)) &lt;span style="color:#3366ff;"&gt;or&lt;/span&gt; ((&lt;span style="color:#3366ff;"&gt;Not&lt;/span&gt;
Version.NTPlatform) &lt;span style="color:#3366ff;"&gt;and&lt;/span&gt; (MSI_VER &amp;lt; &amp;#39;2&amp;#39;)) &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;begin&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;SuppressibleMsgBox(&amp;#39;You do not have all
the required Windows Updates to install this program.&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;Visit ***
http://windowsupdate.microsoft.com *** to get the needed Windows Updates,&amp;#39; + NL
+&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;and then reinstall
this program&amp;#39;,&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mbCriticalError,
MB_OK, MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;GoToWindowsUpdate;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Result := False;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Exit;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;//CHECK THE IE
VERSION (NEEDS TO BE 5.01+)&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;IE_VER := GetIEVersion;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt; IE_VER
&amp;lt; &amp;#39;5.01&amp;#39; &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
IE_VER = &amp;#39;&amp;#39; &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;MsgBox(&amp;#39;Microsoft Internet Explorer
5.01 or higher is required to run this program.&amp;#39; + NL2 +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;You do not currently have
Microsoft Internet Explorer installed, or it is not working correctly.&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;Obtain a newer version at
www.microsoft.com and then run setup again.&amp;#39;, mbInformation, MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;else&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;MsgBox(&amp;#39;Microsoft Internet Explorer
5.01 or higher is required to run this program.&amp;#39; + NL2 +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;You are using version &amp;#39; +
IE_VER + &amp;#39;.&amp;#39; + NL2 +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;Obtain a newer version at
www.microsoft.com and then run setup again.&amp;#39;, mbInformation, MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;GoToWindowsUpdate;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result := false;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;exit;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#339966;"&gt;//MAKE SURE USER
HAS ADMIN RIGHTS BEFORE INSTALLING&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;if&lt;/span&gt;
IsAdminLoggedOn &lt;span style="color:#3366ff;"&gt;then&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result := true&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;exit;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;else&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;begin&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;MsgBox(&amp;#39;You must have admin rights to
perform this installation.&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;Please log on with an account
that has administrative rights,&amp;#39; + NL +&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;#39;and run this installation again.&amp;#39;,
mbInformation, MB_OK);&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result := false;&lt;span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:#3366ff;"&gt;end&lt;/span&gt;;&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;color:#3366ff;"&gt;&lt;br /&gt;end&lt;/span&gt;&lt;span style="font-family:&amp;#39;Courier New&amp;#39;;"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;So there you have it. The completed code section of the script. You now have a fully functional INNO setup script that will package the .NET 2.0 framework with your program into a single setup.exe, extract it at install time if needed, and install it silently. The script also checks to make sure the user has admin rights, has the needed service pack levels for certain operating systems, has the needed versions of things like MSI installer and Internet Explorer. There may be other checks you want to do (or even some you want to omit) so I hope my script is a good jumping off point for you to get into customizing your own. My code also offers in several failure spots due to system requirements to launch the windows update page so users can get the updates they need. You would be surprised how many people are not even running SP2 on Windows XP even though it has been out a long time now and we are already up to SP3.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Next time, I plan to show you how to associate a file type with your program at install time. For example, maybe your app is a text editor, and you want to associate *.txt files with your program when it is installed. There are a few registry keys involved, and we will go over them in detail. I will also show you how to install a font file, as well as adding some custom functionality to the UI of the installer, to perform even more custom actions. Then I will go into detail about detecting if the user has the .NET Framework installed from an ASP, PHP, or ASP.NET Page and Internet Explorer (Sorry FireFox users, it doesn&amp;#39;t work for you). This can be useful when you want to offer your user a download with or without the framework (to save the 20+MB) based on if they need it or not.&lt;/p&gt;
&lt;p&gt;You can download the complete script file as it appears in this article from the &lt;a title=".NET INNO Example File" href="http://zerosandtheone.com/media/p/180.aspx"&gt;media download page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://zerosandtheone.com/aggbug.aspx?PostID=167" width="1" height="1"&gt;</description><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/VB.NET/default.aspx">VB.NET</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/Installer/default.aspx">Installer</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/INNO/default.aspx">INNO</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/Setup/default.aspx">Setup</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/.NET/default.aspx">.NET</category></item><item><title>MSDN: Contest for free MSDN Subscription for 1 year.</title><link>http://zerosandtheone.com/blogs/vb/archive/2008/06/13/msdn-contest-for-free-msdn-subscription-for-1-year.aspx</link><pubDate>Fri, 13 Jun 2008 13:53:00 GMT</pubDate><guid isPermaLink="false">25aead6d-839f-4a6e-811a-c90be434890b:75</guid><dc:creator>Matthew Kleinwaks</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://zerosandtheone.com/blogs/vb/rsscomments.aspx?PostID=75</wfw:commentRss><comments>http://zerosandtheone.com/blogs/vb/archive/2008/06/13/msdn-contest-for-free-msdn-subscription-for-1-year.aspx#comments</comments><description>&lt;p&gt;So Microsoft sent me a little envelope the other day, and inside were 3 cards, each for a &lt;b&gt;1 year MSDN Visual Studio Team System 2008 Team Suite Premium Subscription.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Wow that is a mouthful huh?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So I already have this same subscription, and these cards were not
intended for me to use, they were intended for me to GIVE OUT to the
community so developers who are not MVPs can get access to this
tremendous library of software and knowledge that can help you along
your development journey. Sure, I bet Microsoft is also hoping a few
people RENEW these subscriptions after the 1 year is over, but it is
still a VERY generous gesture none the less. I don&amp;#39;t know if you have
looked at the price tag for these subscriptions, but they are not cheap
(around $11,000 USD).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So one already went to a friend and fellow developer who is not an
MVP, however most of my dealings with the community are online, so I
want to extend this offer online.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;I will be awarding 1 MSDN subscription&lt;/b&gt; to anyone who submits an essay titled &amp;quot;What I will do with an MSDN subscription, and why I should have one&amp;quot;&lt;br /&gt;(and you thought your essay writing days ended when school did!)&lt;/p&gt;
&lt;p&gt;I will review all essays and I will pick 1 winner based on what I personally liked the best.&lt;/p&gt;
&lt;p&gt;I had thought about a coding contest, however it is too easy for
people to pull code off the net and pass it off as their own,
unfortunately.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration:underline;"&gt;&lt;b&gt;Rules for Essay:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is no minimum or maximum length. Just keep in mind your 2
sentence essay will likely not do so well against someone else&amp;#39;s 1 page
essay. Likewise your 20 page &amp;quot;chapter&amp;quot; will probably bore me.&lt;/li&gt;
&lt;li&gt;English only&lt;/li&gt;
&lt;li&gt;Submission deadline is &lt;b&gt;7-31-2008 &lt;/b&gt;(anything in my mailbox on 8-1 won&amp;#39;t be read)&lt;/li&gt;
&lt;li&gt;Email your essay to &lt;b&gt;matt&lt;img src="http://zerosandtheone.com/cfs-file.ashx/__key/CommunityServer.Components.UserFiles/00.00.00.21.00/at.jpg" height="24" width="26" alt="" /&gt;zerosandtheone.com &lt;/b&gt;(I will respond to everyone to confirm receipt of their essay)&lt;/li&gt;
&lt;li&gt;Include your name in the essay&lt;/li&gt;
&lt;li&gt;By submitting an essay, you are giving me the right to use them on
the site if I wish. The winning essay will most likely be displayed on
this site, so keep that in mind. The others will most likely not be.&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Check back to this posting or the home page for the latest updates
on this contest. I will post the number of submissions I have gotten,
as well as my opinion on the submissions so far. Good luck and I look
forward to reading your essays.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://zerosandtheone.com/aggbug.aspx?PostID=75" width="1" height="1"&gt;</description><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/Contest/default.aspx">Contest</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/MSDN/default.aspx">MSDN</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>VB.NET : Extended Combobox to better visually handle being disabled</title><link>http://zerosandtheone.com/blogs/vb/archive/2008/05/12/vb-net-extended-combobox-to-better-handle-being-disabled.aspx</link><pubDate>Mon, 12 May 2008 21:51:00 GMT</pubDate><guid isPermaLink="false">25aead6d-839f-4a6e-811a-c90be434890b:21</guid><dc:creator>Matthew Kleinwaks</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://zerosandtheone.com/blogs/vb/rsscomments.aspx?PostID=21</wfw:commentRss><comments>http://zerosandtheone.com/blogs/vb/archive/2008/05/12/vb-net-extended-combobox-to-better-handle-being-disabled.aspx#comments</comments><description>&lt;p&gt;If you do any WinForms programming then chances are you have used comboboxes, and perhaps at one point or another, you disabled one of those comboboxes because you did not want the user to be able to make a selection. This works fine, however I actually was getting some complaints from users of some of my software apps saying it was too hard to read the disabled text in a combo. Sometimes just because a feature is disabled, does not mean that the data being displayed in it is of no importance.&lt;/p&gt;
&lt;p&gt;So today lets see how we can change this standard functionality to make things a bit easier on our end users. &lt;br /&gt;We will use Visual Basic .NET to extended the standard WinForms .NET combobox control.&lt;/p&gt;
&lt;p&gt;Lets start by taking a look at the demo. Here we see 2 disabled comboboxes. The top one is a standard WinForm combobox, which has a gray on gray appearance, and can be pretty hard to read. This demo uses larger fonts, so at a smaller font size, it becomes even more difficult. The second one is the extended ComboBox, and you can see that the ForeColor has stayed black, and the BackColor is gray indicating it is disabled. Much easier to read. So lets see what the code looks like to accomplish this.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://zerosandtheone.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vb.images/comboboxex1.jpg" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Like all the extended controls you can make from the standard WinForm controls, we need to inherit from the control we want to extend, in this case Combobox.&lt;/p&gt;
&lt;p&gt;The real trick here is that we are never going to actually make the control disabled. We are simply going to keep track of if it SHOULD be disabled, and stop certain actions from happening in that case. Those actions would be the ability to drop down the combo to make a selection, or to type in the textbox portion of the combo. Take those away, and the combobox is essentially disabled. The other thing we need to take into account, is the default context menu, which gives the user access to features like paste.&lt;/p&gt;
&lt;p&gt;In order to do this, we setup a few private fields to keep track of the disabled/enabled state manually.&lt;/p&gt;
&lt;p&gt;Here is the start of our class&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;&amp;#39; 2008 - ZerosAndTheOne.com&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;&amp;#39; Matthew Kleinwaks&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;&amp;#39;Extended Combobox Control for better &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:green;"&gt;&amp;#39;handling of disabled appearance&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;Option&lt;/span&gt; &lt;span style="color:blue;"&gt;Strict&lt;/span&gt; &lt;span style="color:blue;"&gt;On&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;Option&lt;/span&gt; &lt;span style="color:blue;"&gt;Explicit&lt;/span&gt; &lt;span style="color:blue;"&gt;On&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;Imports&lt;/span&gt; System.Windows.Forms&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;Public&lt;/span&gt; &lt;span style="color:blue;"&gt;Class&lt;/span&gt; ComboboxEx&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Inherits&lt;/span&gt; ComboBox&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#Region&lt;/span&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;Private Backing Fields&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; Private backing field for the shadowed enabled property&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Private&lt;/span&gt; _Enabled &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:blue;"&gt;Boolean&lt;/span&gt; = &lt;span style="color:blue;"&gt;True&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; BackColor of control when it is enabled&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Private&lt;/span&gt; _enabledBackcolor &lt;span style="color:blue;"&gt;As&lt;/span&gt; Color = &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.BackColor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; BackColor of a control when it is disabled&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Private&lt;/span&gt; _disabledBackColor &lt;span style="color:blue;"&gt;As&lt;/span&gt; Color = Color.LightGray&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#End&lt;/span&gt; &lt;span style="color:blue;"&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Note it is just 3 private fields we will use. One to keep track of the enabled state, and 2 to keep track of the BackColor, depending on the enabled state. The reason we use these 2 BackColor fields, is because we set the controls underlying BackColor property to one of these when the enabled state changes, so we need to keep track of what each color should be when enabled does change.&lt;/p&gt;
&lt;p&gt;Next lets define our public fields that will be exposed to the consumer of this control.&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#Region&lt;/span&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;Public Exposed Fields&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; Gets or Sets the value indicating if this control is enabled&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;value&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;Boolean&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;True of control is enabled, otherwise false&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;This property shadows the ComboBox base class enabled property&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Public&lt;/span&gt; &lt;span style="color:blue;"&gt;Shadows&lt;/span&gt; &lt;span style="color:blue;"&gt;Property&lt;/span&gt; Enabled() &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:blue;"&gt;Boolean&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&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; _Enabled&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Set&lt;/span&gt;(&lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; Value &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:blue;"&gt;Boolean&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; _Enabled &amp;lt;&amp;gt; Value &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _Enabled = Value&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; OnEnabledChanged(&lt;span style="color:blue;"&gt;New&lt;/span&gt; EventArgs)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Set&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Property&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; Gets or Sets the BackColor of the control when it is disabled&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;value&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;Color Structure&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Public&lt;/span&gt; &lt;span style="color:blue;"&gt;Property&lt;/span&gt; DisabledBackColor() &lt;span style="color:blue;"&gt;As&lt;/span&gt; Color&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&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; _disabledBackColor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Set&lt;/span&gt;(&lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; value &lt;span style="color:blue;"&gt;As&lt;/span&gt; Color)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _disabledBackColor = value&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; &lt;span style="color:blue;"&gt;Not&lt;/span&gt; _Enabled &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.BackColor = _disabledBackColor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Set&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Property&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; Gets or Sets the BackColor of the control when it is enabled&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;value&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;Color Structure&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;Shadows the base class BackColor property&lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Public&lt;/span&gt; &lt;span style="color:blue;"&gt;Shadows&lt;/span&gt; &lt;span style="color:blue;"&gt;Property&lt;/span&gt; BackColor() &lt;span style="color:blue;"&gt;As&lt;/span&gt; Color&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&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; _enabledBackcolor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Get&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Set&lt;/span&gt;(&lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; value &lt;span style="color:blue;"&gt;As&lt;/span&gt; Color)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; _enabledBackcolor &amp;lt;&amp;gt; value &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _enabledBackcolor = value&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.BackColor = _enabledBackcolor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Set&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Property&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#End&lt;/span&gt; &lt;span style="color:blue;"&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;So just like we have 3 backing fields, we have 3 public properties. The biggest thing to note is that 2 of these properties (BackColor and Enabled) are declared shadows. This means they hide and replace the functionality that the base Combobox class provided for these given properties. It is now totally up to us to handle these properties in our new class.&lt;/p&gt;
&lt;p&gt;To do the magic here, we will override a few protected methods from the combobox base class, and add our custom functionality.&lt;/p&gt;
&lt;p&gt;Lets start with OnEnabledChanged. This is the method that is called when Enabled is changed. In the Enabled public property we defined above, we call this method.&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; When the shadowed enabled property changes, this method is called&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&amp;#39;&amp;#39; &lt;/span&gt;&lt;span style="color:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Protected&lt;/span&gt; &lt;span style="color:blue;"&gt;Overrides&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; OnEnabledChanged(&lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; e &lt;span style="color:blue;"&gt;As&lt;/span&gt; System.EventArgs)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;COMMON ROUTINE FOR TOGGLING ENABLED STATUS&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ToggleEnabled()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;SEND NOTIFICATION TO BASE CLASS&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.OnEnabledChanged(e)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Pretty simple (we will define the ToggleEnabled method after we define all our overrides).&lt;/p&gt;
&lt;p&gt;Next is the PreProcessMessage override. We use this to look at key presses and decide if we want to throw them out, or let them pass to the control to do whatever the given keypress might do. Basically in this example, if the control is enabled, we don&amp;#39;t do anything at all, so that is the first thing we check. Next we allow through key presses like Tab, Left, and Right. You could customize what you allow based on the needs of your program.&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;OVERRIDE PreProcessMessage TO LOOK FOR KEY PRESSES AND FILTER THEM&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Public&lt;/span&gt; &lt;span style="color:blue;"&gt;Overrides&lt;/span&gt; &lt;span style="color:blue;"&gt;Function&lt;/span&gt; PreProcessMessage(&lt;span style="color:blue;"&gt;ByRef&lt;/span&gt; msg &lt;span style="color:blue;"&gt;As&lt;/span&gt; Message) &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:blue;"&gt;Boolean&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;PREVENT KEYBOARD ENTRY IF CONTROL IS DISABLED&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; &lt;span style="color:blue;"&gt;Not&lt;/span&gt; _Enabled &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;CHECK IF ITS A KEYDOWN MESSAGE (&amp;amp;H100)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; msg.Msg = &amp;amp;H100 &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;GET THE KEY THAT WAS PRESSED&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Dim&lt;/span&gt; key &lt;span style="color:blue;"&gt;As&lt;/span&gt; Int32 = msg.WParam.ToInt32&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;ALLOW TAB, LEFT, OR RIGHT KEYS&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; key &amp;lt;&amp;gt; Keys.Tab &lt;span style="color:blue;"&gt;OrElse&lt;/span&gt; _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; key &amp;lt;&amp;gt; Keys.Left &lt;span style="color:blue;"&gt;OrElse&lt;/span&gt; _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; key &amp;lt;&amp;gt; Keys.Right &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Return&lt;/span&gt; &lt;span style="color:blue;"&gt;True&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;CALL BASE METHOD SO DELEGATES RECEIVE EVENT&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Return&lt;/span&gt; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.PreProcessMessage(msg)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Function&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Next we override the WndProc method. In here we are looking for 2 possible messages, which have to deal with the drop down of the list in the combobox. We don&amp;#39;t want that to happen when the control is disabled, so we filter out those specific messages, and allow all other messages to go through as normal.&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;OVERRIDE WndProc TO LOOK FOR DROP DOWN MESSAGES AND FILTER THEM&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Protected&lt;/span&gt; &lt;span style="color:blue;"&gt;Overrides&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; WndProc(&lt;span style="color:blue;"&gt;ByRef&lt;/span&gt; m &lt;span style="color:blue;"&gt;As&lt;/span&gt; Message)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;PREVENT DROPDOWN LIST DISPLAYING IF READONLY&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; &lt;span style="color:blue;"&gt;Not&lt;/span&gt; _Enabled &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; m.Msg = &amp;amp;H201 &lt;span style="color:blue;"&gt;OrElse&lt;/span&gt; m.Msg = &amp;amp;H203 &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Return&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;CALL BASE METHOD SO DELEGATES RECEIVE EVENT&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.WndProc(m)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
Finally, the last override we need to do, is the OnParentEnabledChanged method. This is because if the control is in a container, like a groupbox or panel, and you set the container&amp;#39;s enabled property to false, you would expect the combobox to also have it&amp;#39;s enabled property set to false. However, the parent control does not simply loop its child controls and set their enabled properties. It actually calls the OnParentEnabledChanged for each child, and lets the child handle what it want&amp;#39;s to do in that case. If the control is enabled, we pass through the message like normal. If it is disabled, then we call the ToggleEnabled routine, which is our last routine to define.&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;WHEN THE CONTROL IS IN A CONTAINER, AND THE CONTAINER&amp;#39;S ENABLED PROPERTY&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;IS SET TO FALSE, THIS CONTROL GETS ITS OnParentEnabledChanged CALLED&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;NOT JUST THE CONTROLS ENABLED PROPERTY SET SO WE OVERRIDE THIS, AND &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;TOGGLE ENABLED STATE ACCORDINGLY&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Protected&lt;/span&gt; &lt;span style="color:blue;"&gt;Overrides&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; OnParentEnabledChanged(&lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; e &lt;span style="color:blue;"&gt;As&lt;/span&gt; System.EventArgs)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; _Enabled = &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.Parent.Enabled&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; _Enabled &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.OnParentEnabledChanged(e)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; ToggleEnabled()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;So it is time to define our ToggleEnabled routine. It is actually pretty simple. We set tabstop to false if the control is disabled, and true if it is enabled, so users won&amp;#39;t set focus to it with the tab key. We also set the ContextMenuStrip equal to a New ContextMenuStrip. This actually causes NO menu to appear when the control is right clicked, since the NEW context menu we make has no menu items on it. Setting this property to nothing will bring back the standard cut/copy/paste context menu. Keep this all in mind if you happen to use a custom context menu on this control. We also set the BackColor property to our desired colors were, and also set the SelectionLength to 0. This just deselects any selected text, and is really optional and up to you.&lt;/p&gt;
&lt;p&gt;

&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#Region&lt;/span&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;Support Methods&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;COMMON ROUTINE FOR TOGGLING ENABLED STATE&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Private&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; ToggleEnabled()&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;IF THE CONTROL IS DISABLED, TURN OFF ITS TABSTOP&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.TabStop = _Enabled&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;IF THE CONTROL IS DISABLED, SET ITS CONTEXT MENU TO&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;A DUMMY NEW CONTEXT MENU SO WE DON&amp;#39;T GET THE&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;DEFAULT CONTEXT MENU, OTHERWISE SETTING IT TO&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;NOTHING REAPPLIES THE DEFAULT CONTEXT MENU&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;ALSO SET BACK COLOR ACCORDINGLY&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; &lt;span style="color:blue;"&gt;Not&lt;/span&gt; _Enabled &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.ContextMenuStrip = &lt;span style="color:blue;"&gt;New&lt;/span&gt; ContextMenuStrip&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.BackColor = _disabledBackColor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.ContextMenuStrip = &lt;span style="color:blue;"&gt;Nothing&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.BackColor = _enabledBackcolor&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;DESELECT ANY TEXT FROM COMBOBOX&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Me&lt;/span&gt;.SelectionLength = 0&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#End&lt;/span&gt; &lt;span style="color:blue;"&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p style="margin:0px;"&gt;So that all there is to it. We end up with these results:&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;img src="http://zerosandtheone.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vb.images/comboboxex2.jpg" alt="" /&gt;&lt;img src="http://zerosandtheone.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vb.images/comboboxex3.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;Attached is the source code for this project in Visual Studio 2008 format, targetting .NET 2.0&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;As always, please leave your comments and suggestions.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://zerosandtheone.com/aggbug.aspx?PostID=21" width="1" height="1"&gt;</description><enclosure url="http://zerosandtheone.com/media/p/22.aspx" length="18099" type="text/html; charset=utf-8" /><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/WinForms/default.aspx">WinForms</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/Custom+Controls/default.aspx">Custom Controls</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/VB.NET/default.aspx">VB.NET</category><category domain="http://zerosandtheone.com/blogs/vb/archive/tags/ComboBox/default.aspx">ComboBox</category></item><item><title>VB.NET : Translucent Controls in Windows Forms (Part Deux)</title><link>http://zerosandtheone.com/blogs/vb/archive/2008/05/06/translucent-controls-in-windows-forms-part-deux.aspx</link><pubDate>Tue, 06 May 2008 12:14:00 GMT</pubDate><guid isPermaLink="false">25aead6d-839f-4a6e-811a-c90be434890b:6</guid><dc:creator>Matthew Kleinwaks</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://zerosandtheone.com/blogs/vb/rsscomments.aspx?PostID=6</wfw:commentRss><comments>http://zerosandtheone.com/blogs/vb/archive/2008/05/06/translucent-controls-in-windows-forms-part-deux.aspx#comments</comments><description>&lt;p&gt;So yesterday &lt;a target="_self" href="http://zerosandtheone.com/blogs/vb/archive/2008/05/06/translucent-controls-in-windows-forms.aspx" title="Translucent Controls in Windows Forms"&gt;I talked about making a translucent button in WinForms&lt;/a&gt; using VB.NET. If you have not read that yet, then you should probably do so before digging into part 2, where we expand part 1 to cover more controls.&lt;/p&gt;
&lt;p&gt;Today lets look at making a translucent TabPage control.&lt;/p&gt;
&lt;p&gt;Here is our end result:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://zerosandtheone.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/vb.images/translucent_5F00_button_5F00_demo2.jpg" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;So we have a nice cherry sunburst Gibson Les Paul as our form background, with a TabControl overlaying it, with a few buttons on it.&lt;/p&gt;
&lt;p&gt;So what is different about the implementation of the translucent tab control versus the buttons we did last time? Well for starters, the translucent painting of the background needs to be done on the TabPages which are the individual tab objects that the TabControl contains.&lt;/p&gt;
&lt;p&gt;I am not going to redefine all the code used for this control, as much of it is the same as from the button control. The full source of the project is attached to this post, so you can download that for all the code.&lt;/p&gt;
&lt;p&gt;I will go over the specific differences between the button and the TabControl so you can see what we had to do differently.&lt;/p&gt;
&lt;p&gt;The first thing is, we want to make the control translucent regardless of what tab is currently selected. So we need to track controls being added or removed from the TabControl. TabControls can ONLY have TabPages added to their controls collection, otherwise the framework throws an error. So we wire up the OnControlAdded and OnControlRemoved event handlers to add or remove the given TabPage from being custom drawn as translucent.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#Region&lt;/span&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;OVERRIDES TO HANDLE CHILD TABPAGES&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Protected&lt;/span&gt; &lt;span style="color:blue;"&gt;Overrides&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; OnControlAdded( _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; e &lt;span style="color:blue;"&gt;As&lt;/span&gt; System.Windows.Forms.ControlEventArgs)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;AddHandler&lt;/span&gt; &lt;span style="color:blue;"&gt;DirectCast&lt;/span&gt;(e.Control, TabPage).Paint, &lt;span style="color:blue;"&gt;_&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;AddressOf&lt;/span&gt; DrawFormBackgroundOnTabPage&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.OnControlAdded(e)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Protected&lt;/span&gt; &lt;span style="color:blue;"&gt;Overrides&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; OnControlRemoved( _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; e &lt;span style="color:blue;"&gt;As&lt;/span&gt; System.Windows.Forms.ControlEventArgs)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;RemoveHandler&lt;/span&gt; &lt;span style="color:blue;"&gt;DirectCast&lt;/span&gt;(e.Control, TabPage).Paint, &lt;span style="color:blue;"&gt;_&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;AddressOf&lt;/span&gt; DrawFormBackgroundOnTabPage&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;MyBase&lt;/span&gt;.OnControlRemoved(e)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#End&lt;/span&gt; &lt;span style="color:blue;"&gt;Region&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Note the DrawFormBackgroundOnTabPage method we are wiring up. We will define that next.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div style="background:#f9f9f9 none repeat scroll 0%;font-family:Courier New;font-size:11pt;color:black;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;"&gt;
&lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;#Region&lt;/span&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;CUSTOM PAINTING ROUTINE&amp;quot;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Private&lt;/span&gt; &lt;span style="color:blue;"&gt;Sub&lt;/span&gt; DrawFormBackgroundOnTabPage(&lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; sender &lt;span style="color:blue;"&gt;As&lt;/span&gt; &lt;span style="color:blue;"&gt;Object&lt;/span&gt;, _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;ByVal&lt;/span&gt; e &lt;span style="color:blue;"&gt;As&lt;/span&gt; PaintEventArgs)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;DON&amp;#39;T DO ANY CUSTOM PAINTING IF THE FEATURE IS DISABLED&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; &lt;span style="color:blue;"&gt;Not&lt;/span&gt; _isTranslucent &lt;span style="color:blue;"&gt;Then&lt;/span&gt; &lt;span style="color:blue;"&gt;Return&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Dim&lt;/span&gt; myTab &lt;span style="color:blue;"&gt;As&lt;/span&gt; TabPage = &lt;span style="color:blue;"&gt;DirectCast&lt;/span&gt;(sender, TabPage)&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;GET THE CONTROL THAT THE IMAGE IS ON WE WANT TO USE FOR TRANSLUCENCY&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Dim&lt;/span&gt; parentControl &lt;span style="color:blue;"&gt;As&lt;/span&gt; Control = &lt;span style="color:blue;"&gt;Nothing&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; _backgroundImageSource = _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ITranslucentControl.eBackgroundImageSource.Form &lt;span style="color:blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;GET FORM&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parentControl = &lt;span style="color:blue;"&gt;Me&lt;/span&gt;.FindForm&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;Else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;GET PARENT (WILL BE FORM IF NO CONTAINER EXISTS)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parentControl = &lt;span style="color:blue;"&gt;Me&lt;/span&gt;.Parent&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;End&lt;/span&gt; &lt;span style="color:blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;IF THE PARENT CONTROL WE ARE REFERNCING HAS NO &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:green;"&gt;BACKGROUND IMAGE, DO NOTHING&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;ALSO CHECK TO MAKE SURE STRETCH IS THE LAYOUT TYPE&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; parentControl.BackgroundImage &lt;span style="color:blue;"&gt;Is&lt;/span&gt; &lt;span style="color:blue;"&gt;Nothing&lt;/span&gt; &lt;span style="color:blue;"&gt;Then&lt;/span&gt; &lt;span style="color:blue;"&gt;Return&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;If&lt;/span&gt; parentControl.BackgroundImageLayout &amp;lt;&amp;gt; _&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ImageLayout.Stretch &lt;span style="color:blue;"&gt;Then&lt;/span&gt; &lt;span style="color:blue;"&gt;Return&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;SOURCE RECTANGLE IS THE CLIPPED REGION OF THE &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:green;"&gt;FORMS BACKGROUND IMAGE &lt;/span&gt;&lt;span style="color:green;"&gt;THAT IS BEHIND THE TABPAGE. &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:green;"&gt;CLIPPING ALLOWS US TO THEN PASTE THE COVERED PART&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:green;"&gt;OF THE FORM BACKGROUND IMAGE &lt;/span&gt;&lt;span style="color:green;"&gt;ONTO &lt;/span&gt;&lt;span style="color:green;"&gt;THE LISTVIEW &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:green;"&gt;&amp;#39;BACKGROUND TO MIMIC TRANSPARENCY&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp