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.
  • 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