Link to home
Start Free TrialLog in
Avatar of hugoitt
hugoitt

asked on

Dialog Window Disappears

I have an SDI application with a FormView base class. I Create the Dialog in OnInitialUpdate() and Hide it until it is ready to be used as follows.

  pRTGMaintenanceDlg = new CRTGMaintenanceDlg();
  pRTGMaintenanceDlg->Create(IDD_RTGMAINTENANCE,NULL);
  pRTGMaintenanceDlg->ShowWindow(SW_HIDE);


I use an OnCommand function to display the Dialog.

// On Command Function to Display Maintenance Dialog.
void CDisplay2View::OnRngtrackerpopupMaintenance()
{
  // TODO: Add your command handler code here
   pRTGMaintenanceDlg->ShowWindow(SW_SHOW);
   CRect oSize;
   pRTGMaintenanceDlg->GetWindowRect(&oSize);
   pRTGMaintenanceDlg->SetWindowPos(NULL,640,585,oSize.Width(),oSize.Height(),SWP_NOZORDER);
}

I have two problems.
1.The first is how do I lock the Dialog Window in place so that the user cannot move it.
2. My second problem is if the Dialog Window is currently displayed and I minimize the application and then maximize it, the Dialog Window is no longer displayed. How do I keep the Dialog Window displayed on a minimized-maximize operation.
I'm already using OnActivateView to re-paint the Display.

// Windows Message that is called to Re-Activate (Paint) the Display after a Screen Saver or other Window has been Displayed.
void CDisplay2View::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
     // TODO: Add your specialized code here and/or call the base class
     Invalidate(TRUE);
     UpdateWindow();

     CFormView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}





ASKER CERTIFIED SOLUTION
Avatar of Lockias
Lockias

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of hugoitt
hugoitt

ASKER

Lockias, thks for the response.

Let's address question two. In my Dialog.cpp I added a windows message handler for WM_SHOWWINDOW as follows:

void CAnyDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
   CDialog::OnShowWindow(bShow, nStatus)

    // TODO: Add your specialized code here and/or call the base class

       if (nStatus == SW_PARENTOPENING && bShow == TRUE)
            pRTGMaintenanceDlg->ShowWindow(SW_SHOW);
}

This works well in bringing up the dialog window if the main application window is minimized then maximized. The
problem is I have other dialog boxes that can be displayed. If one of the other dialog boxes are displayed and the minimize-maximize is initiated, it will bring up the pRTGMaintenanceDlg as well even though it wasn't displayed at the time. It seems like I will have to set flags to tell me if the current dialog was displayed before I show it, but I was thinking there was a cleaner way of doing this.

anyone?


Well, from how I *think* that you have things setup, you should be able to do this:

void CAnyDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
  CDialog::OnShowWindow(bShow, nStatus)

   // TODO: Add your specialized code here and/or call the base class

      if (nStatus == SW_PARENTOPENING && bShow == TRUE)
      {
         if (pRTGMaintenanceDlg->IsWindowVisible())
           pRTGMaintenanceDlg->ShowWindow(SW_SHOW);
      }
}

The IsWindowVisible() should return true if the WS_VISIBLE flag is set.  This should be set if the dialog was shown before its parent was hidden.  If I am remembering this wrong and it doesn't work that way then setting a flag of your own would probably be the best solution.

~Lockias

Avatar of hugoitt

ASKER

Lockias, thks for the response.

Let's address question two. In my Dialog.cpp I added a windows message handler for WM_SHOWWINDOW as follows:

void CAnyDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
   CDialog::OnShowWindow(bShow, nStatus)

    // TODO: Add your specialized code here and/or call the base class

       if (nStatus == SW_PARENTOPENING && bShow == TRUE)
            pRTGMaintenanceDlg->ShowWindow(SW_SHOW);
}

This works well in bringing up the dialog window if the main application window is minimized then maximized. The
problem is I have other dialog boxes that can be displayed. If one of the other dialog boxes are displayed and the minimize-maximize is initiated, it will bring up the pRTGMaintenanceDlg as well even though it wasn't displayed at the time. It seems like I will have to set flags to tell me if the current dialog was displayed before I show it, but I was thinking there was a cleaner way of doing this.

anyone?


Avatar of DanRollins
>>I have two problems.
>>1.The first is how do I lock the Dialog Window in place
>>so that the user cannot move it.

Don't do this.  It is wrong at many levels.  You must allow a user to reposition windows at any time. If you break this very basic GUI rule, it means that you have no understanding of Windows programming.  You will look like an amateur.

>>2. ... How do I keep the Dialog Window displayed on a minimized-maximize operation.

The modeless dlg closes because it is a parent of the main window.  When you create the modeless dlg, set it's parent to the Desktop:

  pRTGMaintenanceDlg= new CRTGMaintenanceDlg();
  pRTGMaintenanceDlg->Create( CRTGMaintenanceDlg::IDD, GetDesktopWindow() );

That way, it will not need to follow the app window.

-- Dan
Avatar of hugoitt

ASKER

Dan,

thanks for the response. What I'm looking to do is if there was a dialog box displayed in the main application window when the application was minimized, i want the dialog box to be re-displayed when the application is maximized. Currently, the dialog box disappears when I maximize the application. Your suggestion leaves the dialog box displayed when the application is minimized which is a feature I do not want.

In reponse to question one, I see your point, however the user of this application will not be using the "computer" for anything but his assigned task.The design calls for the user to be able to use one of three applications. He will be performing repetitive tasks, and making quick decisions on short notice, the user has to know that a control is available to him at the same location every time he needs it. If the user moves the window he would be covering other controls that could cause him to miss information critical to his assignment. Mistakes do happen, and were trying to prevent the application from working in a way that could jeapordize his assigned task.

thanks again
>>i want the dialog box to be re-displayed when the application is maximized.

Q1: That is the default behavior, so I did not address it.  You must be doing something strange in order for your program to *not* display all child modeless dialogs when the parent window gets maximized.

Q2: I agree that there may be a place for fixed-location windows on a one-task, dedicated PC.  I still recommend against it.  Howeverh ere is a simple way to handle it.


class CAboutDlg : public CDialog
{
public:
    CAboutDlg();
    afx_msg void OnWindowPosChanged( WINDOWPOS* lpwndpos );
...


BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
     //{{AFX_MSG_MAP(CAboutDlg)
     ON_WM_WINDOWPOSCHANGED()
     //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CAboutDlg::OnWindowPosChanged( WINDOWPOS* lpwndpos )
{
    SetWindowPos(0, 100,100, 0,0, SWP_NOSIZE  );
   // CDialog::OnWindowPosChanged( lpwndpos );
}


-- Dan
I agree with DanRollins.
It really does break any GUI design rules if you forbid dragging of a window having a caption.

A window with a caption should be able to be dragged. Therefore it has a caption. If you don't want the user to drag the window then don't display a caption.
Dan,
  I already stated that one could use WM_WINDOWPOSCHANGING.  Further more the code you provide will enter an infinite loop.  The OnwindowPosChanged will fire the SetWindowPos, which will fire the OnWindowPosChanged, which will...
This is why there is a changING version of this message.

~Lockias
Avatar of hugoitt

ASKER

Ok, I need to move on. I've decided to go with the following.
Question One - Since the consensus is I would be breaking GUI design rules if I disallowed moving of the dialog window, I will remove the caption from the dialog box, thus
not allowing the user that option, thanks Pacman, Dan.

Question Two - I will set flags to tell me which dialog boxes are currently displayed and use the windows message handler WM_SHOWWINDOW to show them in a maximize operation.

void CAnyDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
 CDialog::OnShowWindow(bShow, nStatus)

  // TODO: Add your specialized code here and/or call the base class

     if (nStatus == SW_PARENTOPENING && bShow == TRUE)
     {
        if (iRTGMaintenanceDlgFlag == TRUE)
          pRTGMaintenanceDlg->ShowWindow(SW_SHOW);
     }
}

thanks Lockias

I appreciate everyone's input.

Lockias,
>>I already stated that one could use WM_WINDOWPOSCHANGING.

WM_WINDOWPOSCHANGED is the better message to handle.  WM_WINDOWPOSCHANGING will cause unwanted recursion.

>> Further more the code you provide will enter an infinite loop.  The OnwindowPosChanged will fire the SetWindowPos, which will fire the OnWindowPosChanged,
which will...

I also thought that might happen, so I tested the code.  That is something that you didn't bother to do.  Had you done so, you would know that it works perfectly.
-=-=-=-=-=-=-=-=-=-=

hugoitt,
I'm glad you used my suggestion to allow the window to move.

There is no need *at all* to use the code you posted to make the child dialog appear when its parent is maximized.  Your code simply enforces what happens automatically.  I'm guessing that it is just undoing some mistake that you made elsewhere in your program.

-- Dan
I did test it.  You must have not tested it correctly.  You say that WM_WINDOWPOSCHANGING will cause recursion.  That can only be if you do not know how to use it.
Lockias,
>>You must have not tested it correctly.  

OK, you made me redo the test.  As usual, my work was sound and my test -- and my code -- was correct.  There is no infinite recursion.  You can drag the modeless dialog box around, but it always returns to 100,100.

Now, perhaps you will take a moment to verify that your testing procedure was correct.  The code I showed was cut and pasted from a functional program.  Use it and see. I'll wait here for your appology.

-- Dan
I have learned something new!  SetWindowPos always fires a WM_WINDOWPOSCHANGING message.  However, if the values relevant to the flags do not different than the current ones, WM_WINDOWPOSCHANGED never gets sent.  They built in recursion protection!

However, Dan, please try out my code and see which you think is more appealing to the user:

class CAboutDlg : public CDialog
{
public:
   CAboutDlg();
   afx_msg void OnWindowPosChanging( WINDOWPOS* lpwndpos );
...


BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    //{{AFX_MSG_MAP(CAboutDlg)
    ON_WM_WINDOWPOSCHANGING()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CAboutDlg::OnWindowPosChanging( WINDOWPOS* lpwndpos )
{  
   if (!(lpwndpos->flags & SWP_NOMOVE))
   {
      lpwndpos->x = 100;
      lpwndpos->y = 100;
   }

   CDialog::OnWindowPosChanging(lpwndpos);
}




BTW: Sorry!
Avatar of hugoitt

ASKER

Dan,
thanks for your persistence. You made me go back and look at my code again.

Dan
I'm guessing that it is just undoing
some mistake that you made elsewhere in your program.

I didn't override the OnCancel member function which by default calls EndDialog. EndDialog makes the dialog box invisible but does not destroy it.

The first time after my application first comes up, I bring up the dialog box - I can minimize and maximize and the dialog window comes up like it should.

As soon as I close it, bring it back up, and minimize-maximize, the dialog window is gone.

I'm still not clear as to why this is happening but I beleive I can fix it by overriding the OnCancel Member function and Hiding the window when I decide to close it.

Below is the way I'am currently using OnCancel to hide the Dialog window.

void CRTGMaintenanceDlg::OnCancel()
{
  pRTGMaintenanceDlg->ShowWindow(SW_HIDE);
  CDialog::OnCancel();
}

Just a refresher, I create all dialog Windows on Startup and then Show and Hide them as I use them.
Hi Lockias,
I'll assume that your code prevents movement altogether, which would undoubtedly be better than my kludgy-looking snap-back technique.  I quit looking for a better technique when hugoitt accepted your answer.

hugoitt,
You might be able to just...

void CRTGMaintenanceDlg::OnCancel(){
 pRTGMaintenanceDlg->ShowWindow(SW_HIDE);
// CDialog::OnCancel();
}

...to prevent any undesured side-effects of the base-class handler.  After all, the only goal is to hide the window, and your override does that.

-- Dan
Avatar of hugoitt

ASKER

thanks Dan,

That's exactly what I did and it works great.