Windows XP helper classes
-------------------------

by Ellis Dee


Note: When viewing from notepad, set Format => Word Wrap to checked.


REQUIREMENTS

When adding these classes to your project, you must declare the following constant in a module: (details below)

Public Const ErrorIgnore = 37001 


OVERVIEW


clsWindowsXP
- clsDrive
- clsFile
- clsFolder
- clsRegistry

clsWindowsXP contains an instance of each of the four dependent classes. The four dependent classes can also be instanced individually. (For example, if you just want to manipulate the registry, you can bypass the other classes and only inlcude clsRegistry in your project.)

Sample usage:

At the beginning of your project, create an instance of the main class (or only the individual class(es) you want), and then destroy it when your project closes. For example:

Option Explicit

Public Const ErrorIgnore = 37001 ' <== REQUIRED; see clsFile below
Public xp As clsWindowsXP

Sub Main()
    Set xp = New clsWindowsXP
End Sub

Sub CloseApp()
    Set xp = Nothing
End Sub

Having done this, from anywhere in your project you can reference the various functions. For example:

xp.File.Copy "C:\Old.txt", "C:\New.txt"

All functions have been designed to be in compliance with the "Designed for XP Logo" requirements, so in addition to being the recommended way to access the operating system, the transition to Vista should (in theory) be simple.


clsWindowsXP
------------

AssociateIcon()
xp.AssociateIcon
Method to tell Windows to refresh file associations. This is most useful on a run-once basis the first time your application is run, in case the install procedure doesn't refresh the file associations for you.

DebugMode
blnDebugMode = xp.DebugMode
Property that is True if the app is being run from inside the IDE.

EmptyRecycleBin()
xp.EmptyRecycleBin
Empties the recycle bin. Will display an automatic progress meter if operation takes long enough to merit one.

GetDesktop()
xp.GetDesktop Left, Top, Width, Height
The four long variables you send will be filled with the desktop region. This excludes the taskbar if it doesn't autohide, as well as any other registered AppBars.

LockWindow()
xp.LockWindow hWnd
Suppress the paint requests to any form or control to reduce flicker. In most cases, flicker can be removed through better practices, such as checking if a property value is different before setting it. If that doesn't work, use this method. Note that normally, nested calls tend to increase flicker, so this method maintains an internal counter and only suppresses the first (outer-most) call when nested.

Mouse
xp.Mouse = msWait
Use this property to set the mouse cursor to an hourglass, hide the cursor, or set it back to normal. The valid values are enumerated. The difference between msWait and msSystemWait is that the former is form-specific, while the latter shows the hourglass anywhere on the screen.

OpenURL()
xp.OpenURL "www.vbforums.com"
Opens the specified URL in the default browser.

SetAlwaysOnTop()
xp.SetAlwaysOnTop hwnd[, False]
Set a form to be always on top. Send an optional False to return the form to normal.

SetMousePosition()
xp.SetMousePosition X, Y
Move the mouse to the given screen coordinates in pixels.

ShowOpenDialog()
strFile = xp.ShowOpenDialog(strFolder, "Audio Files (*.mp3)|*.mp3", "mp3")
Displays the Open File common dialog, returning either the file selected or an empty string if the user cancels. Supports multiple extensions; separate each valid extension (and description) with the pipe (|) character.

ShowSaveAsDialog()
strFile = xp.ShowSaveAsDialog(strFolder, strFile, "Audio Files (*.mp3)|*.mp3", "mp3")
Displays the Save File common dialog, returning either the file selected or an empty string if the user cancels. Supports multiple extensions; separate each valid extension (and description) with the pipe (|) character.

ShutDownWindows()
xp.ShutDownWindows [Reboot] [Force]
Not written by me, and unfortunately the code is so old I've lost track of where I originally found it so I can't offer proper credit. Can either Shutdown or Restart, and can optionally force the action if processes are busy.

SystemColorRGB()
lngColor = xp.SystemColorRGB(vbButtonFace)
System color values are dependent on user settings. Use this function to translate any system color to its resultant color value.

UnlockWindow()
xp.UnlockWindow
Companion to LockWindow, this should be called exactly once for every LockWindow call.

UserName
strUser = xp.UserName
Property that holds the currently logged in XP user's username.


clsDrive
--------

CloseDoor()
xp.Drive.CloseDoor [Drive]
Closes the CD or DVD door only if the drive is of the appropriate type. Trying close a hard drive or floppy disk is safely ignored. [Drive] should be a string in the format "D:"; if you omit the Drive parameter the default CD is closed.

Eject()
xp.Drive.Eject [Drive]
Ejects the CD or DVD only if the drive is of the appropriate type. Trying to eject a hard drive or floppy disk is safely ignored. [Drive] should be a string in the format "D:"; if you omit the Drive parameter the default CD is ejected.

FormatSize()
strSize = xp.File.FormatSize(curSize)
Returns a formatted string description of the specified (currency) size. This string is formatted the same way as displayed in the Explorer status bar. (eg: 37 bytes, 63.2 KB, 123 KB, 64.2 MB, 153 MB, 4.22 GB)

GetDriveSpace()
xp.Drive.GetDriveSpace "C:", curTotal, curFree, curUsed
Retrieves all three drive space statistics (Total, Free, Used) in a single operation. Send three currency variables to be filled in by reference. Use the FormatSize() function to convert these values for display.

GetFreeSpace()
curFree = xp.Drive.GetFreeSpace("C:")
Returns the free space on the specified drive. Use the FormatSize() function to convert the value for display.

GetTotalSpace()
curFree = xp.Drive.GetTotalSpace("C:")
Returns the total space on the specified drive. Use the FormatSize() function to convert the value for display.

GetUsedSpace()
curFree = xp.Drive.GetUsedSpace("C:")
Returns the used space on the specified drive. Use the FormatSize() function to convert the value for display.

GetFileSystem()
strFileSystem = xp.Drive.GetFileSystem("C:")
Returns the file system (eg: "NTFS") of the specified drive.

GetName()
strLabel = xp.Drive.GetName("C:")
Returns the volume label.

GetSerialNumber()
lngSerial = xp.Drive.GetSerialNumber("C:")
Returns the serial number of the specified drive. (Some drives return 0 due to not being branded by the manufacturer.)

GetType()
enType = xp.Drive.GetType("C:")
Returns the enumerated drive type of the specified drive.

SetName()
xp.Drive.SetName "C:", "MyVolumeLabel"
Sets the volume label.

DRIVE ENUMERATIONS

The four types of drive enumerations (All, Hard Drives, CD/DVDs, Floppies) all work the same way. Send a dynamic string array to be populated as a one-based array, and it will return the number of drives found. The strings in the array will be in the format "A:", "C:", etc...

lngDrives = xp.Drive.EnumerateAll(StringArray)
lngDrives = xp.Drive.EnumerateCDs(StringArray)
lngDrives = xp.Drive.EnumerateFixed(StringArray)
lngDrives = xp.Drive.EnumerateFloppies(StringArray)


clsFile
-------

IMPORTANT: The following line must be placed in a module, (see below) though you are free to change the specific value to whatever you like:

Public Const ErrorIgnore = 37001

The file class uses the SHFileOperation API for Copy, Delete, Rename, and Move operations. This allows for deleting to the Recycle Bin if desired, as well as displaying a progress dialog if the operation takes long enough to merit one.

Note that nowhere in this class is the native Dir() function used, so you don't need to worry about calling any function from inside a loop based on Dir. Dir is a global function, meaning that its queue gets reset even if called from a different function.

Also note that due to the nature of files, this class can and will raise errors. For example, if you try to copy a file that doesn't exist. Some errors will be raised that can safely be ignored, such as when the user cancels a file operation. These errors will have the error number ErrorIgnore, a public constant that you must define somewhere in your project. Then in your error handling code, be sure not to bother the user if the error number is ErrorIgnore. Other errors, such as File Not Found, will be raised with the appropriate native error number.

DeleteInUse()
xp.File.DeleteInUse File
Delete a file that is in use. This command tells Windows to wait and delete the file on next reboot.

Exists()
blnExists = xp.File.Exists(File)
Returns True if the specified file exists. No errors are generated if the file is invalid in some way, (eg: path not found, drive not ready, etc...) instead it simply returns False. Correctly returns False if file does not exist but folder of the same name does.

FormatSize()
strSize = xp.File.FormatSize(curSize)
Returns a formatted string description of the specified (currency) size. This string is formatted the same way as displayed in the Explorer status bar. (eg: 37 bytes, 63.2 KB, 123 KB, 64.2 MB, 153 MB, 4.22 GB)

GetLongName()
strLong = xp.File.GetLongName(File)
Returns the long path and file name.

GetShortName()
strShort = xp.File.GetShortName(File)
Returns the short path and file name.

GetSize()
curSize = xp.File.GetSize(File)
Returns a currency value holding the size in bytes of the specified file. Currency is used because Longs would max out at 2 gigs. Currency can handle sizes of just over 800 terabytes.

GetType()
strType = xp.File.GetType(File)
Returns the text description of a file type based on its extension. This is the same text that is displayed in the Type column of Windows Explorer when in Details view.

GetVersion()
strVersion = xp.File.GetVersion(File)
Returns a string holding the version of an exe, dll, or any file that contains version info.

LoadToString()
strText = xp.File.LoadToString(File)
Returns the entire contents of text file in a single string.

MakeNameDOS()
strFilename = xp.File.MakeNameDOS(strFilename)
Strips invalid DOS characters, replacing them with similar valid characters. For example, colons (:) are converted to dashes (-).

MakeNameUnique()
strFilename = xp.File.MakeNameUnique(strFilename)
Returns a unique filename by adding an incremental suffix if the file already exists. For example: "C:\Text.txt", "C:\Text_a.txt", "C:\Text_b.txt"

Run()
xp.File.Run File[, DefaultFolder]
Run any type of file. Exe files are simply executed, while document files (eg: "ReadMe.txt") are opened with whatever program is associated with that file extension.

RunAs()
xp.File.RunAs File, Ext[, DefaultFolder]
Runs a file using the application associated with a different extension.

FILE OPERATIONS

The four file operations (Copy, Delete, Move, Rename) as implemented in this class do not support wildcards, nor do they support file lists delimited with vbNullChar. The API call does support lists, but the implementation in this class performs validation on both Source and Dest before starting, which would be more complicated when supporting lists. Adding list support is left as an exercise for the reader.

xp.File.Copy Source, Dest
xp.File.Move Source, Dest
xp.File.Rename Source, Dest
xp.File.Delete File[, True]
Send an optional True to send the deleted file to the Recycle Bin.


clsFolder
---------

IMPORTANT: The folder class has the same requirements/notes as the file class, outlined above.

Abbreviate()
strDisplay = xp.Folder.Abbreviate(Path)
Abbreviate will do just that if the specified path is located under the My Documents or Shared folders. Sample return values:
C:\...\My Documents\MyFile.txt
C:\...\Shared Documents\MyFile.txt

Browse()
strFolder = xp.Folder.Browse("Title", RootFolder)
Opens the Windows browse folder dialog, allowing the user to easily select a folder. RootPath is one of the enumerated special folders. (see below) Returns an empty string if the user selects the cancel button.

Create()
xp.Folder.Create Path
creates the folder specified if it doesn't already exist. No errors are generated on failure. This will create an entire tree in one shot, even if the parent folders didn't exist.

DeleteMultiple()
xp.Folder.DeleteMultiple StringArray[, RecycleBin, Silent]
Send a string array of folders to delete.

Exists()
blnExists = xp.Folder.Exists(Path)
Returns True if the specified folder exists. No errors are generated if the folder is invalid in some way, (eg: drive not ready, etc...) instead it simply returns False. Correctly returns False if the folder does not exist but a file of the same name does.

Explore()
xp.Folder.Explore Path
Opens the specified folder in the Windows Explorer. Path is a string containing the path, not the folder enumeration. Of note is that if the specified folder is or is under My Documents, and the user selects the Folders pane from inside Explorer, Explorer will show the shortcut tree for My Documents instead of the complete Documents & Settings tree. This is greatly preferred behavior.

GetDatetime()
xp.Folder.GetDatetime strFolder, dtmCreated, dtmModified, dtmAccess
Retrieves all three folder dates (Created, Modified, Access) in a single operation. Send three date variables to be filled in by reference.

GetLongName()
strLong = xp.Folder.GetLongName(Path)
Returns the long path name.

GetShortName()
strShort = xp.Folder.GetShortName(Path)
Returns the short path name.

HasSubFolders()
blnIsParent = xp.Folder.HasSubFolders(Path)
Returns True if the specified folder exists and has subfolders. Returns False if the path has no subfolders or doesn't exist. (Check for existance using Exists.)

IsEmpty()
blnEmpty = xp.Folder.IsEmpty(Path)
Returns True if the specified folder exists and is empty. Returns False if the path isn't empty or doesn't exist. (Check for existance using Exists.)

MakeNameUnique()
strFolder = xp.Folder.MakeNameUnique(strFolder)
Returns a unique folder name by adding an incremental suffix if the folder already exists. For example: "C:\Temp", "C:\Temp_a", "C:\Temp_b"

SetDatetime()
xp.Folder.SetDatetime strFolder, dtmCreated, dtmModified, dtmAccess
Companion function to GetDateTime.

FILE OPERATIONS

The file operations here work the same way as in clsFile. (see above)

xp.Folder.Copy Source, Dest
xp.Folder.Move Source, Dest
xp.Folder.Rename Source, Dest
xp.Folder.Delete Folder[, True]
Send an optional True to send the deleted folder and its contents to the Recycle Bin.

SPECIAL FOLDERS

clsFolder exposes the special folders as properties, and includes a public enumeration for easy reference. (Quick tip: "My Documents" is UserDocs.)

The special folders are obtained using Microsoft's recommended best practice of using SHGetFolderPath.

strFolder = xp.Folder.Application
strFolder = xp.Folder.CDBurnArea
strFolder = xp.Folder.CommonAppData
strFolder = xp.Folder.CommonDesktop
strFolder = xp.Folder.CommonDocs
strFolder = xp.Folder.CommonMusic
strFolder = xp.Folder.CommonPics
strFolder = xp.Folder.CommonStartMenu
strFolder = xp.Folder.CommonStartMenuPrograms
strFolder = xp.Folder.ProgramFiles
strFolder = xp.Folder.ProgramFilesCommon
strFolder = xp.Folder.User
strFolder = xp.Folder.UserAppData
strFolder = xp.Folder.UserCache
strFolder = xp.Folder.UserCookies
strFolder = xp.Folder.UserDesktop
strFolder = xp.Folder.UserDocs
strFolder = xp.Folder.UserFavorites
strFolder = xp.Folder.UserHistory
strFolder = xp.Folder.UserMusic
strFolder = xp.Folder.UserPics
strFolder = xp.Folder.UserRecent
strFolder = xp.Folder.UserSendTo
strFolder = xp.Folder.UserStartMenu
strFolder = xp.Folder.UserStartMenuPrograms
strFolder = xp.Folder.UserStartup
strFolder = xp.Folder.Windows
strFolder = xp.Folder.WindowsSystem


clsRegistry
-----------

The registry class supports three different data types: String, Numeric (long) and Boolean (binary). Because boolean values are stored as binary data, this class cannot be used to manage actual binary data values in the registry. (They are treated as boolean.)

The different roots have been enumerated. Every function accepts an optional Root parameter that defaults to CurrentUser. Of note is that to comply with Microsoft best practices, you should never write to any root other than CurrentUser.

This class will not generate any runtime errors if the registry functions fail. Instead, two properties are exposed: ErrorNumber and ErrorDescription. ErrorNumber holds an enumerated error number, and ErrorDescription holds a short string description of the error. These properties hold the most recent error returned.

CreateKey()
xp.Registry.CreateKey Key[, Root]
This will create an entire tree in one shot if it doesn't already exist. Sample usage:
xp.Registry.CreateKey "Software\MyCompany\MyApp"

DeleteKey()
xp.Registry.DeleteKey Key[, Root]
This will delete the specified key even if it has subKeys.

DeleteValue()
xp.Registry.DeleteValue Key, Value[, Root]
Send this a key and value name to delete the value. Specify "(default)" or "" to delete the (default) value of key.

EnumerateKeys()
lngKeys = xp.Registry.EnumerateKeys(Key, ChildKeys()[, Root])
Send a key and a dynamic string array to be filled as a one-based array with the subkey names. Returns the number of subkeys found.

EnumerateValues()
lngValues = xp.Registry.EnumerateValues(Key, Values()[, Root])
Send a key and a dynamic string array to be filled as a one-based array with the value names. Returns the number of values found. Use GetType to identify the value type.

ErrorDescription
MsgBox xp.Registry.ErrorDescription
Property that holds a short string decsription of the last registry error raised.

ErrorNumber
enRegistryError = xp.Registry.ErrorNumber
Property that holds an enumerated error number from the last registry function called.

GetType()
enType = xp.Registry.GetType(Key, Value[, Root])
Returns the enumerated type of the specified value, or 0 (rdNone) if either the value or key doesn't exist.

HasSubKeys()
blnSubKeys = xp.Registry.HasSubKeys(Key[, Root])
Returns True if the specified key has subkeys, False if not or if the key doesn't exist.

KeyExists()
blnValid = xp.Registry.KeyExists(Key[, Root])
Returns True if a key exists, False if not.

ReadStringArray()
xp.Registry.ReadStringArray Key, Value, StringArray[, Root]
Similar to the standard ReadValue functions, reads a string array instead of a single string.

ReadStringEnviron()
strExpanded = xp.Registry.ReadStringEnviron(Key, Value, Default[, Root])
Some registry strings contain environment variables that need to be expanded. Retrieves them in expanded form.

ValueExists()
blnValid = xp.Registry.ValueExists(Key, Value[, Root])
Return True if the specified value exists, False if not.

WriteStringArray()
xp.Registry.WriteStringArray Key, Value, StringArray[, Root]
Companion to ReadStringArray function, writes a string array to the registry. 

WriteStringEnviron()
xp.Registry.WriteStringEnviron(Key, Value, String[, Root])
Companion to ReadStringEnviron.

READ VALUES

There are three basic ReadValue functions, one for each data type.  You must specify a default value to return in case the value or key doesn't exist. To read the value of a key's (default) value, send a Value parameter of either "(default)" or "". If the value exists but is of the wrong type, the specified Default is returned.

blnValue = xp.Registry.ReadBoolean(Key, Value, Default[, Root])
lngValue = xp.Registry.ReadNumber(Key, Value, Default[, Root])
strValue = xp.Registry.ReadString(Key, Value, Default[, Root])

WRITE VALUES

The companion functions to the ReadValue functions, the WriteValue functions will create the key if it does not already exist before creating or overwriting the specified value. Again, specify "(default)" or "" to write to a key's default property. Don't confuse the parameters; "Value" is the name of the value, while "Data" is the actual data to be written.

xp.Registry.WriteBoolean Key, Value, Data[, Root]
xp.Registry.WriteNumber Key, Value, Data[, Root]
xp.Registry.WriteString Key, Value, Data[, Root]