15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


How to prevent MDI child close

Howard Rubin -- hrubin@nyx.net
Wednesday, October 09, 1996

Environment: VC 4.0, NT 3.51

I'm working on an MDI program which is based on the chkbook sample.
So I have multiple views of a single document. I need to keep the MDI
child windows from closing. There are 3 things to catch: (1) double
click on the top left box of the MDI child (same as win 95's X?), (2)
control-F4, (3) Select close from the menu. Does anyone know how I
can do this?

Howard Rubin - hrubin@disc.com hrubin@nyx.net



David Easterby -- davide@dsg.com
Thursday, October 10, 1996

[Mini-digest: 14 responses]

In your CMDIChildWnd derived class, catch the OnInitMenu (WM_INITMENU) event
and disable the Close item.  Example:

CMyMDIChild::OnInitMenu(CMenu* pMenu)
{
  pMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED | MF_BYCOMMAND);

  CMDIChildWnd::OnInitMenu(pMenu);

}

That will both gray out the menu command and prevent the window from being
closed (all three cases).



David Easterby
DataSystems Group
-----From: Andrew Dalgleish 

For asthetics, disable the system menu "Close" and the 'X' button by:
// Get the MDI child frame's system menu
CMenu *pSystemMenu = GetSystemMenu(FALSE);
// Get the text for "Close"
CString  ItemText;
pSystemMenu->GetMenuString(SC_CLOSE, ItemText, MF_BYCOMMAND);
// Gray the "Close" (which also grays the 'X' button)
pSystemMenu->ModifyMenu(SC_CLOSE, MF_BYCOMMAND|MF_STRING|MF_GRAYED,
SC_CLOSE, ItemText);

This looks better than having the button do nothing, and prevents the
user from selecting them

Note that Ctrl+F4 will still call CFrameWnd::OnClose().

You can prevent the window closing by over-riding
CDocument::CanCloseFrame().

Regards,
Andrew Dalgleish

-----From: Alaks Sevugan 

Hi Rubin:

There is a virtual function in CDocument - 
'SaveModified' which you can override if you want 
to save changes or there is another virtual 
function - 'CanCloseFrame' which you can use for 
for first 2 things you have mentioned (ie) double 
click on MDI child window and Close from the menu.

Hope this helps.

-alaks

---------------------------------------------------
--
  Alaks Sevugan                
asevugan@csci.csc.com    
  CSC CIS	  	       (217)-351-8250 x2161 
  Champaign, IL 61820
---------------------------------------------------
--
-----From: "Manolis Chr.Papadopoulos" 

Add a function to your document class and/or your view class for =
WM_CLOSE message that does nothing.=20

-----From: "Philippe Cluzeaud" 

Derive your MDI child window class from CMDIChildWnd, and
override the OnClose member function.

ex : 
class CYourChildWnd : public CMDIChildWnd
{
	...
	afx_msg void OnClose();
	...
}

void CYourChildWnd::OnClose()
{
	// Don't close !
}

and in CYourApp::InitInstance :

pTemplate = new CMultiDocTemplate ( IDR_xxx, 
		RUNTIME_CLASS(CYourDoc),
		RUNTIME_CLASS(CYourChildWnd),
		RUNTIME_CLASS(CYourView));
      
Hope it helps.

Philippe Cluzeaud. 	pcluz@club-internet.fr

-----From: csn@dhi.dk (Carsten Schwartz)
Most of your problems can be solved by implementing a handler 
for the WM_CLOSE event. Do any necessary checking and return
before the default OnClose function is call.

Good Luck
_____________________________________________________
Carsten Schwartz            Email : csn@dhi.dk
Software Engineer           www   : http://www.dhi.dk
Danish Hydraulic Institute  Tel.  : +45 45 76 95 55
Agern Alle 5                Fax.  : +45 45 76 25 67
2970 Horsholm
Denmark

And they shall know no fear...
_____________________________________________________

-----From: muni@aditimx.vsnl.net.in (Muni Raju)

Hi Howard,

  You can put a handler for WM_SYSCOMMAND and do nothing when the id is
SC_CLOSE, else call the base class implementation of OnSysCommand.
WM_SYSCOMMAND is not displayed in class wizard. Hence you need to put
the handler manually.

 In childfrm.h add,

  	afx_msg void OnSysCommand( UINT nID, LPARAM lParam );

 In Childfrm.cpp,
 
 BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
	//{{AFX_MSG_MAP(CChildFrame)
	ON_WM_SYSCOMMAND() // Add this
	//}}AFX_MSG_MAP
 END_MESSAGE_MAP()



void CChildFrame::OnSysCommand( UINT nID, LPARAM lParam )
{
	if(nID == SC_CLOSE)
		return; // do not call base class
	CMDIChildWnd::OnSysCommand(nID, lParam );
}

 Hope this helps you. Please do feel free to get back.

 Regards,

 Muniraju
 Aditi Corp( Previously known as NetQuest).
-----From: Si Cruse 

Override your documents CanCloseFrame member.

-- 

...A closed mouth gathers no foot...
_____________________________________________________________
Si Cruse
Front Office IT Development, Credit Suisse Financial Products
1 Cabot Square, London E14 4QJ
Phone: +44 171 516 2948			Fax: +44 171 516 2688
mailto:scruse@csfp.co.uk	 http://www.cruse.demon.co.uk
-----From: pxc@kid01pml.icl.co.uk (Paul Cook)

You could use AfxRegisterWndClass on your MDI Child class and give it the
CS_NOCLOSE style.  I used it in one situation and I'm fairly sure it handled
all three of the cases above.   It removes the 'Close Ctrl+F4' menu item.

HTH
Paul.
---
      o o o o o o . . .   ________________________ _________________________
    o      _____          ||Paul Cook            | ||pxc@kid01pml.icl.co.uk|
  .][__n_n_|DD[  ====___  ||Process Solutions    | ||+44 (0)1782 794742    |
 >(________|__|_[_______]_||ICL__________________|_||______________________|_
 _/oo OOOOO oo`  oo  oo   'o^o                o^o` 'o^o                 o^o`
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-----From: Jim Barry 

All these actions result in a WM_CLOSE message. The default handler calls   
DestroyWindow to destroy the window. You can override this by adding an   
empty OnClose() handler to your CMDIChildWnd-derived class   
(CCheckBookFrame in the chkbook sample).

Cheers,

 - Jim
-----From: David.Lowndes@bj.co.uk

Howard

Here's a few tips I've got (from a similar question on the newsgroups)
that might help...

bFlag is a boolean flag (TRUE = ok to close, FALSE = don't allow close).

1. If you want to Enable/Disable the system menu close item
(Win95's X button) at some suitable point in your application.

    CMenu * ps = ((CFrameWnd *) AfxGetMainWnd())->GetSystemMenu(FALSE);
	
    ps->EnableMenuItem( SC_CLOSE, bFlag ?
		MF_BYCOMMAND | MF_ENABLED :
		MF_BYCOMMAND | MF_GRAYED );

2. You might also want to Enable/Disable the File, Exit menu
in the ID_APP_EXIT command update handler.

void CMyDoc::OnUpdateAppExit(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable( bFlag );
}

3. You can prevent the document frame from closing (by using the
Alt+F4 keystroke) by handling CanCloseFrame.

CMyDoc::CanCloseFrame()
{
	return( bFlag );
}

4. If the application is MDI, you can also Enable/Disable the File, Close
menu item

void CMyDoc::OnUpdateFileClose(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable( bFlag );
}

The problem is compounded if you allow multiple views on the document
as you may want to allow all views except the last one to be closed! In
that case you can access the document's count of views (m_viewList.GetCount())
to expand on the logic.

Dave Lowndes
-----From: Vikas Patel 


Very simple in the Frame window of your Document Template for this view over 
ride the OnClose method and then comment out the default implementation 
generated by the Class Wizard as follows:

void CMyFrame::OnClose()
{
     // TODO: Add your message handler code here and/or call default
     //CMDIChildWnd::OnClose();
}
This will do the trick. A user will not be able to close this view any more.

/Vikas Patel

vjp@safco.com
-----From: Mario Contestabile

You mentionned the environment being NT 3.51. Unless your application will 
never run
under 95 or NT 4.0, you will want to do tests on those environments also, 
considering
the slight interface differences.

Also, preventing a document from closing is easy. It's when you want to do 
things like
preventing the _last_ document from closing that things get complicated.

To disable closing of a CMDIChildWnd, u can use ON_WM_INITMENUPOPUP( )
menu_ptr->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | 
(numW==1)?MF_GRAYED:MF_ENABLED);
Notice here it checks how many numW there are.

mcontest@universal.com

-----From: Gerry Sweeney 

Howard,

This is fairly simple. Derive a new class from CMDIChildWnd and add the 
following code to it.

// Add this to your class to prevent the window from being closed by the 
Ctrl-F4 or
// menu items. This will need a message map entry:-

ON_WM_SYSCOMMAND()
// Use class wizard to map this message

void ::OnSysCommand(UINT nID, LPARAM lParam)
{
     if(nID == SC_CLOSE)
          {
          PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0L);
          return;
          }
     else
          CMDIChildWnd::OnSysCommand(nID, lParam);
}

Don't forget to use your new class instead of the CMDIChildWnd class when 
you create your CMultiDocTemplate class in you main application. This code 
will prevent the window from being closed with any of the above mentioned 
methods. If the user attempts to close the window it will be minimised to an 
icon


Hope this helps

Gerry Sweeney
gerry@hornbill.com







| Вернуться в корень Архива |