VISUAL BASIC PC Hardware | PC Software | Networking | Web Designs | News Letter | Home |
Visual Basic | C++ | Java |
ADVANCED VISUALBASICPROGRAMMING ISSUES |
How do I tell when an application executed using the SHELL command is finished?For 32-bit VB: see Q129796 in Microsoft Knowledge Base. For 16-bit VB: 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. 'Put this in the general
declarations of your form/module 'Here's where you shell out to the
other program DoEvents Loop [Kenn Nesbitt, Microsoft Consulting Services <kennn@netcom.com>] 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. How do I access C style strings?Use the 'lstrlen' and 'lstrcpy' calls found in the Kernel DLL. 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. Microsoft's Knowledge Base on their web page, article Q105839,
has a full example of the code to do this (16-bit). 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. Declare Function SendMessage(ByVal
hWnd As Integer, ByVal
wMsg As Integer, ByVal wParam As Integer, lParam
As Any) As Long [Nic Gibson <nic@skin.demon.co.uk>] To change between landscape and portrait orientation, search of VBKB_FT on "lands*" finds Article ID: Q80185 "How to Set Landscape or Portrait for Printer from VB App". [Ayn Shipley <ashipley@hookup.net>] Any tips for speeding up VB?Who said "code in C"???? ;-)
The following tip is along the same lines, but with a code sample. They are provided by Andy Dingley <dingbat@codesmth.demon.co.uk>: You're limited by the system as to how quickly you can go from calling frmMyForm.Show to being able to type into the controls, but you can make the form appear to display faster. One technique is to keep forms loaded, and just switch their visibility on and off. This is heavy on resource usage, and doesn't help for the first time they're shown. Most forms have some processing (eg. querying a table to fill a list box) that goes on when they're first opened, and this is what causes the most serious delay. It's possible to display the form, make its controls appear on screen, then do the slow processing before finally making the form "live". As the user can see things happening, the perceived delay is less obvious. Include the following code in your form Show the form by using: Screen.MousePointer = HOURGLASS Bruce Garrett <bruceg@access2.digex.net> had the following tips from his VBITS 93 notes:
There was also a lot of discussion about "apparent" speed i.e: how it looks on the screen as opposed to how fast it's chugging internally. It was noted that the cute little flashing menu items and exploding windows in the Mac amounted to a little razzle-dazzle to distract you from how long it took to actually load something and get it on the screen. Keeping all your forms loaded but hidden until needed was suggested. Also the use of progress indicators and a simple quickly loaded and drawn startup form. Also preloading data you expect to need. 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: 'Add this to your code: This same method applies to list boxes and other controls. 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. Some beta tester of VB 5.0 claimed increases in raw number-crunching speed of up to 30 times. I have yet to test the number crunching capabilities of VB 5.0. Feedback welcome. How do you make a TEXTBOX read only? Or, how do I prevent the user from changing the text in a TEXTBOX?Visual Basic 5.0 provides a .locked property. Setting it to True will make the TextBox read-only. Earlier, there's was 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 (16-bit code follows): 'After making the following
declarations... Declare Function SendMessage Lib "User" (ByVal hWnd As Integer ByVal wMsg As Integer, ByVal wParam As Integer, lParam As Any) As Long 'Then Try: [Pete Jones <pjones@csi.compuserve.com>] 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. How can I create a OCX/VBX?VB 4.0 supports some OCX creation. VB 5.0 has full support for creating OCXes including ActiveX. However, they are not standalone. Applies to VB 3.0: 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. 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 Global Const MF_BYPOSITION=&H400 'Use the following code to remove
the "close" option. 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 Message Blaster (msgblast.vbx, see details in beginning of FAQ about how to get files) contains example code. How do I play MID, WAV or other multimedia files?Use the MSMCI.VBX/OCX, provided with VB/Win Pro. You can also declare and call the MM-functions manually: Declare Function mciExecute Lib
"MMSystem" (ByVal FileName as String) As Integer 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. Declare Function sndPlaySound Lib
"MMSYSTEM.DLL" (ByVal WavFile$, ByVal Flags%) As Integer [John McGuire <(jmcguire@jax.jaxnet.com>] How can I call a 'hidden' DOS program from VB?Applies to Windows 3.x: 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. Another possibility is to use the Shell-command not directly on your DOS-executable but to shell COMMAND.COM with the parameter "/C" to make the DOS-Box automatically close when the DOS-application has ended, for example (the /c parameter tells the Command interpreter to execute the following command line): taskID = Shell(Environ$("Comspec") & " /c dosexe.exe", 6) With VB4 (and above) you can use "vbHide" (= 0) as a parameter to make the minimized DOS-Window neither appear in the taskbar nor in the tasklist, for example: taskID = Shell(Environ$("Comspec") & " /c dosexe.exe", vbHide) 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! This applies also to Windows 95 and NT 4.0. Note that Explorer hides the extensions of .pif files no matter what; they are now called shortcuts. How do I do drag & drop between applications?Applies to VB 3.0 with Windows 3.x: MSGBLAST.ZIP (the famous Message Blaster by Ed Staffin and Kyle Marsh) available on various web sites, 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 mentioned above for more info. Short glossary for the confused ones :-)
How do I use GetPrivateProfileString to read from INI files?Windows 95: use GetSetting and SaveSetting which accesses the registry entries under "VB and VBA applications" directly. If you want to manipulate any and all registry entries, VB provides no direct method and the code needed is surprisingly complex. Also, bear in mind that a small error in writing to the registry may blow up your entire 95 or NT and require a reinstall! Applies to Windows 3.x: 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: 'Then in your code you do like
below: strReturn = String$(iLength, "
") 'Pad the string first! WARNING: Be aware that there was an ERROR in the Windows 3.1 API documentation that came with VB 3.0. 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 Writeblablabla: 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 How do I implement Undo?A multi-level undo is implemented in Windows 95 controls, and a normal undo in Windows 3.x. Your user can press Ctrl-Z for undo. If you can't use these, you will have to keep track of changes yourself. There's no magic involved, just some coding. To use the standard Text box or Combo box undo functions: 'Do the following declares: 'And in your Undo Sub do the
following: How do I create a window with a small title bar as in a floating toolbar?Applies to Windows 3.x: 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 included a full explanation here! I hear that VB makes pseudocode. What is is Pseudocode?VB/Win does not (before VB 5.0) 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 execute 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. 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. (The previous sentences were written before rumours of VB being ported to the Alpha processor came out. Ironically, at the same time VB is being made a true compiler with VB 5.0) 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. Does VB support pointers to functions?Yes. VB 5.0 adds callbacks and pointers. See AddressOf operator in docs/help. For earlier versions, this answer applies: No, it does not.
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. 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. (Note: it seems this method changes the icon of ALL the
active DOS boxes) 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... How do I create controls dynamically (at run-time)?Search of VBKB_FT 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. 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 Declare Function SystemParametersInfo Lib "User" (ByVal uAction As Integer, ByVal uParam As Integer, lpvParam As Any, ByVal fuWinIni 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. How do I call Windows Help files from a VB program?If you set HelpContextID for a control, pressing the F1 key will open this topic in the help file you have associated with your project. (App.Helpfile). I.e. TextBox1.HelpContextID=21004 will open the associated help file and display topic "21004" (see the chapter on help file development in documentation to see how you create your help files). In Visual Basic 5.0, the common dialog control supports help access directly. Private Sub TextBox1_Click() The old method if setting CommonDialog1.Action=6 is still supported for backwards compatibility, and is essentially equivalent. How do I shut down or reboot Windows from my program?In 32-bit VB use the following: Declare the API-function Declare Function ExitWindowsEx Lib
"user32" (ByVal uFlags As Long, _ and use success = ExitWindowsEx(EWX_SHUTDOWN, 0) If successful, the function returns true. You can force the shutdown by using EWX_FORCE = 4. To make Windows 95 reboot use EWX_REBOOT = 2. To only log off use EWX_LOGOFF = 0. With 16-bit VB, you do: Declare Function ExitWindows Lib
"user" (ByVal wReturnCode as Long, _ To exit Windows: RetVal% = ExitWindows(0, 0)
|
For more details contact the webmaster |