Find the Focused Control When Tab Moves Focus Out Of View

Author: Jeff Noble

While working on a recent project (using CAB) I found that I was able to cause the Tab key to switch focus to a control that was not within the viewable area. This can happen in several situations in windows programming as well as it being a problem in a CAB application (Composite UI Application Block). In CAB, you can use a deck workspace. Think of it as a deck of cards, where the view you are dealing with is on top. Well, now think about stacking decks within decks within decks, etc. Tabbing your view will run through the controls on that view, and then continue into the deck for some reason. This is bad mkay?

The problem is not setting the TabStop = false on the control, but rather; finding the offending control so that you can add that code to it. If the control is not on the screen, you wont see the focus rectangle around it — because it’s not on the screen. Imagine tabbing from control to control to control to nothing. If you continue hitting the tab key, you will eventually come back to the first control in the Tabindex, but how can we find which control has the focus at any given time?

I came up with two approaches. The first one sounded good, but didnt work for me.

What didnt work

I added a timer to my control, and a button and a label. The idea was that I could click the button to turn on the timer. When the timer fired, I could loop all of the controls (except labels which cant get focus). I would then test if it was the control that currently had focus. Well, I quickly figured out that controls have child controls, so I created a recursive method that would walk the tree of controls. This worked as expected … well almost. Here is the code, can you spot the problem?

private void timer1_Tick1(object sender, EventArgs e)
{
timer1.Enabled = false;
FocusedControlRecursive();
timer1.Enabled = true;
}

private void FocusedControlRecursive()
{
foreach (object control in Controls)
{
if (control is Control)
{
FocusedControlRecursive((Control)control);
}
}

}
private void FocusedControlRecursive(Control control)
{
if (control.HasChildren)
{
foreach (Control ctrl in control.Controls)
{
if(!(ctrl is Label))
{
FocusedControlRecursive(ctrl);
}
}
}

if (control.Focused)
{
label1.Text = “Ctrl: ” + control.Name;
}
}

The problem is that the controls in my case were not children of the current control, but rather they existed in another “slice” of the deck workspace.

The Solution

The solution was to create a control that I could drop onto a form that would report the currently focused control. Since the contro lmay not be within my children (or childrens children) I turned to an API call called GetFocus().

The pInvoke looks like this:

[DllImport("user32.dll")]
public static extern IntPtr GetFocus();

With the returned IntPtr, you can call the static method FromHandle() which returns a Control. The Focused Control!! Perfect.

I created a control you can drop onto your form and enable or disable. When enabled it calls the API every 2 seconds and gives you the control.Name of the focused control.

 Here is the code:

private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;

IntPtr pointer = GetFocus();
Control ctrl = this.FromHandle(pointer);
label1.Text = ctrl.Name;

timer1.Enabled = true;
}

-Savij

4 Responses to “Find the Focused Control When Tab Moves Focus Out Of View”

  1. af Says:

    But how do prevent the focus from leaving the viewable area and don’t continue to another vie in the deck?

  2. savij Says:

    af,

    You have to turn off the tab stops on things like the workspaces themselves. Use the code on this page to see what you are stopping on and I think you will be able to find it. You will not (at least should not) be able to tab to another view in the deck, BUT you can tab to things you cant see like the deck itself. Also, dont be afraid to set the tabstop in code even if you dont see the property, it might be there for you.

    -Savij

  3. af Says:

    Thanks Savij,
    I’ll use your code to investigate. I’ll turn tab stops off for all workspaces and views and any other control find – hopefully it will fix this problem.
    af

  4. Chris Holmes Online » Blog Archive » CAB: Handling Focus In Workspace Says:

    [...] Savij just blogged about a problem he had with tabbing through a CAB application and invoking logic on a control that was not being shown. This is a problem we ran into as well. He posts his solution here. [...]

Leave a Reply