From: Joseph M. Newcomer on
See below...
On Fri, 9 May 2008 06:41:03 -0700, Nick Meyer <NickMeyer(a)discussions.microsoft.com> wrote:

>
>
>"David Wilkinson" wrote:
>
>> Nick Meyer wrote:
>> > I'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
>> > OnShowWindow:
>> >
>> > 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?
>>
>> Nick:
>>
>> 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: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: David Ching on

"Nick Meyer" <NickMeyer(a)discussions.microsoft.com> wrote in message
news:BFD64C49-6024-4B2B-95C4-2EDCA228DBAA(a)microsoft.com...
>> Why not just send a custom message to the dialog (or call a specific
>> method)
>> when your user selects the menu item?
>>
> That sounds like a pretty good bet. Thanks for the advice!
>

This is the cleanest way, but FWIW, I think if you overrode
WM_WINDOWPOSCHANGING and cleared the SWP_SHOWWINDOW flag, you could prevent
the window from being shown.

-- David