Closing a CPropertySheet

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
win32Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

komarCommented:
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
win32Author Commented:
But that does not solve the problem if the user press the |X| in the upper right corner ??
0
komarCommented:
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
win32Author Commented:
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
komarCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.