Solved

ProgressBar

Posted on 2000-02-22
9
389 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 

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

Enroll in May's Course of the Month

May’s Course of the Month is now available! Experts Exchange’s Premium Members and Team Accounts have access to a complimentary course each month as part of their membership—an extra way to increase training and boost professional development.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

732 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