[VB6Core]

Introduction

Wednesday, March 1, 2000

This topic is about my main COM component written in Visual Basic 6, VB6Core.dll. It's an ActiveX DLL containing classes, dialogs and utility functions you can use in VB6 (and probably in VB5, too) as well as in VBA clients like MS Office. The component contains 52 public classes (among them several global classes with utility functions and some interface classes).

You can download the source as well as the binary.

The binary is compiled against dependencies that were updated by the VS.NET Beta 2 install, so you need those updated dependencies if you want to use the binary "as is". However, I suggest you compile the source yourself if you want to use it in a production environment. Use the binary as a mirror typelib for binary compatibility if you plan to redistribute the component.

What you should know

Dependencies

The component depends on some other binaries. You have most of them with your VB6 install, except WinShell.dll (provided at the download page). VB6Core compiles against the listed OCXs and DLLs using Visual Basic, Professional Edition without any services packs, and it works with the updates that come with VS.NET Beta 2, too. Of course, you need the Visual Basic runtime files, too (any VB6 distribution will suffice).

Note that the binary file you can download depends on updated versions of some of the files listed here (and some updated runtime files), which are available with VS.NET Beta 2. However, these updates are not required if you compile the source yourself (I ask you to use the binary file to ensure binary compatibility if you redistribute the component).

Of course, you can use VB6Core without some of these components, but you really should have at least MsComCtl.ocx, ComDlg32.ocx, and Scrrun.dll present to do useful things.

State of the code

I've written this component because I had many circular dependencies in modules and components I had been using before. Therefore, the quality of the code varies to some degree; this also reflects my own learning process with VB6 component programming, so there is some code that I'm not exactly proud of and that I'd rewrite, if VB6 (as a tool) only had a longer life expectancy. All in all, however, the code is OK.

You'll notice that every routine has its own error handler; the component does not raise errors, rather, it handles everything that comes up. You might want more flexibility, but I chose to stick with this kind strategy. Also, some routines don't really need error handlers, but I put them in anyway. Planning ahead, I guess. Sue me.

There some strings in there that had better be in resource files. Everything that the user reads will be in English. Variable names are in various Hungarian dialects, the postfixes mostly in English, sometimes in German. I've put in a lot of comments, but if you don't speak German, some of them might not be very useful. Damn globalization, huh?

This is VB code, not Windows code. I only make a few API calls, even though the Declare statements are given a lot of room in eight bastard modules. Most of the stuff evolves arround VB's controls (and their limitations), the file system, the Windows Shell, text editing, dialogs, and internet client features. In fact, this component is the heart and soul of WebEdit, a strange cross of text editor, file manager, and FTP client. But you can use the stuff elsewhere, too.

Using VB6Core

With preliminaries out of the way, we can now examine VB6Core more closely. This is not a complete description of the features, but you can find things out. I plan to provide more detailed documentation when I find the time. For now, I'll just introduce the naming convention I used, and then talk about some of the classes.

Naming convention

I use the following prefixes for types:

Method parameters and variables have the following prefixes (but don't nail me down on it):

CHistory

This class keeps two lists internally, and lets you manage history information based on strings. The first list (managed by methods and properties without the "Total" part in their names) is your ordinary back-and-forward browse context you know from web browsers. The second list (right, use the members the have the "Total" part in their names) is based on the MRU principle (no duplicates, no overwrites); it can be persisted. To navigate, make sure you hook up the "Jump" event (this will prevent overwrites due to other method calls in the context of "Jump").

CFileFind, IFileUser, NFiles, TFile

These let you search for files in a given folder, optionally recursing into subfolders. You get all the file information there is, plus the type name and the icon (as an index in the system image list, or optionally as a StdPicture). Implement IFileUser (the "Hit" method will give you a TFile structure for every file; return True to continue), create an instance of CFileFind, call "Attach", then "Start". If you don't call Attach, the "Files" property will return an NFiles collection you can iterate through (this way, you don't need to implement the interface, but you can't cancel long-lasting searches as with the interface approch):

Dim ff As New CFileFind
ff.Start "C:\", "*.txt;*.dat"
Dim fil As TFile
For Each fil in ff.Files
	Debug.Pring fil.DisplayName
Next fil

CFileExecution

This one carries out file operations. Actually, it calls SHFileOperation to ensure you have all the protection Windows gives the user. You pass collections containing the file paths, and optionally pass a target folder. Deleting files will move them to the recycle bin. There are several events (hook them up to provide extra checks in a centralized fashion, or to update the user interface). Call "ItemProperties" to display drive/folder/file properties in a custom dialog box that let's you rename items.

NFilters, CFilter, GDialogs, GComboUtil

Create file filter patterns with the first two classes and use them in the dialog functions in GDialogs. Or use an ImageCombo, and call AddImageComboFilters (in GComboUtil) to create a graphical filter combo with icons (pass a type extension, like "*.txt", or a StdPicture instance to the vPicture argument of NFilters's Add method). You can also display filter hierarchies by setting individual "Levels" for every filter in the collection.

CTreeView, ITreeSource, CFolderSource, CFileSource, CFtpSource

This largish gang of classes gets TreeView controls going. CTreeView is a wrapper arround the TreeView control; you create an instance, and call ConstructObject to delegate to a TreeView and an ImageList control (the image list will be attached automatically). Then, create an instance of a class that implements ITreeSource (which is an object that gets the data for the control), and pass it on via CTreeView's Attach method. You get three classes (those with "Source" in the name) that implement ITreeSource, filling the tree with Shell Namespace items, a combination of folders and files, or directories on an FTP server. You can create your own classes implementing ITreeSource for other data, too. CTreeView communicates with these classes to handle drag&drop, deletion of nodes, icons, selection changes, and so on.

CListView

This class wraps ListView controls. It lets you sort not only string-wise (check the method "ConstructObject"). It enables complete deselection and returns some collections containing keys and names (the former is useful if you have file system paths that you want to pass to CFileExecution). You can also get information about the column last clicked by the user.

CRtfBox

Turns RichTextBox into an editor. If you want clone WordPad, it's about all you need.

CSplitter

A class that turns a PictureBox into a splitter. It docks two controls, and ensures they stay in their bounds as the form resizes. When the splitter is moved the controls can be resized immediately, or this can be delayed until the user releases the mouse. The splitter can be used without specifiying controls (useful if you have complex layout logic and need to calculate on your own). You can split horizontally as well as vertically.

CScripter

This one wraps up the MS Script control, but you only need to create an instance of this one here. Call "AddObject" to add objects from your application that the user can program against. Call "LoadScriptFile" (passing a folder string optionally) to bring up a dialog that lets the user select a VB-Script file. This file is then examined, raising "ProcedureAdded" events, which tell you the procedures' names. The "Run" method will execute these procedures.

CTrayIcon

CTrayIcon encapsulates notify icons you can put into the system tray. You can change any property at any time.

NList, CListItem, ICompare, ICheck

NList is a wrapper arround VBA.Collection, fixing its limitations. You change existing elements, manipulate keys, and do other list operations like moving elements, sorting, filtering, and cutting, copying or inserting entire sections. It's possible to create nested lists, too. Like VBA.Collection, it's based on Variants, but you can specify a subtype (using the "ElementType" property) that NList will enforce. If you use Strings, you can easily read or write them to or from a text file.

NOptions, COption

An attempt to deal with program settings. You add COption objects, which define persistance details as well as the controls to use in the built-in dialog. Persistance happens behind the scenes (using the "VB and VBA Program Settings" key), while you can react to changed settings reading COption's "Dirty" property. COption has a "Value" property returning a Variant; this can be an instance of NList (see above) for more complex settings (like lists the user enters).

CHttpConnection and friends

This one connects your app to the internet, downloading documents via Http. "GetContents" works syncronously, while "TransferContents" works asynchronously and requires you to implement the IHttpIO interface. Check the "BusyState" event, and read from the "Response" property.

CFtpServer and friends

Using this class, you can walk through FTP servers and transfer files. Implement the IFtpNavigator and IFtpIO callback interfaces, and walk through the NFtpFolders and NFtpFiles collections that you access via the first interface, or upload/download textfiles via the second one.

GFileUtil

GFileUtil wraps up SHGetFileInfo, ShellExecute, and ShellExecuteEx in various ways.