Visual Basic For Windows (VB/Win)

Frequently asked Questions & Answers
Section IX - B
Part 4

Last-modified: 22-Aug-95


[Preface] [General VB] [Common VB Questions] [Advanced VB Questions] [Calling the Win. API & DLL's] [VB/Win & Databases] [Distributing Apps] [General Tips] [VB for Apps (VBA)]

The following symbols indicates new & updated topics:

Hope this makes it easier for Our Regular Readers ;-)


TABLE OF CONTENTS:

D. ADVANCED VISUAL BASIC PROGRAMMING ISSUES

D. ADVANCED VISUAL BASIC PROGRAMMING ISSUES


1. How do I tell when an application executed using the SHELL command is finished?

Shell() doesn't really return a task handle, it returns an instance handle. Any documentation that says otherwise is wrong. But never mind that; the answer to your question is to use the API call GetModuleUsage. [Kenn Nesbitt, Microsoft Consulting Services(kennn@netcom.com)]
'Put this in the general declarations of your form/module 



Declare Function GetModuleUsage Lib "Kernel" (ByVal hModule As Integer) As Integer



'Here's where you shell out to the other program

intHandle = Shell("PROGRAM.EXE")

Do While GetModuleUsage(intHandle) > 0

	DoEvents

Loop

The FindWindow command can also be used (search the Tips help file for "How VB Can Determine if a Specific Windows Program Is Running"). I have had to use this when the program I shelled to unloaded itself and ran a different EXE. My program thought the shell was done (since the shelled EXE ended), but it really had just "moved on" to another EXE. Generally, the code in cases like this must be customized to fit the situation. [John McGuire (jmcguire@jax.jaxnet.com)]

[Top of Page][Table of Contents][Top of FAQ]


2. How do I access C style strings?

Use the 'lstrlen' and 'lstrcpy' calls found in the Kernel DLL.

[Top of Page][Table of Contents][Top of FAQ]


3. How can I change the printer Windows uses in code without using the print common dialog? How can I change orientation?

You can change the printer the VB 3.0 Printer object is pointing to programmatically (without using the common dialogs). Just use the WriteProfileString API call and rewrite the [WINDOWS], DEVICE entry in the WIN.INI file! VB will instantly use the new printer, when the next Printer.Print command is issued. If you get the old printer string before you rewrite it (GetProfileString API call), you can set it back after using a specific printer.

This technique is especially useful, when you want to use a FAX printer driver: Select the FAX driver, send your fax by printing to it and switch back to the normal default printer. [Hajo Schmidt (hajo@bwl.bwl.th-darmstadt.de)]

It is recommended (and polite, as we're multitasking) to send a WM_WININCHANGE (&H1A) to all windows to tell them of the change. Also, under some circumstances the printer object won't notice that you have changed the default printer unless you do this. [Nic Gibson (nic@skin.demon.co.uk)]

Declare Function SendMessage(ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, lParam As Any) As Long

Global Const WM_WININICHANGE = &H1A

Global Const HWND_BROADCAST = &HFFFF



' Dummy means send to all top windows.

' Send name of changed section as lParam.



lRes = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0,ByVal "Windows")



To change between landscape and portrait orientation, a search of the Knowledge Base on "lands*" finds Article ID: Q80185 "How to Set Landscape or Portrait for Printer from VB App". This is an extract: [Ayn Shipley (ashipley@hookup.net)]

Declare Function Escape% Lib "GDI" (ByVal hDC%, ByVal nEsc%, ByVal nLen%, lpData As Any, lpOut As Any)



Sub Command1_Click ()

	Const PORTRAIT = 1

	Const LANDSCAPE = 2

	Const GETSETPAPERORIENT = 30

	Dim Orient As OrientStructure

	

	Printer.Print ""

	Orient.Orientation = LANDSCAPE

	x% = Escape(Printer.hDC, GETSETPAPERORIENT, Len(Orient), "", Null)

	Print x%

End Sub

[Top of Page][Table of Contents][Top of FAQ]


4. Any tips for speeding up VB?

Who said "code in C"???? ;-)

When SHOWing a form with lots of bound controls, have a blank frame covering everything. Then, in the Form_Activate event, set the Frame.Visible = False. This greatly speeds the display of the form and hides ugly thrashing as the data controls initialize. [Christopher Biow (biow@cs.umd.edu)]

[Top of Page][Table of Contents][Top of FAQ]


5. How do I speed up control property access?

Instead of using a property in a loop, you will be better off using a normal variable in the loop and then assign the variable once to the property afterwards. Also, when reading a property, you should read it once into a variable instead of using it in a loop.

Sometimes it is not possible to simply put contents of a property into a variable. For example, if you are using a list box or you need to conserve memory. In these cases you can send the WM_SetRedraw message to the control to prevent redrawing. You can typically increase the speed 6-10 times - or even more.

'Add the following declares:

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

Const WM_SetRedraw = &HB



'Add this to your code:

Result% = SendMessage(Text1.hWnd, WM_SetRedraw, 0, 0)

'redraw off



'Do your stuff here!

Result% = SendMessage(Text1.hWnd, WM_SetRedraw, 1, 0)

'redraw on

This same method applies to list boxes and other controls.

[Top of Page][Table of Contents][Top of FAQ]


6. How much gain in performance will I get if I write my number crunching routines in C instead of Visual Basic?

Probably the best solution to the number crunching problem is to write the number crunching routines as a custom control or a DLL, and plug it into a VB app. VB interface handling is not significantly slower than, say C++, and most of the wait is associated with Windows.

Some real world experience speaks volumes about this one:

I wrote some time consuming code in VB to solve a combinatorical (does this word exist in English?) problem. The code consists of one main recursive function, which calls itself very often. It took a night to compute a certain problem. I was rather disappointed and then decided to write the central routine in C++. It was a 1:1 transcription. The routine was compiled with the MS C++-Compiler. It took only 22 Minutes for the same problem. Amazing, isn't it? The routine doesn't do any floating point arithmetic, only integer, and handles some arrays. The PC was a 33MHz 486. And the second amazing thing is, that a IBM RS6000 (560)-Risc-machine needed 17 Min for the same code. I was the only one on the machine. I thought it should be much faster. The MS C++ seems to make very fast, optimized code. The optimization was configured to make fast code. [Christoph Steinbeck (steinbeck@uni-bonn.de)]

[Top of Page][Table of Contents][Top of FAQ]


7. How do you make a TEXTBOX read only? Or, how do I prevent the user from changing the text in a TEXTBOX?

There's a lot of ideas on this one. You can grab the _KeyPress and _KeyDown events and set them to zero. However, the best idea is to use the Windows API SendMessage function to tell the control to become read-only: [Pete Jones (pjones@csi.compuserve.com)]
'After making the following declarations...

Global Const WM_USER = &H400

Global Const EM_SETREADONLY = (WM_USER + 31)

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



'Then Try:



SendMessage(Text1.hWnd, EM_SETREADONLY, 1, 0)

This will still allow the user to copy *from* the text box. If you need to disable this (why?), steal the Ctrl-C in the _KeyPress event.

[Top of Page][Table of Contents][Top of FAQ]


8. How can I create a VBX?

VBXs (Visual Basic eXtensions) are practically always written is C (Borland C++, but mainly MS VC++). You should refer to the _Control Development Guide_ (in VB Professional Features Vol. I) and any relevant documentation for your compiler. Followup questions should normally be directed to comp.os.ms- windows.programmer.* or comp.lang.c*.

There are some example VBX's with C code supplied with VB3 Pro. You'll find them under the directory [VB]\CDK.

[Top of Page][Table of Contents][Top of FAQ]


9. How do you change the system menu (on the Control-Menu Box)?

You can turn off the minimize and maximize menu options by changing properties, but what if you need to remove the "close" option?
'Make the following declares.

Declare Function GetSystemMenu Lib "User" (ByVal hWnd As Integer, ByVal bRevert As Integer) As Integer

Declare Function RemoveMenu Lib "User" (ByVal hMenu As Integer, ByVal nPosition As Integer, ByVal wFlags As Integer) As Integer

Global Const MF_BYPOSITION=&H400



'Use the following code to remove the "close" option.



SystemMenu% = GetSystemMenu (hWnd, 0)

Res% = RemoveMenu(SystemMenu%,6, MF_BYPOSITION)



'(also remove the separator line)



Res% = RemoveMenu(SystemMenu%,6, MF_BYPOSITION)

Adding menu items to the control menu is more complicated, since you need to respond to the events triggered when the user selects the new options. The newest Message Blaster (msgblast.vbx, see details in beginning of FAQ about how to get files) contains example code.

[Top of Page][Table of Contents][Top of FAQ]


10. How do I play MID, WAV or other multimedia files?

Use the MSMCI.VBX, provided with VB/Win Pro 3.0. You can also declare and call the MM-functions manually:
Declare Function mciExecute Lib "MMSystem" (ByVal FileName as String) As Integer



Sub Form1_Click ()

	iResult = mciExecute("Play c:\windows\mkmyday.wav")

End Sub

Also:

Playing a WAV file is covered in the VB Tips help file (there is a Windows call that is for this specificially; see below). The routine won't play MIDI files or other sound formats, however. [John McGuire (jmcguire@jax.jaxnet.com)]

Declare Function sndPlaySound Lib "MMSYSTEM.DLL" (ByVal WavFile$, ByVal Flags%) As Integer

Global Const SND_SYNC = &H0

Global Const SND_ASYNC = &H1

Global Const SND_NODEFAULT = &H2

Global Const SND_LOOP = &H8

Global Const SND_NOSTOP = &H10

Global Const SND_USUAL = SND_ASYNC And SND_NODEFAULT

[Top of Page][Table of Contents][Top of FAQ]


11. How can I call a 'hidden' DOS program from VB?

If you run a DOS program minimized using the SHELL command, it will never complete. This is because DOS tasks by default are NOT setup to run in the background. The easiest way to get around this is to make a PIF file for the program you need to run with the "Background" option checked. Then SHELL to the PIF file to run the DOS program and it will return control to your VB application when it terminates.

Tip: If you edit or replace the _DEFAULT.PIF file in the Windows directory to allow execution in background, this will apply to all DOS boxes that is not run with it's own .pif!

[Top of Page][Table of Contents][Top of FAQ]


12. How do I do drag & drop between applications?

MSGBLAST.ZIP (the famous Message Blaster by Ed Staffin and Kyle Marsh) available on Cica and mirrors tell you *everything* you want to know about this and other advanced stuff. This is now (inexpensive) shareware, but the older freeware version is still supposed to be available. Get the file mentined above for more info. Short glossary for the confused ones :-)

[Top of Page][Table of Contents][Top of FAQ]


13. How do I use GetPrivateProfileString to read from INI files?

There's a good example of accessing *.INI files in the Knowledge Base, but here's the basic idea:
'You declare these API function as usual:



Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer



'Then in your code you do like below:

strIniFile = "WIN.INI"

strSection = "MyProgram"

strKey = "Language"

strDefault = "English"

iLength = 70

strReturn = String$(iLength, " ")  'Pad the string first!

iResult = GetPrivateProfileString(strSection, strKey, strDefault, strReturn, iLength, strIniFile)

WARNING: Be aware that there was an ERROR in the Windows 3.1 API documentation that came with VB. Here's the scoop: Knowledge Base article Q110826 (DOCERR: GetPrivateProfileString Declaration Incorrect in API) corrects a documentation error for the GetPrivateProfileString function call as described in the Windows version 3.1 API Reference help file that shipped with Microsoft Visual Basic version 3.0 for Windows. The CORRECT declaration is as follows:
Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer

Note that the "ByVal" keyword was omitted from the second parameter in the online reference. This means that the function is passing the second parameter (lpKeyName) by reference. It needs to be passed by value.

The most common problem that occurs when using the incorrect declaration is that when the function is called, it returns a copy of "lpdefault" in the "lpReturnedString" parameter instead of the actual value referenced by KeyName.

OOPS: As P. Wierenga (pwiereng@sol.UVic.CA) told me, the same doc error applies to Write: DOCERR: WriteProfileString Declaration Incorrect in API Article ID: Q115328

The correct declaration is as follows:

Declare Function WritePrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lplFileName As String) As Integer (all on one line of course!)

[Top of Page][Table of Contents][Top of FAQ]


14. How do I implement Undo?

For most controls, you will have to keep track of changes yourself. There's no magic involved, just some coding. However, if you use the standard Text box or Combo box, Windows provides a "free" undo function for you!
'Do the following declares:

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

Global Const WM_USER = &h400

Global Const EM_UNDO = WM_USER + 23



'And in your Undo Sub do the following:

UndoResult = SendMessage(myControl.hWnd, EM_UNDO, 0, 0)

'UndoResult = -1 indicates an error.

[Top of Page][Table of Contents][Top of FAQ]


15. How do I create a window with a small title bar as in a floating toolbar?

Download the MSGBLAST VBX from ftp.microsoft.com (filename msgblast.zip) or (better) from ftp.cica.indiana.edu or mirrors. The example files provide an example of a form with a small title. When you see it, you'll understand why I haven't include a full explanation here!

[Top of Page][Table of Contents][Top of FAQ]


16. What is Pseudocode?

VB/Win does not generate machine code like most compilers do. Instead it creates what is called pseudocode (a real misnomer, IMO). A good explanation is given below:

A bit of history: the original P-code was an instruction set for a "virtual Pascal" machine. This came with a portable Pascal compiler written at ETH in Zuerich. The portable compiler produced instructions for this phony machine which had an instruction set ideally suited to the stack and heap management of Pascal. To executed portable Pascal programs, you had two choices: either write an interpreter for P-code, or translate the small set of P- code instructions (there were about 80) into assembler; assemble it; and run it at native speed.

Thus "P-code" originally stood for "Portable" or "Pascal" code. The broader meaning, "pseudo- code" came later. P-code was widely popularized by the UCSD Pascal system, a small workstation that was implemented entirely in Pcode and interpreted. It was sold for some years, and one company even re-did the microcode for a PDP-11 microchip to interpret P-code. The original Borland Turbo Pascal had obvious similarities to the UCSD system although it was not interpreted. The dialect was virtually identical.

Today P-code is used extensively in Microsoft apps, for two reasons. First, it is much more compact than native code; so the apps are smaller. Second, having an interpreter at the core of an app makes it much easier to customize and extend. That is why VB is becoming the heart of the MS major apps. It is simply not true that P-code apps run much slower than native apps. The slowdown is determined by the granularity of the interpreted routines. If every little thing is an interpreted op, the slowdown might be as much as 3-to-1 for the 80x86 architecture, or about 2-to-1 for the Motorola 68000 family (which is better suited to writing interpreters). But in practice, modern P-code systems have large-scale instructions, each of which is executed by a big compiled subroutine. These subs run at native speed, so the overhead of the interpreter is occasional at worst. [Roger E. Ison (r_ison@csn.org)]

It is also possible that since the code may not need recompilation to run on other platforms *if* the run-time interpreter is first ported, VB applications can become very portable. This depends on Microsoft's long-term plans.

A note on the word "pseudocode": I wrote above that it is a misnomer, and I stand on that. Pseudocode is *really* the pascal- like (mostly) explanation of an algorithm that is intended for human readers, not computers. But since somehow the term pseudocode stuck to the psaudo-machine-code created by VB the word is used here.

[Top of Page][Table of Contents][Top of FAQ]


17. Does VB support pointers to functions?

No, it does not. [George Tatge (gat@csn.org)]

[Top of Page][Table of Contents][Top of FAQ]


18. How do I program the Novell NetWare API from VB?

Tom Tregilgas (Tom.Tregilgas@InfoB.unisg.ch) had a lot of information on this one. Normally I leave it to the other FAQ parts to list books & how-to-get-info's, but since this topic is very specific and more NetWare than VB I include all the stuff here for your convenience:
If you are interested in seeing how Visual Basic can be used for NetWare programming, obtain the following files from your friendly neighboorhood Novell FTP Mirror site. Mirror sites are (according to ftp.novell.com):

novlib\11\nivb.zip Netware Interface for Visual Basic

novlib\11\nwtest.zip NetWare Test for Visual Basic

There are also two Novell App Notes on the subject of using NetWare with Visual Basic (although this is _NOT_ supported by Novell...) which are:

  • October 92- Interfacing Visual Basic for Windows and NetWare
  • July 93 - A NetWare Interface for Visual Basic

The AppNotes can be obtained by contacting the Novell Research Order Desk, FAX: +1 303 294-0903, Voice 800 377-4136, +1 303 297- 2725. Address as follows:

Novell Research Order Desk
1601 Park Avenue West
Denver, CO 80216-5199
AppNotes are $95/year ($135 outside US). Here are a few books which might help you out to figure the calls out:
  • Windows Development on NetWare Systems, Lori Gauthier and Sue Whitehead (c) 1994, Windcrest, Blue Ridge Summit, PA 17294-0850 (McGraw-Hill) $34.95 Comes with disk This book also tells you how to "upgrade" to the currently supported SDK calls
  • NetWare System Interface Technical Overview, Novell (c) 1990,1989 (Addison-Wesley), $32.95 (describes Novell's C Network Compiler API's)
  • Visual Basic Programmer's Guide to the Windows API, Daniel Appleman Ziff-Davis Press, 5903 Christie Ave, Emeryville, CA 94608, $34.95 Comes with disk.
It should be mentioned that the APIs included with the NIVB are _not_ current, and for this purpose, you should get the Novell SDK kit. Also, Novell will not support NIVB, but you can sometimes get some helpfrom Compu$erve, or from others on the Infobahn

Good luck!

p.s. It behooves you to become a member in the PDP (Professional Developer's Program) since you get the AppNotes (& Bullets!) for...free.

p.p.s. Novell does NOT support the NIVB...

p.p.p.s. Also, no docs come with it. You'll probably need the Client C SDK kit to be able to really _use_ the code.

p.p.p.p.s. To make things even better, the calls in NIVB are fairly old, and not of the Client C SDK kit variety. However, there are books which could help you out, e.g. NetWare System Interface Technical Overview, by Novell. ISBN:0-201-57027-0, published by Addison-Wesley Publishing co, $32.95 US, $42.95 in Canada.

Update:

AppNotes are dead, however, Develper Notes live on. There is one article about NetWare programming with Visual Basic here:

  • July/Aug 94 - NetWare Programming in Visual Basic:
  • Using Apiary's NetWare Client SDK for Visual Basic

[Top of Page][Table of Contents][Top of FAQ]


19. Visual Basic 4 news [**]

Here is the news we have observed (and which was a guess in previous versions of this FAQ)

[Top of Page][Table of Contents][Top of FAQ]


20. How do you change the icon and otherwise manipulate the DOS box?

Enclosed is the results of my digging around to enable me to change the icon of a DOS box launched with the SHELL function. It illustrates most aspects of dealing with DOS boxes. Example of launching PIF file minimized and running it in the background (Needs Execute Background box checked in PIF file), and assigning the PIF file a new Icon rather than the default DOS Box Icon. [Dr David Baird (BairdD@AgResearch.CRI.NZ)]

(Note: it seems this method changes the icon of ALL the active DOS boxes)

Option Explicit



Global Const SWP_NOSIZE = 1

Global Const SWP_NOMOVE = 2

Global Const SWP_NOACTIVATE = &H10

Global Const SWP_SHOWWINDOW = &H40

Global Const SWP_HIDEWINDOW = &H80

Global Const SWP_FLAGS = SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOACTIVATE

Global Const SWP_SHOW = SWP_SHOWWINDOW Or SWP_FLAGS

Global Const SWP_HIDE = SWP_HIDEWINDOW Or SWP_FLAGS

Global Const HWND_BOTTOM = 1

Global Const GCW_HICON = (-14)

Global Const GCW_HMODULE = (-16)



Declare Function GetModuleUsage Lib "Kernel" (ByVal hWnd%) As Integer

Declare Function ExtractIcon Lib "Shell" (ByVal hInst%, ByVal lpExeName$, ByVal hIcon%) As Integer

Declare Function DestroyIcon Lib "User" (ByVal hIcon%) As Integer

Declare Function FindWindow Lib "User" (ByVal lpClassName As Any,ByVal lpCaption As Any) as Integer

Declare Function SetWindowPos Lib "User" (ByVal h%, ByVal hb%,ByVal X%, ByVal y%, ByVal cx%, ByVal cy%, ByVal F%) as Integer

Declare Function GetClassWord Lib "User" (ByVal hWnd%, ByValnIndex%) As Integer

Declare Function SetClassWord Lib "User" (ByVal hWnd%, ByValnIndex%,ByVal wNewWord%) As Integer



Sub LaunchPif(PifFile as String, IconName as String)

	Dim Res As Integer     'Return value from API call

	Dim MyInst As Integer  'Instance handle for this app

	Dim PifIcon As Integer 'Pif Icon Resource name

	Dim OldIcon as Integer 'Original Pif Icon resource (default =0)

	Dim PifhWnd As Integer 'Dos Box Window handle



	'Launch PIF file

	PifInst = Shell(PifFile, 6)



	'Get Instance handle for main MDI Window (assumed to be frmMDI)

	MyInst = GetClassWord((frmMDI.hWnd), GCW_HMODULE)



	'Create new Icon resouce by loading Icon from disk file

	'Check Icon file exists

	If Dir$(IconName) <> "" Then

		'Make sure string is null terminated

		IconName = IconName & Chr$(0)

		'Create Icon resource in this window

		PifIcon = ExtractIcon(MyInst, IconName, 0)

	Else

		PifIcon = 0

	End If



	'Reset Default Icon on DOS Box to PifIcon

	'Check PIF file still running and Icon resource created

	If GetModuleUsage(PifInst) <> 0 and PifIcon > 0 Then

		'Get Pif Window handle

		PifhWnd = FindWindow(0&, "Window name in PIF file")



		'Set Icon handle to PifIcon resource

		OldIcon = SetClassWord(PifhWnd, GCW_HICON, PifIcon)



		'Hide and show window to get a redraw of the Icon

		Res = SetWindowPos(PifhWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDE)

		Res = SetWindowPos(PifhWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_SHOW)



	End If



	'Wait for PIF file to complete

	Do While GetModuleUsage(PifInst) <> 0

		DoEvents

	Loop

	

	If PifIcon > 0 then

		'Reset Icon to original

		Res = SetClassWord(PifhWnd, GCW_HICON, OldIcon)

		

		'Tidy up by removing PIF Icon resource

		Res = DestroyIcon(PifIcon)

	Endif

End Sub

[Top of Page][Table of Contents][Top of FAQ]


21. How do I make the mouse cursor invisible/visible?

Use the API call ShowCursor(False) or ShowCursor(True). Just be aware that the Windows cursor is a shared object, so if your process hides it then it must also redisplay it as well. Also the function is not truly "True" or "False" in nature - it is LIFO, so that if your process has for some reason set it "False" multiple times then you must set it "True" the same number of times in order to re-display the cursor. Hard to explain but play with it - you'll see what I mean... [Galen Raben (galenr@hpgrla.gr.hp.com)]

[Top of Page][Table of Contents][Top of FAQ]


22. How do I create controls dynamically (at run-time)?

A Search of the Knowledge Base on "control* near array*" finds a number of articles, including Article ID: Q79029 "Creating Nested Control Arrays in Visual Basic" This is THE article to read to understand control arrays (plus a number of other neat concepts). In particular, look at the procedure "loadall_click".

The key is that you need to create the first instance of your_control (ie. your_control(0)) at design time. [Ayn Shipley (ashipley@hookup.net)]

[Top of Page][Table of Contents][Top of FAQ]


23. How do I set the Windows wallpaper at runtime?

I'm surprised this isn't in the FAQ yet. [ED: now it is!]

You need the SystemParametersInfo API function and the SPI_SETDESKWALLPAPER constant. For this you will need the following constants and function declaration...

Const SPI_SETDESKWALLPAPER = 20

Const SPIF_SENDWININICHANGE = &H2

Const SPIF_UPDATEINIFILE = &H1

 

Declare Function SystemParametersInfo Lib "User" (ByVal uAction As Integer, ByVal uParam As Integer, lpvParam As Any, ByVal uWinIni As Integer) As Integer



'You then call the function as follows...

Result% = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, ByVal BMPFile$, SPIFlags%)



'... where SPIFlags% is 0 if the change is not to be made permanent, or

'(SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE) if it is to be carried across

'into future Windows sessions.



NOTE: Please be certain to include the ByVal keyword before the bitmap filename, as this argument is declared as Any, NOT as ByVal String. [Luke Webber(webber@werple.apana.org.au)]

[Top of Page][Table of Contents][Top of FAQ]


24. How do I call help files from a VB program? [**]

There are 2 ways you can display help files: [Blake Miller (bemiller@amoco.com)]
  1. In code
    • Using the common dialog control
    • Making a winhelp api call (see below for examples)
  2. Pressing F1 when App.HelpFile is set to your help file. Note - if a control's HelpContextID property is set to the context id of a help topic, that topic will be displayed if the control has focus and the user presses F1, otherwise the contents is displayed.

    (see Mapping Context-Sensitive Topics, Chapter 6 pg. 117 of the Professional Features Book 1 for information on setting the context ids for your help file. Many help authoring tools will generate the context ids for you.)

'Include constant.txt in your project

Set App.HelpFile = "c:\yourfile.hlp"



'Declare the following function in a .bas module  (make sure it is all on one line):

'Function for display windows help files



Declare Function WinHelp Lib "User" (ByVal hWnd As Integer, ByVal lpHelpFile As String, ByVal wCommand As Integer, dwData As Any) As Integer

COMMON DIALOG
Note - The HelpContext property can only be assigned an integer. The equivalent WinHelp Api call can use a long. In this example the context id is 1000
  • Jump to a context id within help file.
    CMDialog1.HelpFile = "c:\yourfile.hlp"
    
    CMDialog1.HelpCommand = HELP_CONTEXT
    
    CMDialog1.HelpContext = 1000
    
    CMDialog1.Action = 6
    
    

  • Bring up contents
    CMDialog1.HelpFile = "c:\yourfile.hlp"
    
    CMDialog1.HelpCommand = HELP_CONTENTS
    
    CMDialog1.Action = 6
    
    

  • Bring up search window
    CMDialog1.HelpFile = "c:\yourfile.hlp"
    
    CMDialog1.HelpCommand = HELP_PARTIALKEY
    
    CMDialog1.HelpKey = ""
    
    CMDialog1.Action = 6
    
    

  • Quit help
    CMDialog1.HelpFile = "c:\yourfile.hlp"
    
    CMDialog1.HelpCommand = HELP_QUIT
    
    CMDialog1.HelpContext = 0
    
    CMDialog1.Action = 6
    
    
WINHELP API:
In the following examples iRetCde is declared as an integer.
  • Jump to context id (e.x., context id is 1000)
    iRetCde = WinHelp(Me.hWnd, "c:\yourfile.hlp", HELP_CONTEXT,  ByVal CLng(1000))
    
    

  • Bring up contents
    iRetCde = WinHelp(Me.hWnd, "c:\yourfile.hlp", HELP_CONTENTS,  CLng(0))
    
    

  • Bring up search window
    iRetCde = WinHelp(Me.hWnd, "c:\yourfile.hlp", HELP_PARTIALKEY,  ByVal "")
    
    

  • Quit help
    iRetCde = WinHelp(Me.hWnd, "c:\yourfile.hlp", HELP_QUIT,  CLng(0))
    
    

[Top of Page][Table of Contents][Top of FAQ]



[Next Section][Previous Section]