Copyright: Copyright ¢ 1993 by Desaware


CONTENTS
Desaware

1100East Hamilton Ave, Suite 4    Campbell, CA 95008
(408) 377-4770  fax: (408) 371-3530, Compuserve: 74431,3534

Online Catalog (Visual Basic 4 Unleashed edition)

Thank you for visiting our online catalog. We are pleased to present you with detailed information and demonstrations on our products. Our new OLE custom controls (OCXs) are now available, but we were not able to provide demos for them in time for this show. You can still read about them here, please contact us for more information on our latest line of products.

SpyWorks-VB Now shipping Version 2.1 - compatible with Windows95. The ultimate low level programming toolkit for Visual Basic.

VersionStamper-VB Eliminate VBX and DLL incompatibilities when distributing your Visual Basic applications

The Common Dialog Toolkit - Tap into the full power of the Windows common dialog from Visual Basic.

CCF-Cursors - Create and use customer cursors (Mousepointers) in your Visual Basic applications.

The Custom Control Factory - The ultimate button factory: completely customizable including 3D effects, animation and virtually unlimited states.

Visual Basic Programmer's Guide - Learn to use the Windows API from Visual Basic.

How Computer Programming Works - A new book for non-programmers and beginners.

Technical Notes - A brief letter from the President of Desaware.

Ordering Information - The bottom line: prices and how to order.

Visual Basic Bulletin #1 - Access Issue #1 of our advanced technical newsletter.

SpyWorks Version 4.0 - The ultimate low level programming toolkit for Visual Basic, now available as an OLE custom control.

VersionStamper Version 4.0 - The best way to resolve file incompatibilities, now available as an OLE custom control.

StorageWorks-VB Version 1.0 - New Product! The ultimate data storage and file manipulation toolkit.

Custom Control Factory Version 4.0 - The ultimate button factory, now available as an OLE custom control.


SpyWorks-VB
SpyWorks-VB Version 2.1

SpyWorks-VB allows you to do virtually anything in Visual Basic that is possible with other languages. It does this by supporting powerful Windows programming techniques that are not part of Visual Basic. Subclassing allows you to intercept any Windows message going to a form or control. Callbacks allow you to provide function pointers to Windows and other DLL's which trigger VB events when called. Hooks give you system or task access to keyboard and mouse events.

•	Philosophy of SpyWorks - An unusual approach to extending Visual Basic. progman.hlp

•	Run the SpyWorks-VB Demo

Custom Controls:

•	SBC.VBX - Generic subclassing custom control.

•	CBK.VBX - Callback custom control.

•	SBCKBD.VBX - Keyboard hook custom control.

•	SBCHOOK - Windows hooks custom control.

•	SBCEASY.VBX - Scrolling forms, rollups and more.

•	DWTIMER.VBX - A more reliable timer than the standard timer control. Supports unlimited timers and it will not miss timer events.

•	DWSPYDLL.DLL - Extensive function library.

Debugging Tools:

•	SpyMsg - View Windows messages and Visual Basic events.

•	SpyParam - Detect Windows API parameter errors.

•	SpyWin - Determine windows hierarchy.

•	SpyMem - Analyze Windows memory, resource use, etc.

•	SpyMenu - Read the menu structure for any window.

•	SwIniEdt - Organize messages into groups.

•	SpyNote #1 - Application notes


SpyWorks-VB Philosophy
The Philosophy of SpyWorks-VB

One of the great advantages of Visual Basic over any other Windows development language is that it is extremely "safe" to use.  In theory, it is impossible for a Visual Basic programmer to crash the system or to cause a General Protection Fault or other system error from within Visual Basic.  This makes programming extremely efficient - you can quickly experiment and modify your code, examining intermediate values in the immediate window as needed.  This differs markedly from other development systems where bugs frequently cause memory corruption, use of invalid pointers, and other errors that require sophisticated debuggers and many reboot/restart cycles.

Visual Basic protects you from your mistakes, but there is a price to pay for this safety.  Visual Basic only implements a subset of the features that are available under Windows.  As a result, there are many tasks that are difficult or impossible to do with Visual Basic directly.  There are currently two methods for extending Visual Basic.  You can directly access Windows API functions from VB, or you can write Dynamic Link Libraries or VB custom controls using C or C++ and traditional Windows programming techniques.

SpyWorks-VB provides a third approach to extending Visual Basic.  It consists of a number of tools and programs to support extending the capabilities of Visual Basic from within the VB environment.  No C or C++ language or other tools are required.  These tools take two forms: Extension tools and Debugging tools.

The extension tools consist of five custom controls: SBC.VBX (Generic subclass) CBK.VBX (Generic Callback), SBCKBD.VBX (Keyboard hook), SBCHOOK.VBX (Windows hooks) and SBCEASY.VBX (subclassing solutions).  SBC.VBX is a powerful custom control that allows you to intercept and manipulate the underlying Windows message stream for any Visual Basic form or control (including custom controls).  CBK.VBX is a custom control that contains a pool of function addresses that can be uses as "callback" functions for Windows API functions.  With these two controls and access to the Windows API functions, you can do virtually anything in Visual Basic that you could do using a dynamic link library.  SBCKBD.VBX is a task or system keyboard event detector which allows you to intercept keyboard entries before they are received by Visual Basic or another application.  SBCHOOK.VBX uses Windows "hooks" and is ideal for intercepting windows messages on a global basis.  SBCEASY.VBX implements common subclassing tasks including Mouse tracking, scrolling and virtual forms, tiny captions and rollup windows.

The debugging tools are designed to help you to work with the extension tools and with the Windows API.  The SPYPARAM.VBX custom control detects Windows API parameter errors to help track down elusive bugs in the API interface.  SpyMsg.exe is a powerful detection program that allows you to detect and record both the Windows messages and Visual Basic events that are sent to a form or control.  SpyMem.exe is a memory browsing tool to help track memory usage - indispensable for making sure that all memory blocks and GDI objects are properly released. SpyMenu.exe helps you to understand the menu structure for a window. SpyVBX.exe can be used to analyze any VB form or control.

There is a price to pay for this power.  SpyWorks-VB is one of the few products you will ever buy that proudly and clearly claims to make it much easier to crash your program.  This tradeoff is common in the programming world: with power and flexibility comes a reduction in the level of protection provided by the environment.  SpyWorks-VB, by intercepting the Windows message stream and improving access to the Windows API makes it very easy to crash not only the application that uses it, but other applications as well.

SpyWorks-VB is designed for the intermediate to advanced Visual Basic programmer who has a knowledge of how to use the Windows Application Programmer's Interface (API).  Some components of the package are useful to anyone (the SpyMsg.exe program, for example, by tracing all VB events that occur in an application, provides a useful debugging tool even for beginners).  However, a good understanding of Windows is required to really use this package successfully.

If you already know Windows well, you will find SpyWorks-VB extremely easy to use.  Simply consider the task you wish to perform and how you would do it in C or C++, then write it in Visual Basic.  Any code that you would normally write in a Windows procedure in response to a Windows message, you can place in an event in an appropriately configured SBC.VBX custom control.  Any time you need a function pointer to use as a callback function, simply use a CBK.VBX custom control to obtain one.  Where you would use Windows hooks, use SBCHOOK.VBX.

If you have never programmed in Windows, you must learn about it in order to use this package effectively.  The professional version of Visual Basic comes with the help file for the Windows API - this can be used as a reference for all available Windows API functions and Windows messages.

There are other references available.  Desaware strongly recommends "PC Magazine's Visual Basic Programmer's Guide to the Windows API" as a supplementary text for working with SpyWorks.  This book was written by the author of SpyWorks, and in fact includes a subset of the SpyWorks package (including a limited subset of the CBK.VBX custom control).  You can order this book at a 20% discount directly from Desaware.

SpyWorks-VB is a tool.  Most add-on programs have a clearly defined set of operations that they can perform.  Their documentation can, and often does, include extensive examples to show the capabilities of the product.  A dozen books and manuals could not begin to do this with SpyWorks, because it has no clearly defined set of operations.  It is a can-opener that enables you to tap the full power of Windows from within Visual Basic.  This manual includes a number of examples of how the extension controls can be used, but we cannot even begin to guess at the potential of what can be accomplished.  Try running the SpyDemo demonstration program to get a taste of some of the possibilities.


SBC.VBX
SBC.VBX - Generic Subclass Control

•	Detect windows messages for any window, form or control in the system and trigger a VB event when it occurs.

•	Detect messages before the Windows default processing, after the Windows default processing, or simply post it to yourself for later examination.

•	When detecting messages before the default processing, you can change the message or its parameters, or cause the message to be completely ignored.

•	Detect messages that are sent from Windows, or those sent directly by Visual Basic - this allows you to see the internal VB messages in VB forms and controls.

•	Even detect messages for the new VB2/VB3 graphical controls.

•	Subclass windows in other applications - you can effectively create VB programs that add their own menu commands to another application so that your VB program acts as an Add-on to that application.

•	Specify exactly which messages to detect - this minimizes the overhead to provide the fastest possible performance.

•	Detect registered windows messages.

•	Delayed event processing - allows you to "post" an event to yourself without setting up a timer control.

•	Each SBC.VBX control can subclass multiple windows or controls (limited only by memory).

•	The SBC.VBX control can be configured to queue up messages received while a message box is visible (overcoming a limitation in VB).


CBK.VBX
CBK.VBX  - Generic Callback Control

•	Provides a pool of function addresses which can be passed to the Windows API or any Dynamic Link Library for use as callback functions.

•	Over a dozen standard parameter sequences (callback function types) are provided, along with Desaware's guarantee:  If you need a callback type that is not provided we'll add it and send you and update - fast.

•	Over 100 function addresses in the internal function pool (far more than you're ever likely to need, but we'll add more if you need them).

•	Support for both the standard 'Pascal' and the 'C' calling convention.

•	Cross task callbacks makes it possible to use callbacks that occur in the context of a different task.

•	Posted callbacks allows use of the CBK control even with callbacks which restrict use of API functions to PostMessage only (low or interrupt level).

•	Can be page locked for use with low level multimedia API callbacks.


SBCKBD.VBX
SBCKBD.VBX - Keyboard Hook Control

•	Receive all keystrokes sent to any task.  Keystrokes are detected before they are sent to the application, thus you can even trap the enter key, control break, and tab key.

•	Place a system wide keyboard hook.  This allows your VB program to be a "hotkey" type application which is triggered by a specific key sequence regardless of which application is active.


SBCHOOK.VBX
SBCHOOK.VBX - Windows Hooks Control

•	Implementation of Windows hooks including WH_MOUSE, WH_GETMESSAGE, WH_MSGFILTER, WH_SYSMSGFILTER and WH_CALLWNDPROC, New hooks supported in Version 2.1 - WH_CBT, WH_JOURNALPLAYBACK, WH_JOURNALRECORD - Allows interception of messages going to many controls without subclassing each one.

•	Full control over scope of message detection - per form, per task, or System-wide.

•	Can be configured to queue up messages received while a message box is visible (overcoming a limitation in VB).

•	Specify exactly which messages to detect - this minimizes overhead to provide the fastest possible performance.

•	Detect registered windows messages.

•	Detect messages as they occur, or post them for later processing.

•	Ability to change or discard messages (depending on the hook and message)


SBCEASY.VBX
SBCEASY.VBX - Windows Hooks Control

•	True 'MouseEnter', 'MouseExit' event for every form or control in your application - including Visual Basic graphical controls.  Ideal for status bars.

•	Easy detection of menu select events - also ideal for status bars.

•	Determine update area of a window during VB Paint events.

•	Create 'Tiny' captioned windows similar to the VB control toolbar out of forms and most container controls.

•	Ability to modify or draw your own window captions.

•	Create rollup windows (drop down form) out of forms and most container controls.

•	Intercept, block or modify system menu commands.

•	Turn on scrollbars for any form, picture control and many container controls.

•	Perform automatic scrolling on any form, picture control and many container controls.

•	Turn forms, picture controls and most container controls into "virtual" controls where control acts as a window to a larger area than is visible.


DWSPYDLL.DLL
DWSPYDLL.DLL - Function Library

•	Dozens of functions that allow you to access Windows API functions easily and to manipulate data.

•	Functions for obtaining the address of VB variables, performing huge memory calculations, splitting integer and long variables into component parts, and so on.

•	Functions to provide access to the DeviceCapabilities, DeviceMode and ExtDeviceMode functions in any printer driver.

•	A subset of the Visual Basic API including functions to obtain the name of a form or control, to determine the hierarchy of forms and controls, and so on.

•	Indirect property access - read/write property values to any VB form or control in any application.

•	Read/write picture properties. Allows easy combination of API picture functions with VB properties.

•	Complete set of functions for analyzing the internal structure of any VB form or control.


SpyMsg

•	View any or all of the messages and events going to a form, control or task.

•	Your choice of detection technologies to use: subclassing, SendMessage hooks or GetMessage hooks.

•	Set the scope of message and event detection: Any combination of one or more windows, any task, or system wide.

•	Detect VB events for any form or control.  Events are detected even if there is no code attached to the event.

•	View detailed information on the form or control that received the message or event.

•	View information on the parameters to the message or event.

•	Easy selection of Windows to subclass - use a Windows hierarchy "tree" or point at a window and click.

•	Detects messages and events for VB2 graphical controls.

•	Write output to a file to create a complete history of the messages and events that occur in your application.

•	Parameter descriptions for most standard windows messages.


SpyParam

•	Detect API parameter errors as they occur (under Windows 3.1, many parameter errors are simply ignored).

•	Trigger a VB runtime error when an API parameter error occurs.  This can save hours in trying to track down an obscure problem.


SpyWin

•	The first truly Visual Basic aware window/form/control browser.

•	Windows are organized by task, making it easy to track down the windows for a given application.

•	Provides a great deal of information about each window/form or control, including VB specific information such as control name and model information, styles, class information and so on.

•	Allows you to select windows for further processing by your own programs.

•	SpyWin includes complete Visual Basic source code!


SpyMem

•	Browse the Windows global heap, and any local heap (including USER and GDI).  View any block of memory.

•	Browse the Windows task and module list.  Free any module (ideal for cleaning up after a GPF).

•	View the GDI resource list.  View information about each resource (for example: if it is a brush, you will see an area painted by the brush - if it is a bitmap, you can view the bitmap).

•	Automatic comparison of the current heap with a saved reference - makes it easy to track down global memory or resources that are not being freed.


SpyMenu

•	Analyze the system menu and regular menu for any window in the system.

•	Includes complete Visual Basic source code.


SpyVBX

•	Analyze the model, property and event structures for any Visual Basic form or control including custom controls.

•	Direct analysis of VBX files that export MODEL information using VBModelInfo.

•	Dump complete analysis of a form, control or custom control to a text file.

•	Supports version 1.0 through 3.0 of Visual Basic.

•	Demonstrates how to read or write properties of any VB form or control.

•	Includes complete Visual Basic source code.


SwIniEdt

Provides easy editing of the SpyWorks.ini initialization file.  Used for creating groups of messages that are used by the other SpyWorks-VB applications and debugging tools.


SPYNOTE1
SpyNotes #1

SpyNotes are a series of application paks that will deal with a particular subject and include both code and documentation in Windows Help file format.  SpyNotes #1 is included free with SpyWorks-VB version 2.0.  Refer to the On-line help for further information on this package.


Visual Basic Programmer's Guide
Visual Basic Programmer's Guide to the Windows API

Build on your knowledge of Visual Basic to become a Windows expert by learning to take advantage of the hundreds of functions contained in the Windows API.  No knowledge of 'C' or prior Windows knowledge is required.  Written by the president of Desaware, it covers virtually every aspect of Windows and includes extensive sample code.  Over 1000 pages plus disk.  Published by Ziff-Davis Press. ISBN: 1-56276-073-4.  List is $34.95, but we have it for only $27.96 (20% off).


How Computer Programming Works

This new book from Ziff-Davis Press is part of their best selling "How It Works" series. Written by Daniel Appleman, president of Desaware, this fully illustrated book introduces the fundamentals of programming and computer science in a way that is easy to understand for non-programmers and beginning programmers alike.

Ideal for helping friends and family to understand what it is that you actually do during all those hours that you sit in front of your computer!

Available from Desaware for 20% off list - only $19.96


VersionStamper-VB

You get a technical support call....

"Your program has stopped working!"

Did someone install an older version of a VBX or DLL required by your application?

Is another program using an incompatible version of a VBX or DLL that it loaded from a private directory, preventing yours from loading?

Is an incompatible version of a VBX or DLL present somewhere in the PATH and being loaded before the one that is required?

Did the user delete a component that is needed?

Did the user reinstall your application using an older release disk - copying over your most recent files because your VB application does not contain version information?

If only your application could tell you what was wrong....

Now it can....

Solving the Installation Problem

Solving the Distribution Problem

Fixing the Visual Basic Setup Kit

Additional Tools and Information

Run the VersionStamper-VB Demo


Solving the Installation Problem
Solving the Installation Problem.

Make no mistake - there is no simple "fix" to the problem of safely distributing Visual Basic applications. However, if you have complete information about the incompatibilities that occur and the versions of both components and VB executables, it is possible to quickly determine exactly what problems exist. Once you have this information, it becomes easy to find the correct solution.

Embedding version resources into VB applications.

The first, and most obvious need is to embed a standard Windows version resource into executables created by Visual Basic. This will make it possible for any standard Windows installation program to correctly handle your Visual Basic programs and prevent the accidental overwriting of later versions of your executables.

VersionStamper-VB contains the dwvstamp.vbx custom control which makes the process of embedding a version resource into your executable completely automatic. The version information is entered by setting the control's properties at design time just as you would set the properties for any custom control. This information will be converted into a standard version resource automatically during the compilation process.


Solving the Distribution Problem
Solving the Distribution Problem.

The key to eliminating problems relating to the distribution of Visual Basic applications is to be able to determine, quickly, whether all of the components required by the application are, in fact, present in the runtime environment.

Embedding component version information into your application.

The dwvstamp.vbx control makes it possible to embed into the executable a complete list of every DLL, VBX or other software component that is needed by your program. This embedded component information includes the required version information for each component. You can also specify the conditions under which a warning will be triggered.

Dwvstamp.vbx is able to automatically scan a project for a list of the custom controls used by the program and a list of all DLLs referenced by the Declare statements in the project.

Detecting component incompatibilities at runtime.

Since an executable stamped by dwvstamp.vbx "knows" exactly what components it requires at runtime, it is an easy matter for it to check if all of those components are available and up to date. This comparison process is also built into the dwvstamp.vbx custom control.

VersionStamper-VB provides a great deal of flexibility in terms of how you handle the scanning and reporting process. Beginning programmers may simply choose to add the standard Vervrfy.frm form or vervrfy2.frm form and associated modules to their application to provide a default verification check at load time or under user control. More advanced programmers may choose to modify the code to create their own custom report. You might also provide the user with a step-by-step procedure on how to fix certain problems, or perhaps a request that they call your customer support line.

It is possible for the software components required by an application to be so old that the program will not run at all. For these cases VersionStamper-VB includes two sample "Rescue" program which are able to compare the component requirements of an executable with the runtime environment without actually loading that executable. These rescue programs include complete source code and can be fully customized to suit your own needs.


Fixing the Visual Basic Setup Kit
Fixing the VB setup kit.

There are many setup and installation programs available. The Visual Basic setup kit is actually quite good for many applications. However, it does contain one major error in the way it handles version comparisons.

VersionStamper-VB includes suggestions not only on how to fix this problem, but on how to add additional improvements. We use these techniques in the installation programs for all of Desaware's products.


Additional Tools and Information

VersionStamper-VB includes a program called VerInfo.exe which is able to report on the version information of any executable that contains a version resource. It is also able to report on the embedded component information added by the dwvstamp.vbx control.

This program also includes full source code. Which brings us to one of the final features of this package, a feature that we feel is one of the most important.

One of our goals at Desaware is to not just provide "canned solutions" for programmers but to also help educate programmers to take advantage of all of the technology that is available to Visual Basic programmers. Following this philosophy, you will find a fair amount of technical material in this manual and a generous amount of Visual Basic source code as well. We will also cover some of the reasons why certain things work the way they do and how they influenced the design of VersionStamper-VB.

But fear not - this product was designed to be used by absolute beginners as well. And for those who just need a quick solution to the distribution problems discussed earlier, feel free to skip forward to the Quick Start section which will walk you through the process of embedding a version resource, embedding component information and adding a runtime conflict report in a few easy steps.


Common Dialog Toolkit
The Common Dialog Toolkit (SpyNotes #2)

What are SpyNotes?

The release of SpyWorks-VB opened an entire new set of capabilities for the Visual Basic programmer.  The primary goal of SpyWorks-VB is, in fact, to make it possible to accomplish virtually anything in Visual Basic that is possible to do using more traditional Windows programming techniques. As a result, SpyWorks-VB has been one of the most succesful add-on products for Visual Basic to date.

We have found that there is a real need among Visual Basic programmers for more advanced information than is commonly available - especially when it comes to dealing with the intricacies of Windows itself.

The Common Dialog Toolkit is the second of ongoing series of application paks for use with SpyWorks-VB.  These application paks combine text in windows help file format along with plenty of sample code.  Most of these paks will be on a single subject, for example: multimedia, or Database Access, and will cost about the same as a good book or newsletter might.

The Common Dialog Toolkit discusses advanced programming topics with an emphasis on using and modifying the Windows Common Dialog box library.  It provides far more capability than the limited cmdialog.vbx custom control provided with the professional edition of Visual Basic. Many of the techniques described can apply towards other tasks and third party DLL's as well - so you should find the package worthwhile even if you never use the common dialogs themselves.

And as always, you'll find more than one technique demonstrated that is generally thought to be "impossible".

The following is a brief summary of the techniques that are demonstrated in this package:

•	How to call the common dialog API functions directly.

•	Finding and manipulating controls within a common dialog.

•	Using the CBK.VBX control to implement a common dialog hook.

•	Hiding command dialog controls.

•	Positioning a common dialog before it is shown.

•	Making common dialogs Modal or Modeless.

•	Communicating with common dialogs and use of registered messages.

•	Hooking the Visual Basic GetMessage loop.

•	Embedding Visual Basic controls into common dialogs.

•	Creating new controls on common dialogs.

•	and much more....

Run the Common Dialog Toolkit Demo


CCF-Cursors

The cursor's primary role in a Windows program is to indicate the position of the mouse on the screen.  However, in many applications the cursor plays a key role in indicating the state or operating mode of a program.  For example:  The hourglass cursor indicates that the user should wait.  The I beam cursor is often used to indicate a position in a text string.  In paint programs, cursors often indicate the tool in use.  A pencil, paint can and aerosol spray cursor can indicate the draw, fill and airbrush operations.

Visual Basic comes with only 12 built in cursors (or "mousepointers" as they are called), and could not easily be extended - until now.  CCF-Cursors has been designed to provide this capability and much more.

CCF-Cursors Features:

•	The ability to create cursors from scratch, or to convert any icon into a cursor.

•	The ability to set the cursor for a form or control including VB 2.0/3.0 graphical controls.

•	The ability to set the default cursor for all controls on a form.

•	The ability to detect mouse events (MouseUp, MouseDown and MouseMove) for ANY control (including those that do not support mouse events).  Also detects DblClick in most controls.

•	Detection of menu selection events and characters entered when a menu is active.

•	Support for automatic cursor animation.

•	The ability to set and retrieve the cursor location, both in screen coordinates and control coordinates and to restrict the cursor to any control or part of a control or form.

•	Full compatibility with Desaware's Custom Control Factory makes it easy to save cursors in your Visual Basic form or .exe file.

•	A set of windows resource and coordinate transformation functions to simplify cursor operations.

•	Icon to cursor conversion program icon2cur.exe and other demonstration programs with Visual Basic source.

•	Application oriented documentation with detailed examples including cursor animation, cursor selection based on various criteria, etc.

•	Over 50 Sample cursors including directional arrows and the rotating hourglass.

Run the CCF-Cursors Demo Program


Custom Control Factory
The Custom Control Factory

Much of the power of Visual Basic derives from use of controls to build an application's user interface.  The Custom Control Factory by Desaware has been developed to help bridge the gap between the standard controls included with Visual Basic, and custom controls which otherwise require advanced programming using the Visual Basic Control Development Kit, Windows System Development Kit and a 'C' compiler.

The Custom Control Factory allows you to create a wide variety of button controls.  For example:

•	Animated Buttons - Define a sequence of images to form an animated flic that will play each time you click on a button.  Four different animation cycles are available.

•	Multistate Buttons - A Mulitstate button can have any number of states, each with its own unique image.

•	2-State Animated Buttons - A button that supports two states (like a checkbox) except that the transition between the two states can be fully animated.

•	Enhanced Standard Buttons - Enhanced versions of the standard Visual Basic button, checkbox and option button controls.  One can define the appearance of a button in both pressed and unpressed states.

•	Toolbar Buttons - Create a toolbar similar to that used in Visual Basic and other Windows applications.

•	BONUS!  Now includes MLIST2.VBX - an enhanced listbox control that allows list box entries to contain bitmaps, to be colored individually, and more.  Includes all source code!.

In addition, all Custom Control Factory buttons support the following features:

•	Flexible Text Placement - The button caption can be placed on any side of the image or positioned anywhere on the image.

•	Multi-line Captions - The button caption can contain multiple lines, and can be left, center or right aligned.

•	Use any Bitmap , Icon, Cursor or Metafile - Any Windows compatible bitmap, icon, cursor or metafile may be used to define the image frames for a button.

•	Save/Load to File - Image sequences and CCF button properties can be saved to files to create libraries of custom controls.

•	Automatic 3D Effects - Build 3D style borders with user defined attributes such as color and width.

•	Synchronization and Owner Draw Capability - Control every aspect of drawing for each state or frame in the control.

•	DDE Support - Use Dynamic Data Exchange to allow images to be transferred to and from CCF Controls.

•	Image Compression - Bitmaps can be compressed when saved to disk and may be compressed in memory.  This helps reduce EXE file size.

•	256 Color Support - with user specified palettes.

•	Runtime Configurable - Most CCF button properties (including images) can be changed under program control at runtime.

•	No Special Programming  - Custom Control Factory buttons are created interactively at design time.  No special programming is required to create or use these controls.

•	Adjustable Animation Speed

•	Software Trigger - CCF buttons can be triggered under program control.  This allows additional effects, such as continuous animation, to be supported.

... and others (including image scaling, automatic control sizing, click position detect, and so on....

Run the Custom Control Factory Demo


Tech Notes
Technical Notes

Desaware's products are designed to be used by professionals. This means that we do our best to make them efficient in terms of resource and memory use. Some of the most important features of these products are often "behind the scenes". The purpose of this paper is to introduce you to some of these hidden features.

SBC.VBX - Efficient Subclassing:

Subclassing a window by its very nature implies that the subclassing code will receive and process every message received by the window being subclassed. The performance impact of subclassing itself is very small - however we were concerned about several issues when developing this control.  First, neither we, nor Microsoft guarantees that it is safe to fire a VB event during every Windows message. We know for a fact that there are many operations that are not allowed during certain types of message processing. Second, executing Visual Basic code for each message has higher overhead than processing it in C. In order to handle both situations, SBC.VBX only triggers VB events for those messages that you specify. This significantly reduces the chance of accidental errors, plus it reduces the amount of VB code required for message processing.

SBC.VBX is also able to safely subclass windows in other VB or non-VB applications, and to subclass VB3 graphical controls (that do not have a window handle).  Each SBC control can subclass any number of controls, providing an efficient mechanism for subclassing multiple windows.

Subclassing is a simple idea in concept, but can be very tricky in practice - especially in an environment such as Visual Basic where a form or control may be subclassed several times by different 3rd party tools.  SpyWorks-VB has been designed with this in mind, and uses a number of advanced techniques to cooperate with and protect itself from other tools and applications.  These are detailed in the August 93 issue of Windows Tech Journal in an article titled "Rules of the Road".

dwVStamp.VBX - Automation or Full control + efficiency.

Visual Basic promotes the use of software components - VBX's, DLL's and so on.  But while Windows provides good technical support for use of components, it is pretty clear that its designers never considered the real world problems that occur on systems with multiple versions of shared components.  We ourselves have spent plenty of time on the phone chasing down bugs that turned out to be old versions of controls that somehow "reappeared" on our customer's systems.

VersionStamper-VB is our way of providing a tool to solve these problems when they occur. We had three major design criteria.  First, we wanted it to be easy to use for those who wanted a quick and simple solution to these distribution problems. If you accept the control's defaults, all you need to do is select embedded files, type in your version numbers, and add a module and form to your application that contains our default report generator (assuming you want that capability).

But we also wanted to provide flexibility for serious programmers. As such, all conflict resolution is handled through Visual Basic events, allowing you to take complete control over the way any problems are handled. The package includes plenty of source code (all of the Visual Basic utilities include source code).

Finally, we wanted the control to be efficient. As such, we placed all code used at design time into a separate design time DLL that is not distributed with your application.

CBK.VBX - Different protocols, and a unique guarantee

Callbacks involve passing a function address to a DLL or Windows API function which it will call in order to trigger a VB event. Most callback functions use what is known as the PASCAL calling convention, however a few use the 'C' calling convention. CBK.VBX is designed to handle either type.

There are some callbacks under Windows that take place at a very low level (even at the interrupt level).  The documentation for these callbacks warns that only the PostMessage API function may be safely called by the callback function.  The low level multimedia functions are an example of functions that use this type of callback.  With SpyWorks-VB version 2.0, CBK.VBX is able to handle these callbacks by posting a message to itself which will later trigger the Visual Basic callback event.  You can specify a default return value to for this type of callback (though in practice, few of these callbacks expect a return value).

There can be any number of callbacks types - depending on the parameters that are passed with the callback. In theory, it is possible to create a generic callback that simply points to an area on the stack, however we felt this would be extremely difficult for most people to use. Instead, we provide a VB event for each callback type with this unique guarantee: if you require a callback type that is not already implemented in CBK.VBX, we will add it for you at no charge. The new callback type will be incorporated into all future versions of the control, so you need not worry about incompatibility as long as your customer is using the version of the control that you distribute or a later one (and of course, all of our controls are properly version stamped).  We've done this about 5 times so far, each time we've delivered the update within 72 hours (on one occasion on the same day).

SpyParam - Parameter error notification with a subtlety

We've wasted hours of time debugging some API calls. You see, Windows 3.1 often ignores API parameter errors such as invalid window handles (these errors used to cause UAE's under Windows 3.0). The SpyParam program detects these API parameter errors. It has two intriguing capabilities - first, the ability to trigger a Visual Basic runtime error on the exact line that an error occurs. Second, SpyParam is able to ignore parameter errors that are caused within Visual Basic or by custom controls (the kind that you have no control over, and that are often harmless).

SpyMsg - Event spying

We feel that SpyMsg is one of the most flexible message spy programs available. It allows you to specify the method to use for spying (subclassing or windows hooks), and to precisely control the task or window(s) that are being monitored.

But what we're really proud of is the fact that SpyMsg is able to spy on actual Visual Basic events for any VB 2.0 or 3.0 application. This means that you can literally create a history of the events in a program (including the parameters to those events). It spies on events regardless of whether or not there is VB code attached to the event. This is ideal for tracking down many types of bugs, especially those relating to reentry problems.

Our Technical Vision - a note from the president:

It is my belief that Visual Basic represents the future paradigm for programming. Visual Basic itself is an impressive implementation of that paradigm, and I expect that it will continue to be one of the dominant platforms for Visual programming.

One reason for this is that it is possible to use Visual Basic to write Windows applications without compromising on the power of traditional C and SDK based techniques. I've seen a great many VB programmers get frustrated by their inability to do something in VB and blame the environment itself.  My primary goal with Desaware (aside from keeping a roof over my head), is to help VB programmers break through these walls both through education, and by providing innovative development tools.

I think we've made a good first step in this direction. My book, "PC Magazine's Visual Basic Programmer's Guide to the Windows API" is being very well received as a "Windows SDK" for the Visual Basic programmer. SpyWorks-VB provides the low level hooks and debugging tools required to do the heretofore "impossible" in VB.  VersionStamper-VB is the first product to seriously address the problems of distributing applications made from a large number of components.

In the future Desaware will continue with this approach. You won't be seeing large libraries of controls or high end solutions - there are many vendors providing excellent tools of that type. Instead watch for development tools that enable you to develop your own solutions, for the debugging tools needed to learn enough to create those solutions, and for additional information in the form of application notes such as our new Common Dialog Toolkit, or newsletters that will build on the knowledge base of the Visual Basic community at large (and of course, Desaware's customers in particular).

Thank you for your support in the past, and I look forward to working with you in the future.


Ordering Information

We at Desaware strive to provide top quality products at reasonable prices. You can print out the enclosed order form, or call or fax for further information.

Ordering information:

SpyWorks-VB 2.0	______  X  $129 each	___________________
VersionStamper-VB 1.0	______  X  $129 each	___________________
SpyNotes #2 - Common Dialog Toolkit	______  X  $35 each	___________________
CCF-Cursors	______  X  $35 each	___________________
The Custom Control Factory	______  X  $48 each	___________________
Visual Basic Programmer's Guide to the Windows API	______  X  $27.96 each	___________________
How Computer Programming Works	______  X  $19.96 each	___________________
SpyWorks-VB T-Shirt Circle Size     M    L    XL	______  X  $12 each	___________________
Package Discount (see below)		___________________
CA residents, add sales tax:	X 8.25%	___________________
Shipping	$5 U.S. / Canada, $15 International $15 FedX 2Day.  $20 UPS Red or FedX Standard.	___________________
	Total:	___________________
Ship To:

Name: ________________________________________________________________________

Company:  ____________________________________________________________________

Address:  ______________________________________________________________________

______________________________________________________________________________

City/State/Zip  _________________________________________________________________

Phone  __________________________

Payment:  Visa/MC/Amex_________________________________________exp:  ___________

Package Discounts:  Order two of Desaware's software products at one time and take $10 off your total.  Order all five and take $40 off.  Discount does not apply to non-software products (books or T-shirt)

For Visa/MC/Amex orders, fax this order form to (408) 371-3530, or mail to Desaware.  Checks accepted via mail.  Company purchase orders at Net 30 on credit approval.

Shipment on book orders outside of the U.S. and Canada is an extra $10 to $30 depending on country. Contact Desaware for pricing.

30 day satisfaction guarantee on software products.

Allow 4 weeks for book and T-Shirt deliveries.  T-Shirt back shows "You Can't do that in Visual Basic", with Can't crossed out and Can substituted, "with a little help from Desaware" (in white & red on black).  Front shows "SpyWorks-VB by Desaware" on pocket area".  Shirt availability is limited.

Call Desaware at (408) 377-4770 for further information.


SpyWorks-VB Version 4.0

The Standard Edition

The original SpyWorks-VB package became one of the most successful Visual Basic add-on products of all time by allowing programmers to do virtually anything in Visual Basic that is possible with other languages. It does this by supporting powerful Windows programming techniques that are not part of Visual Basic.

SpyWorks 4.0 extends this philosophy to the new world of 32 bit programming for not only Visual Basic 4.0, but other full OLE control containers as well. It does this by providing easy access to low level system capabilities such as subclassing, callbacks and hooks that are rarely built in to higher level programming systems such as Visual Basic and VBA applications. In fact, SpyWorks makes these tasks so easy, that it will often be more economical to use SpyWorks for these tasks even with languages such as C and C++!

Version 4.0 standard edition is a 16 and 32 bit OLE Control based edition of the SpyWorks series.

The Professional Edition: A subscription that Includes 3 free updates!

We know that OLE controls are a new technology, that the containers that you will be using such as Visual Basic 4.0 have only just appeared, as have the operating systems that you will be using: Microsoft Windows® 95 and Windows NTTM 3.51. What new capabilities are built into the operating systems that SpyWorks can help you utilize? What kind of features will your customers demand? There is a lot to learn, and the Professional Edition is intended to not only help you learn it, but to evolve to meet your needs. Every four months you will receive a complete update of the entire SpyWorks series, 16 and 32 bit OLE Control and 16 bit VBX along with the latest utilities, application notes and so on. We will be adding features to the controls based on the most often requested (and most intriguing) features. Plus, it includes the full SpyWorks 2.1 package and Common Dialog Toolkit.

SpyWorks-VB 4.0 Custom Controls:

The DWSBCxx.ocx subclassing control provides you with complete access to the underlying Windows message stream for the forms, controls and other windows in your application or other applications. It allows you to modify the behavior of forms or controls, to detect system notifications and to perform easy messaging between applications. You can use it to subclass other applications - to create system utilities or add-ins to other programs.

The DWSHKxx.ocx hook control allows you to take advantage of Windows hooks. Detect messages for groups of controls, for entire applications or for the entire system. Detect keystrokes on a task or systemwide basis to create hot keys. Use journaling to create macro recorders or computer assisted training sessions - or to monitor user interaction to test your user interface. The applications are limitless.

The DWCBKxx.ocx control allows you to use windows callbacks. These are Windows API and DLL functions that require a procedure address in order to work. These functions call the procedure either to notify the application that something has occurred, or to enumerate objects such as windows or objects in a metafile. DWCBKxx.ocx provides you with procedure addresses to pass to these API and DLL functions, and maps their calls into events, allowing you to take advantage of this powerful technique from languages such as Visual Basic that do not provide function addresses.

The DWEASYxx.ocx control provides an easy to use implementation of common subclassing tasks including virtual forms, MouseEnter/MouseExit detection, rollup windows, caption buttons and much more.

The DWSPYxx.dll dynamic link library provides an array of library functions designed to help you take full advantage of both the Windows API and the SpyWorks controls. It also includes indirect property access capabilities, which let you programatically access properties of other forms and controls in your application.

Other SpyWorks-VB 4.0 Features:

The first release of the professional edition includes 32 bit OLE controls and the SpyWorks 2.1 VBX based package. 16 bit OLE controls and additional utilities and application notes will follow in the second release currently scheduled for January 96, $249 for a one year subscription. The standard edition priced at $129, containing 16 and 32 bit OLE controls only, will ship in that time-frame as well.  As always, applications created with any SpyWorks edition may be distributed without royalties.


VersionStamper Version 4.0

Reduce Technical Support Costs! Detect Version Incompatibilities Instantly!

An end-user or customer calls. Your program is behaving strangely, or no longer loads. Did another program install an older DLL, VBX  or OCX on their system? Or maybe a later, but incompatible version? Is it a conflict due to an incompatible DLL already loaded in memory? Has the PATH environment setting changed? Is the file properly registered in the registry?  Is a required file missing? Now your program could tell you what's gone wrong... with VersionStamper.

Detect OCX, VBX and DLL Incompatibilities Instantly

VersionStamper allows you to easily embed into your Visual Basic executable or other OLE container information about all of the dynamic link libraries and custom controls used by that application, along with required current versions, file date and time, and your choice of warning conditions. The VersionStamper OLE custom control can use this information to check the versions of the actual modules that are available on the target system.  Incompatibilities are instantly detected!

VersionStamper is designed with your needs in mind. You can perform version verification automatically on load, or at any time you wish under program control, or even dynamically verify a list of files at run time.  Plus, a customizable and redistributable "rescue" program can be used to detect and log problems when an application won't load at all. VersionStamper is designed primarily for DLLs, OCXs, and VBXs, but will work with any type of file, even those without embedded version information.

A COMPLETE Solution and Tool Kit.

VersionStamper is easy to use even if you are an absolute beginner - but we didn't forget the experts. Look what else you get:

•	dwvstp??.ocx - The 16 and 32 bit OLE control includes extensive dialog box support for embedding version information for selected DLLs, OCXs, VBXs and other files.  Each control can embed two file lists so you can use a single control to create dual platform executables. It also has the ability to scan Visual Basic 4.0 -based projects to automatically create a list of DLLs, OCXs, and VBXs required by the application. The OLE version even allows you to scan for files not specified in your file list during run-time. The run-time distributable control is royalty free. These controls are fully compatible with Visual Basic 4.0 and other true OLE Control containers!

•	dwvstamp.vbx - This version stamping custom control has extensive dialog box support for embedding version information for selected DLLs, VBXs and other files.  This VBX version can also embed true version resources into Visual Basic version 3.0 executables. It contains corresponding properties for each of the standard version information fields. It also has the ability to scan Visual Basic-based projects to automatically create a list of DLLs and VBXs required by the application. The runtime distributable control is royalty free, and is extremely small and efficient while using an absolute minimum of Windows resources.

•	VerInfo.exe - A Visual Basic-based program that allows you to quickly view the version information for any executable, DLL, OCX or VBX that contains versioning information. Includes source code.  It also produces a complete list of the files required by the application based on information embedded by the VersionStamper control.

•	VerResQ.exe - A Visual Basic-based program that analyzes any Visual Basic-based executable stamped by VersionStamper. It instantly detects any incompatibilities that exist between the requested files and those actually present on disk. Includes source code so that it can be customized for distribution with your application.

•	VerSplsh.mak - This sample project demonstrates using a standalone executable to perform file verification for your main application. It displays a splash screen during file verification. If no conflicts were found, it Shells your application, otherwise a form is displayed notifying the user of the conflicts. This method will allow you to identify any incompatibilities that exist - even if the executable cannot be loaded. Designed to be easily modified so that you can create your own splash screen shell program to distribute with your application.

•	VsRTDemo.mak - This sample project demonstrates a new feature of VersionStamper (OLE control only) - how to scan files dynamically during run-time.

•	Technical Notes include a complete discussion of the Windows-based system of version stamping and the embedding techniques used by VersionStamper.  It also includes detailed suggestions and examples for improving the Visual Basic setup toolkit. Version 4.0 extends includes an extensive discussion of platform dependent issues including Windows 95 and Windows NT.

Whether you are developing for corporate use in house, or for distribution worldwide, VersionStamper will pay for itself the very first time a customer calls with a compatibility problem. You'll have a solution in seconds - with VersionStamper.

Includes 16 & 32 bit OCX for Visual Basic 4.0 and other OCX containers.  Includes VB 3.0 VBX version which can embed true version resources into your VB executables.  Supports Microsoft Windows 3.1x, Windows NT and Windows 95. Only $129.


StorageWorks-VB Version 1.0

The ultimate data storage and file manipulation toolkit!  Change the way you work with files and data forever!

You may have heard about OLE 2.0 with its ability to control applications and embed objects from one application into another. But there's another feature built into OLE 2.0 that until now was not accessible to Visual Basic programmers. It's called "Structured Storage" and StorageWorks-VB is your key to this powerful technology.

Structured Storage allows you to create files that organize information easily.  Blocks of data can be placed in hierarchical form, just as files are placed in directories.  Its like having an entire file system in each file. You can also create and work with compound documents - a new standard for document storage.

OLE 2.0 takes care of allocating and freeing space within a file, so just as you need not concern yourself with the physical placement of files on disk, you can disregard the actual location of data in the file. Plus: with its support for transactioning you can easily implement undo operations and incremental saves in your application.

StorageWorks-VB allows you to take advantage of the same file storage system used by Microsoft's own applications.  Includes sample programs (with source) that let you examine the structure of any OLE 2.0 based file so you can see exactly how they do it!

StorageWorks-VB Storage Control:

The Storage control uses Visual Basic OLE Objects to represent storages and streams, creating a familiar interface for manipulating those elements.  Within the Structured Storage standard are a number of functions that let you upgrade your file handling procedures easily: you can detect whether files are in Structured Storage format or not, and you can read any normal file as if it was a Structured Storage file.  The Storage control also adds a number of features specifically for Visual Basic programmers.  It lets you read and write information in any of the styles Visual Basic uses, such as Sequential, Binary or Random, including arrays.

StorageWorks-VB is the key to unlocking the following Structured Storage capabilities:

•	Utilize a powerful new method for organizing information within a file or compound document.

•	Buffered file modifications allow you to easily undo modifications to a file using Transactioning.

•	Expose important information to outside applications by including a standard document information stream.

•	You can organize information in memory exactly like you organize information on disk.  Only one function call is required to copy information between a Storage in memory and a Storage on disk.

•	Reduce disk access time by only saving the parts of the document that have changed.

•	All disk space allocation and organization are done for you.

•	And more....

StorageWorks-VB Registry Control:

The Registry Control makes it easy to access the Registry and the Registration Database.  It provides all the power of Windows API calls and more.  Keys within the Registry are accessed like directories.  Values are converted to data types compatible with Visual Basic.  Powerful search capabilities are included, allowing you not to only search among keys and value names, but within the value data itself.  The documentation includes descriptions of areas in the Registry that might be useful and how to access them.

Using StorageWorks-VB - the Registry becomes the key to transforming your Visual Basic program into a truly professional application.  Here are just some of the thing you can do:

•	Register the filename extension to your documents, so your program is automatically launched when a user activates one.

•	Create user-specific and machine-specific configuration settings, dramatically improving your user interface.

•	Expose DDE links to your program.

•	Interface with Windows 95: set icons, register an uninstaller, update reference counts for  DLLs you use, and much more.

•	Expose your programs version information.

•	Read and modify system settings.

•	And more....

StorageWorks-VB includes 16 & 32 bit OLE controls, documentation and sample code. only $129.


Custom Control Factory Version 4.0

For 16 and 32 bit OLE Containers and Visual Basic

The Custom Control Factory by Desaware provides a powerful tool for creating your own custom button controls for Visual Basic.   CCF controls are created interactively while working in Visual Basic design mode without programming.  CCF controls may be distributed with a royalty free runtime library.  The Custom Control Factory has the unique ability to hold virtually unlimited numbers of bitmaps or icons. Now supports Visual Basic 4.0 and other OLE Control Clients. CCF controls can be used to create the following:

Version 4.0 features include:

•	Multiline captions with flexible alignment:  Aside from the normal left, center and right alignment, the entire text block can be placed anywhere in the control window.

•	Automatic 3D style borders with user defined colors, borders bevel widths and so on.  Offsets can be specified for both the text and image in order to add the illusion of movement when a button is pressed.

•	256 & 24 bit color support.  Specify a palette directly or use one of the control images to set the palette.

•	Image compression reduces the size of executable files and (optionally) memory use.  Even works with 24 bit bitmaps (with reduction to 32k colors).

•	Custom cycle/drawing capabilities.  This ranges from optional programmer control of the frame sequence to true "owner draw" capability.

•	Synchronization events during animation.

•	Metafile support - including flexible positioning and sizing.

•	Ability to load cursors for improved compatibility with CCF-Cursors.

•	Frame alignment dialog box makes it easy to align frames and match their sizes.  This reduces the necessity for precision when cutting bitmaps out of other drawing programs.

•	Improved performance and efficiency.  Each frame in a CCF control requires a single global handle.  No Windows resources are used.  This makes the Custom Control Factory the most efficient way to store arbitrary sized bitmaps, icons and metafiles in your Visual Basic program.

•	The MLIST2 control is a powerful LISTBOX control that handles single select, multiple select, multiple column modes.  User definable tabstops are supported along with the ability to embed an image in each entry in the list box.  Each list entry can have a user defined foreground and background color as well.  This control comes with complete 'C' or C++ language source code. Includes VBX, and 16 & 32 bit OLE Controls.

Over 50 sample controls are provided that illustrate the capabilities of the package.

16 & 32 bit OCX plus 16 bit VBX controls included.  Compatible with Windows 3.1x, Windows NT & Windows 95. All this for only $48 (plus S&H).


The Desaware Visual Basic Bulletin

Volume 1 Issue 1

Welcome to our Newsletter

Welcome to the first edition of what we hope will be an ongoing newsletter.  Why a newsletter, you ask?  Because if we are going to impose upon you by sending a mailing, the least we can do is make it something worthwhile. It is true that you will find some product information in here (after all, we can't afford to send these out if they don't generate some sales), but you will also find tips and techniques that are useful to VB programmers in general, and of course, our customers in particular.

 Dan Appleman

Inside...

Transferring information between forms and applications using Windows messages

Using the SendMessage API Function

Using long variables to transfer data during callbacks and messaging

OLE Custom Controls (OCX) - Why and when?

Safely distribute your Visual Basic applications...

Distributing Applications Created with Visual Basic

Make your VB Applications Tile like non-VB Applications.

Trapping and blocking the Control-Escape Sequence

Parsing Lines Read from Win.ini

Handling Null Terminated Strings

Product Information:

NEW!!  VersionStamper-VB

SpyWorks-VB Wins VBPJ Readers Choice (+ Full Features List)

SpyNotes #2 The Common Dialog ToolkitTM

Classics from Desaware - CCF-CursorsTM and The Custom Control FactoryTM

How Computer Programming Works

PC Magazines Visual Basic Programmers Guide to the Windows API


Transferring information between forms and applications using Windows messages
Transferring information between forms and applications using Windows messages.

Windows has long recognized the need for applications to exchange data with each other. Initially data could only be exchanged manually using the clipboard. Later, Microsoft implemented Dynamic Data Exchange (DDE) which allowed applications to send data to each other automatically. DDE is supported in Visual Basic, however it is relatively inefficient. Performance can be poor, and due to  its asynchronous nature, timeout errors can occur.

An ideal solution to interform/ intertask communications is the use of Windows messages to transfer the data. It is easy for VB applications to send messages (See Using SendMessage on page 2), but a VB application requires the SBC.VBX control from Desaware's SpyWorks-VB package to be able to intercept incoming messages. Messages have the advantage of being both fast and synchronous (your code does not return from a SendMessage call until the other form or application has processed the message). A message triggers an event in the destination form that can include data or a pointer to the data, so you can avoid the need to use global variables.

The following steps are involved in using messaging to communicate between forms or applications.

1.	Obtain a message number to use.

2.	Obtain a destination window handle. For forms in your own application, you can simply use the Hwnd property for the form. For forms in other applications, use one of the techniques described later in this article to obtain a window handle..

3.	The destination form uses SBC.VBX to subclass the form. This involves setting the ctlParam property to the name of the form to subclass, and setting the Messages or RegMessage property to identify the message to detect.

4.	Prepare the data or obtain a handle or pointer to the data. (See: Using long variables to transfer data during callbacks and messaging, page 3).

5.	Use the SendMessage API function to transfer the data.

6.	On receipt of the message (SBC WndMessage event), the destination copies the data into the appropriate local variables.

Obtaining Message Numbers

Every Windows message is represented by a number. Standard Windows messages have constant values assigned, for example: the WM_PAINT message is always &H0F. If you need a message number to use within an application or between cooperating applications, you can also use a constant message number. The numbers above &H400 (WM_USER) are available for your use. You need not worry about other programs sending those messages to your form. For Visual Basic, you should avoid using message numbers between &H1000 and &H2FFF, as the lower part of these ranges are currently used internally by Visual Basic.

If you wish to obtain a message number that is unique in the system, you can use registered messages. Registered messages are obtained using the function RegisterWindowMessage(lpstring$), where lpstring$ is the name of the message. Any application that calls RegisterWindowMessage with the same name will receive the same message number. This is ideal for cases where you wish to publish message numbers to use with other applications and be assured that they are unique.

Obtaining a Window Handle in Another Application

You must obtain a handle to a window in another application in order to send it a message. At first glance, the FindWindow (classname$, windowname$) API seems a suitable choice. Unfortunately, there are many cases where it is not reliable. Finding a window by class runs into problems any time more than one window of a class exists. For example: if more than one instance of NotePad is running, FindWindow will return the handle of the first one found, which may not be the one you want. The same problem applies to doing a FindWindow based on the window name (which is the same as the window caption), plus you have the added problem of handling those applications who modify their caption based on the open document. For example: the default windowname for Notepad is actually "Notepad - (Untitled)".

The real solution for this problem is to use the EnumWindows API function to enumerate all of the top level windows in the system, checking first if it belongs to the module handle that you are searching for (as returned by the Shell command or WinExec API) and also if it matches the class that you are looking for (for cases where an application has more than one top level window). The EnumWindows API function takes as one of its parameters a pointer to a function. Since Visual Basic does not provide you with an address of a VB function, you can use the CBK.VBX callback control (part of SpyWorks-VB) to obtain a function address to pass to EnumWindows. Each time that function is called, it will trigger a callback event in the CBK custom control.


Using the SendMessage API Function

The SendMessage API function is used to send Windows messages to other applications. Unfortunately, there is frequently confusion on how to handle the lParam parameter which is defined to be "As Any".  The declarations that we provide in the Visual Basic Programmer's Guide to the Windows API are as follows:

Declare Function SendMessageBynum& Lib "User" Alias "SendMessage" (ByVal hWnd%, ByVal wMsg%, ByVal wParam%, ByVal lParam&)

Declare Function SendMessage& Lib "User" (ByVal hWnd%, ByVal wMsg%, ByVal wParam%, lParam As Any)

Declare Function SendMessageByString& Lib "User" Alias "SendMessage" (ByVal hWnd%, ByVal wMsg%, ByVal wParam%, ByVal lParam$)

We recommend that you use the aliased versions where possible to prevent errors, but here is a brief summary of how to send values, strings, structure addresses and nulls.

When the message expects a string:

dl& = SendMessageByString(hWnd, MSG, wParam, lParam$) or

dl& = SendMessage(hWnd, MSG, wParam, ByVal lParam$)

When a message expects a NULL value (can substitute a long variable as well)

dl& = SendMessageBynum(hWnd, MSG, wParam, 0) or

dl& = SendMessage(hWnd, MSG, wParam, ByVal 0&) (must be long type!)

When a message expects a pointer to a structure or numeric variable

dl& = SendMessage(hWnd, MSG, wParam,  lParam) (lParam is any variable or structure)

You can see how the aliased versions significantly reduce the chance of error, since the declaration takes care of both adding the ByVal and forcing the parameter to be passed as the correct type.


Using long variables to transfer data during callbacks and messaging

The lParam parameter to a window message will frequently point to a data structure. Many callback functions also use pointers. In some cases you simply need to examine values in the structure. In others you may need to change values in the structure.

The trick to doing this is to dimension an object of the referenced structure type in the event code itself. You can then use the dwCopyData function to copy the data to and from the structure.

For example: you can define a structure to transfer two integers and a string:

Type YourStruct

A As Integer

B As Integer

S As String * 40

End Type

Sending the data via a message is easy. The source form or application uses SendMessage as follows:

Dim YS As YourStruct

SendMessage(desthwnd, msg, wp, YS)

This causes a pointer to structure YS to be passed as the lParam parameter. You can receive and process it as follows:

Sub WndMessage(wnd As Integer, msg As Integer, wp As Integer, lp As Long, retval As Long, nodef As Integer)

Dim YS2 As YourStruct

 ' Get a copy of the structure

dwCopyData ByVal lp, YS2, Len(YS2)

 Now you can access the data using

 the fields in YS2

x% = YS2.A

YS2.S = New string data

 To set data into YS, copy the data

 back as follows

dwCopyData YS, ByVal lp, Len(YS2)

End Sub

Be very careful using the dwCopyData function. You will always need to specify the ByVal keyword for lp. Be sure that the size of the structure is correct.  It is also a good idea to check if lp is zero before attempting the copy.


The Newest Component: OLE custom controls

Microsoft has recently announced a new component model called OLE custom controls (though we expect everyone will soon be calling them by their extension - OCX controls). With all the press you may wonder, what is hype and what is real? Well, heres our opinion....

It has been apparent to us for some time that the VBX control model is limited and would not be easy to port to the 32 bit programming model. Thus in the long term there is no doubt that the VBX model will become obsolete. But then again, so will DOS, right? Yet how many people still use DOS applications?

As this paper goes to press, the next version of Visual Basic remains little more than rumor - it is clearly some time in the future. 32 bit application development is also clearly only in its earliest stages, though we expect it to accelerate with the appearance of Windows 4.0 sometime late this year (or so they say).

The VBX programming model is extensively supported by C++ compilers, application development platforms and Visual Basic. Microsoft has publicly said that VBXs will be supported under the 16 bit edition of the next edition of Visual Basic. We expect VBX to be the dominant component model for the rest of this year without any doubt, and probably well into 1995.

That said, we at Desaware are turning our attention now to the new OLE custom control format and do plan to support all of our products under this control model in both the 16 and 32 bit environments as quickly as possible. After all, our entire focus as a vendor is to provide the highest quality and most sophisticated developers tools.  So stay tuned!


Safely distribute your Visual Basic applications
Safely distribute your Visual Basic applications...

An end-user or customer calls. Your program is behaving strangely, or no longer loads. Did another program install an older DLL or VBX on their system? Or maybe a later, but incompatible version? Is it a conflict due to an incompatible DLL already loaded in memory? Has the PATH environment setting changed? Is a required file missing? If only your program could tell you what's gone wrong...  Now it can - with VersionStamper-VB

Detect VBX and DLL Incompatibilities Instantly

VersionStamper-VB allows you to  embed into your Visual Basic executable information about all of the dynamic link libraries and custom controls used by that application, along with their required versions, file dates, and choice of warning conditions. The dwvstamp.vbx custom control uses this information to check the versions of the actual modules that are available on the target system. Incompatibilities are detected instantly.

VersionStamper-VB is designed with your needs in mind. You can perform version verification automatically on load, or at any time under program control.  A customizable and redistributable "rescue" program can be used to detect and log problems when an application won't load at all. VersionStamper-VB is designed primarily for DLL's and VBX's, but will work with any type of file, even those without version information.

Simply set a few control properties in the dwvstamp.vbx custom control and VersionStamper-VB automatically adds a standard Windows version stamp into your Visual Basic based executable when you compile..

Add true Versioning to your Visual Basic EXEs

A COMPLETE solution

VersionStamper-VB is easy to use even if you are an absolute beginner - but we didn't forget the experts. Look what else you get:

dwvstamp.vbx - This version stamping custom control has properties for each of the standard version information fields, and extensive dialog box support for embedding version information for DLLs, VBXs and other files which you select..  It also has the ability to scan Visual Basic-based projects to automatically create a list of the DLLs and VBXs required by the application. The runtime distributable control is royalty free, and is small and efficient.

VerInfo.exe - A Visual Basic-based program that allows you to view the version information for any executable, DLL or VBX that contains versioning information. Source code is included.  It also produces a complete list of the components required by the application based on information embedded by the dwvstamp.vbx control.

VerResQ.exe - A Visual Basic-based program that analyzes any Visual Basic-based executable stamped by VersionStamper-VB. It instantly detects any incompatibilities that may exist between the requested files and those actually present on disk. Source code is included so that it may be customized for distribution with your application.

VrsqTest.mak - A sample rescue program that shows how to scan a version stamped executable and determine any incompatibilities that exist - even if the application cannot be loaded. It is designed to be easily modified so that you can create your own rescue program to distribute with your application.

Technical Notes include a discussion of the Windows-based system of version stamping, using the versioning API, suggestions for improving the Visual Basic setup toolkit and more.

Whether you are developing for corporate use in house, or for distribution worldwide, VersionStamper-VB will pay for itself the first time a customer calls with a compatibility problem. You'll have a solution in minutes - with VersionStamper-VB.

NOTES:

VersionStamper-VB posed an interesting problem for us. How do you create a package that is at once so easy to use that even an absolute beginner can use it, yet powerful enough for the most advanced VB developer?  We ended up placing 99.9% of the functionality into a single custom control and several prepackaged forms and modules. Use the defaults and you have a complete solution using just a few lines of code. Or modify our VB code and override the VBX event defaults to create your own customized solution.  Our manual is designed the same way: use the quick-start for a canned solution, or read the text (>100 pages) to learn everything you would want to know about versioning and component distribution.

- Dan


Distributing Applications Created with Visual Basic

Quite a bit of attention has been paid lately to the problem of source code control and group project management. Fortunately, a number of source code control projects have begun to appear. It is only recently that developers have turned their attention to the problem of safely distributing applications that make use of components such as Visual Basic custom controls (VBXs) and Dynamic link libraries. The presence of an obsolete component on a system can cause an application to fail, and even cause a General Protection Fault.

Developers have attempted a number of solutions. Some try to place their VBXs and DLLs in their own application directory. This approach can fail in two ways. First, once another application loads a different version of the control, that version will be used - Windows will not attempt to load the correct version. Next, it is not possible to guarantee that the current directory will be the same as the one containing the components, and Windows always searches the current directory first.

Some developers attempt to make sure that they have the correct control by installing their versions of a component into the system directory regardless of the presence of an existing control that may have a later version. This could almost be considered criminal, as it is very likely to break other applications on the end users system.

Windows searches for components in the following order:

1.	Any component with the same module name that is already in memory.

2.	The current directory.

3.	The Windows directory.

4.	The System directory.

5.	The project directory (contains the executable that is loading the component).

6.	Directories specified by the PATH environment variable.

There is no way to completely assure that an incompatible control does not exist somewhere on a target system, or to prevent it from being loaded.

Worse yet, there is no way to determine the version of a Visual Basic executable, as VB does not support standard Windows version resources. This means that a user could take an older version of your application, and overwrite a later version without warning.

Given these facts, two things are clearly needed. First, a way to embed a version resource into a VB executable. Second, a way to mark an executable with a list of the components that it requires so that it would be possible to determine if the correct components are in fact present on a target system. Desawares new VersionStamper-VB addresses both issues.


Make your VB Applications Tile like non-VB Applications
Make your VB Applications Tile like non-VB Applications.

One of the biggest complaints about programs created with Visual Basic is that they cannot be tiled by the Windows Task Manager. Instead, Task Manager leaves the VB program where it was, and leaves a large hole where it was supposed to go. Desawares SpyWorks-VB allows you to let your VB application tile with the rest.

First, you need to subclass the hidden main window that belongs to every VB application (class name ThunderRTMain - Use the EnumTaskWindows API with the CBK callback control to get this handle). This is because task manager tries to tile this window - not your form. But you can intercept the task managers attempt to size this window and move the form yourself.

Use the SBC.VBX control to intercept the WM_WINDOWPOSCHANGING message and use the following code:

Sub SubClass1_WndMessage (Wnd As Integer, msg As Integer, wp As Integer, lp As Long, retval As Long, nodef As Integer)

Dim lpwinpos As Long, flags As Integer

Dim isicon As Integer, ismax  As Integer

Select Case msg

Case WM_WINDOWPOSCHANGING:

' Make sure our application is not in iconic or

' maximized state before tiling or cascading.

isicon = IsIconic(Me.hWnd)

ismax = IsZoomed(Me.hWnd)

If ismax Or isicon Then Exit Sub

 'get structure information

lpwinpos = dwGetAddressForObject(winpos)

dwCopyDataBynum lp, lpwinpos, Len(winpos)

'The hwndInsertAfter field of the WINDOWPOS structure is normally the handle of this apps  main form, but is NULL when a tile  or cascade message is sent. The SWP_NOCOPYBITS bit of the flags field is turned on during a tile or cascade message, and off for others.

If (winpos.hwndInsertAfter = 0) And (winpos.flags And SWP_NOCOPYBITS) Then

flags = winpos.flags And &HFEFC

' Position and size the main form.

SetWindowPos Me.hWnd, 0, winpos.x, 	winpos.y, winpos.cx, winpos.cy, flags

End If

End Select

End Sub

You also need to place code in the forms Resize event to hide the ThunderRTMain window when the form is minimized or maximized. Use the ShowWindow API to do this.

A sample program demonstrating VB tiling can be found on the Newsletter Bonus Disk described on page 7.


Trapping and blocking the Control Escape Sequence
Trapping and blocking the Control-Escape Sequence.

When the user hits the Ctrl+Esc key, Windows sends a WM_SYSCOMMAND message to the active application. The information in the message tells the active application to bring up the Task List. You cannot use the Keyboard Hook to throw the Ctrl-Esc key message away because the WM_SYSCOMMAND message is sent before the key message.

The solution is to use the SBCHOOK.VBX control to place a task or systemwide hook that detects the WM_SYSCOMMAND message (Set the HookType property to GetMessage).

In the WndMessage event, the lp parameter contains the cursor coordinate if the user selects the "Switch To..." command from the System menu. When the user hits the Ctrl+Esc key, lp is set to 0.  By blocking the WM_SYSCOMMAND message only when lp = 0, you can allow the user to bring up the Task List via the System menu.

In the WndMessage event place the following code:

If msg = WM_SYSCOMMAND Then

 If wp = SC_TASKLIST Then

 If lp = 0 Then

nodef = True

msg = 0

End If

End If

End If

Setting nodef to True prevents further hooks from being called, but in many cases you must also set the msg value to zero to truly block the control-escape key.


Parsing Lines Read from Win.ini

What do you do when you have a list of words in a string that are separated by a delimiter such as a comma or null character, and you wish to find out if a word is in the list? You might use the Instr$ function, except that it also detects partial words such as now in snow. You can use the Instr$ function however, if you include the delimiters in the search string. So in this case you would search for ,now,. The only problem with this approach is that it will fail to check the first and last word in the list because they only have one delimiter. The solution? Add an extra delimiter to the start and end of the list as follows:

Instr(, & list$ & , , ,now,)

accurately detects the word now in the word list. This technique is especially useful when you use an initialization file that has a list of words separated by commas, or API functions that return a list of entries delimited by null characters.

NOTES:

When VB3 came out, I snagged a bunch of free copies of VB2 from a local users group and handed them out to some local teens. One of them, Eyal Soha (16), learned enough to write the swiniedt program which became part of SpyWorks-VB, and came up with this clever tip in the process.  Dan


Handling Null Terminated Strings

Many Windows API functions can return a string to your application by loading a null terminated string into a buffer. The end of this string is marked by a null character, however Visual Basic will still use the entire length of the buffer in string operations. Consider this example:

Declare the GetClassName function that retrieves the Windows class name for a window:

Declare Function GetClassName% Lib "User" (ByVal hWnd%, ByVal lpClassName$, ByVal nMaxCount%)

Then use this code to get a forms class:

classname$ = String$(32, "A")

di% = GetClassName(yourform.hWnd, classname$, 31)

The string buffer is filled with the letter A to illustrate clearly what is taking place.

Print classname$ in the immediate window:

You will see:

ThunderForm AAAAAAAAAAAAAAAAAAAA

Visual Basic allows embedded nulls, so even though the API correctly set the buffer to a null terminated string, the length of the string from VB's point of view is still 32, and the characters after the null terminator remain unchanged.

Fortunately, it is easy to extract a VB string that contains only that part of the buffer before the null termination:

Function NullTermToVBString$ (usestr$)

Dim position%

position% = InStr(usestr, Chr$(0))

If position% <= 1 Then ' Avoid errors

NullTermToVBString$ = ""

Exit Function

End If

NullTermToVBString$ = Left$(usestr$, position% - 1)

End Function


SpyWorks-VB
SpyWorks-VBTM - Winner of the Visual Basic Programmers Journal 1994 Readers Choice Award!

SpyWorks-VB allows you to do virtually anything in Visual Basic that is possible with other languages. It supports powerful Windows programming techniques that are not built into Visual Basic. Subclassing allows you to intercept any Windows message going to a form or control. Callbacks allow you to provide function pointers to Windows and other DLL's which trigger VB events when called. Hooks give you system or task access to keyboard and mouse events.

You CAN do it in Visual Basic

We can barely begin to describe all of the possibilities provided by SpyWorks-VB, but here are a few: Create VB add-ins to other applications or VB itself using cross-task subclassing. Printer configuration. MouseEnter/MouseExit for status bars. Tiny Captions and Rollup Windows. Scrolling Forms/Controls.  True LostFocus & GotFocus detection. Create owner draw controls. Trap tab and alt-tab keys. Use Windows enumeration functions. Detect WIN.INI changes. Use private and owner draw clipboard formats. Change the behavior of standard controls. Indirect property access. Obtain an event history for a program. Detect Windows API parameter errors.

SpyWorks-VB 2.0 Custom Controls:

SBC.VBX - our subclassing custom control provides you complete access to the underlying windows message stream for the forms, controls and even graphical controls in your application. It even detects internal Visual Basic messages.

CBK.VBX - our generic callback custom control handles Windows API function or third party DLL functions that require a function address as a parameter.  It even handles multimedia callbacks.

The SBCEasy.VBX custom control adds true Mouse enter and exit events, Menu selection events, "tiny" captions and "rollup" windows, virtual forms, and more.

The SBCHOOK.VBX custom control provides extensive support for Windows hooks allowing you to detect underlying Windows messages on a form, application or system level.

SBCKBD.VBX, the keyboard hook custom control, lets you detect all keystrokes for an application or the entire system. Even detects hard to get tab, enter and arrow keys.

The DWSPYDLL.DLL dynamic link library provides utility functions, access to Visual Basic CDK functions, and the ability to read and write property values for controls in other applications, and even the VB design environment.

SpyWorks-VB Debugging Tools

SpyParam.exe uses the Windows 3.1 built in parameter error detection capability to detect and trap API function parameter errors - errors that are  hard to find because they are simply ignored by Windows.

SpyMem.exe is a memory, resource, module and task browser.  Its snapshot mode allows you to compare current heap & resource states with a previous reference - ideal for detecting resource leaks and memory that is not being freed.

SpyMsg.exe is a classic "spy" program with the ability to record any or all messages going to one or more Windows in your system. It also has the unique ability to detect Visual Basic events.

SpyWin.exe is a window browser that lets you examine information about all of the windows in your system. Visual Basic awareness allows it to report VB specific information such as form and control names, and to detect graphical controls..

SpyMenu.exe is a menu browser that can analyze the structure of the menu and command identifiers for any window on your system.

SpyVBX.exe is a form, control and custom control analysis program.

SpyWorks-VB comes with extensive on-line help, lots of VB source examples, SpyNotes #1 (advanced application notes),  and more....

Next time someone tells you that you cant do something in Visual Basic the joke will be on them. Now you CAN do it - with SpyWorks-VB.

(update - SpyWorks- just won the 1995 VBPJ Reader's Choice award as well)

NOTES:

I had the original vision for SpyWorks-VB within minutes of seeing the original VB 1.0 beta. The efficiency of VB was obvious, and once I saw that it was possible to access DLLs and create custom controls I knew that I would not have to compromise on power - I could still use the capabilities of Windows. It took over a year for this vision to evolve into a way to share this power with everyone - without requiring that they program in C or become Windows experts.

Id like to take this opportunity to thank you all for your support and encouragement. You are the people who made SpyWorks the amazing success that it has become..

 Dan


SpyNotes #2 The Common Dialog Toolkit
SpyNotes #2 The Common Dialog ToolkitTM

The Common Dialog Toolkit, an applications pack for use with SpyWorks-VB, lets programmers access and modify the Windows Common Dialog Box library using  API functions.

The common dialog box library included with Windows makes it possible for programmers to significantly customize the behavior and appearance of common dialogs.  However, the common dialog custom control (VBX) that comes with Visual Basic Professional does not provide this capability. The Common Dialog Toolkit shows Visual Basic programmers how to directly access the Common Dialog libraries using the tools in SpyWorks-VB to take advantage of all of the capabilities of the Windows Common Dialogs.

Desaware has launched the SpyNotes series of application notes to help prog-rammers learn the advanced techniques made possible by SpyWorks-VB. The Common Dialog Toolkit is the second application note in this series. As such, in addition to a description of how to access Common Dialogs, the package includes in depth technical information and complete documented source code to do the following (and more):

•	How to access all of the standard Common Dialog boxes from VB.

•	Using callbacks to trap the messages received by Common Dialogs.

•	How to embed Visual Basic controls into a common dialog box.

•	How to use modeless dialog boxes and give modal dialogs modeless behavior.

•	How to add controls to a common dialog box.

•	How to set the size and position of a common dialog box.

•	How to register and use user-defined messages and registered messages.

•	How to create 3D common dialogs.

•	How to Hook into the main Visual Basic GetMessage loop.

•	How to access and modify the behavior of controls in a dialog box.

With its advanced technical information, the Common Dialog Toolkit will prove valuable even if you never use  the Common Dialogs themselves!


CCF Cursors and The Custom Control Factory
Classics from Desaware - CCF-CursorsTM and The Custom Control FactoryTM

Visual Basic comes with only 12 built in cursors (or "mousepointers" as they are called), and could not easily be extended. CCF-Cursors provides a complete package for design and use of custom cursors and includes other enhancements to VBs mouse and cursor control.

•	Create Cursors from scratch, or convert any Icon into a cursor.

•	Set the cursor for a form or control.

•	Animated cursors - automatic animation with specified intervals.

•	Support for Visual Basic 3.0  graphical controls.

•	Detect mouse events  for ANY control.

•	Detect menu selection events.

•	Coordinate transformation, resource and other functions.

•	Over 50 sample cursors, including an animated hourglass.

The Custom Control Factory lets you create customized button controls interactively while working in VB design mode. With their unique ability to hold virtually unlimited numbers of bitmaps, icons, cursors or metafiles, CCF controls can be used to create Animated Buttons, Multistate Buttons, Toolbars,  and other enhanced user interface objects.

Features include: Multiline Captions, flexible text/image alignment, image scaling and automatic control sizing, programmable animation speed, runtime configurable, automatic 3D borders with flexible widths and colors, 256 color support, Image compression, Custom drawing/cycles. Now includes our new MLIST2.VBX control, a powerful list box that also holds bitmaps and supports unique colors for each item in the list box.  (Includes C source code for MLIST2).


How Computer Programming Works

A new book by Daniel Appleman

from Ziff-Davis Press.

ISBN: 1-56276-195-1

Have you ever tried to explain to someone what it is that you actually do as a programmer?  Are you a self taught programmer who sometimes wonders if maybe you missed some important information along the way - or do you know someone in that situation? Have you ever met someone, a friend, parent or child that you wanted to introduce to programming in an easy to read manner?

Well... Ive been in all of these situations - and I have wanted to do something about it for a long time. Now, thanks to the good folks at Ziff-Davis Press, Ive been able to take what I think it is a good step in the right direction.

How Computer Programming Works is part of Ziffs award winning How It Works series. Its fully illustrated (color, of course) and focuses on the fundamentals and concepts of programming and comp-uter science. Plus, Ive arranged again to offer a 20% discount on the book when purchased through Desaware.

 Dan


Visual Basic Programmers Guide to the Windows API
PC Magazines Visual Basic Programmers Guide to the Windows API

Build on your knowledge of Visual Basic to become a Windows expert by learning to take advantage of the hundreds of functions contained in the Windows API.  No knowledge of 'C' or prior Windows experience is required. It covers virtually every aspect of Windows and includes extensive sample code. Even Windows experts will benefit from the information on API/VB compatibility. Over 1000 pages plus disk.  Published by Ziff-Davis Press. ISBN: 1-56276-073-4. 20% discount on this book when purchased through Desaware.