Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Multiline Edit Control Closes Parent Window? I'm Confused!

268 views
Skip to first unread message

John Kale

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
I'm writing a Win32 application with MSVC 5.0 in C (no C++ or MFC). The
application's main window is a modeless dialog box of a private window
class. One of the controls in this dialog is a multiline edit control. My
problem is that when the input focus is in the edit control and the user
presses escape, a WM_CLOSE message gets sent to the main dialog (from where
exactly, I'm not sure), and the application closes itself. This might be OK
for a dialog box that had a parent window, but it's not acceptable to close
the whole application with a single, possibly accidental, keystroke.

I've fixed this temporarily with a hack; I subclassed the edit control and
stopped WM_KEYDOWN - VK_ESCAPE messages from being sent to it. (Stopping the
WM_CHAR message that follows doesn't work, it's too late by then, WM_CLOSE
is already queued.) But I can't help feeling that I'm missing some
fundamental tenet of message passing (which is more complicated than I ever
imagined, before delving into this problem) and that there is a "right" way
to fix this.

The only other ways to fix this that I've found in many hours of trial and
error nonsense are:
- removing the IsDialogMessage() call from the main message loop. Of course,
with that gone, the TAB key no longer works to move from one control to
another, which is also unacceptable.
- switching to a single-line edit control, which shouldn't make any
difference, really, but it does. I can't use a single line edit control
here, though.

I'd really appreciate any tips on this; I'd love to know if it's
IsDialogMessage() or the edit control's standard WndProc that's sending the
WM_CLOSE - and why. For the escape key, shouldn't I get WM_COMMAND -
IDCANCEL instead? (That's what I get when the input focus is on any other
control and the user pressed Escape.)

I wrote a test application to duplicate the problem in a smaller, simpler
project. It worked - the problem is there too. Here are some possibly
relevant pieces of the code from that test app:

// Main dialog has a private window class, so I need to provide both
// a WndProc (for the RegisterClass() call) and a DialogProc (for the
// CreateDialog() call). My WndProc just calls DefDlgProc,
// because I don't really want to do anything special with the WndProc.

LRESULT CALLBACK MainDlg_WndProc( HWND hwndDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
return DefDlgProc( hwndDlg, uMsg, wParam, lParam );
}

BOOL CALLBACK MainDlg_DlgProc( HWND hwndDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
HANDLE_WM_INITDIALOG( hwndDlg, wParam, lParam, MainDlg_OnInitDialog );
return TRUE;

case WM_COMMAND:
HANDLE_WM_COMMAND( hwndDlg, wParam, lParam, MainDlg_OnCommand );
return TRUE;

case WM_CLOSE:
HANDLE_WM_CLOSE( hwndDlg, wParam, lParam, MainDlg_OnClose );
return TRUE;

case WM_DESTROY:
HANDLE_WM_DESTROY( hwndDlg, wParam, lParam, MainDlg_OnDestroy );
return TRUE;
}

return FALSE;
}

BOOL MainDlg_RegisterWindowClass( void )
{
WNDCLASS wc;

// get info on standard dialog class
GetClassInfo( NULL, MAKEINTATOM( 32770 ), &wc );

wc.lpfnWndProc = MainDlg_WndProc;
wc.hInstance = g_hInst;
wc.hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_PAGER ) );
wc.hbrBackground = (HBRUSH)( COLOR_BTNFACE + 1 );
wc.lpszMenuName = MAKEINTRESOURCE( IDM_MAIN );
wc.lpszClassName = "TESTMAIN";

return ( 0 != RegisterClass( &wc ) );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow )
{
HWND hwndMain;
MSG msg;

g_hInst = hInstance;

MainDlg_RegisterWindowClass();

hwndMain = CreateDialog( g_hInst, MAKEINTRESOURCE( IDD_MAIN ),
NULL, MainDlg_DlgProc );

if ( hwndMain == NULL )
{
return GetLastError();
}

while ( GetMessage( &msg, NULL, 0, 0 ) )
{
if ( !IsDialogMessage( hwndMain, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}

return 0;
}

Many thanks in advance,
John
e-mail: jwk (at) en (dot) com

Oleg Pilipenko

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
Are you positive that it is edit control that sends WM_CLOSE to your dialog?
It seems more probable that this is default behavior of the CDialog class.
Try to override OnCancel method of your dialog.

Oleg

John Kale <jwk@[deletethis]en.com> wrote in message
news:r7Oc3.27$qh1.1...@news.en.com...

John Kale

unread,
Jun 25, 1999, 3:00:00 AM6/25/99
to
Thanks for responding, Oleg.

No, I'm not sure what the source of the WM_CLOSE message is. Is there
a way to find out (say with Spy++) the source of a message? I'm not
familiar with one. All I know is that my hack (stopping the WM_KEYDOWN
message) solved the problem.

Unfortunately, I am not yet learned in the ways of MFC, so there is no
CDialog class to override or change.

If anyone could refer me to some good material about the ways messages
are passed between control's WndProcs, DefDlgProc, DefWndProc,
IsDialogMessage(), etc, maybe that would be helpful. Mostly what I've
been able to discover is that 1) it's more complicated than I thought
and 2) I still don't understand it all.

Oleg Pilipenko wrote in message
<5vOc3.29$4z5....@iagnews.iagnet.net>...

Ole Nielsby

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to
Oleg Pilipenko <ol...@spammenot.flashline.com> wrote:

> Are you positive that it is edit control that sends WM_CLOSE to
> your dialog? It seems more probable that this is default behavior
> of the CDialog class. Try to override OnCancel method of your dialog.

I had the same problem with a richedit control, with no CDialog,
in an essentially Notepad-like app. I solved it by wrapping the
edit control in a child window that ignores the WM_CLOSE.

I have found no explanation for this behaviour. I guess it is
a "bug by design"...

ON


Klaus-Werner Konrad

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to
Ole Nielsby schrieb in Nachricht <7l155m$q2h$1...@news.inet.tele.dk>...

>
>I had the same problem with a richedit control, with no CDialog,
>in an essentially Notepad-like app. I solved it by wrapping the
>edit control in a child window that ignores the WM_CLOSE.
>
>I have found no explanation for this behaviour. I guess it is
>a "bug by design"...
>

Noooo !

It's not a BUG, it's the normal behaviour for dialogs. It's caused by
The Dialog Manager that is called by IsDialogMessage().
If you hit ESC, it will send WM_CLOSE and return ID_CANCEL
to the parent window.
If you hit RETURN, it will send a WM_CLICK message to the
default Pushbutton (I believe).

You simply have to handle the WM_CLOSE message in your
Dialog Procedure and return TRUE from it to signal the dialog
manager that you have already processed the Message.
Also you have to maintain a flag that is set when you hit the
EXIT button in your dialog form; then, in the response to the
WM_CLOSE message you can return FALSE if the flag is
set to end your program.

HTH

--
Klaus-Werner Konrad

klaus....@cityweb.de

Paul-Erik Raué

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to
Actually not a bug by design but standard behaviour for dialog boxes. There are
two standard keys that are normally handled by a dialog box, namely the enter
key (which is equivalent to clicking on the default button) and the escape
key(!) (cancelling the dialog).

One way to solve this problem is to use a PreTranslateMessage handler in the
dialog and check for WM_KEYDOWN/VK_ESCAPE characters and do not pass these to
the standard dialog. I have used this trick succesfully many times.

The WM_CLOSE is therefor generated not directly by the pressing of an escape
key, but rather by the default behaviour of a dialog. If your dialog is the main
application window you will always have to handle the escape key to prevent
accidental closing.

Hope this helps,

Paul-Erik Raué

Ole Nielsby wrote:

> Oleg Pilipenko <ol...@spammenot.flashline.com> wrote:
>
> > Are you positive that it is edit control that sends WM_CLOSE to
> > your dialog? It seems more probable that this is default behavior
> > of the CDialog class. Try to override OnCancel method of your dialog.
>

> I had the same problem with a richedit control, with no CDialog,
> in an essentially Notepad-like app. I solved it by wrapping the
> edit control in a child window that ignores the WM_CLOSE.
>
> I have found no explanation for this behaviour. I guess it is
> a "bug by design"...
>

> ON

per.vcf

John Kale

unread,
Jun 26, 1999, 3:00:00 AM6/26/99
to
I'm the original poster. I'd like to thank everyone for responding
with information on my problem. I'm happy to see I'm not the only one
who's run in to this.

The general consensus seems to be that (1) this is something I'll have
to deal with in a way similar to what I've done (window subclassing,
ignoring WM_KEYDOWN/VK_ESCAPE), and (2) that it's standard behavior,
and intentional.

I'll agree that the standard behavior is for a dialog to close when
the user presses escape. But this is usually acheived by translating
the WM_KEYDOWN/VK_ESCAPE message to WM_COMMAND/IDCANCEL, not by
sending WM_CLOSE. This way, the application behaves exactly as if the
user had pressed the cancel button. That's important, because the
dialog may have code in the IDCANCEL handler that needs to be called
for correct termination of the dialog. That code won't get called if
the dialog just gets WM_CLOSE.

In fact, in my application, the escape key does generate
WM_COMMAND/IDCANCEL if:
- I change the multiline edit control to a single line edit control.
OR
- The input focus is NOT on the multiline edit control

But if the input focus is on a multiline edit control, I don't get
WM_COMMAND/IDCANCEL, I get WM_CLOSE and only WM_CLOSE. There's no way
to tell if the WM_CLOSE came from the system's translation of the
escape key or from the user actually trying to close the application.

It sure sounds to me like the author of the multiline edit control
attempted to emulate standard dialog behavior, and got it slightly
wrong. I don't see how IsDialogMessage() fits in to the mix, in that
case, but this message-passsing scenario is complex.

This kind of thing makes me wish Windows was open-source - then I'd be
able to find out for certain what's going on.

Thanks again, everyone.
John


jwk (at) en (dot) com


Paul-Erik Raué wrote in message <3774C944...@quintiq.nl>...

Raymond Chen

unread,
Jun 29, 1999, 3:00:00 AM6/29/99
to
Yes, when you hit ESC in a multiline edit, it posts a WM_CLOSE to
its parent in the mistaken belief that it is part of a dialog
box. This is for compatibility with Windows 2.0, which behaved
this way. It's annoying now, but compatibility means having to
be bug-for-bug compatible with the previous version...

--
(My return address is intentionally invalid; delete ".---" to get my real address.
My responses are not to be considered official technical support or advice.)

0 new messages