|
|
Title |
Catching and Preventing the Close event.
|
Summary |
An article about how to catch and or prevent an operator from closing a dialog, SDI or MDI application. |
Contributor |
John McTainsh
|
Published |
5-Mar-2001 |
Last updated |
5-Mar-2001 |
|
|
Introduction
It is often the case that you do not want the user to be able to close the
application by accident. To prevent this you could disable the [X] close button,
or ask the user if they are "sure" they want to do this. This article
covers ideas on how the prevent accidental closing..
Keeping a MDI child window open
Although, not the most common practice, it is often necessary to prevent the
user from closing and MDI child window. To do this simply remove the window type
menu to option to close and the System menu close option. Note when the system
menu option is removed the [X] close button is disabled.
Start by handling the system menu close event and disabling the button.
In ChildFrm.cpp add ON_WM_SYSCOMMAND to the message map
and implement OnSysCommand . Also disable the button ans seperator
in the OnCreate which can be added by using wizard to handle WM_CREATE .
BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
//{{AFX_MSG_MAP(CChildFrame)
.....
.....
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_WM_SYSCOMMAND()
END_MESSAGE_MAP()
...
...
// ***************************************************************************
//DESCRIPTION:
// Disable the Close button and menu item (Only for the children)
//PARAMS:
// see help
//RETURN:
// see help
//CREATED:
// 3-3-2001, 8:49:14 PM by john@mctainsh.com
// ***************************************************************************
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CMenu *pSysMenu = GetSystemMenu(FALSE);
ASSERT(pSysMenu != NULL);
VERIFY( pSysMenu->DeleteMenu( SC_CLOSE, MF_BYCOMMAND ) );
VERIFY( pSysMenu->RemoveMenu( 5, MF_BYPOSITION ) );
return 0;
}
void CChildFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
if(nID == SC_CLOSE)
return;
CMDIChildWnd::OnSysCommand(nID, lParam);
}
In ChildFrm.h add.
...
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
DECLARE_MESSAGE_MAP()
Finally delete the File->Close menu item from the type menu resource.
Preventing the closing of a MDI or SDI application.
Here we will try an alternative method to remove the [X] close app button
from the main frame. This is done by modifying the way the frame is created.
This sample allows the user to close the app by using File->Exit but not
with {ALT+F4} or the [X] close button. As a free bonus code is also shown to set
the original position and size of the window and whether it can be minimised or
maximised.
//////////////////////////////////////////////////////////////////////////////
//Setup the pre display view of the main frame
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
// | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
if(CMDIFrameWnd::PreCreateWindow(cs))
{
//cs.style &= ~WS_MINIMIZEBOX; //This hides the Minimise box
//cs.style &= ~WS_MAXIMIZEBOX; //This hides the Maximise box
//cs.style &= ~WS_SYSMENU; //This option hides the nice icon
cs.lpszClass = AfxRegisterWndClass( CS_NOCLOSE
, AfxGetApp()->LoadStandardCursor( IDC_ARROW )
//,( COLOR_APPWORKSPACE + 1)
, CreateSolidBrush( RGB(0,0,0))
, AfxGetApp()->LoadIcon( IDR_MAINFRAME ) );
cs.x = 0;
cs.y = 0;
cs.cx = 640;
cs.cy = 480;
return TRUE;
}
return FALSE;
}
Finally a dialog.
A simple dialog app when first created will close when the user presses
{Enter}, OK, {Esc}, Cancel, {ALT+F4} or the [X] close button. To overcome this we will
handle each of these events starting with {Enter}.
In closing...(ha)
In most cases these methods can be mixed and matched. Try each one to see
which works best for you. Remember, changing the default windows behaviour often
upsets people so only do it for good reason.
|