How to close a modeless MFC dialog in C++ - c++

I have a modeless dialog that is sometimes left up on the screen when I go to close my main app. If I close it manually, all destructors get called properly. But so far, if I try to do it through C++ code, I encounter problems in the Debug build that don't give me confidence in what is happening in the Release build.
What is the correct way to close a modelss dialog? Documentation for PostQuitMessage() indicates it closes entire threads (is a modeless dialog run in a separate thread, or just part of the single MFC App UI thread?). Calling DestroyWindow() gives me issues in practice. Sending a WM_CLOSE doesn't feel like the right thing to do. And CWnd::EndDialog() only applies to Modal dialogs. Does the correct answer lie among these... or somewhere else?

Related

How can I debug a constantly losing focus window (dialog, for instance) in MFC?

I am maintaining I big and mature application, without background on MFC paradigm and layout. I have experience with Qt, OO designs and UI frameworks (I'm aware of each thread responsibility, event loops, event handling hierarchies, etc.
I'm stuck with a settings CDialog window losing focus constantly, while I'm trying to configure my application. I also have a file explorer dialog that behaves exactly the same way. Both are activated by DoModal calls.
I've read that this is probably because I have two modal dialogs competing for focus. How can I debug that? What function could I break on to get a helpful callstack, so I can find the offending code? Is there an MFC::focusWindow(WHND window) or something that I could intercept?
The problem according to your description is that you 'have two modal dialogs competing for focus'. This should normally not be possible because by definition a modal dialog takes over the application and does not return control to its launch point until the dialog is closed. Without knowing the architecture of the application, the simplest solution would be to make the settings dialog modeless (create it then call ShowWindow(SW_SHOW) instead of DoModal. This will allow the message loop to run for the other modal dialog but not take focus from your settings dialog unless it is doing it explicitly in its own methods.
Use Spy++ to spy the messages/events that occurring in the dialog.
You can use SetFocus function, please refer to
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646312%28v=vs.85%29.aspx

Assynchronous dialog box on Windows with C++

Right now I'm working on a real time software, but I got myself implementing forms - using C++Builder 2007 - for confirmation messages (you know, those dialog box with OK and Cancel or only OK if it's an error), and I read that there's a DialogBox class on Windows MFC. The problem is the calling interrupts the thread until some input is done on the dialog, which I can't afford because another things might be happening on the application.
I've read about Modeless Dialog Box, but I'm not sure it's what I need or how to implement. Is there a default assynchronous dialog box on Windows MFC and if there is, how do I call it?
You don't need threads for this, you need modeless dialog boxes... they end up being windows on the same dispatch thread.

MFC modal dialog close error

I have a strange error and spend hours in the debugger without finding a solution.
(But it helped me to fixed another error that you should never call EndDialog from a WM_KICKIDLE task).
My problem is that i have a main window and a modeless dialog window wich raises a modal subdialog window. When the subdialog window is closed. The modeless dialog window turns itself into a modal window. My code really does leave the modal loop. And if i close the now modal window it behaves like an invisble modal window is active, meaning no interaction is possible anymore.
When i only run a modal dialog on top of the main window it is closed fine.
BTW: The main window is not the one available view CWinApp::m_pMainWnd but a new create FrameWindow. I hide the p_MainWnd and use it as an invisible message only window. From some comments and my debugging session i found that the pMainWnd has some special meaning but i could figure what exactly it has to do with modal windows (there is an undocumented "CWinApp::DoEnableModeless" for example).
EDIT: I'm posting a WM_CLOSE to the dialog and then use EndDialog(0) from the OnClose() handler to exit the modal state. I also tried to use EndDialog(0) directly. There is no difference between this two methods.
When MFC creates a modal dialog, it makes it modal by disabling the windows above it. The code that reenables those windows occurs when the dialog ends normally with a call to EndDialog. If anything prevents that code from running, the other windows will be locked out.
Modeless dialogs are a different beast, and there's a note specifically in the EndDialog documentation warning you to use DestroyWindow instead.
Maybe this is justifiable but I have a question:
why are you using hidden window? Was it created as message only window (passing HWND_MESSAGE as a parent handle and Message as a class) or you just call it message only?
OK, a little more info about MFC and dialogs.
MFC does not use Windows modal dialog. It always creates modeless dialog; either Create or DoModal call in turn ::CreateDlgIndirect windows API.
Modeless dialof rely on the main window message dispatch, while modal calls RunModalLoop that is similar to MFC window message pupmp (not a message loop).
It runs in the main thread of execussion without freezing because it allows for idle processing (calls OnIdle).
How do you dismiss the modeless dialog? As Mark pointed you should use DestroyWindow.
As for m_pMainWnd, MFC framework uses it extensively to determine may things that control main window behavior. By changing it you may have created the behavior you experience.
Did you set the value to a newly created frame you treat as a main window?
What kind of MFC application is it? SDI or MDI?
Would it be possible to create test app to duplicate this behavior and post it somewhere for download?
By the way, you do not have to be concern about DoEnableModeless, since it does not do anything but calls hook (COleFrameHook type) that is spasly used, unless you are trying to implement some functionality using OLE or ActiveX or you are trying to marry MFC and .NET Windows Forms.
In conclusion if your (or third party code uses this hook, I would suggest checking the code in the COleFrameHook class.

XP scrollbars going haywire in Windows7/Vista

I have this XP app (win32 C++) that I am just now testing under Windows7 (vista actually, but it does the same thing in windows 7).
I'm surprised that virtually the only issue I'm encountering is the following:
None of the scroll bars in a complex modelless dialog are functioning correctly. The main problem is the scroll thumb is not responding - just stays locked in position if you try and move it. Have had no issues going all the way back to win98, win2000, and winxp. Only in windows 7/Vista just now
But there is no commonality in the scrollbars in this dialog to explain it: One is in a plain richtext control created through a resource file. Another is in a richtext created through CreateWindow. And yet a third scrollbar is in a custom window class. None of them are working correctly (although you can make them scroll by right clicking and selected "Scroll Here".)
So I'm presuming maybe most encountered this a few years ago when porting to Window7/Vista for the first time, but I'm not finding anything in google now.
For modeless dialogs, you have to run IsDialogMessage in the main application GetMessage Loop, so messages for modeless dialogs are not subject to TranslateMessage and DispatchMessage. So I was doing that previously. However, Vista/Win7 doesn't like WM_MOUSEMOVE, and WM_LBUTTONDOWN and WM_LBUTTONUP to be bypassed like that for the dialog (i.e. they need to stay in the main App message loop). At least this was the problem in my case. I check for those message types now in the main message loop and that solved my problem. Can't explain it necessarily. Also couldn't explain why no one's encountered this previously (could be some idiosyncracy of my set up I guess). THanks for those who looked into this.

Windows messages serviced whilst assert dialog is being displayed?

I have an MFC application that spawns a number of different worker threads and is compiled with VS2003.
When calling CTreeCtrl::GetItemState() I'm occasionally getting a debug assertion dialog popup. I'm assuming that this is because I've passed in a handle to an invalid item but this isn't my immediate concern.
My concern is: From my logs, it looks as though the MFC thread continues to service a number of windows messages whilst the assert dialog is being displayed. I thought the assert dialog was modal so I was wondering if this was even possible?
The message box that shows the assertion failure has a message pump for its own purposes. But it'll dispatch all messages that come in, not just those for the message box (otherwise things could get blocked).
With a normal modal dialog, this isn't a problem because the parent window is typically disabled for the duration of the dialog.
The code that launches the assertion dialog must've failed to figure out the parent window, and thus it wasn't disabled. This can happen if your main window isn't the active window at the time of the assertion. Other things can go wrong as well.
You can change how Visual Studio's C run-time library reports assertion failures with _CrtSetReportMode. You can make it stop in the debugger and/or log to the output window instead of trying to show the dialog.
Dialogs (even a messagebox) need to pump the message queue, even if they're modal. Otherwise how would they know you clicked on the "OK" button?
If you need to stop everything when an assert triggers it's usually not too difficult to write your own implementation of assert() (or ASSERT() or whatever) that will break into the debugger instead of displaying a messagebox that asks if you want to break into the debugger (maybe only if it determines that the debugger is attached).