Solved

MDI child frame without a close button

Posted on 1998-05-26
12
1,056 Views
Last Modified: 2013-11-20
I'm new to MFC and Windows programming, making the leap from DOS (a dark screen with a C:\>, remember?)

Can I create an MDI child frame that does not have a close button. I do not want the user to be able to close the first child window opened when the program starts. I've played around with the ::LoadFrame(), ::Create(), and ::PreCreateWindow() member functions of the CChildFrame class to no avail. I've tried various combinations of the WS_XXXX bits in the frame styles, but haven't hit the correct one. Is this possible in MFC?

Note that I also have to get rid of the Close option from the Windows system menu.

Thanks,
Nelson Chenkin
0
Comment
Question by:nchenkin
12 Comments
 
LVL 15

Expert Comment

by:Tommy Hui
ID: 1315335
No, it is possible. But you can do the next best thing by trapping WM_SYSCOMMAND in the child frame and if the number of child windows is 1 (meaning it is the first), then ignore the command if the wparam has SC_CLOSE in it:

  void MyWnd::OnSysCommand(wp, lp)
  {
    BOOL ignore = FALSE;
    if (count == 1)
      if ((wp & SC_CLOSE) == SC_CLOSE)
        ignore = TRUE;
    if (!ignore)
      CChildFrame::OnSysCommand(wp, lp);
  }


   
0
 

Expert Comment

by:t004024
ID: 1315336
GetSystemMenu, gives a handle to the system menu. Maybe U can get this and manipulate the menu using the CMenu class functions. U need to call the GetSystemMenu for the MainFrame window. SO Maybe U could do something like
CMenu *tMenu = AfxGetMainWnd()->GetSystemMenu() and then call
tMenu->RemoveMenu(SC_CLOSE, MF_BYCOMMAND); and then call maybe
CMDIChildWnd *ptWnd = GetParent() // This is only if U are in the View class otherwise, call MDIGetActive of the CMDIFrameWnd and call the SetSystemMenu and RemoveMenu for this.
0
 

Expert Comment

by:footloose
ID: 1315337
***** The standard code generated by MFC for CChildFrame contains this override:

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
     // TODO: Modify the Window class or styles here by modifying
     //  the CREATESTRUCT cs

     return CMDIChildWnd::PreCreateWindow(cs);
}

***** Change it as below:

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
     cs.style &= ~WS_SYSMENU;
     cs.style |= WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
     return CMDIChildWnd::PreCreateWindow(cs);
}

***** This gets rid of the system menu but retains the minimize/maximize buttons.
***** As THUI suggested, you need to override WM_SYSCOMMAND handler as below.
***** WM_SYSCOMMAND may not appear on the standard message list, so you will
***** have to go to the CLASSINFO tab of class wizard (for CChildFrame), change
***** MESSAGE FILTER option to WINDOW, and then go back to MESSAGE MAPS tab
***** and override WM_SYSCOMMAND handler as below:

void CChildFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
     if ( nID == SC_CLOSE )
     {
          //do some checking, as THUI suggested and/or call the default
     }
     CMDIChildWnd::OnSysCommand(nID, lParam);
}

***** Also remember to go to IDR_appTYPE menu on the resource editor and get rid of
***** FILE/CLOSE menu item.
0
 

Author Comment

by:nchenkin
ID: 1315338
Footloose,

I tried as you suggested in the ::PreCreateWindow() function. However this got rid of ALL three buttons: the minimize and maximize buttons were not displayed. I could still maximize the child by double clicking on the title bar, and then use Window/Cascade to restore it, but the buttons weren't there. This was one of the things I stumbled on in my attempts.

By the way, to ensure nothing else had changed I did this in newly generated App Wizard code.

Thanks,
nchenkin
0
 

Author Comment

by:nchenkin
ID: 1315339
Adjusted points to 100
0
 

Expert Comment

by:Beatachon
ID: 1315340
Does the window still have the normal looking title bar? Make sure you have your operators right. I.E: cs.style |= and NOT cs.style =.....
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:nchenkin
ID: 1315341
The title bar looks normal execpt the system menu icon on the left is gone and there are no buttons at all on the right.

Here's the code lifted from the file. Again, this is the only change to a new App Wizard app using all defaults.

BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
   // TODO: Modify the Window class or styles here by modifying
   //  the CREATESTRUCT cs

   cs.style &= ~WS_SYSMENU;
   cs.style |= (WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
   return CMDIChildWnd::PreCreateWindow(cs);
}


0
 

Expert Comment

by:footloose
ID: 1315342
duh! how come I missed the missing minimize/maximize boxes!! Sorry! Will keep trying.
0
 

Accepted Solution

by:
footloose earned 100 total points
ID: 1315343
OK, let's try again: t004024's earlier suggestion on using GetSysMenu works. I tried this out, and the close button is disabled. Thui's earlier suggestion to trap WM_SYSCOMMAND still has to be carried out if you want to prevent Ctrl-F4 from closing the child window.

Override CChildFrame::Create as below:

BOOL CChildFrame::Create(  LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
                                                     DWORD dwStyle, const RECT& rect,
                                                     CMDIFrameWnd* pParentWnd, CCreateContext* pContext )
{
   if ( CMDIChildWnd::Create( lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd,
                                                    pContext ) )
   {
      CMenu *p = GetSystemMenu( FALSE );
      p->RemoveMenu( 5, MF_BYPOSITION );
      p->RemoveMenu( 5, MF_BYPOSITION );

      return TRUE;
   }

   return FALSE;
}

0
 

Author Comment

by:nchenkin
ID: 1315344
Footloose, Thanks it worked!

But I wound up combining your suggesstion with t004024's comment. The final code is:

BOOL CChildFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
                         DWORD dwStyle, const RECT& rect,
                         CMDIFrameWnd* pParentWnd, CCreateContext* pContext)
{
   if ( CMDIChildWnd::Create( lpszClassName, lpszWindowName, dwStyle,
                              rect, pParentWnd, pContext ) )
   {
      CMenu *p = GetSystemMenu( FALSE );
      p->RemoveMenu( SC_CLOSE, MF_BYCOMMAND );
      return TRUE;
   }
   return FALSE;
}

This gets rid of having to call RemoveMenu twice as your example required (why is that?!),
and also changes the hardcoded '5' to a friendlier SC_CLOSE symbol.

I realize I also need to implement Thui's trap.
Thanks all for your help.
0
 

Expert Comment

by:footloose
ID: 1315345
Final comment: RemoveMenu is called twice because you have to remove CLOSE first and then the seperator below it. Otherwise you get two seperators one next to another.
0
 

Author Comment

by:nchenkin
ID: 1315346
Footloose, A final comment to your final comment:

Gotcha. Given that, I'll probably put the 2nd call back in to get rid of the seperator.
Thanks for the clarification.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now