See below...
Post by Nick MeyerPost by David WilkinsonPost by Nick MeyerI'm working on a modeless dialog which needs to get some data each time it is
shown. If it fails to obtain the data, I want to show a message box and
prevent the dialog from being shown. I've tried handling this in
void CMyDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
CDialog::OnShowWindow(bShow, nStatus);
if (bShow)
{
// get data here
AfxMessageBox(_T("Failed to get data!"), MB_ICONERROR | MB_OK);
ShowWindow(SW_HIDE);
}
}
Calling ShowWindow inside OnShowWindow doesn't seem to have an effect. The
dialog is shown anyway. Commenting out the call to the base class has no
effect, and neither does setting bShow to FALSE. The only thing I've found
that works is doing a SendMessage(WM_CLOSE). However, then the dialog
flickers on the screen, as it is clearly shown and then hidden very quickly.
What's the best way to do this? Can you "cancel the showing" from inside
OnShowWindow, or is that too late?
The life-cycle of this dialog is not clear to me. When is it showing, and when
not? What triggers the attempt to gather data?
--
David Wilkinson
Visual C++ MVP
Hi David,
Thanks for the quick response, and you're right: I could have been much more
detailed.
Our app uses a large number of dialogs to configure an external piece of
hardware, which it communicates with via CORBA. The app has a DialogManager
class which takes responsibility for managing the lifetime of each of these
dialogs. When the user selects a menu item, the menu command handler calls
the DialogManager and asks it to display the appropriate dialog. The first
time, the DialogManager creates the modeless dialog. When the dialog is
closed by the user, it is not destroyed, but only hidden, so subsequent calls
simply cause DialogManager to call ShowWindow(SW_SHOW).
Each dialog needs to query the hardware for different aspects of its current
configuration so it can display the current values for the user to modify.
We've been having the dialogs do this in OnShowWindow (in response to
WM_SHOWWINDOW) because the current values may have been changed by a
different client while the dialog was not visible, so the dialog needs to
update itself each time it is shown. If, for example, the hardware returns
an error or the connection is lost and the dialog cannot retrieve the current
configuration from the hardware, then we want to show a message box and then
prevent the dialog from actually appearing. Since the data is updated in
OnShowWindow when bShow == TRUE, that's when we're responding to the error.
The closest we've come is by sending a WM_CLOSE message from inside
OnShowWindow, but that causes a visible flicker. We're hoping to find a
better solution that doesn't cause this.
Thanks again,
Nick
****
I think the basic problem is you are reacting to the wrong message. Instead of calling
ShowWindow and reacting to the OnShowWindow event, you should send a user-defined message
UWM_PLEASE_SHOW_YOURSELF. Those windows that need to gather data and pop up MessageBoxes
will process this message and get the data, then call ShowWindow(SW_SHOW) if successful,
and if there is a failure they will call AfxMessageBox only, and not show themselves.
Those that don't need to get data can revert to the parent handler. I would probably do
this by subclassing all the dialogs from a common dialog superclass which is a subclass of
CDialog (see my essay on my MVP Tips site on subclassing dialogs; I do this all the time).
The superclass handler would be
LRESULT CSuperclassOfAllDialogs::OnShowMe(WPARAM, LPARAM)
{
ShowWindow(SW_SHOW);
return 0;
}
and the superclass message map would call this method. Then, for the subclasses, I would
do
LRESULT CDataFetchingSubclass::OnShowMe(WPARAM, LPARAM)
{
get data
if (failure)
AfxMessageBox
else
ShowWindow(SW_SHOW);
return 0;
}
and the message map of the subclass would route to this handler.
By trying to combine two operations based on implict Windows behavior, you have greatly
complicated your problem. So approach the problem from a totally different direction.
joe
****
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm