Site hosted by Build your free website today!
Home page

Windows VB and C/C++ programming tips, sample code and links

Miscellaneous discoveries and sample code made whilst developing our software

Before you leave ---

Click the links to the left to investigate our software. Most of it is free! Here are some links to useful programming sites

The Programming Sharehouse   A large searchable directory of programming resources.  Download Inno Setup, the program we use to create the installation programs.   Download DEPENDS.EXE, which shows all the libraries an application or DLL depends on, and others.

The samples written in Visual Basic work by calling the Windows API and are therefore equally relevant to C/C++ programmers. Source code and a compiled executable is provided with all the samples. The VB5 runtime program is required to run compiled VB programs.

How to change the display mode

This VB sample is available from the Download area. It illustrates the use of the DEVMODE structure and the API calls EnumDisplaySettings, ChangeDisplaySettings, CreateDC, DeleteDC and GetDeviceCaps.

You can change some parameters which (under Windows 9x) the control panel does not allow you to change, for example the vertical frequency. If you change one of these parameters it is not restored, even if you try to make the change temporary. You may be able to change the parameters to values which cause your display to malfunction. If you do you may need to reboot to recover. You may be able to damage the display unit.

You use the display mode change program and the code in it at your own risk!

Question and topic list   Download area   Home page

How to free memory and prevent RAM from swapping to disk

The VB sample code is available from the Download area. It illustrates the use of the MEMORYSTATUS structure and the API calls VirtualAlloc, VirtualFree and RtlMoveMemory.

First the address range is reserved with parameters MEM_RESERVE and PAGE_NOCACHE Or PAGE_READWRITE. It is then committed to RAM with the parameters MEM_COMMIT and PAGE_NOCACHE Or PAGE_READWRITE. It is not allocated any physical memory until it is accessed. This is done in the sample with the RtlMoveMemory API call. Windows does its best to honour the no cache request but the call does not fail if it cannot, for example if the machine does not have sufficient memory.

To free RAM, it is simply allocated and accessed in the way just described and then freed using VirtualFree.

Question and topic list   Download area   Home page

Multiple files and OFN_EXPLORER in the Open File dialog

By including the OFN_ALLOWMULTISELECT flag, you allow the user to select more than one file in the Open File dialog. But did (s)he? Either way, the nFileOffset member of the structure points at the first file name. The trick is that if only one file was specified, nFileOffset points within the first string in the buffer, which contains the full path. If multiple files were selected, the first string contains only the path and nFileOffset points after it. The following code snippet extracts all the files as full path names. Buffer contains the string(s) returned by the GetOpenFilename call. Message is a temporary buffer used to construct one of the multiple file names.

if ( ofn.nFileOffset < lstrlen(Buffer) )
	AddToFileList( Buffer );
	strcpy( FilePath, Buffer );
	FilePath[ofn.nFileOffset] = 0;
	while ( Buffer[ofn.nFileOffset] != 0 )
		strcpy( Message, FilePath );
		strcat( Message, "\\" );
		strcat( Message, Buffer+ofn.nFileOffset );
		AddToFileList( Message );
		ofn.nFileOffset += (strlen(Buffer+ofn.nFileOffset) + 1);

For this code to work OFN_EXPLORER must also be specified. Otherwise, the NULL characters between strings are replaced by spaces. There is a further surprise in store if OFN_EXPLORER is not specified, the old 16 bit style dialog is shown. This has separate windows side by side for the file names and the folders. According to some Microsoft documents the new 32-bit style is always shown, regardless of OFN_EXPLORER. This document error is corrected in recent versions of MSDN.

Question and topic list   Download area   Home page

Why does the WinHelp API fail with HELP_FINDER but work with all other values?

It may be different for you, but in our case it was due to having a copy of comctl32.dll in the same directory as the help file. Winhlp32.exe does a LoadLibrary of this file when it shows the finder dialog. It was getting the local copy, not the one in the systems directory, and the load failed. Anything which avoided showing the finder worked.

Thanks to Steve Miller and Depends.exe, which enabled me to track down the source of the problem (link at the top of the page).

Question and topic list   Download area   Home page

Giving a window the "Always on top" attribute

SetWindowPos() is not the most obvious API call, but it is the one to use.


Question and topic list   Download area   Home page

How do I make Windows 95 recognize a Font File it says is not valid ?

The method used in Windows 3.1 still works. Put the font file into the fonts directory and add an entry to WIN.INI in the [Fonts] section.

Font name=Somefont.fon

The next time Windows reboots, the font will be added to the system and the entry will be removed from WIN.INI

Question and topic list   Download area   Home page

Getting the full pathname, lower case and all

GetModuleFileName() and other API calls return either the short file name, or the long file name in all upper case. The following routine uses FindFirstFile() to recover the true case.

	BOOL FindLongPath( LPCSTR ModuleFile, LPSTR Message)
	 WIN32_FIND_DATA wfd;
	 char Temp[_MAX_PATH];
	 int i = 1;
	 char Term;
	 HANDLE hFind;
	 Message[0] = 0;
	 lstrcpy( Temp, ModuleFile );
	   for ( ;; )
	    while( Temp[i] != '\\' && Temp[i] != 0 ) i++;
	    Term = Temp[i]; Temp[i] = 0;
	    if ( Temp[i-1] == ':' ) lstrcat( Message, Temp );
	      if ( (hFind = FindFirstFile(Temp, &wfd)) == INVALID_HANDLE_VALUE )
	         return FALSE;
	      (void) FindClose( hFind );
	      lstrcat( Message, wfd.cFileName );
	    if ( Term == '\\' ) lstrcat( Message, "\\" );
	    Temp[i] = Term;
	    if ( Term == 0 )
	   return TRUE;

Question and topic list   Download area   Home page

Incorrect results from EnumChildWindows

We discovered this when tracking down a VB error in Process Master. The listboxes associated with combo boxes have to be children of the desktop, to enable them to cover other windows. However, they are sometimes listed as children of another window in the callback procedure of EnumChildWindows. It is easy to detect, calling GetParent() on the child returns the handle of the desktop window or 0, which also means that the parent is the desktop.

The Google toolbar dropdown list has this characteristic. Possibly it applies to windows whose parent is changed after they are created.

Question and topic list   Download area   Home page

What Windows version is my 16 bit application running under?

This C sample for VC1.5 (16-bit) is available from the Download area. The 32 bit help files don't tell you what GetVersion() returns, because its not a part of the Win32 API. The 16 bit help files don't tell you what it returns on a 32-bit Windows version because they pre-date it.

You need to call both GetVersion() and GetWinFlags(). Windows 95 OSR2 and Windows 98 give the same results. From GetWinFlags() test bit 0x4000, if set it means windows NT. Getver.exe also decodes all the other bits. The results from GetVersion() are tabulated below.

Windows version Reported DOS version Reported Windows version
16-bit Windows The actual version The actual version
Windows 95 7.0 3.95
Windows 95 OSR2 7.10 3.95
Windows 98 7.10 3.95
Windows NT4 5.0 3.10
Windows 2000 5.0 3.95

Question and topic list   Download area   Home page

Why has my 16-bit application failed to launch a program or document under NT4?

The ShellExecute() API returns a value of greater than 32 to indicate success, according to the Microsoft documentation. However, under Windows NT4 (but not Windows 2000), 16-bit ShellExecute() returns 33 if it cannot find the program.

Question and topic list   Download area   Home page

Why won't this VB program run/load into the IDE any more?

Sometimes programs compiled with Visual Basic do not run on particular machines. Windows may not be able to run them at all, or message boxes stating "Unexpected Error" or "Unexpected error 50003" may appear. After installing some software Visual Basic projects may not load. These subjects have a page all to themselves. Go to Visual Basic Runtime and Controls for details of how to solve these problems.

Question and topic list   Download area   Home page

Why does VB say "Component cannot be loaded" in the Components dialog?

We first ran across this problem when a software installation replaced Richtx32.ocx, which has different versions with the same file name. The OCA type library cache file relating to another version of the control, generated by Visual Basic, was still in the systems folder. Unregistering and re-registering the control had no effect. Deleting the OCA file cured the problem. Yet another case of Microsoft breaking the rules of COM.

There are similar problems with the common controls, and probably others. There is extensive information on the Visual Basic Runtime and Controls page.

Question and topic list   Download area   Home page

How to show any icon, cursor, animated cursor or bitmap on a Visual Basic form

This VB sample is available from the Download area. There are samples on the web which show you how to animate the cursor, but what we mean here is showing one on a form as a picture. Windows 9x and NT4 onwards can create a 32x32 bit icon out of any bitmap, icon, cursor or animated cursor file. It can also extract icons from any file which has icon resources, such as .EXE, .DLL and .OCX. What you need to show them is the STATIC window class, which is built in to the operating system but not available in Visual Basic.

The way it is done is to put an image frame onto the form, not a picture box. The size should be about 32x32 pixels, but it does not really matter because it's only a position indicator. An API call draws in the area, not VB. When a form is loaded a STATIC class window is created and placed over the image frame. A single SendMessage call makes Windows draw the scaled image. Icons are extracted from all the file types by the single ExtractIcon API function.

If you want to put the icon frame in a VB frame, you must in addition subclass the form. Respond to the WM_ERASEBKGND message by first calling the default window procedure and then drawing the icon. If you don't do this, the icon is not refreshed when you cover the form up and re-expose it.

It is possible to draw an Icon in a picture box with the DrawIcon API call, but this method does not work in the form Load event.

Question and topic list   Download area   Home page

How to find the number of dimensions of an array in Visual Basic

This VB sample is available from the Download area. Visual Basic does not provide a way of finding out how many dimensions an array has. It is easy in C/C++, GetDims.ocx and Dimensions.dll are tools to do the job. To use the OCX it must be registered. Where you put the file does not matter, the windows system folder is the conventional place. The DLL must be on the path, the Windows folder or system folder are suitable.

You can rename the files if you wish. To rename the OCX, unregister the control, do the renaming (and moving if required) then register again. If you rename the DLL the Declare statement must be changed to suit.

A regular DLL has no type checking so you have to be quite sure to pass the address of a Variant which contains an array. The code in the sample project uses one method, there may be others.

Here is the complete source code of the DLL:

#include <oaidl.h>

long FAR PASCAL GetDimensions( VARIANT far *Array )
        if ( (Array->vt & VT_ARRAY) != VT_ARRAY ) return 0;
        return SafeArrayGetDim( Array->parray );

Question and topic list   Download area   Home page

How can I run a VB program as an NT service?

This C++ sample for VC4 is available from the Download area. The Microsoft MSDN web site had this sample until recently. It has been replaced by a VC5 version called ntrsvocx. The ZIP file available here contains all the original VC4 files unaltered plus the help and OCX files.

Question and topic list   Download area   Home page

How can I register a component using a VB program?

Components are registered and unregistered by calling the procedures DllRegisterServer and DllUnregisterServer exported by the component. This is what regsvr32 does, and you can do the same. If you know the name of the DLL (or OCX) when the program is compiled you can do this with a Declare statement.
Private Declare Function DllRegisterServer Lib "MyControl.dll" () As Long
Result = DllRegisterServer

The return value is zero for success.

There is no easy way of specifying the name or path of the control at run time. To solve this problem you can download a DLL (not ActiveX) written in C which makes the call for you. The download contains a sample VB project, the DLL and the source code of the DLL. To get it visit the download area.

Question and topic list   Download area   Home page

How do I write an application in C/C++ that is only a dialog?

The source code of GETVER.EXE is included in the GETVER.ZIP from the download area.

Question and topic list   Download area   Home page

Filling an image list for the ListView common control

Suppose you have created an image list with the following statement:

hImageList = ImageList_Create( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR, MAX_ITEMS, 0 );

This list has no images in it when created. You might think that you could put an image into any element you wanted with the statement:

ImageList_ReplaceIcon( hImageList, Index, hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);

but it does not work unless the image is already there. What you have to do is load up the images in the order you want, allowing Windows to assign the index. It starts from 0.

ImageList_ReplaceIcon( hImageList, -1, hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);

Question and topic list   Download area   Home page

The easy way to give a dialog box an Icon

32-bit Windows. Within the WM_INITDIALOG code, do

SendMessage( hDlg, WM_SETICON, (WPARAM) IconType, (LPARAM) hIcon );

Look up the help files to find out what IconType means. If you Post the message, instead of Sending it, the icon is drawn over the first couple of characters of the title, although this gets corrected if the dialog is minimized and re-drawn.

16-bit Windows. A bit harder, but not a lot. You must give the dialog its own window class, and make the icon the class icon. The window procedure for the class can simply return DefDlgProc(..........).

Question and topic list   Download area   Home page

Why label editing in a ListView may close the dialog

Believe it or not, the edit control created to edit the label uses the identifier IDOK. Its notifications are sent to the parent window as a WM_COMMAND message, just like the OK button. So, in processing IDOK, check that the control really is your OK button, and if not ignore the message.

case IDOK:
if ( (HWND)lParam != GetDlgItem(hDlg, IDOK) ) return TRUE;

Question and topic list   Download area   Home page

Download area

Software Click on the file name to download Server 1 Server 2 File size Kb
Sample project to change the display mode 12
Sample VB project, DLL and OCX to find the number of array dimensions 23
Sample project to allocate and free non-swapping RAM 9
Sample project and DLL to register and unregister components 14
Sample program for showing icons, cursors and bitmaps on a VB form 9
NTSvc.OCX to run a VB program as an NT service 87
Getver.exe, a 16-bit program which reports the Windows version information 6

Question and topic list   Download area   Home page

Question and topic list   Download area   Home page

Back to the RHA (Minisystems) Ltd home page

Freeware, shareware, DDE components and tools, launch and setup menus