How to detect the changing of ActiveControl property on a winform?

N

nano2k

Each form has its ActiveControl property, but no ActiveControlChanged
event to signal that the active control has changed (like
ParentChanged event).
I tried to trick the form by declaring this property in my form:

public new Control ActiveControl {
get{ return base.ActiveControl; }
set{ base.ActiveControl = value; }
}

but the execution won't at the breakpoint defined on "set" method of
the property.
This means that the code is never executed.

Maybe some workarounds exist, like handling the Enter event on ALL
controls of my form, but it's not a solution for me.

Any idea?
Thanks.
 
N

Nicholas Paldino [.NET/C# MVP]

I would create an implementation of IMessageFilter and register it with
the Application class (through the AddMessageFilter method). In it, I would
look for the WM_SETFOCUS and WM_KILLFOCUS windows messages. They will
basically tell you when the focus shifts from control to control (you will
have to look at the window handles, but that's not too hard).
 
P

Peter Duniho

Each form has its ActiveControl property, but no ActiveControlChanged
event to signal that the active control has changed (like
ParentChanged event).
I tried to trick the form by declaring this property in my form:

public new Control ActiveControl {
get{ return base.ActiveControl; }
set{ base.ActiveControl = value; }
}

but the execution won't at the breakpoint defined on "set" method of
the property.
This means that the code is never executed.

There are two issues here. One is that the property isn't a virtual
property, and so all you are doing is hiding the original version (thus
the "new" instead of "override"). The only way your version would be
called is if it were used from code that knows about your Form-derived
type.

The other is that the property isn't likely to change as a result of
setting. I haven't looked at the implementation, but my guess is that the
property maps directly (or nearly so) to the native Win32 API GetFocus()
and SetFocus() methods. The underlying control implementation isn't going
to go through the property to change the focus; all that happens at a much
lower level.

So even if you could override the property, it's not likely you'd ever see
the setter called for normal focus changes.
Maybe some workarounds exist, like handling the Enter event on ALL
controls of my form, but it's not a solution for me.

Why not? Unfortunately, it's likely to be your only practical option.
The basic issue is that not even the underlying native Win32 API provides
a window-level notification of focus changes, at least not specifically.
I think if you really want a notification-style implementation of this,
you'll have to dive into hooking the window messages (see
http://msdn2.microsoft.com/en-us/library/ms644990.aspx)

For a pure .NET implementation, I suppose you could add a Timer to your
form with some reasonable interval (100-500 milliseconds, for example) and
check the current focus with each tick, maintaining your own current
state. But there are obvious problems with something like that.

Pete
 
P

Peter Duniho

[...]
Why not? Unfortunately, it's likely to be your only practical option.
The basic issue is that not even the underlying native Win32 API
provides a window-level notification of focus changes, at least not
specifically. I think if you really want a notification-style
implementation of this, you'll have to dive into hooking the window
messages (see http://msdn2.microsoft.com/en-us/library/ms644990.aspx)

Okay...I didn't know about the Application.AddMessageFilter() method.
Looks like there's a .NET version of window hooks after all, per
Nicholas's reply. :)

Pete
 

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