Visual Basic Sample Code


About this code

   A number of VB experts have been very generous in making sample code available on the Internet for VB6 and Win32 API functions, but some things are still poorly documented for VB. The samples here are for things that may be hard to find elsewhere.

   No particular claim is made for the quality of this code, and it is not backed up by the "reassurance" of any Microsoft awards, decorations, certifications, or other (possibly dubious) tokens of officiality. You use this code at your own risk.

A Note to .Net programmers:

   If you are using "Visual Basic.Net", or "VB 2003", or "VB 2005", or "VB7", or "VB8", or "VB9", those are all VB.Net. Anything released after VB6 is .Net. VB.Net is not the same thing as VB. VB does not use the .Net runtime and has none of the .Net classes. (When you write "Using..." in VB.Net, that used object does not exist in VB.) The coding is not the same between VB and VB.Net, and even many of the common control properties are not the same. The code samples here are written in VB (VB6). They will likely be of little or no value to you.

Explanation:

   There is a great deal of confusion among .Net developers about what constitutes Visual Basic. That confusion was created deliberately by Microsoft, as part of what might be best characterized as a marketing scam - an attempt to sell VB developers on .Net. Despite the fact that Microsoft has reused the name "Visual Basic" in .Net, there is very little in common between "the two VBs":

VB(including VB5 and 6) - Requires a 1 MB runtime library, which is pre-installed on most Windows systems. Compiles Win32 native executables. COM-centric. Uses VB functions, ActiveX controls and the Win32 API.

VB.Net - Requires a .Net "framework", a "virtual machine" of some 70 MB that sits on top of the Windows API. Produces Java-style, JIT-compiled "assemblies"; incapable of producing a true Windows executable. Not directly COM compatible. Uses mainly VB.Net functions and the .Net framework classes. While .Net has some ability to access the actual Windows libraries (Win32 API), it is designed to work with the ".Net Framework" virtual machine. In classic Microsoft style, the ".Net Framework" is a "cross-platform" virtual machine ... except that it only runs on a very limited subset of Windows PCs.

   In order to push VB developers toward .Net, Microsoft called one of the .Net languages "VB.Net", gave it a syntax similar to VB, and announced that Visual Basic would eventually be discontinued. More recently Microsoft has dropped the ".Net" part and now refers to VB.Net as simply "Visual Basic". Microsoft has even resumed the original VB version numbering after having dropped it earlier, so that VB.Net v. 2.0, often referred to as "VB 2005", is now also sometimes known as "VB8", while VB.Net 1.0 and 1.1 have been retroactively numbered 7.0 and 7.1, respectively, and the VB.Net version coming after v. 2.0 is being called "VB9". In other words, Microsoft has come full circle, first introducing VB.Net while ending development of VB, then renaming VB.Net to VB, and finally pretending that VB was never discontinued in the first place. So now there's just Visual Basic. But unfortunately, all of those marketing tricks can't turn "Visual Basic" into Visual Basic. Confused? That's the idea.

   It might be helpful to think of VB.Net as something like "MS-BJava". Just as Java was designed to look familiar to C++ programmers, VB.Net was designed to look familiar to VB programmers. In both cases the new product is a radically different system designed for use in a "sandboxed" software system that runs on a set of support libraries (the "virtual machine"), but the code syntax is familiar. Interestingly, Microsoft seems to be applying the same ambiguous naming strategy they used to market VB.net in their attempt to nudge C++ Windows programmers toward .Net with something they're calling "C++/CLI".


Index
Info-zip DLL
   Info-ZIP makes zip libraries that are provided to the public for free. This package contains a sample program that uses Info-ZIP's Zip32.dll to make zip files. The sample is fairly simple and includes only zip - no unzip. Zip32.dll provides numerous options when making a zip file but those options make the operation fairly complex and there's very little documentation available regarding how to code the options in VB. The main part of this sample is a module that provides a simple interface to Zip32.dll. If you just want basic zip functionality this will provide it, with an easy function that creates a zip file given a list of file names, the destination path and the desired compression level.

Download zip32.zip (17 KB)

Back to Index
Active Accessibility
   Active Accessibility is the system that Microsoft has developed to provide functions for handicapped people. In particular, it can be used in making screen readers for blind people. AA provides methods to find out what is currently onscreen, what item is selected, etc.

   Except for the function AccessibleObjectFromPoint, there is very little documentation dealing with the use of AA functions in VB. This sample includes example usage of AccessibleObjectFromEvent, AccessibleObjectFromWindow and AccessibleChildren functions. Included is a class that can list the main elements of a window by using the AccessibleChildren to go down partially through the window hierarchy of a given window. For example, it can list the title, caption, buttons and focussed button of a message box.

Download actacc.zip (25 KB)

Back to Index
VB6 Setup1 Project (Package and Deployment Wizard)
   Setup1 is the executable that carries out VB installations when the Package and Deployment Wizard (PDW) is used. Setup1 is a VB project that can be found in the Wizards\PDWizard folder. Setup1 can be modified. In fact, the original project code includes a great deal of commenting for use in modifying the project.

The sample code here is a modified version of Setup1.exe. Seldom-used functionality has been stripped out (such as silent install and remote install options), some of the more convoluted code has been simplified, and the project has been streamlined to yield an executable of about 1/2 original size (120 KB). Functions have also been added to decorate windows with color gradients, to provide an EULA click-through window, and to provide an option to create a Desktop shortcut when installlation is finished.
   These downloads are not intended to be used as-is, but the editing required to make a unique, professional installer, complete with custom GUI, logos and icons, is minimal.

Updated July, 2006:
• Updated to display a program icon and program size in the Windows XP Add/Remove applet.

• Improved documentation, including a step-by-step guide to making a customized PDW installer for any software program.

Download setup1.zip (296 KB)

Back to Index
VB6 Setup1 Project #2 - The noSE Version
   This is a further rebuild of Setup1, the executable used by the PDW for VB6 setup. This is the "noSE" version. (no Setup.Exe). The Setup.exe functions have been added into the Setup1.exe code, so the total size of your setup can be reduced by a further 135 KB (in addition to the reduction of approximately 120 KB resulting from the weeding and cleanup of the original Setup1 code). And there is no ugly gray box flashing by at the beginning of setup. (That was caused by Setup.exe.)

   When the PDW was first created it was designed for use on Windows 95/98/NT4, where the VB6 runtime was not installed. Setup.exe was needed in that case to install the runtime and reboot. Today, virtually all PCs have the VB6 runtime installed, so setup.exe is unnecessary. At the same time, the PDW is showing its age in some respects. This rebuild of Setup1 provides the necessary updating and adds flexibility to easily create unique, professional installers with custom graphics - something that is difficult or impossible to do with most other installers.

   This rebuild of Setup1 also adds more new functions to update VB setups. In addition to adding an EULA clickthrough, graphical options, and new settings for an Add/Remove icon, this version of Setup1 also adds an option to install files to a subfolder of Application Data. And it adds options for Desktop and Quick Launch icons to the GUI.

   This Setup1 still uses the PDW. You just run the PDW and create a setup package as usual, then substitute your own custom version of Setup1.exe and make some minor changes to the package. The download includes the VB6 code project, a sample installation, and full directions.

   The GUI of this setup can be easily redesigned to create a custom setup for each individual software product. (A background gradient in any color combination is one option that is pre-coded.) To get an idea, see this picture of a basic sample setup. The pictured sample uses the background gradient option, but customizing this setup's GUI is as easy as customizing a VB form. As long as you don't change any control names on the forms you won't need to make any code changes.

Download PDWnoSE.zip (238 KB) (Latest update 8-15-06.)

Back to Index
RichTextBox Functions
   This zip contains a sample project that demonstrates some of the RTB API functions. There are 11 EM_ functions used in a simple RTB program. Some of these are very easy to use. Others are tricky and hard to find sample code for. Some are included here because they're faster than the normal RTB control version of the function. Others are included because they're useful functions that have been left out of the RTB control. The functions used in this project:

EM_EXSETSEL - sets selected text range.
EM_FINDTEXT - direct version of RTB.Find.
EM_FINDWORDBREAK - finds word boundaries.
EM_GETFIRSTVISIBLELINE - returns number of top line showing.
EM_GETLINE - returns text string of 1 line.
EM_GETTEXTRANGE - returns text string from between two offsets.
EM_LINEINDEX - returns offset of 1st character in line.
EM_LINELENGTH - returns length of given line.
EM_LINESCROLL - scrolls the RTB.
EM_POSFROMCHAR - returns coordinates of a given character offset.
EM_REPLACESEL - replaces selected text.

Download RTB-EM.zip (21 KB)

Back to Index
ActiveX DLL Sample
   This is a sample project for a simple ActiveX DLL. It demonstrates how to provide public objects in a DLL, both creatable and not. It also demonstrates the use of GUI elements and the format used to provide public methods and properties.

Download dllsamp.zip (19.5 KB)

Back to Index
Email Sending UserControl
   This is a UserControl for sending email, HTML or not, with or without attachments. Oddly, it seems that no one has made available basic VB code to simply send email without dependencies on the Winsock OCX or worse (i.e. CDO, MAPI, Outlook, etc).

   The CTL module can be added to a project and adds only about 40 KB of code with no dependencies and no extra BAS modules. It requires only wsock32.dll, which seems to be pre-installed on all Windows versions, including Win95.

   This UserControl may need slight editing for your purposes. It handles all basic requirements for sending email, such as Winsock functions, SMTP server conversation, two forms of password submission(if required), email formatting, Base64 encoding, and the detailed MIME headers required for different data formats in email. Some extra options, such as CC mailing and proxy server settings, have not been coded.

Detailed explanation:

   Email is sent using SMTP (Simple Mail Transfer Protocol). SMTP itself is, indeed, simple. It is just a standardized text-based "conversation" between an SMTP server and a client that contacts that server. Unfortunately, the documentation for SMTP is not at all simple. The official standard is contained in what are known as "RFC" documents, which are long-winded expositions, unnecessarily abstruse and legalistic, and all but useless to anyone who reads them to glean information.

   This UserControl provides all the functionality to send email via SMTP, with no dependencies, but some kind of email account is still required. Email programs like Thunderbird, Eudora, Outlook Express, etc. work by formatting your email and carrying out the SMTP server conversation. They require that you provide the address of a valid SMTP server (typically something like "smtp.someisp.com") that will accept your email and send it along. Likewise, this UserControl is a replacement for the email program, not a replacement for the SMTP server.

   The download also includes a file explaining email layout. The text strings sent to the SMTP server as email header and content require very specific formatting, but no one should have to suffer slogging through the all-but-useless, official "RFC" documents in order to find that information. With that in mind, the included text file contains basic template layouts for four email variations: Plain text, with or without attachments; and HTML email, with or without embedded images.

Download smtpuc.zip (21 KB)

Back to Index
HTTP UserControl for File Download
   This is a UserControl for downloading files via HTTP. It uses Winsock1.1 (wsock32.dll) for functionality, making it compatible with all versions of Windows from Win95 up. The only dependency is the VB6 runtime. You don't need to bother with the Winsock OCX or check the installed version of IE.

   This UC is fairly basic. It starts Winsock, connects to a server, requests a file, and handles the download. Server response codes and redirect info. (if any) are also retrieved with the file, and there are functions to write text and binary files to disk after download.

Download httpuc1.zip (12 KB)

Back to Index
ListBox UserControl
   This is a ListBox UserControl that adds a few extra, useful functions to the common ListBox:
    • Add a horizontal scroll bar for wide items.
    • Specify color of text and background for each ListBox item.
    • Find given text among ListBox items.

   Included with this sample project is a discussion of UserControls for people who may not be familiar with them. In brief:

   The convenience of VB controls makes it fast and easy to set up a functional graphic interface but available controls do not always have the required functions built in, and the process of compiling them as external OCX files reduces their efficiency.

   A UserControl is just the code of an OCX before it is compiled. A UC can be compiled directly into your EXE. That makes it faster and easy to modify for each project, while maintaining the separation of code, the easy drag-and-drop placement in the VB IDE, and the convenient OCX wrapper properties such as Top, Left, Height, Width, hWnd, etc.
Easily using multiple, subclassed "owner-drawn" controls
   The downside of UserControls is in handling multiple subclassing functions when multiple UCs are used that require subclassing for their extra functionality. This ListBox UC, for example, requires subclassing to handle the drawing of differently colored ListBox items.

   Subclassing is generally awkward in VB. It is easy to crash a project running in the IDE with subclasses active. It also requires at least one hook, unhook and WindowProc function for each subclass. If that awkwardness could be avoided then numerous UserControls could easily be used in a project to encapsulate modified control behavior (like this ListBox sample) and also to enable the easy use of highly efficient owner-drawn windows.

   An "owner-drawn" window is a control such as a ListBox, TextBox, TreeView, etc. that is created directly from the system DLLs using CreateWindowEx, as is typically done in C++. The owner-drawn window is then handled using Windows API messaging to do things like add an item to a ListBox. VB controls and third-party OCXs take care of all that work, providing simple properties and methods like ListBox.Add that make it easy for VB programmers to use visual components. But the problem with using controls, especially anything that's not among the basic VB "intrinsic controls", is that they're relatively slow, limited and require shipping extra files with your program.
   They're slow because there is an extra call for every method. For example, if you want to search for a given string in a RichTextBox, you call the RTB OCX using the RTB.Find method. The RTB OCX then makes the API call to the actual RTB that it has created and finally returns the result to you.
   Controls are also often limited because you can only access the properties and methods that have been provided by the author of the OCX. Example: The VB ListBox does not provide access to a method that can search for a given string in the ListBox, even though the built-in Windows ListBox, which the VB ListBox is a wrapper for, does provide such a method (the LB_FINDSTRING message).

   By creating owner-drawn windows from a UserControl, on the one hand you get the efficiency and flexibility of using the built-in Windows components directly. On the other hand, you also have the convenient design-time properties provided by using a UserControl (a visible design-time object with width and height, etc.). The result is the ability to design and use customized, owner-drawn windows as easily as if they were ActiveX controls. For example, you can use your own RichTextBox control, without needing to use the RTB OCX. Since your version would be drawing the RTB itself, and using direct API calls that don't need to be routed through an external RTB OCX, it will be significantly faster than the VB RTB control and you won't have to ship the RTB OCX.

...So then the big challenge is how to take advantage of these owner-drawn windows without creating subclass spaghetti in order to do it....

   Matthew Curland outlined a "scalable" subclassing method in his book Advanced Visual Basic 6 (Addison Wesley publ.) that solves the problem of handling multiple subclass procedures by sending the subclass WindowProc pointer back inside the UserControl during the initial subclass function, with the result that all of your UCs can subclass themselves internally. In other words, during intialization the UC calls a function(s) to set up one or more subclass routines, and the function then redirects the address of the routine to a WindowProc sub back inside the UC. Once set up, this method allows each instance of a UC to receive and handle its own messages. You only need a small external module and a single, one-line redirect function for each type of object that you are subclassing. So there is no limit to how many UC instances you can use and how many subclass routines you can handle. Your owner-drawn, UserControl-mounted component window becomes as easy to use as an ActiveX control, once you've fleshed it out with functionality, but it functions with the efficiency of the Windows API and has your own custom set of properties and methods. For instance, you could use existing API functions to add a line scrolling method like the following to an owner-drawn RichTextBox:
   CustomRTB.Scroll NumberOfLines, Direction

   Matthew Curland also provided sample subclassing code and a DLL for nearly crash-free IDE testing. This ListBox sample, while useful by itself, was particularly created to point out the wealth of possibilities available with UserControls once the subclassing headaches are eliminated.

   Matthew Curland's code samples and DLL are copyrighted property that go with his book. They could not be included in this download. If you can no longer find his book, you may be able to find sample code and a copy of his subclassing DLL in the code download for his August 2001 Visual Basic Programmer's Journal article Black Belt Programming: Provide Pointers to Class Functions here. The article itself may not be available and VBPJ is long gone (a casualty of .Net) but Fawcette publishing has made the respective code downloads available online for past VBPJ articles.

Download lboxuc.zip (14 KB)

Back to Index
Webmaster's Raw Log Host Name Converter
   This is a simple program for webmasters who like to read and/or process their "raw" server logs. It is listed on this page because it's a technical utility, not of interest to most people, and because it has only been minimally developed but source code is included.

   The download includes a VB6 project and a compiled EXE. The EXE can be used as-is to process raw server logs. It will convert all IP addresses in your logs to more readable host names, where possible. For example, where a log line begins with:
    100.100.100.100 - [15/Mar/2005:00:11:12 -0500]...
             ... "GET /jsware/boss.php3 HTTP/1.0" 200 1118....
the program will find the host name and replace the IP address, resulting in something more readable and informative, like:
    server1.acmeaccounting.com - [15/Mar/2005:00:11:12 -0500]...
            ... "GET /jsware/boss.php3 HTTP/1.0" 200 1118....
The program then writes a new log file incorporating the IP/host name translations. In some cases, depending on the layout of your raw logs, the program source code may need to be edited and recompiled before use. The download includes an info. file with further explanation.

Download logpack.zip (24 KB)

Back to Index
RSS ActiveX Control
   This is an OCX that has functionality to process RSS files. The "Roll Your Own StartPage" utility includes a component for partial processing of RSS, but this control is more flexible. It can download files, write downloaded files to disk, and return a downloaded RSS file as an RSSFile object, which provides structured object model access to the RSS elements.

   This download includes a compiled OCX control , ready for use, which does not require any VB experience. It also includes source code for the control.

   This control has had limited testing. Please feel free to email with questions, reports, etc.

Download jsrss.zip (52 KB)

Back to Index
Type Library Reader / Object Browser
Updated 10-07

   The object browser in VB and in MS Word provides a view into type libraries - binary documentation of COM objects. The file TLBINF32.DLL provides that functionality and is redistributable. TLBINF32.DLL wraps the functionality in OLEAUT32.DLL that provides the ability to read type libraries. TLBINF32.DLL can be used by VB programmers who want to build their own object browser or otherwise read type libraries. But it's actually probably easier to use OLEAUT32.DLL directly than it is to use TLBINF32.DLL. (And it also avoids needing to ship a 150 KB file that's incompatible with the VB5 version.) As is so often the case, writing the code is not nearly so difficult as is finding thorough, accurate documentation.

   The code here includes a sample program and a single, compact class that reads typelibs and extracts the information into orderly data structures. (This is essentially the same code used in the Typelib reader ActiveX DLL on the VBScript samples page.) This code is designed for use in an object browser or for object interface research. In other words, it extracts information and organizes it in accord with what's relevant for an object browser, as opposed to just reading all typelib data and "dumping" it as a list of interfaces like Microsoft's OLEView.exe Type Library browser does.

   The updated version includes more thorough explanation of how the code works, and also adds functionality to list early-bound interfaces. (The vast majority of COM interfaces are dual, but there are a few cases where an early bound interface is present without a dispatch interface. Those were not listed in the first version of this code.)

Download tlbread.zip (25 KB)

Back to Index
CAB Files - Creation, Extraction, Information
   Creating and unpacking CAB files is often useful from VB, but VB is not capable of using the system file, cabinet.dll, that provides the functionality. So people are left to paste together hokey command-line alternatives, using makecab.exe, cabarc.exe, etc.

   If you look online for VB code you will find several examples that use SetupIterateCabinet, from setupapi.dll, for extracting from CAB files. One example is a project named Cab Explorer. There was also an in-depth article detailing the use of SetupIterateCabinet in the November, 2000 issue of VBPJ, by one Ken Getz. But SetupIterateCabinet doesn't really work! And none of the available code or articles bothers to mention that. SetupIterateCabinet can extract only from CAB files compressed using the MSZIP format. It fails if the CAB was compressed with the LZX or QUANTUM method. And LZX compression is actually fairly common.

   Other operations, like listing files in a CAB, can be done by directly parsing the CAB file header. So learning about the setupapi.dll functions is probably a waste of time.

   Since VB cannot call the CDECL functions in cabinet.dll without a lot of acrobatics, the solution here is a very simple C++ DLL, made in VC6. It provides the basic functionality needed to extract from and create CAB files programmatically using cabinet.dll. This download includes a .CPP, .H and .DEF file. In combination with the LIB and header files from the Microsoft CAB SDK it provides everything needed to build your own DLL for use from VB.
   If you don't want to deal with C++ code, see the jsCAB download on the VBScripts page. It provides a pre-made ActiveX DLL for use with VBScript, as well as a compiled standard DLL for use from VB.

Download vbcab.zip (9 KB)

Back to Index
Easily Create a Standard Windows DLL in VB
   It is generally said that a "standard" DLL with exported functions cannot be made in VB. In fact, it only requires a simple process of hooking into the linker command line at compile time, in order to tell VB to add extra functions to the export table.

   Thank you to Ron Petrusha for this. Although creating a standard DLL (or controlling the compiler switches generally) turns out to be an extremely simple task, it is not at all an obvious one.

Download vbdll1.zip (22 KB)

Back to Index
Shell Operations - Explorer Folders
   This is an interesting collection of methods to access open Explorer folders and return such things as a list of currently selected items. The sample code uses the Shell object and Active Accessibility to access open folder windows. There are actually three separate methods used here to get a folder's items, selected items, focused item, etc. Each method is more funky than the last. But they work!

   1) The first method is used on pre-XP systems, where a folder window view is actually a webpage in an IE browser window. It provides access to the actual Document object, the ShellFolderView, and the Shell's Folder object for any open folder. The way it does that is to use ObjectFromLresult (in oleacc.dll) to get the true Document object from a folder window's embedded IE browser window. It then accesses the DOM to get the ShellFolderView from the Document, which is an ActiveX control on the folder.htt webpage that represents a folder view.

   2) The second method is used on XP because XP has a fake Web View. XP folder windows have been returned to the plain Win95-style ListView window. There is no IE window, no webpage, and thus no actual Document object for XP folder views. With no Document object the first method can't be used. But Microsoft seems to have emulated the basic Web View objects in XP for compatibility, so the ShellFolderView and Folder objects are still available. In the second method, a QueryInterface for the ShellFolderView is called on the Document property of the pseudo-IE instance returned from the Shell.Windows collection. Raymond Chen, an official Microsoft "blogger", actually showed how to do something like this with some very involved C++ code. But it turns out that most of his code is unnecessary. The method is actually quite simple (aside from the fact that it takes a little work to get at IUnknown in VB).

   3) The third method, which should never normally be necessary but was added for thoroughness, uses Active Accessibility (oleacc.dll). It doesn't return the ShellFolderView or Folder objects, but it still returns a list of items and selected items in a folder. So all three methods will return the currently selected items in an open folder.

   This code also shows how to return a true Document object from a running instance of IE, and that method can be easily adapted to also return the Document object from a running HTA. In fact, a Document object can be returned from any process that has a child window titled "Internet Explorer_Server", which is the actual browser window. That includes IE, HTAs, folder windows in Windows versions with WebView (Win95-2000), and even Outlook Express when an HTML email is being viewed.

Download shellop.zip (14 KB)

Back to Index
Windows Installer (MSI)
   This is not VB6 code but rather VBScript that uses the Windows Installer automation interface to make an MSI Utility. It's listed here because it might be useful to people wanting to author MSI packages, or to those who want to know more about how MSI packages work. For more details, see the MSI Utilities page.

Back to Index
VB on Linux
   See the VB on Linux page for information and code samples related to using VB with the Wine implementation of the Win32 API on Linux.

Back to Index