Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Closing CDialog when it looses the focus

Closing CDialog when it looses the focus

Scheduled Pinned Locked Moved C / C++ / MFC
questionhelp
13 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    msn92
    wrote on last edited by
    #1

    Hi I have a COptionsDlg class delivered from CDialog. I open it when user right clicks on the main window:

    ...
    COptionsDlg* dlg=new COptionsDlg();
    dlg->Create(COptionsDlg::IDD,this);
    dlg->ShowWindow(TRUE);
    ...

    Now once it's shown I want to close it when user clicks anywhere outside of COptionsDlg. I tried overriding OnKillFocus() of COptionsDlg but it didn't work. And also one more question: How can I exchange data between my main window and COptionsDlg? Any help would be greatly appreciated :)

    I 1 Reply Last reply
    0
    • M msn92

      Hi I have a COptionsDlg class delivered from CDialog. I open it when user right clicks on the main window:

      ...
      COptionsDlg* dlg=new COptionsDlg();
      dlg->Create(COptionsDlg::IDD,this);
      dlg->ShowWindow(TRUE);
      ...

      Now once it's shown I want to close it when user clicks anywhere outside of COptionsDlg. I tried overriding OnKillFocus() of COptionsDlg but it didn't work. And also one more question: How can I exchange data between my main window and COptionsDlg? Any help would be greatly appreciated :)

      I Offline
      I Offline
      Iain Clarke Warrior Programmer
      wrote on last edited by
      #2

      When you say you override OnKillFocus and it didn;t work, what did you mean? It didn't get called? Don't forget ON_WM_KILLFOCUS()... Did it get called, but the window didn't go? Then you need better code! Look in Generic Picker Dropdown Control[^] for a window that goes *poof* if you click away from it. Iain.

      I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

      M 1 Reply Last reply
      0
      • I Iain Clarke Warrior Programmer

        When you say you override OnKillFocus and it didn;t work, what did you mean? It didn't get called? Don't forget ON_WM_KILLFOCUS()... Did it get called, but the window didn't go? Then you need better code! Look in Generic Picker Dropdown Control[^] for a window that goes *poof* if you click away from it. Iain.

        I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

        M Offline
        M Offline
        msn92
        wrote on last edited by
        #3

        Iain, thank you for your reply. It gets called. The problem is it crashes when I use DestroyWindow() inside OnKillFocus(). Looks like you had the same problem(quote from your source code):

        void CGenericPickerPopup::OnKillFocus(CWnd* pNewWnd)
        {
        CWnd::OnKillFocus(pNewWnd);

        ReleaseCapture();
        //DestroyWindow(); - causes crash when Custom colour dialog appears.
        

        }

        // KillFocus problem fix suggested by Paul Wilkerson.
        void CGenericPickerPopup::OnActivateApp(BOOL bActive, HTASK hTask)
        {
        CWnd::OnActivateApp(bActive, hTask);

        // If Deactivating App, cancel this selection
        if (!bActive)
        	EndSelection(CPN\_SELENDCANCEL);
        

        }

        Now I tried overriding OnActivateApp():

        void COptionsDlg::OnActivateApp(BOOL bActive, HTASK hTask)
        {
        CDialog::OnActivateApp(bActive, hTask);
        if (!bActive)DestroyWindow();
        }

        But nothing seems to be happening. What I'm doing wrong?

        J I 2 Replies Last reply
        0
        • M msn92

          Iain, thank you for your reply. It gets called. The problem is it crashes when I use DestroyWindow() inside OnKillFocus(). Looks like you had the same problem(quote from your source code):

          void CGenericPickerPopup::OnKillFocus(CWnd* pNewWnd)
          {
          CWnd::OnKillFocus(pNewWnd);

          ReleaseCapture();
          //DestroyWindow(); - causes crash when Custom colour dialog appears.
          

          }

          // KillFocus problem fix suggested by Paul Wilkerson.
          void CGenericPickerPopup::OnActivateApp(BOOL bActive, HTASK hTask)
          {
          CWnd::OnActivateApp(bActive, hTask);

          // If Deactivating App, cancel this selection
          if (!bActive)
          	EndSelection(CPN\_SELENDCANCEL);
          

          }

          Now I tried overriding OnActivateApp():

          void COptionsDlg::OnActivateApp(BOOL bActive, HTASK hTask)
          {
          CDialog::OnActivateApp(bActive, hTask);
          if (!bActive)DestroyWindow();
          }

          But nothing seems to be happening. What I'm doing wrong?

          J Offline
          J Offline
          Joe Woodbury
          wrote on last edited by
          #4

          Try EndDialog() (you should rarely, if ever, call DestroyWindow().)

          M 1 Reply Last reply
          0
          • J Joe Woodbury

            Try EndDialog() (you should rarely, if ever, call DestroyWindow().)

            M Offline
            M Offline
            msn92
            wrote on last edited by
            #5

            Joe Woodbury, thank you for your reply. EndDialog(IDOK); That works, but how do I catch the mouseclick outside of the CDialog that I show? I should close it when user clicks outside of the CDialog. Is it possible?

            J D 2 Replies Last reply
            0
            • M msn92

              Joe Woodbury, thank you for your reply. EndDialog(IDOK); That works, but how do I catch the mouseclick outside of the CDialog that I show? I should close it when user clicks outside of the CDialog. Is it possible?

              J Offline
              J Offline
              Joe Woodbury
              wrote on last edited by
              #6

              Only if you capture the mouse.

              1 Reply Last reply
              0
              • M msn92

                Joe Woodbury, thank you for your reply. EndDialog(IDOK); That works, but how do I catch the mouseclick outside of the CDialog that I show? I should close it when user clicks outside of the CDialog. Is it possible?

                D Offline
                D Offline
                David Crow
                wrote on last edited by
                #7

                You should call DestroyWindow() to destroy a modeless dialog. In the dialog's PostNcDestroy() method, you should delete the this pointer.

                "Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown

                "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                1 Reply Last reply
                0
                • M msn92

                  Iain, thank you for your reply. It gets called. The problem is it crashes when I use DestroyWindow() inside OnKillFocus(). Looks like you had the same problem(quote from your source code):

                  void CGenericPickerPopup::OnKillFocus(CWnd* pNewWnd)
                  {
                  CWnd::OnKillFocus(pNewWnd);

                  ReleaseCapture();
                  //DestroyWindow(); - causes crash when Custom colour dialog appears.
                  

                  }

                  // KillFocus problem fix suggested by Paul Wilkerson.
                  void CGenericPickerPopup::OnActivateApp(BOOL bActive, HTASK hTask)
                  {
                  CWnd::OnActivateApp(bActive, hTask);

                  // If Deactivating App, cancel this selection
                  if (!bActive)
                  	EndSelection(CPN\_SELENDCANCEL);
                  

                  }

                  Now I tried overriding OnActivateApp():

                  void COptionsDlg::OnActivateApp(BOOL bActive, HTASK hTask)
                  {
                  CDialog::OnActivateApp(bActive, hTask);
                  if (!bActive)DestroyWindow();
                  }

                  But nothing seems to be happening. What I'm doing wrong?

                  I Offline
                  I Offline
                  Iain Clarke Warrior Programmer
                  wrote on last edited by
                  #8

                  Hehe, you missed the trick. I do SetCapture, so I get "all" mouse messages. Then I check for OnLButtonUp, and check whether the click was on my popup window or not. If not on the window, then Destroy the window. This is the part of the article that owes the most to C Maunder's original colour picker popup. (Only about 10% survives, but this is the biggest bit) Iain.

                  I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

                  M 1 Reply Last reply
                  0
                  • I Iain Clarke Warrior Programmer

                    Hehe, you missed the trick. I do SetCapture, so I get "all" mouse messages. Then I check for OnLButtonUp, and check whether the click was on my popup window or not. If not on the window, then Destroy the window. This is the part of the article that owes the most to C Maunder's original colour picker popup. (Only about 10% survives, but this is the biggest bit) Iain.

                    I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

                    M Offline
                    M Offline
                    msn92
                    wrote on last edited by
                    #9

                    LOLz, Yes I've really missed it! :-D Thanks man! All I need is to override OnNcDestroy() and OnLButtonUp(), and it's working!!!

                    BOOL COptionsDlg::OnInitDialog()
                    {
                    CDialog::OnInitDialog();
                    SetCapture();//Thank you Iain
                    return TRUE;
                    }

                    void COptionsDlg::OnNcDestroy()
                    {//Thanks to DavidCrow
                    CDialog::OnNcDestroy();
                    delete this;
                    }

                    void COptionsDlg::OnLButtonUp(UINT nFlags, CPoint point)
                    {//Thanks to Iain
                    CDialog::OnLButtonUp(nFlags,point);
                    CRect rect;
                    this->GetWindowRect(rect);
                    DWORD pos=GetMessagePos();
                    point=CPoint(LOWORD(pos),HIWORD(pos));
                    if(!rect.PtInRect(point)){this->DestroyWindow();}//close only if click was outside of the window
                    }

                    Thank you Iain and DavidCrow!!! :-D And one last question: How do I exchange data between my main window and that dialog I show?

                    I 1 Reply Last reply
                    0
                    • M msn92

                      LOLz, Yes I've really missed it! :-D Thanks man! All I need is to override OnNcDestroy() and OnLButtonUp(), and it's working!!!

                      BOOL COptionsDlg::OnInitDialog()
                      {
                      CDialog::OnInitDialog();
                      SetCapture();//Thank you Iain
                      return TRUE;
                      }

                      void COptionsDlg::OnNcDestroy()
                      {//Thanks to DavidCrow
                      CDialog::OnNcDestroy();
                      delete this;
                      }

                      void COptionsDlg::OnLButtonUp(UINT nFlags, CPoint point)
                      {//Thanks to Iain
                      CDialog::OnLButtonUp(nFlags,point);
                      CRect rect;
                      this->GetWindowRect(rect);
                      DWORD pos=GetMessagePos();
                      point=CPoint(LOWORD(pos),HIWORD(pos));
                      if(!rect.PtInRect(point)){this->DestroyWindow();}//close only if click was outside of the window
                      }

                      Thank you Iain and DavidCrow!!! :-D And one last question: How do I exchange data between my main window and that dialog I show?

                      I Offline
                      I Offline
                      Iain Clarke Warrior Programmer
                      wrote on last edited by
                      #10

                      Firstly - nicely done on presenting what you did, with credits to the helpers. And helpful to others! As for communicating back... You have many approaches. You could have a structure of information somewhere in the main program, and pass COptionsDlg a pointer to it. Then, if the dialog is closed "properly" (ie, OK button), fill in the structure with the DoDataExchange / UpdateDate method. I would also post a message to your parent window saying "I'm goooone!". That way the parent can tidy up any pointers to your option dialog, and enable any Tools | Options menu. It's a good idea to post on success AND failure, and let the parent window decide whether it cares. You could put IDOK / IDCANCEL in the WPARAM of the PostMessage. You could also drop David's delete this bit, keep the options in the dialog, and then delete it all in the PostMessage handler in your main program. How you do it really depends on the details of your software, but I hope that's given you the idea. Iain

                      I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

                      M 1 Reply Last reply
                      0
                      • I Iain Clarke Warrior Programmer

                        Firstly - nicely done on presenting what you did, with credits to the helpers. And helpful to others! As for communicating back... You have many approaches. You could have a structure of information somewhere in the main program, and pass COptionsDlg a pointer to it. Then, if the dialog is closed "properly" (ie, OK button), fill in the structure with the DoDataExchange / UpdateDate method. I would also post a message to your parent window saying "I'm goooone!". That way the parent can tidy up any pointers to your option dialog, and enable any Tools | Options menu. It's a good idea to post on success AND failure, and let the parent window decide whether it cares. You could put IDOK / IDCANCEL in the WPARAM of the PostMessage. You could also drop David's delete this bit, keep the options in the dialog, and then delete it all in the PostMessage handler in your main program. How you do it really depends on the details of your software, but I hope that's given you the idea. Iain

                        I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

                        M Offline
                        M Offline
                        msn92
                        wrote on last edited by
                        #11

                        Iain, thanks once more! I tried what you suggested: I created a class that holds the options:

                        //I think you know graphing calculators...
                        class WindowOptions {
                        public:
                        double xmin;
                        double xmax;
                        double xscl;
                        double ymin;
                        double ymax;
                        double yscl;
                        };

                        When I create my optionsdialog, I'm passing a pointer to variable of WindowOptions class. But I'm unable to compile my project, I'm getting LNK2005 errors. "...You could have a structure of information somewhere in the main program, and pass COptionsDlg a pointer to it. Then, if the dialog is closed "properly" (ie, OK button), fill in the structure with the DoDataExchange / UpdateDate method." Can you give me an example please? Or link where I can read more about it?

                        I 1 Reply Last reply
                        0
                        • M msn92

                          Iain, thanks once more! I tried what you suggested: I created a class that holds the options:

                          //I think you know graphing calculators...
                          class WindowOptions {
                          public:
                          double xmin;
                          double xmax;
                          double xscl;
                          double ymin;
                          double ymax;
                          double yscl;
                          };

                          When I create my optionsdialog, I'm passing a pointer to variable of WindowOptions class. But I'm unable to compile my project, I'm getting LNK2005 errors. "...You could have a structure of information somewhere in the main program, and pass COptionsDlg a pointer to it. Then, if the dialog is closed "properly" (ie, OK button), fill in the structure with the DoDataExchange / UpdateDate method." Can you give me an example please? Or link where I can read more about it?

                          I Offline
                          I Offline
                          Iain Clarke Warrior Programmer
                          wrote on last edited by
                          #12

                          OK, I'll assume you have a small idea about classes, dialog, and dodataexchange. If not, go create some and get an idea! What I meant was similar to...

                          struct Options
                          {
                          double xmin;
                          ...
                          };

                          class CMyApp
                          {
                          ...
                          Options m_Options;
                          ...
                          };

                          In your main frame, you have a menu handler:
                          void CMainFrame::OnToolsOptions ()
                          {
                          CMyOptionsDlg *pDlg = new CMyOptionsDlg; // make a new options dlg - it will self delete.
                          CMyApp *pApp = (CMyApp *) AfxGetApp ();
                          dlg->m_pOptions = &(pApp->m_Options); // give the dialog a pointer to the options struct.

                          dlg->Create (this); // make the dialog window
                          }

                          void COptionDlg::DoDataExchange (CDataExchange *pDX)
                          {
                          ASSERT(m_pOtions);
                          if (!m_pOptions) return;

                          // get/set a double from an edit box
                          DDX_Text (pDX, IDC_XMIN, m_pOptions->xmin);
                          ...
                          }

                          I hope those snippets gave you a better idea of what I was thinking! Iain.

                          I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

                          M 1 Reply Last reply
                          0
                          • I Iain Clarke Warrior Programmer

                            OK, I'll assume you have a small idea about classes, dialog, and dodataexchange. If not, go create some and get an idea! What I meant was similar to...

                            struct Options
                            {
                            double xmin;
                            ...
                            };

                            class CMyApp
                            {
                            ...
                            Options m_Options;
                            ...
                            };

                            In your main frame, you have a menu handler:
                            void CMainFrame::OnToolsOptions ()
                            {
                            CMyOptionsDlg *pDlg = new CMyOptionsDlg; // make a new options dlg - it will self delete.
                            CMyApp *pApp = (CMyApp *) AfxGetApp ();
                            dlg->m_pOptions = &(pApp->m_Options); // give the dialog a pointer to the options struct.

                            dlg->Create (this); // make the dialog window
                            }

                            void COptionDlg::DoDataExchange (CDataExchange *pDX)
                            {
                            ASSERT(m_pOtions);
                            if (!m_pOptions) return;

                            // get/set a double from an edit box
                            DDX_Text (pDX, IDC_XMIN, m_pOptions->xmin);
                            ...
                            }

                            I hope those snippets gave you a better idea of what I was thinking! Iain.

                            I have now moved to Sweden for love (awwww). If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[^]

                            M Offline
                            M Offline
                            msn92
                            wrote on last edited by
                            #13

                            Thank you Iain! I'm able to pass data between my dialogs. I have the last question. Promise, the last one :) I can catch outside clicks by using SetCapture & OnLButtonUp, but since I run SetCapture() my options dialog receiving no mouse messages inside(If I click on a button in the dialog, the button doesn't get clicked.) What can I do to fix that?

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups