How to use a scanner (or TWAIN-compatible digital camera) in VB6

Today’s project demonstrates how to implement full scanner support from within a VB6 project. As a bonus, it also provides support for TWAIN-compatible digital cameras.

Before we begin…

Because VB6 does not include a native scanner library, some sort of third-party DLL is required for scanner access. My preferred choice is the free, public-domain EZTW32 library, which I have happily used for many years. (The first version of EZTW32 was released in 1994!) This project uses the most recent version of EZTW32 at the time of this writing: v1.19, updated 2009.02.22. You can check for a newer version of the library here.

There are two versions of the EZTW32 library: a free, public-domain library – called “classic” – and a more sophisticated, paid version – called “pro.” This project utilizes only the classic version. The paid version includes many advanced features, and if you are interested in anything beyond simply capturing images from a scanner, it may be worth a look. A full description of the “pro” version’s feature set is available here.

While the EZTW32 library provides many ways of interacting with the scanner, this project will focus on the following:

The sample project includes a copy of v1.19 of the EZTW32 library. If you would like to download a newer version of the library, simply copy the new version of EZTW32.dll into the same directory as the executable file (or .VBP file). It should work without a problem.

Bonus tip: how to load DLLs from any location

Because a 3rd-party library is required to access a scanner in VB6, it is useful to know how to load a DLL from any location. By default, VB6 will attempt to load a DLL from the computer’s system folder. This is not ideal when developing portable applications (e.g. applications that can be run without requiring an installer), because it requires the user to manually copy files into their system folder… and that’s bad for a variety of reasons (security, potential for mistakes, etc). It is possible to load a DLL from other locations using the regsvr32 command, but I don’t like regsvr32 because it adds additional entries to the user’s system registry, and it must be re-run every time the project is moved to a new folder.

So the best solution, in my opinion, is to tell VB to expect the DLL to appear in the same folder as the project itself. (Alternatively, a /plugins/ sub-directory could be used.) We do this by adding the following code to the General Declarations section of the project:

TWAIN has some advantages and disadvantages compared to WIA and SANE. One of TWAIN’s unique characteristics is that it requires the scanner to provide its own user interface. The advantage of this approach is that on a given system, TWAIN-compatible programs all launch the same scanner user interface – the interface provided by the scanner itself. This is good for casual users, because regardless of whether they use this program or Photoshop or GIMP, the scanner interface will always be the exact same. The downside is that if you want to implement custom scanner features or options, TWAIN makes it difficult.

Because TWAIN relies upon the scanner to provide its own user interface, the user will see a different scan window depending on their scanner brand. My Canon scanner software looks like this.

Another advantage of TWAIN is its longevity. The TWAIN standard has been around since 1992, so pretty much every scanner made in the last 20 years will offer TWAIN drivers. By comparison, WIA didn’t exist until the year 2000, and it wasn’t until Windows Vista that most scanners offered WIA support.

One disadvantage of TWAIN is that Windows Vista and Windows 7 give WIA preferential treatment. If you set up a new scanner using the default Windows Hardware Wizard, it may only load WIA drivers – meaning you’ll need to hunt down the install CD that came with your scanner, or download the latest driver bundle from the scanner manufacturer’s website. I discovered this the hard way when testing this program with my Canon all-in-one printer/scanner/fax. If my program can’t find your scanner, download the free GIMP image software from this link and use the File -> Create… -> Scanner/Camera… option. If my program can’t find your scanner, and GIMP can’t find your scanner, you probably don’t have TWAIN drivers installed. If GIMP works but my program does not, send me a message and I’ll investigate further.

Download the sample project

My sample project is pretty minimalist:

The sample project keeps things simple.

I tried to keep the code as small and simple as possible. Again, the latest version of the EZTW32 dll (v1.19) is included in the download. Future versions of the file should be backwards-compatible; simply replace the existing dll with a newer version.

DISCLAIMER: These download files are regularly scanned to ensure they remain free from malicious content. Unfortunately, some virus scanners will flag these .zip files as suspicious simply because they contain source code and/or executable files. I have submitted my projects to a number of companies in an attempt to rectify these false-positives. Some have been cooperative. Others have not. If your virus scanner alerts you regarding these files, please allow the file to be submitted for further analysis (if your program allows for that). This should help ensure that any false-positive warnings gradually disappear for all users.

This site - and its many free downloads - are funded by donations from visitors like you.Please consider a small donation to fund server costs and to help me support my family.Even $1.00 helps. Thank you!

thnx for u r valuable code, i am using canon imageclass mf4450 printer/scanner/fax model to scan the document[drivers r installed],i copied all code from your sample project and run the project and set the scanner setting to remote scanner. but when i click to scan button on my vbform or even in u r sample project, scanner starts scanning progress bar moves and shows the scanning % but it do not pulls the document so blank copy gets scan, i dont know whats the ploblem plz help me i am really stuck….

1) Are you checking for scanner errors? Use a Long-type variable to check the return value of TWAIN_AcquireToFilename(). If it returns a value other than zero, the error occurred during scanning. (The sample project shows the errors that correlate to various return values.) If that function returns zero, the EZTWAIN library believes the scan was successful, and the problem probably lies in VB.

2) Check the temporary BMP file that is created. Is it blank? If it is, then you’ll need to review your scanner documentation for additional information. If it is not blank, there is no reason you shouldn’t be able to load the picture into VB.

3) If TWAIN_AcquireToFilename() returns zero and the BMP file is created successfully, then the problem occurs somewhere in the loading-into-VB section. Make sure the Picture Box you are using has AutoRedraw set to True.

20 kb is extremely small for an image, but you might be able to do it by using the JPEG format at a very low quality. VB doesn’t provide a way to save JPEGs directly, so you’ll need to use a custom piece of code. I recommend this class by John Korejwa:

Hi ergheegh. Note that the code above does not save a JPEG. It saves a bitmap file with a JPG extension. It’s like taking a Microsoft Word document and changing the file extension to .JPG – the file is still a Word document, and all you’ve done is change the extension. VB6 can only save bitmap images.

Why would anyone develop new functionality using a 15 years old development platform? Don’t get me wrong, it’s not trolling (maybe just ignorance).

Even if you had to maintain and old and giant codebase, wouldn’t make sense to develop such new functionality, like scanning images, in .NET (or whatever else) and include it as an external binary so its possibilities to be reused, test and maintain are at least greater than zero?

You’re not the first to ask this question, so don’t worry about trolling. :) I’ve talked about this elsewhere, and a full answer would be too long for this comment box, but here are the most obvious points:

– Portable applications. How many languages can you run from a USB drive on any Windows machine, XP through Windows 8? Certainly not .NET, as the .NET framework is not a guaranteed presence on Windows machines. The VB6 runtimes are included by default on every OS since XP (through Win8, as of this writing).
– Ease of development. With VB6 and EZTWAIN, a full scanning application – with GUI – can be developed in less than 20 lines of code.
– Performance. I know this sounds ridiculous, but it’s completely valid. VB6 compiles down to native code. Many modern languages (python, javascript, etc), are outperformed by classic VB, surprisingly.

Others may have their own reasons, but I think people would be surprised by how much traffic the VB sections of my little site get – let alone large ones like planet-source-code.com, which still receive new classic VB projects almost daily.

Really, I think a better question would be – why *wouldn’t* people still use VB6? A good answer is not as obvious as most people might think.

Hi Andhika. I’m only familiar with the EZTwain calls that automatically display a UI. I believe it’s possible to scan without a UI, but you must set certain parameters manually (like resolution). Here is a website that may be helpful to you: Accessing TWAIN compatible scanner in Visual Basic

Hi Vivek. The scanner saves the image to a file by default (hence the “TWAIN_AcquireToFilename” function name). If you want to re-save it after it’s been rendered to the picture box, use VB’s SavePicture function.