- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Search this forum for PeekMessage loop; such a loop should be called every while from a code which does a long calculation. I'm not sure if the problem comes because of Excel -- what exactly do you mean by "Shells out Excel template"? How do you "shell it out"? If you wait for it using WaitForSingleObject, you stale your own thread -- in that case, you still need a message loop instead -- Google MsgWaitForMultipleObjects (that stuff lets you wait for a sync object handle and process messages in the meantime).
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Message Edited by anthonyrichards on 09-05-2005 08:11 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Message Edited by anthonyrichards on 09-08-2005 06:46 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
and from the WM_ERASEBKGND help
"The DefWindowProc function erases the background by using the class background brush specified by the hbrBackground member of the WNDCLASS structure. If hbrBackground is NULL, the application should process the WM_ERASEBKGND message and erase the background.
An application should return nonzero in response to WM_ERASEBKGND if it processes the message and erases the background; this indicates that no further erasing is required. If the application returns zero, the window will remain marked for erasing. (Typically, this indicates that the fErase member of the PAINTSTRUCT structure will be TRUE.) "
Since you say yours is a true Windows app., you must specify a background brush when you create the window class, or else a default (probably white) brush is used. Since you use a bit-map background, I guess you have to reload it into the window device context (or into a compatible one in memory and swap it into the window device context). Anyway, good luck!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
(As you might have guessed, I was absent for a while :-). ).
Here's an explanation of what is (was?) going on:
You have encountered a common problem of screen updating while performing a long task. Usually, while the task is done, you want the user just to sit and watch what's going on, but because of the way how Windows does window repainting, your own screen can vanish for a while. Namely, in a GUI application you're supposed to run a message loop one way or another, and everything you do in the message processing is supposed to be short. That provides the appearance of a smooth GUI without glitches. The problems emerge when you do need to execute longish things.
First, have in mind that you're (unless you did your own CreateThread) always in a single-threaded application, so things don't happen automagically. Thus, first:
iret = WaitForSingleObject(pi%hProcess,INFINITE)
will do just that -- sit and wait. While it's waiting, you don't do anything else. WM_PAINT messages sitting in the queue (well, not 100% true but close*) will get processed/window redrawn only when you either
a) return from your DlgProc or
b) call GetMessage/DispatchMessage yourself one way or another.
c) I think that InvalidateRect+UpdateWindow will call the dialog procedure directly, but I'm not certain**.
It is the DispatchMessage which actually calls your DlgProc eventually. However, modal dialogs (DialogBox and MessageBox) have embedded message loops. Thus, your call to MessageBox did initiate a message processing, so your DlgProc actually got called from there (yes, recursively) for a WM_PAINT and whatever else got accumulated in the message queue***.
Second, your call rtn_designtofmis(hProgress, hDlg, IDC_task, ghWndMain,...) apparently does some progress bar updating. I'm not sure if the entire dialog is correctly redrawn though.
*) WM_PAINT is actually generated by GetMessage when (a) message queue is otherwise empty and (b) the window has an invalid region. Note the concept of "invalid region", i.e. an area that needs updating.
**) In any case, SendMessage(WM_PAINT) is always futile, as the window has no invalid region. InvalidateRect will invalidate appropriate area, and UpdateWindow will (maybe?) actually call the window procedure with WM_PAINT. RedrawWindow should also work, but I could have never swallowed its documentation so I don't use it.
***) Thus, Tony's PostMessage would also not help in this case, as it will be processed only after you return from DlgProc.
To wait for Excel to complete and redraw the window, you have to use MsgWaitForMultipleObjects loop. Of course, you should take care to disable the OK button and other controls and/or adjust program's logic (see here)
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
write(errcode,'(I6)')GetLastError()
call prgerr(0,'Error creating Excel process, error code: '//errcode)
else
ncount = 1
handles(1) = pi%hprocess
iret = MsgWaitForMultipleObjects(ncount,loc(handles),0,INFINITE, & QS_ALLEVENTS)
csvname = trim(fmis$work)//''//jobname//'1.csv'//char(0) !Output from Excel
inquire(file=csvname,exist=FileExists)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
do while (.TRUE.)Jugoslav
iret = MsgWaitForMultipleObjects(1, LOC(handles), TRUE, &
INFINITE, QS_ALLEVENTS)
if (iret .EQ. WAIT_OBJECT_0) then
!Excel is terminated
exit
else
!A message was posted
if (PeekMessage(msg, NULL, 0, 0, PM_REMOVE) .ne. WM_QUIT) then
!An ordinary message
if (.not. IsDialogMessage(hDlg, msg)) then
TranslateMessage(msg)
DispatchMessage(msg)
end if
else
!WM_QUIT message, i.e. your application is closed
!(if it's possible)
exit
end if
end if
end do
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
write(errcode,'(I6)')GetLastError()
call prgerr(0,'Error creating Excel process, error code: '//errcode)
else
handles(1) = pi%hprocess
loop_a: do while(.true.)
iret = MsgWaitForMultipleObjects(1,loc(handles),TRUE,INFINITE,QS_ALLEVENTS)
if(iret==WAIT_OBJECT_0)then
exit loop_a
else
if(PeekMessage(msg,null,0,0,PM_REMOVE)/=WM_QUIT)then
if(.not.IsDialogMessage(hDlg,msg))then
iret = TranslateMessage(msg)
iret = DispatchMessage(msg)
end if
else
exit loop_a
end if
end if
end do loop_a
end if
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think it should read:
...
else
do while (PeekMessage(msg,null,0,0,PM_REMOVE).NE.0)
!Special case msg%message for WM_QUIT if you want here.
if(.not.IsDialogMessage(hDlg,msg))then
iret = TranslateMessage(msg)
iret = DispatchMessage(msg)
end if
end do
end if
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
exit loop_a
else
if(PeekMessage(msg,null,0,0,PM_REMOVE)/=0)then
if(.not.IsDialogMessage(hDlg,msg))then
iret = TranslateMessage(msg)
iret = DispatchMessage(msg)
end if
else
exit loop_a
end if
end if
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Look at MsgWaitForMultipleObjects or this link directly :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waiting_in_a_message_loop.asp
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Jugoslav,
Many thanks for your example - yes it works, but unfortunately it does not represent the situation I have been trying to describe. In my case, it is not just a matter of running another process, finishing it, then coming back to the calling process. The Excel that I run uses a VB macro to output a file which the calling process needs in order to continue. If that file exists, the number crunching swings into action, and it's during this phase (20 seconds?) that no screen repainting occurs and the user gets no progress reports.
In order to demonstrate this I have attached a zip file containing a totally stripped down version of my code. I have hardwired all necessary data in the Excel template - the clicking of an OK button is all that is required, but the demo works best if you delay clicking the OK button for about 10 seconds.
Many thanks once again for all your help.
Mike
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page