Nonmodal dialog cancel itself without any user input

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

AlexFMCommented:
Please show your code. Where is "if(!file)OnCancel()" fragment is placed?
0
AndyAinscowFreelance programmer / ConsultantCommented:
non-modal dialog - OnCancel (and OnOK) is usually used for modal dialogs.
Try this instead.
if(!file)
  PostMessage(WM_CLOSE, 0, 0);
0
rajeev_devinCommented:
Can't you something like this.

if(!file) {
   CDialog::OnCancel();
}
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

AndyAinscowFreelance programmer / ConsultantCommented:
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....
0
rickatseasoftAuthor 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.
0
rickatseasoftAuthor 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
0
AndyAinscowFreelance programmer / ConsultantCommented:
If the dialog is modeless do NOT call the CDialog::OnCancel as I said earlier.
0
AndyAinscowFreelance programmer / ConsultantCommented:
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.
0
DanRollinsCommented:
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.
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
rickatseasoftAuthor 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
0
AndyAinscowFreelance programmer / ConsultantCommented:
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.  
0
rickatseasoftAuthor Commented:
Thanks to all for the help; it has been invaluable.

Rick
0
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.