How do I subclass the EM_SETSEL message

M

Mark

Hello

I've got a combo box control on a form with its DropDownStyle set to
DropDown (so the user can still type in it).

The problem is when the user tabs to the combo box all the text is
highlighted in the Text Box (Edit class) part of the ComboBox, whereas I only
want certain text highlighted.

I've tried putting code in the CombBox Enter event to set the SelectionStart
and SelectionLength properties accordingly, but the ComboBox control seems to
reset these values after the Enter event to highlight all the text.

So I've used Spy++ and I can see that the Text Box (Edit class) part of the
combo box receives the EM_SETSEL message when the selection is being set.

Can someone please show me how I can subclass the EM_SETSEL message on the
ComboBox control and cancel it, so all the text doesn't get selected?

I'm using VS2005.

Many thanks
 
P

Peter Duniho

[...]
Can someone please show me how I can subclass the EM_SETSEL message on
the
ComboBox control and cancel it, so all the text doesn't get selected?

You need to do it the managed-but-unmanaged way, via a override of the
WndProc() method.

Most of the .NET Forms controls are thin wrappers over the unmanaged
Windows controls. This means that they don't actually go through any of
the .NET API as they implement their own functionality; those are simply
exposed at the end of an operation, so you can only layer behavior on top
of the control, rather than changing what it does.

If you want to change what it does, you need to get down to the window
message level, which is what overriding the WndProc() method will do.

Pete
 
M

Mark

I've tried to add code into the overridden WinProc method to detect
EM_SETSEL, but it never gets received. I've also added code to detect
CB_SETEDITSEL, but that doesn't get received either.

I've "Message Logged" both the EM_SETSEL message on the Edit Field part of
the combo box and the CB_SETEDITSEL message on the Combo Box itself. The
CB_SETEDOTSEL and EM_SETSEL messages are received when I set the ComboBox
SelectionStart and SelectionLength properties in the Enter event of the
ComboBox, but when the ComboBox itself selects all the text (after the Enter
event), the EM_SETSEL is just received.

How can I stop the ComboBox selecting all the text in the Edit Field after
it gets focus? Is it possible to subclass the EM_SETSEL on the Edit Field
part of the ComboBox?

Thanks for your help.

Peter Duniho said:
[...]
Can someone please show me how I can subclass the EM_SETSEL message on
the
ComboBox control and cancel it, so all the text doesn't get selected?

You need to do it the managed-but-unmanaged way, via a override of the
WndProc() method.

Most of the .NET Forms controls are thin wrappers over the unmanaged
Windows controls. This means that they don't actually go through any of
the .NET API as they implement their own functionality; those are simply
exposed at the end of an operation, so you can only layer behavior on top
of the control, rather than changing what it does.

If you want to change what it does, you need to get down to the window
message level, which is what overriding the WndProc() method will do.

Pete
 
M

Mark

Sorry. Forgot to say I "Message Logged" the messages using Spy++.

Mark said:
I've tried to add code into the overridden WinProc method to detect
EM_SETSEL, but it never gets received. I've also added code to detect
CB_SETEDITSEL, but that doesn't get received either.

I've "Message Logged" both the EM_SETSEL message on the Edit Field part of
the combo box and the CB_SETEDITSEL message on the Combo Box itself. The
CB_SETEDOTSEL and EM_SETSEL messages are received when I set the ComboBox
SelectionStart and SelectionLength properties in the Enter event of the
ComboBox, but when the ComboBox itself selects all the text (after the Enter
event), the EM_SETSEL is just received.

How can I stop the ComboBox selecting all the text in the Edit Field after
it gets focus? Is it possible to subclass the EM_SETSEL on the Edit Field
part of the ComboBox?

Thanks for your help.

Peter Duniho said:
[...]
Can someone please show me how I can subclass the EM_SETSEL message on
the
ComboBox control and cancel it, so all the text doesn't get selected?

You need to do it the managed-but-unmanaged way, via a override of the
WndProc() method.

Most of the .NET Forms controls are thin wrappers over the unmanaged
Windows controls. This means that they don't actually go through any of
the .NET API as they implement their own functionality; those are simply
exposed at the end of an operation, so you can only layer behavior on top
of the control, rather than changing what it does.

If you want to change what it does, you need to get down to the window
message level, which is what overriding the WndProc() method will do.

Pete
 
C

Claes Bergefall

You're going to have a hard time getting access to the editbox part of the
combobox.
Try this instead:

comboBox1.BeginInvoke(new MethodInvoker(delegate {
comboBox1.SelectionLength = 0;
comboBox1.SelectionStart = 0;
}));

What it does is simply delaying the unselect until the combobox is done with
all its own stuff. BeginInvoke uses PostMessage to post a message to the end
of its own queue, meaning that once your code runs all the normal processing
that the combobox does in response to focus (such as selecting the text) is
already done.

/claes
 
M

Mark

Cool. That did the trick.
I can now select the text I want in the EditBox part of the ComboBox when it
gets focus.

One small problem is that there's a little flicker when the ComboBox selects
all the text, and then my code selects the correct text.

Is there any way to stop the flicker?

Use the WindowUpdate API maybe, or is there a better way?

Thanks for your help
 
P

Peter Duniho

I've tried to add code into the overridden WinProc method to detect
EM_SETSEL, but it never gets received. I've also added code to detect
CB_SETEDITSEL, but that doesn't get received either.

[...]
How can I stop the ComboBox selecting all the text in the Edit Field
after
it gets focus? Is it possible to subclass the EM_SETSEL on the Edit Field
part of the ComboBox?

I'm not really sure, actually, that you can do this with managed code. I
wasn't paying enough attention and overlooked that this is a ComboBox.
That is, something that's itself a composite control. As far as I recall,
the underlying controls contained by the ComboBox aren't exposed via
..NET. You'd have to get at them through unmanaged code, intercepting
their window messages that way.

One alternative that unfortunately I'm not really that familiar with is to
use a window message hook, so that you're watching messages globally. I
seem to recall a managed "message filter" class that allows you to do
this. I'm sorry that I don't remember the specifics off the top of my
head, but see the Application.AddMessageFilter() method and the
IMessageFilter interface. Maybe that will help.

Pete
 
C

Claes Bergefall

Not sure actaully. You could try the WM_SETREDRAW message or the
LockWindowUpdate function. I don't think there are any .NET versions of
these so you'll have to P/Invoke them.

/claes
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top