Solved

Closing a CPropertySheet

Posted on 2003-11-10
5
2,147 Views
Last Modified: 2013-11-20
I have created a CPropertySheet with some pages, when I press "Cancel", I wan to have a AfxMessageBox("Not all data saved, still cancel ?"), So this is what I've done

BEGIN_MESSAGE_MAP()
ON_WM_CLOSE();
END_MESSAGE_MAP()

void CMyPropertySheet::OnClose() //Overload OnClose
{
 AfxMessageBox("Sure you wanna cancel ?");
}

... Then I implement it in my program
void CMyProgram::ShowSheet()
{
CMyPropertySheet test;
if(test.DoModal() == ID_OK)
{
 Container.SetData(test.GetData());
}

Problem is, I never get the WM_CLOSE in my CPropertySheet ??,,, I don't want to put the OnClose in my CPropertyPages, if I can avoid it.

I can use the OnOk, and OnCancel.. but what do I do with the |X| in the top of the window, I somemone push it, you will leave the sheet, withaout the warning messagebox .. that is the problem
0
Comment
Question by:win32
  • 3
  • 2
5 Comments
 
LVL 3

Expert Comment

by:komar
ID: 9714211
Hi,

You do not need to override CPropertySheet::OnClose() to implement the requirement. Instead you should override OnCancel() (and OnOK() if needed) member of each CPropertyPage.

I understand that you don't want to put handlers in each CPropertyPage object that you create, this can be avoided by deriving a class from CPropertyPage (call it CBasePage) to override the OnCancel() member to notify the parent property sheet. Then derive all your property pages from the new class. Also, derive a class from CPropertySheet (call it CNewSheet) to provide required handling.

Below are some code snippets of what i'm talking about:

      // BasePage.h
      
      #define UM_CANCEL_RECEIVED            ((UINT)(WM_USER + 0x0101))
      class CBasePage : public CPropertyPage
      {
            ...
            ...
            virtual void OnOK() { }
            virtual void OnCancel();
            ...
            ...
      };
      
      // BasePage.cpp
      
            ...
            ...
      void CBasePage::OnCancel()
      {
            //Notify the parent about the event
            GetParent()->PostMessage(UM_CANCEL_RECEIVED, 0, 0);
      }
            ...
            ...
      
      //NewSheet.h
      class CNewSheet : public CpropertySheet
      {
            afx_msg LRESULT MyHandler(WPARAM wParam, LPARAM lPARAM);
      };
      
      //NewSheet.cpp
      #include "BasePage.h"
      
      //Put this       line in the message map
      ON_MESSAGE(UM_CANCEL_RECEIVED, MyHandler)

      LRESULT CNewSheet::MyHandler(WPARAM /*wParam*/, LPARAM /*lPARAM*/)
      {
            LRESULT lRet = 0;
      
            if(AfxMessageBox("Sure you wanna cancel ?", MB_YESNO | MB_ICONQUESTION) == IDYES)
            {
                  DestroyWindow();
            }
      
            return lRet;
      }

Thanks,
Khalid Omar
0
 

Author Comment

by:win32
ID: 9715268
But that does not solve the problem if the user press the |X| in the upper right corner ??
0
 
LVL 3

Expert Comment

by:komar
ID: 9715804
Hi again,

This time I created a test project to test my solution in the first comment. Here is what I did:
  1. Create a class called CNewSheet derived from CPropertySheet.
  2. Create a class called CBasePage derived from CPropertyPage.
  3. I modified the constructor created by class wizard of the CBasePage so that it looks like:
   In the .h file
      CBasePage(UINT uDialogResource = -1);

   In the .cpp file
      CBasePage::CBasePage(UINT uDialogResource) : CPropertyPage(uDialogResource)
      {
            //{{AFX_DATA_INIT(CBasePage)
                  // NOTE: the ClassWizard will add member initialization here
            //}}AFX_DATA_INIT
      }

  4. In class view, right click the CBasePage class and select "Add Virtual function". In the window that pops-up select OnCancel and hit the "Add and Edit" button.
  5. Modify CBasePage::OnCancel() as follows:
      void CBasePage::OnCancel()
      {
            GetParent()->SendMessage(UM_CANCEL_RECEIVED, 0, 0);
      }
  6. Add a definition for UM_CANCEL_RECEIVED to the top of BasePage.h header file as follows:
      #define UM_CANCEL_RECEIVED          ((UINT)(WM_USER + 0x0101))

  7. Goto NewSheet.h and add an include to BasePage.h so that the value of UM_CANCEL_RECEIVED can be seen by all CNewSheet objects.
  8. In class view, right-click the CNewSheet class and select "Add Windows Message Handler ...", in the window that pops-up select WM_CLOSE and hit "Add and Edit"
  9. Modify the CNewSheet::OnClose() function to look lioke the following:
      void CNewSheet::OnClose()
      {
            CancelHandler(0, 0);
      }
  10. Open the NewSheet.h file and add the definition of the CancelHandler function ass follows:
      ...
      ...
      //}}AFX_MSG
      afx_msg LRESULT CancelHandler(WPARAM wParam, LPARAM lPARAM); //This line is new
      DECLARE_MESSAGE_MAP()
      ...
      ...

  11. Open NewSheet.cpp and add the following to the end of the file
      LRESULT CNewSheet::CancelHandler(WPARAM /*wParam*/, LPARAM /*lPARAM*/)
      {
             LRESULT lRet = 0;

             if(AfxMessageBox("Sure you wanna cancel ?", MB_YESNO | MB_ICONQUESTION) == IDYES)
             {
                        EndDialog(IDCANCEL);
             }

             return lRet;
      }
  12. Modify the message map of CNewSheet so that it looks like:
      BEGIN_MESSAGE_MAP(CNewSheet, CPropertySheet)
            //{{AFX_MSG_MAP(CNewSheet)
            ON_WM_CLOSE()
            //}}AFX_MSG_MAP
            ON_MESSAGE(UM_CANCEL_RECEIVED, CancelHandler)
      END_MESSAGE_MAP()

According to the above, I was able to capture all events when the user hits cancel button or hits the |x| button on the title bar.
I can send you the project I was working on to test my comment. Email me if you are interested, my email is khalid_omar@msn.com

Thanks,
Khalid Omar
0
 

Author Comment

by:win32
ID: 9738189
Ok please mail me the project to cb_priv@hotmail.com I cannot get this to wore, Sure I can debug into the OnCancel in the pages, but the sheet closes anyway, nomatter what I do.
0
 
LVL 3

Accepted Solution

by:
komar earned 60 total points
ID: 9738833
Hi,

I think you are right. After few more debugging i found that you can capture the required events but you cannot prevent the property sheet from closing.

So, I started looking for another way to achieve the requirement, and I think I found it. All you have to do is to derive a class (CBaseSheet) and provide handling for the following events:
  - Provide handling for BN_CLICKED when idButton = IDCANCEL
  - Provide handling for WM_SYSCOMMAND when uCmdType = SC_CLOSE.

According to the above, the message map for CBaseSheet becomes as follows:

      BEGIN_MESSAGE_MAP(CBaseSheet, CPropertySheet)
            //{{AFX_MSG_MAP(CBaseSheet)
            //}}AFX_MSG_MAP
            ON_BN_CLICKED(IDCANCEL, OnCancel)
            ON_WM_SYSCOMMAND()
      END_MESSAGE_MAP()

The implementation for the handlers is as follows:

      void CBaseSheet::OnCancel()
      {
            if(AfxMessageBox("Sure you wanna cancel ?", MB_YESNO | MB_ICONQUESTION) == IDYES)
            {
                  PressButton(PSBTN_CANCEL);
            }
      }

      void CBaseSheet::OnSysCommand(UINT uCmdType, LPARAM lParam)
      {
            if(nID == SC_CLOSE)
            {
                  OnCancel();
            }
            else
            {
                  CPropertySheet::OnSysCommand(uCmdType, lParam);
            }
      }

The definition of these handler in the .h file is as follows:

      virtual afx_msg void OnCancel();
      virtual afx_msg void OnSysCommand(UINT uCmdType, LPARAM lParam);

I'll send you the test project I was working on to test my solution via email to cb_priv@hotmail.com

Thanks,
Khalid Omar.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

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 …
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
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.
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

743 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

14 Experts available now in Live!

Get 1:1 Help Now