We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Nonmodal dialog cancel itself without any user input

rickatseasoft
on
Medium Priority
306 Views
Last Modified: 2013-11-20
I have a nonmodal dialog that opens a couple of files.  If the files don't exist, I want the dialog to tell the user, then close itself.  I can get right to the point of closing itself, and then I am stumped.  Whatever I do, generates an error message.    In other words, I want something like if(!file)OnCancel().  I tried going back to the function that created the dialog, doing something like if(!pDlg->file)..., but I still get an error.  I believe it is because the dialog has not finished being created, so attempting to destroy it is premature.  Anyway, I am tempted to try a timer, but I hope that someone here has a better answer.  Perhaps I should send a message from the calling function as in if(!pDlg->file)send a close message.  It would certainly help if I better understood the process of dialog and window creation.

BTW, I know that I can open the files before creating the dialog, but that will create other problems, and I still won't understand this issue.

Anyway, thanks in advance, Rick
Comment
Watch Question

Commented:
Please show your code. Where is "if(!file)OnCancel()" fragment is placed?
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
non-modal dialog - OnCancel (and OnOK) is usually used for modal dialogs.
Try this instead.
if(!file)
  PostMessage(WM_CLOSE, 0, 0);
Can't you something like this.

if(!file) {
   CDialog::OnCancel();
}
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
rajeev_devin
excerpt from help
When you implement a modeless dialog box, always override the OnCancel member function and call DestroyWindow from within it. Don't call the base class CDialog::OnCancel, because it calls EndDialog, which will make the dialog box invisible but will not destroy it.

That is why you can't do something like this....

Author

Commented:
I was pretty sleep deprived last night.  In re-reading my question, and doing some additional debugging, I can see that not only was I not explicit enough, but my problem is elsewhere.  Sorry about that.  Anyway, we use a MDI interface to manage the dialogs.  Each one is created with minor deviations from

void CDlgView::EmployerEntry()
{
            CRect cr;
            CArun31eDlg *pDlg;
            GetDocument()->SetTitle("Employer Entry/Edit");
            pDlg=new CArun31eDlg(this);
            cr=CalculateSize(pDlg);
            m_pParentFrame->MoveWindow(cr,TRUE);
            m_pDialog=pDlg;
            if(!pDlg->f05e)pDlg->ForceCancel();   //force cancel is a public function within the dialog that calls OnCancel();
}


the instantiation of the class is only modified by the addition of

m_pParent=pParent;
if(Create(........)){
ShowWindow(SW_SHOW);
}

BTW: the file is opened in the precreate window, but I have also tried in the instantiation


void CArun31eDlg::OnCancel()
{
      // TODO: Add extra cleanup here
      if(f05e)close(f05e);      
      CDialog::OnCancel();
      ((CDlgView*)m_pParent)->GetDocument()->OnCloseDocument();

}

void CDlgDoc::OnCloseDocument()
{
      // TODO: Add your specialized code here and/or call the base class
      CView *cv;
      POSITION pos=GetFirstViewPosition();
      while(pos){
            cv=GetNextView(pos);
            ((CDlgView*)cv)->Destroy();
      }
      CDocument::OnCloseDocument();
}

void CDlgView::Destroy()
{
      if(m_pDialog){
            delete m_pDialog;
      }
      m_pDialog=NULL;
}

FWIW: The OnOK code is

void CArun31eDlg::OnOK()
{
      // TODO: Add extra validation here
      CA5 A5;
      UpdateData(TRUE);
      if(f05e){
                      Do some processing and place the data into the file
      }
      CDialog::OnOK();
      ((CDlgView*)m_pParent)->CloseIt();
}

void CDlgView::CloseIt()
{
      m_pParentFrame=GetParentFrame();
      m_pParentFrame->SendMessage(WM_CLOSE);      

}



All of this seems to work properly if the user presses CANCEL or OK.  However, when the file fails to open, and the close is called from, as in the example above from EmployerEntry() it fails in the last line of the function below.

void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible)
{
      // if the frame does not have an active view, set to first pane
      CView* pView = NULL;
      if (GetActiveView() == NULL)
      {
            CWnd* pWnd = GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
            if (pWnd != NULL && pWnd->IsKindOf(RUNTIME_CLASS(CView)))
            {
                  pView = (CView*)pWnd;
                  SetActiveView(pView, FALSE);
            }
      }

      if (bMakeVisible)
      {
            // send initial update to all views (and other controls) in the frame
            SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

            // give view a chance to save the focus (CFormView needs this)
            if (pView != NULL)
                  pView->OnActivateFrame(WA_INACTIVE, this);


This time, I've tried to post enough code to illustrate the problem without making your eyes cross.  If you need more, let me know.

Any Ideas?


Thanks again for taking the time to help, Rick.

Author

Commented:
In the previous post I should have mentioned that  EmployerEntry() is called from the views OnInitialUpdate().   My guess is that the Close Message is closing the window before the update is complete.  Have I placed the EmployerEntry() function in the wrong place?  Is there some way to close the view, from within the view without causing these problems?  Can I set a set some variable on the failure to open, and call the close function at some later time?  If so, where whould that be so that it would happen without user input?

Thanks again, Rick
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
If the dialog is modeless do NOT call the CDialog::OnCancel as I said earlier.
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
I'd also do the file opening in the OnInitDialog of the dialog.  At that point the dialog has been created.
If you do anything in the PreCreateWindow then the window has not been created at that point, which could lead to big problems if you have code that is to control a window.
CERTIFIED EXPERT
Author of the Year 2009
Commented:
Another note:
There is nothing kludgy about using a timer -- in fact, that is a very clean way to do a lot of things.  The timer handler will not get called until everything "settles down" and the main event loop is running cleanly.  That would be a good point to close and destroy the dialog because that is when the *user* would be able to do so by clicking a button.

An alternative is to post a private message to the dialog at the end of OnInitDialog().  That message will also only get processed at the desired point in the cycle.

Anather option would be to post the WM_CLOSE message to the dialog rather than calling OnClose().  Again, that message will only be handled when everything is settled down and ready to handle it.

-- Dan

P.S.  None of this really explains why anything fails "in the last line of the function below"  
The way to know why that statement is failing is to put a breakpoint there and single-step to find out what's going on.  That does not always reveal everything (especially if event timing is the issue) but it is a good place to start.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Dan and Andy:

Thanks for you input; it has been really helpful.  I'm sorry that my responses have been so slow, but I have been out in the Pacific; Internet access is iffy at best, and my being on the back side of the clock didn't help my  cognitive abilities at all.  Anyway, one last question then I'll close this one out with thanks to all:

Since these dialogs are "children" and are allocated with "new", do I still need a WM_CLOSE message?  The documentation that I read indicates that calling delete when I am finished----as part of the OnCloseDocument() function is more than adequate.

Thanks in advance, Rick
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT
Commented:
Memory assigned by new MUST be removed by delete - else you have a memory leak.

Just deleting the pointer to a window does not (as far as I know) properly cleanup the window.  USing the WM_CLOSE will let the window close itself properly and release all HANDLES assigned to it.  

Author

Commented:
Thanks to all for the help; it has been invaluable.

Rick
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.