New Home
Old Home
Site Map
Tips & Tricks
Q & A
New in VB6
Free Stuff
Awards Received
Most Wanted List

New Most Wanted List
Beginning Intermediate Advanced
Submit an Example
These are the questions I most want answered from, my emails, and other sources. Some I don't have time to dig into deeply enough to give a good answer. Some I have seen solutions for but don't remember where. Others I have no clue about.

If you know how to accomplish these tasks, please email me! Better still, if you can, zip up an example program and send that as a binary attachment (no uuencodings please).

Click the items in the list to see peoples' solutions.

  1. How can I retrieve a metafile from a resource file?
  2. How can I create a floating toolbar?
  3. How can I access the History list of an embedded browser?
  4. How can I load fonts in VB? (By this I mean install a new font on the system, not just use different fonts)
  5. How can I call an ActiveX exe from Visual C++?
  6. How can I pass a Form object from an In-Process DLL back to the main Application?
  7. How can I open a password protected database?
  8. How can I open an Access 95 database that is password protected using VB?
  9. How can I use ADO in a multi-user environment?
  10. How can I list the programs in the task bar?
  11. How can I change the color of a title bar?
  12. How can I make a gradient color title bar?
  13. How can I install multiple programs in one setup program?
  14. How can I empty the wastebasket?
  15. How can I delete temporary internet files?
  16. How can I print a preformated file directly to printer?

If you know how to accomplish these tasks, please email me! Better still, if you can, zip up an example program and send that as a binary attachment (no uuencodings please).

1. How can I retrieve a metafile from a resource file?
David Otero
You have to add the metafile as a custom resource, then when you need the file, u have to do something like this:

    Dim bData() As Byte

        bData() = LoadResData(101, "CUSTOM")
        Open App.path & "\file.wmf" For Binary As 45
        Put #45, , bData
        Close 45
You have to rerplace "101" with the number of the resource, "CUSTOM" with the name of the type of resource, and "file.wmf" with the name that you want to use.
2. How can I create a floating toolbar?
Robert Terblanche
My solution is quite simple. In fact, it's so simple I'm wondering if I haven't missed something or maybe misunderstood your question.

All I did was to add a form to my application, and set the BorderStyle to 4 - Fixed ToolWindow. On this form I created the toolbar that I would normally have created on my main application form. When I show the form, I set the owner to the main form by saying:

    frmToolbar.Show, Me

That's it. Nothing to it. The Toolbar will now always be on top of my application, but not on top of other applications. The toolbar I used is just a simple example, using an aligned picturebox with command buttons on it, but you can of course place any toolbar in the toolbar form that you wish. You can of also totally remove the toolbar form's title bar, and add all sorts of fancy rearrangement of buttons when the toolbar form resizes.

An elegant solution. Note that for MDI applications, the toolbox must be a child of the MDI form, not a child form. See also:
4. How can I load fonts in VB?
Robert Terblanche says you can install a font by simply copying it into the Fonts directory.

He also found some code somewhere on the net that installs a font in a more "official" way (If you recognize it, tell me where it came from originally so I can give credit to the author). To download it exactly as he got it from the net, click here.

Eric Kiersky pointed out this useful Knowledge Base article HOWTO: Add a Scalable Font to Windows from Visual Basic.

5. How can I call an ActiveX exe from Visual C++?
Robert Rottermann has these tips:

My company is producing software for CAD-users, so we do most of our programming in C++ but we intend to create the UI in VB. I therefore face the challenge of linking VB and C++ programs. As long as this only consists in putting a control that is written in the "foreign" language this is (often) painless. But as soon as you have to do something more complicated or there are problems it seems to be rather difficult to get answers to questions you might have...

A couple of scenarios are possible

  1. The Server is a control:

    This is very often painless. Just put the control on a form in the VC++ resource editor. There is one caveat though, the containers VB offers (Forms, picture controls and the like) offer a richer "environment" in which the control lives and with which it can communicate. In VB parlance this environment is called Extender and Ambient properties. They do not exist for non VB containers or offer a reduced set of properties one can call. If such a control is put on a VC++ form (aka resource), the IDE will create a class with the necessary interface glue as soon as you create a member variable for the control the first time. If you change the interface of the control (the public stuff), things become messy, because the IDE just keeps on using the old "interface glue", which of course has become out of date. I have yet to find a way how to remedy this situation without scanning the MFC created files and deleting all references to the control.

    I created a mini MFC application "RRMfcControll" that hosts a simple VB created control, you can set its properties and react to its events.

    [This is the way I would probably try to do it. I should have thought of this. -- Rod]

  2. The server is a DLL or a an EXE

    To incorporate an ActiveX server that is not a control (it also works for controls by the way) MFC offers the #import compiler directive. Using it you get all needed interface glue created and wrapped into a set of smart pointers which are very easy to use. You just call your server properties in a very VB like manner. The nice thing is, that you can change your interface in VB as often and thoroughly as you like. The glue will always be up to date since it is recreated when ever MFC detects an change in the file dates. However, there is a down side too. You do not get a interface map created, so there is no "automatic" communication with your server. You have to do it yourself. As mentioned before, this is a trivial task as long as the communication is VC++ -> VB. Vice versa matters are a bit more complicated. Raising an event in VB that is serviced by a peer actually means calling an function from VB that this peer is exposing. This calls for a two way communication to be built up between peer and VB. MFC generates this two way channel automatically for you when it hosts a control on a resource by creating an message map and an event sink map. Both these maps are actually wrappers around functions that subclass the windows involved. Since nobody creates them for us we have to do it for ourselves. Luckily subclassing comes naturally to C++ and is easy to implement.

    I have included two samples demonstrating the communication of C++ with an ActiveX server. RRConBarBone is a minimal console application calling an ActiveX server RRMfcTwoWays demonstrates the use of a "hand made" message map to build up a two way communication.

    My hand crafted "message map" is of course a much simplified version of what is going on when two com objects talk to each other. I tried to understand Don Box's "Essential Com" but failed. That is why I can offer no better solution.

6. How can I pass a Form object from an In-Process DLL back to the main Application?
Max Lucas
Create a property in your DLL that returns a Variant. Set the Property to return the Form object.
    Public Property Get DLLForm() as Variant
        Set DLLFrom = Form1
    End Property
This trick will work with any object that normally gives that annoying message that it can't be passed back from a DLL.
7. How can I open a password protected database?
8. How can I open an Access 95 database that is password protected using VB?
Svetlana Kutsin
    Dim Dbpath as String
    Dim DB as database
    DBPassword as String

    DBEngine.SystemDB = DBPath & "\MyDB.mdw"
    DBPassword = "database password"
    Set DB = DBEngine.Workspaces(0).OpenDatabase( _
        DBPath & "\MyDB.mdb", False, False, ";pwd=" & DBPassword)

Reinier Kreeft
For both questions this will work:

    dim db as database
    set db = opendatabase(mydatabase,false,false,";pwd=mypassword")

Ryan Newington
Another solution:

    Data1.DatabaseName = "C:\mydb.mdb"
    Data1.Connect = ";pwd=thepassword"
    Data1.Recordsource = "My Table"

9. How can I use ADO in a multi-user environment?
Kevin B. Castleberry
This topic deserves a book. I have been dealing with this for a few months. I have a specific answer to a specific question that drove me nuts for a couple of weeks. I am in the middle of a project that I have to get done right now so don't have time to work all that up. If there is enough interest, I will consider doing this in the next few months.

The question is: In an N-tiered environment (based on Lhotka's VB 6 Business Objects book) where I have an Activex server that uses ADO to talk to an Access .mdb via Jolt 3.51 how do you get reliable error messages returned when two users try to update the same record. Here is the solution (I understand it also works with SQL Server 7.0):

If I use a clientside cursor, with batchoptimistic locking and batchupdate I can get reliable locking results that I can trap. Now when the second client tries to .UpdateBatch (assuming they get past the chgcount check) I get the following error consistently.

Case -2147217864 'The specified row could not be located for updating: Some values may have been changed since it was last read.

In the context of my app this does not make a lot of sense. That is I have the PersistLayer as an activex server running on the same machine as the MS Access .mdb. So I don't really see a reason to have to use clientside cursors. Also I am only dealing with one record in this example so the Batch part does not make since either. But hey at this point if it works I'll use it.

What I am concluding is that with ADO using Jolt 3.51 you cannot get reliable (same errors, same place) with serverside cursors. A friend has also demonstrated this technique works with SQL Server 7.0. He has not gone to the trouble of seeing if the situations that don't seem to work (that I think should using serverside cursors) will work with SQL Server 7.0.

10. How can I list the programs in the task bar?
Click here to download an example program. It seems mostly correct, though in my initial tests it missed a couple tasks.
12. How can I make a gradient color title bar?
Subclass and use an owner draw window. See this example.
13. How can I install multiple programs in one setup program?
Diego Alvarado
When you are using the auto setup maker in VB, near the end of the process before it starts compiling (the last place where you can check things on and off), you can click on an "add" button, this will compress any other program you add to it. The only drawback is that when it is installed the programs you added manually will be in the same directory as the main program.

Robert Terblanche
The source code for the setup program should be in your VB directory. On my computer it is at:

    D:\Program Files\Microsoft Visual Studio\VB98\Wizards\PDWizard\Setup1\Setup1.vbp
You can change the Form_Load event of the form Setup.frm to alter the setup procedure, or you can edit the file Setup.LST to change the files that will be installed.

The Setup1.vbp application is just another VB project, so you can change it to install seven and a half applications, run dos programs, draw fractals and beep incessantly through the PC speaker. ...If that is what you want.

So you have full control over the setup process.

Steve Squires
I made a multiple application setup file by writing down each project's references after running the setup wizard. After finishing the list, I made a setup for one of the programs and then added the files I wrote down. I set the proper directories for these files using the "file details" button. It might be a hassle if you have lots of references to include, but it works for me.

14. How can I empty the wastebasket?
Ross Overstreet
Although maybe not the most reliable way:

In Windows, a hidden directory exists which contains the data from the recycle bin. The "Recycle Bin" on the desktop is only a link to its contents. My "Recycle Bin" directory is "c:\recycled\" so the command Kill "c:\recycled\*.*" works for me.

Will Swift
Use the SHEmptyRecycleBin function.
    Private Sub ClearRecycleBin( _
        Optional ByVal RootPath As String, _
        Optional ByVal hwndParent As Long, _
        Optional ByVal NoConfirmation As Boolean, _
        Optional ByVal NoProgress As Boolean, _
        Optional ByVal NoSound As Boolean)
    Dim nOptions As Long
    Const SHERB_NOSOUND = &H4
        If NoConfirmation Then nOptions = SHERB_NOCONFIRMATION
        If NoProgress Then nOptions = nOptions Or SHERB_NOPROGRESSUI
        If NoSound Then nOptions = nOptions Or SHERB_NOSOUND
        On Error Resume Next
        SHEmptyRecycleBin hwndParent, RootPath, nOptions
    End Sub
Click here to download an example program.
15. How can I delete temporary internet files?
Herv Sherd found a solution by Eduardo Morcillo at Edanmo's VB Page.
16. How can I print a preformated file directly to printer?
Benjamin Bradford
There are two Microsoft references that address this. The best one is Q154078: HOWTO: Send Raw Data to a Printer Using the Win32 API from Visual Basic, which has an example using the WIN API to print directly to a printer device.

But the other one is more important -- if you use the FileCopy solution to copy to a printer device name that contains spaces, it will fail under NT in VB5 and VB6. This is illustrated in Q252607: PRB: The CopyFile Method Does Not Work for Printer DeviceName with Spaces on NT. To use FileCopy you'd have to remove any spaces from the NT printer devicename, therefore it's not a robust solution.

Use the API solution -- it's better!

Robert Terblanche
When you make use of the Printer object, VB will control said printer through the installed printer driver. This leads to the attempted translation of data that does not need translating, causing the problems which you have no doubt already experienced.

The trick is to open the printer as a file, and then simply copy the data from your preformatted file to the printer "file". VB thinks it is a file and does not do any translation. If the printer is connected to your LPT1 port, you can open the port itself as a file, e.g.

    Open MyFile For Input As #1
    Open "LPT1" For Output As #2

    TempString = Input(LOF(#1), #1)

    Print #2, TempString;


Some operating systems will require a colon after LPT1, so you might have to open "LPT1:" instead of "LPT1". If you want to print to a printer connected to a serial port, you can open "COM1" or "COM2" or whatever (or "COM1:"). If you want to print to a remote printer, then I'm stuck. I'm afraid I haven't tried it yet.

I have had mixed results with this technique. My printer starts to print, and then stops. This may just be a configuration issue on my system.

I got the same results with a network printer specifying the printer file name like this:

    Open "//Beauty/Digital" For Output As #2
Here the printer named Digital is being served by the computer Beauty. Presumably this will work, but I have that problem mentioned above.
Ben Rigsby adds:
One fundamental error (hopefully just a typo) is that the slashes should be backslashes, i.e. \\PrintServer\Printer, which may work on its own, but if it doesn't, the answer is to use a virtual port. For example, assign your remote printer to a virtual port, such as LPT2: or LPT3: through a DOS window, like this...
    C:>NET USE LPTn: \\PrintServer\Printer ... 
then simply open LPTn: as a file and proceed as Robert suggests for the local printer. For example:
    Open "LPT2:" For Output As #1
    Print #1, "Hello, world!"
    Close #1
Use caution when working with LPT1 if using Windows NT since LPT1 is a physical port; that is "actual hardware," which NT protects with absolute security permissions. In some, if not all, versions of NT, a failed attempt at directly accessing LPT1 results in a hardware lockout which renders LPT1 unavailable from that point on, unless and until you reboot the OS.
Tim Ayling adds:
This used to be a similar problem when I was trying to print preformatted files to a printer over a Novell network. The solution was to copy the file to the relevant captured port using the DOS binary switch 'COPY /b'.

In VB, the 'Filecopy sourcefile, destfile' method does the same. The reason Robert Terblanche is having problems is that the Input# and Print# methods try to interpret the data on-route (it doesn't say so, but it does).

The following simple code works perfectly:

    Private Sub Form_Load()
        FileCopy "c:\tims.prn", "\\Server\HP"
    End Sub
Where "c:\tims.prn" is the preformatted file and "\\Server\HP" is our networked HP printer.

NOTE: The files that are preformatted in this way are usually produced by a software package that has a default printer selected, then the file is printed with the user selecting 'Print to File' option. The .PRN file produced will then contain all the formatting codes relevant to the selected printer. Sending this ouput file to another printer will confuse the *?*?*?* out of the destination printer if it doesn't understand the control codes.

Sergio Perciballi has another approach:
I had this problem on a network. Admin had disabled MS-DOS commands and VB exe's. We found that notepad can print with the /p flag on the command line. These execute notepad/write(wordpad) and print the file you provide.
    notepad.exe /p filepath 
    write.exe /p filepath
This uses winword(word) to execute a macro
    "PathToWinword\winword.exe" "Path to Doc" /mFilePrintDefault
(DefaultPrintFile) but the program doesn't shut down unlike notepad/write which do. I have not tried FilePrint (/mFilePrint). I had to do this when using oracle forms 4.5 (a really complicated/frustrating program).
Dale Thorn:
In the Dr. Dobb's web site (, under Programmer's Resources, under BASIC, there are some utilities that do a great job of printing.

If you have a preformatted file that's coded for a particular printer, use PRNT, which simply spools characters to the printer.

For various plain-text files, PSET decides the best fit to the paper you use, and optimizes the printing as much as possible to fit.

Note: These are DOS programs called from a SHELL command. Of course, you can import the code into VB and make them VB programs.

I've used PSET extensively on every combination of network and PC, from handheld and serial port to NT and network. As long as the drivers etc. are in place, it works perfectly.

New Most Wanted List
Beginning Intermediate Advanced
Submit an Example

Download all examples as of 6/26/2001

Click here if you have trouble downloading files.

Subscribe to the VB Helper newsletter
Copyright © 1997-2001 Rocky Mountain Computer Consulting, Inc.   All rights reserved. Updated