-1

My application has several windows, each of a different CDialog-derived class.

Hitting the "X" button in the upper-right-hand corner of the window frame closes the window and calls PostNcDestroy.

For one of the four windows, though, it ALSO calls ANOTHER window's PostNcDestroy() in addition and makes that window invisible as well.

Any ideas?

Andrew Komiagin
  • 6,446
  • 1
  • 13
  • 23
Swiss Frank
  • 1,985
  • 15
  • 33
  • Whoever down-voted this, could you please message me and help me understand how I can do a better job in the future. – Swiss Frank Nov 30 '15 at 15:03
  • Again, whoever down-voted this, could you please let me know what I did wrong, so I understand how I can do a better job in the future. – Swiss Frank Feb 10 '16 at 04:10
  • Hey, I'm quite concerned to learn why this was down-voted. Could the downvoter please explain? I'm holding up making other contributions on stackoverflow because I don't want to keep repeating whatever the mistake is. – Swiss Frank Feb 14 '16 at 13:06

2 Answers2

0

You have not given much information. We can only guess... Since you state that all of your windows are dialogs, I would guess that inside your application's InitInstance() method you have a call to DoModal() of the main CDialog derived class. After you close the main dialog, it exits out of the DoModal() loop and then it exits out of InitInstance() and shuts down the application. The application shutting down causes the other dialogs to be destroyed with results in WM_NCDESTROY being sent and then PostNcDestroy() being called.

Joseph Willcoxson
  • 5,853
  • 1
  • 15
  • 29
  • Thanks Joe. I see what you're saying but as you say I didn't give clear-enough information to rule that situation out.. In this case we have four windows open at the same time. Hitting the "X" for window 1, 2, or 3 only closes that single window. Hitting the "X" for window 4 closes windows 3 and 4. – Swiss Frank Nov 28 '15 at 09:00
0

SHORT ANSWER: The behavior was caused by setting m_pMainWnd AFTER creating all four windows. If it is set before creating the second window, the problem above no longer occurs.

LONG ANSWER: the problem is that the windows ARE NOT SIBLINGS with each other. They are each a CHILD of the PREVIOUS.

Parent of window 1 is value "0" (desktop). Parent of window 2 is window 1. Parent of window 3 is window 2. Parent of window 4 is window 3.

My original problem report noted that window 4 mysteriously closed when window 3 was closed. So now the reason why is obvious. (Closing a window closes all its children too.) I subsequently discovered that closing window 2 caused 3 and 4 to close as well, which is also accounted for. (3 is 2's child so closes, and that makes 4, which is 3's child, close.) Finally, closing window 1 checks for unsaved work, and if none calls exit(). I assume that if this window didn't exit, the other windows would have all closed too.

CDialog::Create() has default param NULL for its second arg pParentWnd, and NULL means parent "is set to the main application window." Stepping into CDialog::Create(), which calls CDialog::CreateIndirect(), which calls AfxGetMainWnd() I end up in CWinThread::GetMainWnd(). That method, if m_pMainWnd is not yet set, just returns CWnd::GetActiveWindow() which is the most-recently-created window.

So: the source of the problem is that my app created four windows, THEN set m_pMainWnd. This is why window 3 was a child of window 2 (the active window at that point) 4 is a child of 3, and so on.

By setting m_pMainWnd after creating window 1, then windows 2 3 and 4 are children of 1. So that gets rid of the "closing window 3 makes window 4 close too" problem.

This still not quite what I needed, as it prevents window 1 from being brought in front of the other three windows. This is outside the scope of my original question, but here is the fix to that. Changing the Create() call to pass in GetDesktopWindow() explicitly seems to have gotten the app working as I wanted, with four windows independently able to close and be freely orderable in the window stack:

  Create( resource_ID, GetDesktopWindow() );

I'm surprised this isn't a famous issue, as the documentation (as of VS2008Pro) for NONE of these functions actually explains what they actually do when m_pMainWnd isn't set, and moving that simple assignment to m_pMainWnd to the end of window creation would probably screw up ANY app that created more than two windows...

Swiss Frank
  • 1,985
  • 15
  • 33