Solved

ProgressBar

Posted on 2000-02-22
9
362 Views
Last Modified: 2010-05-02
I'm working on a Word utility, and I'm trying to come up with a way to show a progress bar that marks the opening of  Word.

The problems are:

1) I lose control of the computer when my program passes control to Word. I tried DoEvents, but it had no effect.
(Maybe I didn't do it right.)

2) I thought about a timer, but Word opens in different times, depending on processor speed, memory, and whether or not Word has already been opened.

So, is there a way to get imformation back from Word as it opens, or is there a way to run a loop or timer while Word opens?

And... Is a loop or a time better? I tend toward a loop. Does a loop run slower and faster of different machines?

Here's my code for opening word:
Public Sub OpenWordApp()
Const ERR_APP_NOTRUNNING As Long = 429

'Create error and go to next line.

On Error GoTo ERR_APP_NOTRUNNING

Set appWord = GetObject(, "word.application")

ERR_APP_NOTRUNNING:
    Set appWord = New Word.Application
Exit Sub

End Sub

Thanks
WillP
willmar@syix.com

0
Comment
Question by:WillP
9 Comments
 
LVL 4

Expert Comment

by:wqw
ID: 2547647
No way in VB. You can go multi-threaded but you can't predict when word will finishing loading or opening a document.
0
 

Author Comment

by:WillP
ID: 2549518
Okay...

But I still have the problem of showing something to the user during the Word load.

I've noticed that the Word splash comes up when I use ShellExecute to open a document.

Is it possible to get the splash screen to come up when setting appWord in the the above code.

Other suggestions or solutions would be appreciated.

WillP

0
 
LVL 3

Expert Comment

by:paulstamp
ID: 2550592
Progress bars are very tricky... even Microsoft can't do them properly.

Using the Multimedia Control MCI32.OCX with AVI to display some animation while laoding is an alternative. You can display a form with the animation and force it to stay on top of the display using SetWindowPos, and loop until the word display appears (see http://www.mvps.org/vbnet/code/system/findwindowlikesimple.htm for details of how to do this).

Hope this helps
0
 
LVL 3

Expert Comment

by:Lewy
ID: 2551919
Since it’s an indeterminate amount of time, I would put up a row of dots; one per second or so, to indicate that something is going on. There is no defined end. Allow room for the maximum, like a time out. If it gets to the end something must be wrong. You could start over if it will take a long time.
Another method is to use an animation to occupy the user, like a modem connection does with the thing going back and forth on the cable or the file transfer with the paper moving.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:WillP
ID: 2553469
Still haven't figured this one out.

This is my experiemntal code:

This is for the form:
(One command button, a timer, and a label)

Dim b
______________________________________
Private Sub Command1_Click()

'Calls code in module
Call OpenWordApp
'Does nothing
DoEvents

End Sub

________________________________________
Private Sub Form_Load()
'Start timer.
Timer1.Enabled = True

'Set global variable to false.
bolStop = False

End Sub

____________________________
Private Sub Timer1_Timer()

'Loop prints a square in a label to simulate a progress bar.
If b = 10 Then Label1.Caption = Label1.Caption & "n"
b = b + 1
If b > 20 Then b = 1

'When variable set to true stop timer  and unload form.
If bolStop = True Then
    Timer1.Enabled = False
    'Unload Me
End If

End Sub
_______________________________________
This goes in the module:


Option Explicit

Public appWord As New Word.Application
Public bolStop As Boolean


Public Sub OpenWordApp()
Const ERR_APP_NOTRUNNING As Long = 429

'Create error and go to next line.

On Error GoTo ERR_APP_NOTRUNNING

Set appWord = GetObject(, "word.application")

ERR_APP_NOTRUNNING:
    Set appWord = New Word.Application
   
'Just to clean up because I'm really doing anything here.
appWord.Visible = True
Set appWord = Nothing

'Change global variable to stop timer.
bolStop = True
Exit Sub

End Sub

________________________________________

Notes: The "n" that is added to label in the loop is a square box if the font is changed to wingdings.

Problem: The loop is suspended while the computer loads Word. It starts up again if it's not canceled with bolStop.

So my question is this: How to keep the loop running while Word loads?

Multi-threaded was suggested, and I'm trying to find information (preferably a code example) about that. Any references would be a big help.

Thanks everybody!

I'm still trying.

WillP
willsyix@syix.com


0
 

Author Comment

by:WillP
ID: 2560612
After reading two articles on multi-threading in VB, I've decided that this is not the answer. Too much trouble, not enough gain.

I'm still not sure what I'll show the user.

Anyway, if you added a comment and feel you deserve the points, speak up. Otherwise I'll delete the question. It's been two days and no more comments.

(I'm willing to give up the points, in a way I learned something from each comment, though none of them were the "answer.")


Thanks
WillP






0
 
LVL 14

Accepted Solution

by:
wsh2 earned 100 total points
ID: 2562086
Ok.. after your last heave of frustration.. <Gawd.. we are all related, aren't we?>.. how about giving this schema a thought.. <smile>. (If you want more detail.. just EM back)

First, prior to shelling to Word, use the OpenProcess Windows API (or the Windows Scripting Host object if you have it) to launch an asynchronious process (ie. another program in its own workspace).

In the asynch process, do a (modal?) form with your eye candy. Add to this program, an EnumWindows / EnumChildWindows API callback loop, and iterate through it until the desired Word MDIClient document window to appear.. (as I recall, if you launch word with a parameter 1 the caption text will read the document file name.. if no parameter 1 the window caption text will read New Document) and upon a successful test.. unload the form and terminate the program process. Note: To get the proper search criterea.. launch word and then use MS's Spy++.

If the Word splash screen overlays yours, then you may want to test for the Word splash screen and through API Sendmessage's hide it, or once again through API messages place YOUR splash screen on top, or both. By virtue of the fact that you are already enumerating all open windows, you should be able to pick up the Word Splash Screen hWnd in the process. Once again, run Spy++ to ascertain the necessary tests.. <smile>.

Welp.. <yawn>.. datz it. If you want/need to know more just send me a note at WSH2@aol.com.. I will be happy to help.
0
 
LVL 4

Expert Comment

by:wqw
ID: 2563956
WillP: no easy way. as wsh2 proposed you must get hack-o-matic :-)

actually it's not that difficult in fact. just some funky api calls. make your stub loader this way: form with a timer of 5 ms. wait for timer to launch word. this way you are getting asynchronous. another way: use start (on NT at least)

</wqw>
0
 

Author Comment

by:WillP
ID: 2567027
Thanks!

Here's the code of test program:

In a form (a command and textbox):
____________________________________
Private Sub Command1_Click()

Dim JobToDo As String
Dim lngHandle As Long
Dim lngReturn As Long

'Shells exe that contians progress bar.
JobToDo = "C:\WINDOWS\Desktop\ProjectFolder\Project1.exe"
Shell32Bit JobToDo
   
Call OpenWordApp
Call GetHandle
Call FindWord

'Get Handle from invisiable text box.
lngHandle = txtHandle.Text

'Close progress window
lngReturn = SetActiveWindow(lngHandle)
lngReturn = SendMessage(lngHandle, WM_CLOSE, 0, 0&)
End Sub

______________________________________
Sub Shell32Bit(ByVal JobToDo As String)
   
Dim hProcess As Long
Dim RetVal As Long
   
'Captures process ID
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, Shell(JobToDo, 6))
   
End Sub

_____________________________________


In a module:
_______________________________________
Option Explicit

Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal wCmd As Long) As Long
   
Public Declare Function GetParent Lib "user32" (ByVal hwnd _
As Long) As Long

Public Declare Function GetWindowTextLength Lib "user32" Alias _
    "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
   
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As Long) As Long

Public Declare Function OpenProcess Lib "kernel32" _
    (ByVal dwDesiredAccess As Long, ByVal bInheritHandle _
    As Long, ByVal dwProcessId As Long) As Long

Public Const PROCESS_QUERY_INFORMATION = &H400

Public Const WM_CLOSE = &H10
   
Public Const GW_HWNDFIRST = 0
Public Const GW_HWNDLAST = 1
Public Const GW_HWNDNEXT = 2
Public Const GW_HWNDPREV = 3

Public appWord As New Word.Application
____________________________________
Public Sub OpenWordApp()

Const ERR_APP_NOTRUNNING As Long = 429

'Create error and go to next line.

On Error GoTo ERR_APP_NOTRUNNING

Set appWord = GetObject(, "word.application")

ERR_APP_NOTRUNNING:
    Set appWord = New Word.Application

appWord.Visible = True

Set appWord = Nothing

Exit Sub

End Sub
__________________________________
Public Sub FindWord()
   
Dim CurrWnd As Long
Dim Length As Long
Dim strDocName As String
Dim Parent As Long
Dim bolStop As Boolean

'Get handles for open windows
CurrWnd = GetWindow(Form1.hwnd, GW_HWNDFIRST)
 
Do Until bolStop = True
    Parent = GetParent(CurrWnd)
    Length = GetWindowTextLength(CurrWnd)
    strDocName = Space$(Length + 1)
    Length = GetWindowText(CurrWnd, strDocName, Length + 1)
    strDocName = Left$(strDocName, Len(strDocName) - 1)
    If Length > 0 Then
        'Get Word window by window text.
        If InStr(strDocName, "Microsoft Word") > 0 Then
            bolStop = True
            Exit Sub
        End If
    End If
    CurrWnd = GetWindow(CurrWnd, GW_HWNDNEXT)
    DoEvents
Loop

End Sub

______________________________________
Public Function GetHandle()
Dim CurrWnd As Long
Dim Length As Long
Dim strDocName As String
Dim Parent As Long


'Get handle for open Word window.
CurrWnd = GetWindow(Form1.hwnd, GW_HWNDFIRST)

Do Until Form1.txtHandle.Text <> ""
    Parent = GetParent(CurrWnd)
    Length = GetWindowTextLength(CurrWnd)
    strDocName = Space$(Length + 1)
    Length = GetWindowText(CurrWnd, strDocName, Length + 1)
    strDocName = Left$(strDocName, Len(strDocName) - 1)
    If Length > 0 Then
        If InStr(strDocName, "Opening Word") > 0 Then
            'Dump handle in textbox.
            Form1.txtHandle = CurrWnd
            Exit Function
        End If
    End If
    CurrWnd = GetWindow(CurrWnd, GW_HWNDNEXT)
    DoEvents
Loop
End Function
_______________________________
The other program is a simple exe that has a timer and label as above.

Remember to reference Word in main program.

0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
Introduction While answering a recent question (http://www.experts-exchange.com/Q_27402310.html) in the VB classic zone, I wrote some VB code in the (Office) VBA environment, rather than fire up my older PC.  I didn't post completely correct code o…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now