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

Handling Enter Key in a ComboBox Edit Box

249 views
Skip to first unread message

Norman Landis

unread,
Jul 14, 2003, 12:31:17 AM7/14/03
to
In my continuing saga of making a variety of controls responsive to the
Enter key, I have encountered a new problem. I have now created the
CEnterEdit control which works like a charm. I wish to extend this behavior
to other types of MFC controls, in particular to the CComboBox. Through Joe
Newcomer's generous help, I have developed a new class CEnterComboBox based
on "extracting" the component EnterEdit and List Boxes. That's not a
problem.

The problem arises in making CEnterComboBox respond to the Enter Key. When
I type in the edit box portion of my control, the Edit box captures the
Enter Key. At that point, it puportedly sends a message to its parent, the
Combo Box. However, the Combo Box does not catch that message. I think I
have the appropriate entries in the message map of each of these components.

So my initial question is simply am I on the right track? If I'm doing it
right, then I must have a careless bug somewhere in my code, which I'll be
glad to share. If there is something I am missing in my logic, I assume Joe
or another kind-hearted soul will rush to my rescue.

Norm

Ajay Kalra

unread,
Jul 14, 2003, 12:55:28 AM7/14/03
to
Subclass the edit control portion of the combobox and look for the Enter key
there.

--
Ajay Kalra [MVP - VC++]
ajay...@yahoo.com


"Norman Landis" <nla...@optonline.net> wrote in message
news:pmqQa.6537$QD2.1...@news4.srv.hcvlny.cv.net...

Norman Landis

unread,
Jul 14, 2003, 5:18:15 PM7/14/03
to
Yes. I understand that. But if I create CEnterComboBox, I would need for a
given such control to have a handler to
deal with the Enter key. Sure, the subclassed CEnterEdit control can catch
the Enter key. But I need that message to
be associated with the Combo Box. When the CEnterEdit control performs a
parent->SendMessage(), that message will be
associated with the Edit Box, not the Combo Box. How do I have the Combo
Box catch the message and issue its own
message?

Norm


"Ajay Kalra" <ajay...@yahoo.com> wrote in message
news:e$7loQcSD...@TK2MSFTNGP11.phx.gbl...

Ajay Kalra

unread,
Jul 14, 2003, 5:44:48 PM7/14/03
to
Why would you want such a design though? You are getting it(enter key) in
the edit control. If you want, you can always route it to the ComboBox(using
SendMessage?) w/o forwarding to the base class of edit control.

--
Ajay Kalra [MVP - VC++]
ajay...@yahoo.com


"Norman Landis" <nla...@optonline.net> wrote in message

news:r6FQa.22640$QD2.3...@news4.srv.hcvlny.cv.net...

Norman Landis

unread,
Jul 15, 2003, 12:10:05 AM7/15/03
to
That's exactly the problem. I have tried routing the message to the
ComboBox, but for some reason it doesn't seem to get the message.

Why would I want such a design? Because the Enter Key should be associated
with the Combo Box. Why design a control, such as ComboEditBox if it is
incapable of sending a message to its parent that the edit is complete? The
alternative is to have the dialog capture the message from the EnterEdit
Control that it doesn't even know exists because it is internal to the
ComboEnterBox.

Norm

"Ajay Kalra" <ajay...@yahoo.com> wrote in message

news:ujmclElS...@TK2MSFTNGP11.phx.gbl...

Ajay Kalra

unread,
Jul 15, 2003, 1:12:33 AM7/15/03
to
> I have tried routing the message to the
> ComboBox, but for some reason it doesn't seem to get the message.

What did you do to achieve it? How did you package the message? Can you show
the code which does this?

--
Ajay Kalra [MVP - VC++]
ajay...@yahoo.com


"Norman Landis" <nla...@optonline.net> wrote in message

news:x8LQa.23736$QD2.4...@news4.srv.hcvlny.cv.net...

Norman Landis

unread,
Jul 15, 2003, 1:31:10 AM7/15/03
to
Well, Ajay, I kind of figured out my problem. When subclassing the
CEnterEdit portion of my CEnterComboBox, I performed a GetDlgCtrlID to
obtain a control id for the subclassed edit box. But this control id (in
this case, 1001) conflicts with another resource id in my application. So I
performed a SetDlgCtrlId to set it to a "unique" value. Sure enough, by
hard-coding inside the message map what I know the id to be in this
application, indeed, the CEnterComboBox does in fact receive the message
from the subclassed CEnterEdit box, which it in turn passes on to the dialog
and is received by my application handler.

Now, the problem. Since the CEnterComboBox is a class independent of the
application that uses it, and since I might have several such controls in an
application, and since the subclassed EditEnter box is dynamically created
at execution, what should I put in my message map?

My message map entry for the CEnterComboBox control currently looks like:

ON_CONTROL(EDIT_COMPLETE, 4080, OnEnterKey)

This is obviously not acceptable for an application-independent control. If
the CEnterComboBox class has a field

UINT edit_control_id;

where edit_contol_id is set to the Combo Box's id + 3000, what is allowable
for the id field in the message map?

Norm

"Norman Landis" <nla...@optonline.net> wrote in message
news:pmqQa.6537$QD2.1...@news4.srv.hcvlny.cv.net...

Ajay Kalra

unread,
Jul 15, 2003, 3:23:05 AM7/15/03
to
Instead of sending a message to the combobox from edit control, why not call
a virtual method in combobox. That would leave the capablity of deriving
from it and be able to handle enter key in combobox class. You also then do
not need to handle any message in the combobox itself.

--
Ajay Kalra [MVP - VC++]
ajay...@yahoo.com

"Norman Landis" <nla...@optonline.net> wrote in message

news:ykMQa.24105$QD2.4...@news4.srv.hcvlny.cv.net...

Norman Landis

unread,
Jul 15, 2003, 10:31:38 AM7/15/03
to
The problem is that CEnterEdit is its own class, independent of
CEnterComboBox. In order to do what you suggest, it now becomes a knowing
component of CEnterComboBox. But it has its own uses completely unrelated
to that context. I could create a new class, CEnterEditCombo which is
identical to CEnterEdit but calls the virtual function rather than sending a
message (its normal behavior) but that seems more than clunky.

Norm

"Ajay Kalra" <ajay...@yahoo.com> wrote in message

news:OsxmyHqS...@tk2msftngp13.phx.gbl...

Doug Harrison [MVP]

unread,
Jul 15, 2003, 1:54:56 PM7/15/03
to
Norman Landis wrote:

>Well, Ajay, I kind of figured out my problem. When subclassing the
>CEnterEdit portion of my CEnterComboBox, I performed a GetDlgCtrlID to
>obtain a control id for the subclassed edit box. But this control id (in
>this case, 1001) conflicts with another resource id in my application.

That shouldn't matter. That editbox is a child of the combobox, and the
combobox is free to assign it whatever ID suits it.

>So I performed a SetDlgCtrlId to set it to a "unique" value.

That's a bad idea. The Windows combobox code which created the editbox just
might expect the ID not to change.

>Sure enough, by
>hard-coding inside the message map what I know the id to be in this
>application, indeed, the CEnterComboBox does in fact receive the message
>from the subclassed CEnterEdit box, which it in turn passes on to the dialog
>and is received by my application handler.

I don't get it. You've subclassed the editbox with CEnterEdit, and it
intercepts WM_KEYDOWN or whatever. It can translate that into some
user-defined message which it passes up to its parent, in this case, your
CEnterComboBox. In turn, CEnterComboBox can forward the message on to its
parent, and if the message includes a control ID, it should specify its own
control ID, i.e. the combobox control ID, since that's what the parent knows
about.

>Now, the problem. Since the CEnterComboBox is a class independent of the
>application that uses it, and since I might have several such controls in an
>application, and since the subclassed EditEnter box is dynamically created
>at execution, what should I put in my message map?
>
>My message map entry for the CEnterComboBox control currently looks like:
>
> ON_CONTROL(EDIT_COMPLETE, 4080, OnEnterKey)

Which message map contains this entry? Combobox or dialog?

What's the value of EDIT_COMPLETE? The ON_CONTROL macro translates into
WM_COMMAND, and if the embedded editbox with ID 1001 is giving you trouble
here, this suggests that EDIT_COMPLETE equals some other command
notification ID, and that the combobox/dialog is receiving WM_COMMAND
messages for another control with ID 1001. Otherwise, I don't see why you
said, "But this control id (in this case, 1001) conflicts with another
resource id in my application." Half of the solution is to this problem is
described above. The other half is to define EDIT_COMPLETE so it doesn't
conflict with other notification codes used by the control in question, and
I'm not sure how you do that. AFAIK, those ranges aren't defined. Myself, I
would forget about WM_COMMAND and define a WM_APP-based custom message or
maybe use RegisterWindowMessage.

>This is obviously not acceptable for an application-independent control. If
>the CEnterComboBox class has a field
>
> UINT edit_control_id;
>
>where edit_contol_id is set to the Combo Box's id + 3000, what is allowable
>for the id field in the message map?

That's the wrong approach. Your combobox should use its own ID in messages
it sends to its parent, replacing the editbox ID in messages it forwards.

--
Doug Harrison
Microsoft MVP - Visual C++

Norman Landis

unread,
Jul 16, 2003, 12:17:27 AM7/16/03
to

"Doug Harrison [MVP]" <d...@mvps.org> wrote in message
news:ela8hv4ajdrpd0kut...@4ax.com...

> Norman Landis wrote:
>
> >Well, Ajay, I kind of figured out my problem. When subclassing the
> >CEnterEdit portion of my CEnterComboBox, I performed a GetDlgCtrlID to
> >obtain a control id for the subclassed edit box. But this control id (in
> >this case, 1001) conflicts with another resource id in my application.
>
> That shouldn't matter. That editbox is a child of the combobox, and the
> combobox is free to assign it whatever ID suits it.
>
> >So I performed a SetDlgCtrlId to set it to a "unique" value.
>
> That's a bad idea. The Windows combobox code which created the editbox
just
> might expect the ID not to change.
>

I understand why you say this and I do find it a bit odd. But for some
reason when the edit box had ID 1001 the Combo Box's (parent's) message
handler was not invoked, but when the ID became 4080, it was!!!!

> >Sure enough, by
> >hard-coding inside the message map what I know the id to be in this
> >application, indeed, the CEnterComboBox does in fact receive the message
> >from the subclassed CEnterEdit box, which it in turn passes on to the
dialog
> >and is received by my application handler.
>
> I don't get it. You've subclassed the editbox with CEnterEdit, and it
> intercepts WM_KEYDOWN or whatever. It can translate that into some
> user-defined message which it passes up to its parent, in this case, your
> CEnterComboBox. In turn, CEnterComboBox can forward the message on to its
> parent, and if the message includes a control ID, it should specify its
own
> control ID, i.e. the combobox control ID, since that's what the parent
knows
> about.
>

That's exactly what I do. The Combo Box's OnEnterKey() handler sends its
own message
with the ComboBox's ID to its parent dialog. It's a two-step process:
component EnterEdit
box sends an EDIT_COMPLETE message to the Combo box and then the Combo box
sends
its own message to its parent.

> >Now, the problem. Since the CEnterComboBox is a class independent of the
> >application that uses it, and since I might have several such controls in
an
> >application, and since the subclassed EditEnter box is dynamically
created
> >at execution, what should I put in my message map?
> >
> >My message map entry for the CEnterComboBox control currently looks like:
> >
> > ON_CONTROL(EDIT_COMPLETE, 4080, OnEnterKey)
>
> Which message map contains this entry? Combobox or dialog?
>

This is the CEnterComboBox's message map. The 4080 represents the control
id of
the dynamically subclassed CEnterEdit box.

The dialog in turn contains its own message map entry:

ON_CONTROL(EDIT_COMPLETE, IDC_USERS_LIST, on_user_name_entered)

where IDC_USERS_LIST is the control id of the CEnterComboBox.

> What's the value of EDIT_COMPLETE? The ON_CONTROL macro translates into
> WM_COMMAND, and if the embedded editbox with ID 1001 is giving you trouble
> here, this suggests that EDIT_COMPLETE equals some other command
> notification ID, and that the combobox/dialog is receiving WM_COMMAND
> messages for another control with ID 1001. Otherwise, I don't see why you
> said, "But this control id (in this case, 1001) conflicts with another
> resource id in my application." Half of the solution is to this problem is
> described above. The other half is to define EDIT_COMPLETE so it doesn't
> conflict with other notification codes used by the control in question,
and
> I'm not sure how you do that. AFAIK, those ranges aren't defined. Myself,
I
> would forget about WM_COMMAND and define a WM_APP-based custom message or
> maybe use RegisterWindowMessage.
>

static UINT EDIT_COMPLETE = ::RegisterWindowMessage(UWM_EDIT_COMPLETE_MSG);

So the EDIT_COMPLETE message is unique. It just seems that someone gets
confused
when it is combined with the control id of 1001, which IS used elsewhere in
the application.

The EDIT_COMPLETE notification message is the standard one I use in
CEnterEdit whenever it
detects the Enter key is hit. Very standard stuff, I believe. Of course,
WM_COMMAND combines
this message with the control id in the upper word/lower word format, so
that can't be a cause
of conflict.

> >This is obviously not acceptable for an application-independent control.
If
> >the CEnterComboBox class has a field
> >
> > UINT edit_control_id;
> >
> >where edit_contol_id is set to the Combo Box's id + 3000, what is
allowable
> >for the id field in the message map?
>
> That's the wrong approach. Your combobox should use its own ID in messages
> it sends to its parent, replacing the editbox ID in messages it forwards.

But that is exactly what I'm doing (see above.) But the Combo Box has to
get a message from
its subclassed CEnterEdit box so that it can "do its thing," and send the
appropriate message up
another level. I'm not using edit_control_id in the message the Combo Box
is setting. I'm using
it in the CEnterEdit control to send a message to the Combo Box. But then
the Combo Box has
to receive that message. So it needs an entry in its message map. That's
the one in question.
Apparently I can't stick edit_control_id as the id field of ON_CONTROL.
What DO I do?

Norm

Doug Harrison [MVP]

unread,
Jul 16, 2003, 2:00:58 AM7/16/03
to
Norman Landis wrote:

I'm not sure I see the value in stuffing the EDIT_COMPLETE notification into
WM_COMMAND. While RegisterWindowMessage generates unique message IDs,
WM_COMMAND notification codes are not message IDs. Like I said, I don't know
how to define codes to go along with things like EN_CHANGE, because AFAIK,
the ranges aren't defined. So I would just pass EDIT_COMPLETE to the parent
window directly, instead of wrapping it up in WM_COMMAND. Should be easier,
too.

>> >This is obviously not acceptable for an application-independent control.
>If
>> >the CEnterComboBox class has a field
>> >
>> > UINT edit_control_id;
>> >
>> >where edit_contol_id is set to the Combo Box's id + 3000, what is
>allowable
>> >for the id field in the message map?
>>
>> That's the wrong approach. Your combobox should use its own ID in messages
>> it sends to its parent, replacing the editbox ID in messages it forwards.
>
>But that is exactly what I'm doing (see above.) But the Combo Box has to
>get a message from
>its subclassed CEnterEdit box so that it can "do its thing," and send the
>appropriate message up
>another level. I'm not using edit_control_id in the message the Combo Box
>is setting. I'm using
>it in the CEnterEdit control to send a message to the Combo Box. But then
>the Combo Box has
>to receive that message. So it needs an entry in its message map. That's
>the one in question.
>Apparently I can't stick edit_control_id as the id field of ON_CONTROL.
>What DO I do?

Beyond dumping WM_COMMAND as described above, I'm not sure. You definitely
do not need to change the combobox's embedded editbox control ID. I would
imagine your editbox class would do something like the following to send the
message to its parent:

GetParent()->SendMessage(EDIT_COMPLETE, GetDlgCtrlID(), extra_info);

The parent (combobox) would have a message map entry:

ON_REGISTERED_MESSAGE(EDIT_COMPLETE, OnEditComplete)

and handler:

LRESULT MyComboBox::OnEditComplete(WPARAM wp, LPARAM lp)
{
// wp holds the control ID; nothing really to do with it
return GetParent()->SendMessage(
EDIT_COMPLETE,
GetDlgCtrlID(),
extra_info);
}

And finally the dialog class would have a message map entry and handler very
much like the combobox's, except it wouldn't forward the message, of course,
and it would inspect wp to determine which control sent the message. You
could also pass the HWND instead of or in addition to the control ID if
that's more convenient.

0 new messages