Solved

How to make long process in MFC modal dlg “responsive” in Win7

Posted on 2012-03-10
4
1,142 Views
Last Modified: 2012-03-13
Hi. I have a (dialog-based) app written in C++ with MFC. It puts up a modal dialog, which does a scan of a drive, which obviously takes a few minutes. To give feedback to the user, I have the modal dialog display a count of files processed, which increments with each file. All is fine in Win XP, but under Win 7 I get a problem with the window “freezing”. It stays frozen until the scan is complete, and then comes alive again. I’ve read online that this is because Windows 7 decides that the window isn’t responding, and over-writes it with a “dummy window”, which has the effect of stopping my file count from being updated.
So, an an attempt to prevent this, I added a PeekMessage to the modal dialog’s file handling loop, to pump any messages it found. And although that seemed to work, in that the window doesn’t freeze up any more, I seem to have replaced that problem with several different problems. Now, if I click on the main window while the modal “sub” window is doing its file scan, the Exit button on the top-right of the window turns red. If I click the window again, it gets “greyed” and the modal dialog disappears behind it – and the main window icon in the taskbar says Not Responding. But actually it is responding, because if I click the minimize button, it does minimize itself, and I then see my modal dialog updating its progress count, and all looks well. But, when the modal dialog’s process finishes, it disappears. And the taskbar now has two icons, “nested” together, which when I hover over them both show the modal dialog (neither of them say “not responding”). And – this is the real problem – when I click on them, nothing comes up. The program is now effectively dead.
I’ve come up against a couple of complications while researching this – one, it seems that MFC “modal” dialogs aren’t really modal, they’re modeless, simulated to behave like modal, and two, it seems that there is a bug in Win 7 to do with taskbar icons not working. So all in all, I’m really confused at the moment how I should make my app behave nicely in Windows 7 – can anyone help? I should emphasize that I don't want users doing anything with the main window - except possibly minimizing it - while the file scan is going on.

EDITED:
Sorry, I misdiagnosed this slightly. Just realized that what I thought were my "secondary" problems weren't in fact caused by my message pumping, they were there all along, but showed a bit differently. So without any message pumping, it's still possible to minimize the main window - but this time I only get one icon in the taskbar - and again when the sub dialog finishes it disappears, and the program is dead - clicking the taskbar icon doesn't bring it up.
0
Comment
Question by:RainbowGuy
  • 2
4 Comments
 
LVL 16

Assisted Solution

by:HooKooDooKu
HooKooDooKu earned 250 total points
ID: 37706107
The most strait forward answer in my mind is multi-threading.  Allow the long process to execute in one thread, while you have the user interface execute in another thread.

Check out this link on Multi-threading.  http://msdn.microsoft.com/en-us/library/69644x60%28v=vs.100%29.aspx

Starting a Worker Thread is really simple.  It basically just requires defining a function and calling it with AfxBeginThread.  Your two threads can "talk" to each other.  That way, you have the worker thread doing the "work" that normally locks up your application while the dialog continues to respond to the user.  By having the worker thread update variables, you can easily display progress in the dialog.  You can even include an abort button in your dialog.  Have the abort button simply update a flag that the worker thread can check every once in a while and abort its task if the abort flag gets set.

There are two types of threads.  There are worker threads and UI threads.  The UI threads involve setting up message looks and require multiple steps to get working right.  So for now, don't bother with UI threads.  But just a quick bit of research should get you up and running with worker threads in little time.
0
 

Author Comment

by:RainbowGuy
ID: 37706419
HooKooDooKu, this is not the way I want to go. I know about threads - I already use them to do animation. But as I said in my original question, I don't want the user doing anything while the modal dialog is up - it's updating their basic data and I don't want them making changes which will then potentially be over-written.
Really, the crux of my question is - how to stop Win7 from allowing my parent window from being minimised. It's not supposed to be active, as there is a "modal" dialog up, but the fact that MFC simulates modal is messing things up - that's what I need an answer to.
0
 
LVL 32

Accepted Solution

by:
sarabande earned 250 total points
ID: 37714592
You could try to call BeginWaitCursor() before scan and EndWaitCursor() after scan. I would assume it prevents from "freezing" as those functions actually are designed for such purposes.

if it doesn't help you could call another modal dialog which has only a cancel button and could not be minimized. you would move the scan to the OnTimer function if you could divide the task into smaller parts or use a thread as suggested by HooKooDooKoo. if using a thread you would pass the hwnd of the modal dialog as parameter and so could post a WM_CLOSE message to end the dialog after scan (always use PostMessage and not SendMessage for messages from thread).

Sara
0
 

Author Closing Comment

by:RainbowGuy
ID: 37714934
OK, I'm going to close this one now. I've split the points equally between my two responders (and thanks for the suggestions), but I have now sorted it out myself, after two days intensive research online! In case anyone else looks at this, here is what I did.
To prevent the main window from being minimized while the "modal" dialog was up, I called ModifyStyle to remove the minimize box just before the DoModal, and then called it again afterwards to put it back. That was the easy bit!
The other bit of the problem, where clicking in the main window made it go faded and hide the modal dialog, well, the key to fixing that was finding out about "ghost" windows. This is where Windows 7 steps in to allow the user to minimize, move, or close a non-responsive window. It does this by slapping an image of the last known state of the window over the top of it, and then monitoring interaction with that window. Unfortunately in my case, that ghost window was obliterating my modal dialog as well - bad news as you then couldn't see the progress count. So, the fix was to put a call in from my modal dialog - in the function which was iterating through the files on the drive - to call a new function (which I called "pumper") in the main dialog. And that function just did a PeekMessage and removed any messages from the queue - and so because the main window now isn't seen to be non-responding, it doesn't get "ghosted".
There is also apparently an API called DisableProcessWindowsGhosting() which I'm sure would have worked, but as that isn't part of my ancient Visual Studio 6.0, I didn't use it.
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

One of the features I've come to appreciate about Windows 7 and Windows Server 2008 R2 is the ability to pin applications to the task bar. As useful a feature as I've found this, it does have some quirks.  For example, have you ever tried pinning an…
First some basics on Windows 7 Backup.  It has 2 components one is a file based backup which is stored in .zip files each zip is split at around 200 Megabytes and there is the Image Backup which is as the name implies a total image of the partition …
This Micro Tutorial will give you a basic overview of Windows DVD Burner through its features and interface. This will be demonstrated using Windows 7 operating system.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

747 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

12 Experts available now in Live!

Get 1:1 Help Now