Q. Check Whether Another App is Hung
Can I find the status of running applicationsI mean whether it's "Running" or "Not Responding"just as Task Manager displays on its Applications tab?
ABOUT THIS COLUMN|
Ask the VB Pro provides you with free advice on programming obstacles, techniques, and ideas. Read more answers from our crack VB pros. You can submit your questions, tips, or ideas on the site, or access a comprehensive database of previously answered questions.
A. Task Manager doesn't actually show applications, but it does show a list of top-level visible windows. In the February 1999 column, I showed how to replicate this list using EnumWindows and testing to ensure each is ownerless and visible (see Resources). This strategy is slightly different from determining the Alt+Tab orderwhich I discussed in the March 2000 issue (see Resources)in that Task Manager picks up many more visible windows, including tooltips.
A window is considered "not responding" when it fails to check for waiting messages. You could write such an uncooperative and nonresponsive app like this:
You can perform a simple test to obtain the responsiveness status of any window. If you've done much work with window messages and nonresponsive apps, you probably know that PostMessage returns immediately and SendMessage returns only after the message is processed. A comfortable middle ground between these two is SendMessageTimeout, which returns either after the message has been processed, or after a specified timeout period has elapsed, whichever comes first.
Private Declare Sub Sleep Lib _
"kernel32" (ByVal dwMilliseconds _
Private Sub Form_Click()
Me.Caption = "Sleeping"
Me.Caption = "Awake"
SendMessageTimeout offers a flag, SMTO_ABORTIFHUNG, that is documented as causing the call to return immediately if the system believes the receiving process to be in a "hung" state. Experimentation shows this flag to be nearly useless, especially under Windows 9x, but it can't hurt to toss it in regardless. My own strategy is to specify a relatively short timeout period of one-quarter to one-half of a second, and poll regularly using an innocuous message (see Listing 1). This approach replicates the results offered by Task Manager most closely.
Q. Invoke the Run Dialog
I've seen on your Web site that there are ways to bring up many standard Windows dialogs using rundll32, but I can't find a reference to the Run dialog available through the Start menu. How can I offer that to my users?
A. No documented methods to bring up the Run dialog existed until Internet Explorer 4 (IE4) shipped, along with the automation library shdocvw.dll (which also exposes the Microsoft Internet controls). Now you can create a reference to the Shell object and fire its FileRun method to bring up this dialog:
This approach is less than optimal, though, because it offers absolutely no control over dialog placement or other UI elements. In cases like this, one simple trick allows you to hijack the dialog and bend it to suit your purposes more closely. As I showed in the January 1999 column, you can set a timer just before calling up a dialog, then modify the dialog when the timer fires (see Resources).
Dim so As Object
' Try creating a new Shell instance.
On Error Resume Next
Set so = CreateObject("Shell.Application")
If Err.Number Then
' Bummer :-(
MsgBox "Can't invoke Run " & _
"dialog via Shell object.", _
vbExclamation, "IE4 Required"
' Invoke Run dialog
The Run dialog begs for more customization. It would be nice to set custom text elements, as well as specify a position over your own form (see Figure 1). Do this by wrapping up the automation request within a routine that also sets a system timer and stashes desired settings in module-level variables so you can use them when the timer fires (see Listing 2).
When the timer fires, use FindWindow to obtain a handle to the new dialog. This might take several tries if the system is performing sluggishly. As soon as you have the handle, kill the timer and hide the dialog to smooth the updates. You can now alter the dialog in any way you like, dependent only on your knowledge of its controls. Spy++ shows that the Run dialog's first two children are Static windows that contain the icon and description text, respectively. Knowing that, you can use GetWindow to obtain the needed child handles. When all desired modifications are complete, reshow the dialog and bring it to the foreground.
I mentioned no documented methods exist to invoke the Run dialog. However, an undocumented function exported by Shell32.dll can perform this task. You can
download code that provides the VB implementation of the method detailed on the "Undocumented Windows 95" Web site (see Resources).
Q. Load Large File Into a Textbox
I thought that most 64K limits were a thing of the pastnotably that psuedo-32bit OS, Windows 9x. However, when I put a multiline textbox on a form (under NT4) and tried to load a large file into it, the file was truncated, and Len(txtBox.Text) returned 65,535. Can you provide an example of how to load more than 64K into a VB textbox?
A. Microsoft designed all the intrinsic controls to lowest-common-denominator specs. Because much of Windows 9x is still 16-bit, Microsoft made compromises "for your protection."
Under NT, the underlying edit class is fully 32-bit, but you must go entirely to the API if you want to exceed the built-in 64K limits. The most reliable method to load large amounts of text into a VB textbox is to use SendMessage with WM_SETTEXT (see Listing 3). The SetWindowText API wraps this message, but has the drawback that it doesn't return the proper result code when it fails under Windows 9x, should your code also find itself running there.
Karl E. Peterson is a GIS analyst with a regional transportation planning agency and serves as a member of the Visual Basic Programmer's Journal Technical Review and Editorial Advisory Boards. Online, he's a Microsoft MVP and a section leader on several VBPJ forums. Find more of Karl's VB samples, including updates to code published here, at