MFC dialog close issues - mfc

Good day!
I have an MFC dialog with progress.
Dialog automatically closes after reaching 100% using PostMessageW(WM_CLOSE).
The problem is, when, during progress, I'm moving dialog over the screen, dialog is not closing and WM_CLOSE message is ignored. Any suggestions? Thanks.

For a modal dialog you shouldn't really need to use a WM_CLOSE message.
Normally you'd use the OK or Cancel button events to close it, call the EndDialog method from functional code or just return when your processing is complete (assuming that its the process run as soon as the dialog is initialised). You can set your return value at the same time e.g. EndDialog(2);.
Either way the dialog will close once th current message handler returns, so there could well be a delay, in closure but it shouldn't be much.

Is the activity behind progress bar done in a separate thread? It look like to be the case otherwise when you drag the dialog the progress bar would have froze until you release the dialog than it would have resumed. This means you might have to look into inter thread communication, how the message is being posted to the dialog HWND.
It might have to do with the dialog being in freeze (no activity) state while you are dragging it which seems to be normal windows behavior. If that is the case you could use signals/CEvent to tell the dialog to close down.

Related

Can't focus from main window after closing dialog from other thread

I create a new CWindThread in CWinApp::InitInstance(). In that thread, I create a dialog (for displaying a progress bar in that dialog).
After finishing InitInstance(), I close the dialog by calling DestroyWindow() from the dialog, but the application is loosing focus from main window.
I used AfxGetMainWnd()->SetActiveWindow(); to set focus for main window but it is not working.
How can I return the focus to the main window after closing the dialog?
There is no real good way to do that. The focus is set per thread. So there is no "focus" over all windows.
The only chance you have is to set the new foreground window, that belongs to the other thread with SetForegorundWindow. From within the same application this should work without restrictions.
If it doesn't work you need to "synch" both message queues. This is done by AttachThreadInput. If both messages queue are already attached, than there is no problem with settings the focus directly. But the behaviour of the application will change... Please read the docs, of the functions I linked too.
When a modal popup window is displayed, the reason a user cannot interact with the owner window is that it is disabled. When the modal window is destroyed, care must be taken to re-enable the owner window BEFORE destroying the popup as windows cannot activate a disabled window. This is the usual cause of popup windows re-activating the wrong window.

Programmatically clicking toolbar button in parent of modal window

I have an application that hooks into another application via an API. My application launches a modal window which prevents keypresses to reach the parent as one would expect.
However due to limitations in the API I need to click one of the parents toolbar buttons from time to time (yes it's a kludge).
I wonder if this is possible while still having the modal window of my application active? Is it perhaps possible to send the required command directly into the parent command queue?
Clicking the button programmatically with no modal window should not be a problem, one could go by this link for example: http://forums.codeguru.com/showthread.php?307633-How-to-run-a-very-long-SQL-statement. But I would prefer not having to close my window each time I have to click the button.
Although the fifth answer is what I find interesting as I'm thinking this could make it possible to send the command without having to close my modal window first. Also it feels an ever so small bit less ugly.
First of all, when a modal dialog is shown, it runs its own message pump. So any attempt to fake input messages will land in the modal dialog message pump. Which is no good to you. So, you'd have to send a message rather than fake input.
However, when a modal dialog is shown, its owning windows are disabled. Which means that these windows will not respond to any messages you send. So I guess that means that you could:
Enable the owning top-level window that you hosts the toolbar in question.
Send the message to the toolbar button.
Disable the owning window again.
Not the prettiest way to go about things, but you did ask!

Interpreting QCloseEvent differently

I have a desktop windows application programmed in C++ with Qt. The application has several top - level windows which occasionally need to be closed and recreated programmatically. Also, when the user of the program clicks on the close button (the one next to the minimize and maximize buttons) the whole program is supposed to exit.
The problem I have is that in both cases the top level windows receive a closeEvent() call with a QCloseEvent object. I'd like to quit the program when I see that happen (because the user might have clicked the close button), but it's also possible that the window is closing because I'm deleting it programmatically to recreate it.
Is there a way of distinguishing between these two cases in QMainWindow::closeEvent()?
Is there a way of distinguishing between these two cases in QMainWindow::closeEvent()?
Yes: the close event triggered by the user clicking on the window's close button will be a spontaneous event, the one triggered by you calling window->close() will not. See the documentation of QEvent::spontaneous() for more information.
When you need to close your window programmatically, use deleteLater() instead of close. The window will be closed and deleted. To reopen the window you will need to create another window object.
You can also use hide() method. The window will be hidden but not destroyed. It can be shown again using show().
In both described cases the close event does not happen and closeEvent() isn't called. So when closeEvent is called, you know that the user has pressed the close button.

FindWindowEx not able to find window handle

I am trying to find the handle to a dialog as soon as it opens.
Now as soon as dialog is opened I try to call FindWindowEx for that dialog in a separate thread but it returns NULL.
I then put some sleep before calling FindWindowEx. It works some time after putting sleep.
It looks like FindWindowEx is getting called before even dialog is created and sleep is helping to create the dialog and hence some times it work.
Now I have put some random value in sleep. And it doesnot look a good approach since it can fail anytime.
Is there any full proof approach so that I may get handle every time via FindWindowEx without making thread to sleep.
If the dialog you are looking for is your dialog -- that is, you control the code -- then you can send a message from your dialog to your watching app that says, "Oh, hi there!"
If the dialog is not yours, and you don't want to spin, you can create a Windows hook on the WM_CREATE message.
A very straightforward solution would be to call FindWindowEx repeatedly in a loop.
HWND h = NULL;
while (1) {
h = FindWindowEx(...);
if (h) {
break;
}
Sleep(100);
}
That's not bullet-proof - it's an infinite loop if the dialog nevers opens, or is closed too quickly (although that's unlikely). To catch both cases, let the main thread (which creates and runs the dialog) maintain a simple bool property that the worker thread queries to find out whether there's still a dialog around.

Reopen modal dialog in MFC

I need to open a dialog box instantiated from the same class twice. When I try this
CdelmeDlg dlg;
dlg.DoModal();
dlg.DoModal();
The second call opens the dialog only for a split second, then it is closed. My bet was there is a leftover message in the message queue, so I added this in between the calls
MSG msgCur;
while (::PeekMessage(&msgCur, NULL, NULL, NULL, PM_REMOVE))
;
This solves the problem, but it feels like a wrong kind of thing to do. Is there a way to process the leftover message properly?
Don't call EndDialog( IDOK );
To handle the ok or cancel buttons being pressed just inherit OnOk or OnCancel ... Otherwise EndDialog is going to be called twice and you'll get the problem you are getting!
I actually think that YeenFei has a good point here.
It's been a while since i've played with MFC (thank goodness), but from memory, a timer, may or may not be called from the UI thread depending on which one you use. If the timer is being raised on the main UI thread, then a modal dialog will likely halt the main thread until it is dismissed, after which it would be called by the next timer. If the timer is raised on a separate thread, then your dialog is not blocking the main UI thread as it is being shown on a separate thread.
It's does seem more conceivable as YeenFei has pointed out that you want to re-show your dialog each time the timer is raised, hiding it when the user clicks on the button to dismiss it. That way, if the time is raised again, all it does is re-show the dialog whether it is currently open or not.
There is a great post here (www.eggheadcafe.com) about Timers and concurrency that you may find interesting, and may make things clearer than what I managed to accomplish.
Why can't you code it like this:
CdelmeDlg dlg;
dlg.DoModal();
CdelmeDlg dlg1;
dlg1.DoModal();
If you want your application run in background without UI, why not juz temporary hide it? a simple function this->ShowWindow(SW_HIDE) will do the job for you.
i think you should revise your design decision as it seem illogical for an application to behave like what you wanted it to be.
I solved the problem by hiding the dialog instead of closing it and launching another thread that first sleeps and then unhides the dialog.
May be your code has line:
m_pMainWnd = &dlg;
If so, than application after first call of DoModal() will finished, all other call of DoModal() will return -1. From MSDN:
The Microsoft Foundation Class Library will automatically terminate your thread when the window referred to by m_pMainWnd is closed. If this thread is the primary thread for an application, the application will also be terminated.