Catching WM_CLOSE in a CDialog subclass
Jeff Wishnie -- jwishnie@swellsoft.com
Friday, August 23, 1996
Environment: MSVC 4.2/Win 95
[Moderator's note: Jeff has been told to try Spy++, so if you don't
have any other advice for him...]
I have a dynamically allocated modeless CDialog. I want to catch WM_CLOSE so
that the dialog simply hides itself on close rather than destroying the window.
Pretty straightforward right? Here's what I did:
Used the class wizard to create the message handler as follows:
declartation: afx_msg OnClose();
message map entry: ON_WM_CLOSE();
handler:
void
CMyDialogSubclass::OnClose()
{
ShowWindow(SW_HIDE);
// CDialog::OnClose(); // do _not_ call parent
}
Problem is, OnClose _never_ gets called. I click the little close box as
much as I want but I never receive the WM_CLOSE message and the box does
nothing.
Questions:
1. Where is the message going? Who's catching it?
2. What's wrong with my approach? Why can't I catch the message??
Thanks for any help!
- Jeff
jwishnie@swellsoft.com
415 243-9900 (w)
Andrew Dalgleish -- andrewd@axonet.com.au
Monday, August 26, 1996
[Mini-digest: 4 responses]
You can catch the 'X' button in WM_SYSCOMMAND for ((nID & 0xFFF0) ==
SC_CLOSE)
Regards,
Andrew Dalgleish
----------
From: owner-mfc-l[SMTP:owner-mfc-l@majordomo.netcom.com]
Sent: Friday, 23 August 1996 15:56
To: mfc-l
Subject: Catching WM_CLOSE in a CDialog subclass
Environment: MSVC 4.2/Win 95
[Moderator's note: Jeff has been told to try Spy++, so if you don't
have any other advice for him...]
I have a dynamically allocated modeless CDialog. I want to catch WM_CLOSE
so
that the dialog simply hides itself on close rather than destroying the
window.
Pretty straightforward right? Here's what I did:
Used the class wizard to create the message handler as follows:
declartation: afx_msg OnClose();
message map entry: ON_WM_CLOSE();
handler:
void
CMyDialogSubclass::OnClose()
{
ShowWindow(SW_HIDE);
// CDialog::OnClose(); // do _not_ call parent
}
Problem is, OnClose _never_ gets called. I click the little close box as
much as I want but I never receive the WM_CLOSE message and the box does
nothing.
Questions:
1. Where is the message going? Who's catching it?
2. What's wrong with my approach? Why can't I catch the message??
Thanks for any help!
- Jeff
jwishnie@swellsoft.com
415 243-9900 (w)
-----From: Paramasivan Maddy
Handle the OnSysCommand for the dialog. The ID for close menu item is
SC_CLOSE.
void CAboutDlg::OnSysCommand( UINT nID, LPARAM lParam )
{
if (nID == SC_CLOSE)
AfxMessageBox("Close");
else
CWnd::OnSysCommand(nID, lParam);
}
-----From: "Brad Wilson"
> 2. What's wrong with my approach? Why can't I catch the message??
Try catching WM_SYSCOMMAND and looking for SC_CLOSE instead.
> [Moderator's note: Jeff has been told to try Spy++, so if you don't
> have any other advice for him...]
You would have noticed the WM_SYSCOMMAND message with Spy++.
--
Brad Wilson Objectivist Philosopher, Software Engineer, Web Designer
crucial@pobox.com http://www.thebrads.com/bradw Objectvst@Undernet
"I know that you would love to know the answers,
but to you the truth is just another lie."
-----From: WnDBSoft@aol.com
Dialogs, oddly enough, don't process WM_CLOSE or WM_DESTROY well.
Try using the WM_SYSCOMMAND message! Clicking the Close box is a system
command (like you'd find on a Control menu or box in Win 3.1).
AFX_MSG delclaration: afx_msg OnSysCommand(UINT nID, LPARAM lParam);
message map macro: ON_WM_SYSCOMMAND( )
Have ClassWizard add a message handler for WM_SYSCOMMAND to your message map.
Now, go to wincore.cpp and find CWnd::OnSysCommand( ), if it's there. Once
you find CWnd::OnSysCommand( ), copy (do not cut) the entire body of the
function to the Clipboard.
Then, in the CMyDialog::OnSysCommand( ) handler, select the comments in the
body and then paste the Clipboard contents over the selection. NOTE: Change
over all the calls to CWnd::OnSysCommand( ) to CDialog::OnSysCommand( ).
In OnSysCommand( ), there is a switch(nID & 0xFF0) { } series, with case:
SC_* in it.
Let all of the case: SC_* fall through, except for case: SC_CLOSE. Under
case: SC_CLOSE , call ShowWindow(SW_HIDE). Don't call the base class in this
case, because it would close the dialog.
You see, clicking the close button on the titlebar sends WM_SYSCOMMAND with a
wParam of SC_CLOSE.
For example:
// WM_SYSCOMMAND handler
void CMyDialog::OnSysCommand(UINT nID, LPARAM lParam )
{
if (AfxGetMainWnd( )->m_bHelpMode)
{
//...
//...
// help processing...
//...
//...
}
else
{
// switch/case on nID & 0xFF0, or something like that, I'm not
sure
switch (nID & 0xFF0)
{
case SC_CLOSE:
ShowWindow(SW_HIDE);
break;
// let's put a default here for brevity
default:
// call base class for all other system
commands
CDialog::OnSysCommand(nID, lParam);
break;
}
}
return;
}
| Вернуться в корень Архива
|