MFC modal dialog close error - mfc

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.

Related

Disable all top level window (WS_POPUP) when showing modal dialog

I have the main window, and then the user can "pop up" one of the frames in the application so that it floats rather than being contained in the main window. There are multiple frames that can be popped up so that in a given time there might be three WS_POPUP windows.
The problem is when I want to show the modal dialog, I can only disable one of them using the parameter in the DoModal function. How can I disable all top-level windows using DoModal? I can't simply disable the windows before showing modal and then enable it back because There could multiple chained modal dialog (one modal dialog opens up another modal dialog).
Does the API provide a way to do something like this? I've googled this for two hours and can't find a good enough solution. I'm using a combination of MFC, WTL, and ATL.
Thanks in advance!
As I understand the problem, it is the same like the MFC frame windows work.
In fact only the CFrameWnd of an MFC application gets disabled. On arrival off the WM_ENABLE message (with FALSE) BeginModalState is called and this function just disables it floating "child windows" of the CFrameWnd.
Same again, when EnableWindow (WM_ENABLE arrives with TRUE) is called for CFrameWnd. EndModalState is called and all disabled "child and floating" windows are enabled again.
See the MFC implementation of CFrameWnd::OnEnable, BeginModalState, EndModalSTate in the source code.
So you main window knows it's own popups. Upon launching the true modal dialog, and disabling this parent, it will disable it's floating popups.
The trick is that CDialog::DoModal needs the real parent... if not given in the constructor it guesses the correct one in most cases. For your case it should be necessary that you provide your "main window" as the parent window... same for message boxes...

How to close a modeless MFC dialog in 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?

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

TAB key does not work in MFC application on COM framework. But, arrow keys work

My application is a dialog shipped out as a dll. It can be launched in modal and modeless modes,from a bigger application that I have no control of. We use MFC library and follows COM architecture. For development purpose we have a tester application that launches my dialog.
The problem I face is that tab key do not work at all in both modal and modeless.
but, arrow keys work.
When observed through SPY++, I cannot see tabs coming to my dialog at all.
I am pretty confused on what's happening ?
For tabs to work in a modeless dialog, the application must call IsDialogMessage from its main message pump. But in your case, the application doesn't even know the dialog exists. I believe your only option is to install a Windows hook (see SetWindowsHookEx) and call IsDialogMessage yourself.
Modal dialog should work out of the box though - are you sure it doesn't?

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.