How do I prevent multi-line edit controls from eating the Enter key?


You might decide to put a multi-line edit control in a dialog box, not because you want the user to input multi-line data, but because it's a convenient way to display multi-line text. When you do that, you may notice that the Enter key does not invoke the default dialog button, as you might normally expect. That's because the multi-line edit control tells the dialog manager that it wants the Enter key. So how do you tell the multi-line edit control to stop doing that and let the Enter key do its normal thing?

You already know the answer to this. As we saw quite some time ago, a control responds to the WM_GETDLGCODE message to influence the behavior of the dialog manager. In this case, the edit control is returning DLGC_WANTMESSAGE in response to the keyboard Enter key. What you want to do is prevent this from happening. You want to change the value that the edit control returns to the WM_GETDLGCODE.

Since there is no existing window style to specify this behavior, you're left with subclassing the control and removing the DLGC_WANTMESSAGE code if the message is the Enter key.

Comments (9)
  1. ChrisR says:

    Doesn’t ES_WANTRETURN do exactly this?  The MSDN states the following (emphasis mine):

    “ES_WANTRETURN   Specifies that a carriage return be inserted when the user presses the ENTER key while entering text into a multiple-line edit control in a dialog box. Without this style, <b>pressing the ENTER key has the same effect as pressing the dialog box’s default pushbutton</b>. This style has no effect on a single-line edit control.”

    [ES_WANTRETURN is a messy subject. I’ll try to get to it next year. -Raymond]
  2. Mitch Tenderson says:

    [ES_WANTRETURN is a messy subject. I’ll try

    to get to it next year. -Raymond]

    The speed of the Internet boggles my mind.

  3. J. Edward Sanchez says:

    I’ve found that a dab of Tabasco sauce also does the trick nicely.

  4. El Guapo says:

    Im pretty sure you can handle WM_KEYDOWN and just close the dialog box yourself if you want to.

  5. Steve says:

    > to get to it next year. -Raymond]

    The speed of the Internet boggles my mind.

    I’ve often wondered how far in advance Raymond writes, and if it really is two full months that is both scary and impressive!

    Unless it is just because he has a list of more interesting entries queued to write.

  6. Norman Diamond says:

    > In this case, the edit control is returning

    > DLGC_WANTMESSAGE in response to the keyboard

    > Enter key.

    Then it seems to me MSDN needs fixing, and some of my code needs corresponding fixes.

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/dialogboxreference/dialogboxmessages/wm_getdlgcode.asp

    *  DLGC_WANTALLKEYS All keyboard input.

    […]

    *  DLGC_WANTMESSAGE All keyboard input (the

    *  application passes this message in the MSG

    *  structure to the control).

    In dialog procs sometimes I do this:

    case WM_GETDLGCODE:

     SetWindowLong(hwndDlg, DWL_MSGRESULT,

       DLGC_WANTALLKEYS);

     return TRUE;

    I didn’t set DLGC_WANTMESSAGE because MSDN says the application (who?) will pass that to the control (whom?).  DLGC_WANTALLKEYS has brought me WM_KEYDOWN, WM_CHAR, and WM_KEYUP (but not WM_IME_KEYDOWN or WM_IME_KEYUP, which I didn’t need until a few days ago and now I can’t get it).

    The two times I needed to subclass controls, I didn’t need to try handling WM_GETDLGCODE in their … um … that was under MFC, so I’m not sure if they were window procs or dialog procs.

  7. Matthias St.Pierre says:

    @Norman:

    I think, you misinterpreted DLGC_WANTMESSAGE to be a message instead of a return code, because the formulation in the MSDN documenation is very misleading. Instead of

    > "DLGC_WANTMESSAGE All keyboard input (the application passes this message in the MSG structure to the control)."

    it should say something like

    > "DLGC_WANTMESSAGE All keyboard *messages*(the application passes the (keybord) message in the MSG structure to the control)."

    i.e., the term "this message" refers to the MSG* passed as lparam, not to DLGC_WANTMESSAGE.

  8. Workaround for diabled Enter says:

    Most developers use a dialog editor to design dialogs, and changing the behaviour of Enter is then just a click away.

    Cannot enter a return code (CR) in a edit box that doesn’t allow Enter? Press Ctrl+M

    Most apps forget to prevent that :)

  9. Norman Diamond says:

    Friday, October 13, 2006 5:10 AM by Matthias St.Pierre

    > @Norman:

    > I think, you misinterpreted DLGC_WANTMESSAGE

    > to be a message instead of a return code

    Huh?

    In responding to the WM_GETDLGCODE message I set the DLGC_WANTALLKEYS flag but did not set the DLGC_WANTMESSAGE flag due to confusion as stated.  Surely it wouldn’t be possible to either make or describe this programming error if I had misinterpreted DLGC_WANTMESSAGE to be a message?

    > it should say something like

    >> "DLGC_WANTMESSAGE All keyboard *messages*

    >> (the application passes the (keybord) message

    >> in the MSG structure to the control)."

    That wouldn’t help because DLGC_WANTALLKEYS really means all keyboard *messages* too, doesn’t it?

    I can see, and agree that it would help to document, part of the meaning that something passes the keyboard message to something in a MSG structure that is pointed to by the lparam.  But still what are the something and the something.  If an application is passing this to a control then it’s still nothing I should be using in my dialog proc, because I want my dialog proc (application) to get all keyboard messages from Windows and I’m not asking controls what they want.

    Hmm, the base note is talking about controls not about applications.  I guess that means  DLGC_WANTMESSAGE is really returned by controls not by dialog procs … and in fact Mr. Chen seems to have said exactly that.  Maybe my code is OK.  Hmmmm, if I want to do something juicier in my dialog proc, I could send a WM_GETDLGCODE to a control to ask if it wants to override me.  Maybe I understand it now, almost.

Comments are closed.