Ключевое слово extern
информирует компилятор о том, что функция или переменная имеет внешнюю связь - другими словами, она видна из файлов, отличных от тех, в которых она определена. В этом смысле ключевое слово static
имеет противоположный смысл. Немного странно ставить extern
во время определения, поскольку никакие другие файлы не будут иметь видимость определения (или это приведет к нескольким определениям). Обычно вы помещаете extern
в объявление в какой-то момент с внешней видимостью (например, файл заголовка) и помещаете определение в другое место.
Если у Вас уже есть другие вызовы к Windows API, нет никакого вреда в использовании решения Peters. Но я понимаю Ваше беспокойство об этом и склонялся бы к аналогичному решению как Ваши, использующий только технические возможности Платформы. В конце концов, различие в производительности (если существует один) не должно быть значительным.
я проявил бы не рекурсивный подход:
public static Control FindFocusedControl(Control control)
{
var container = control as IContainerControl;
while (container != null)
{
control = container.ActiveControl;
container = control as IContainerControl;
}
return control;
}
При выполнении до конца ActiveControl рекурсивно, он не берет Вас к листовому управлению, которое фокусируется?
После поиска Интернета я нашел следующий Windows Forms FAQ
George Shepherd, который.Net библиотеки платформы не предоставляют Вам API для запросов для сфокусированного Управления. Необходимо вызвать окна API, чтобы сделать так:
[C#]
public class MyForm : Form
{
[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)]
internal static extern IntPtr GetFocus();
private Control GetFocusedControl()
{
Control focusedControl = null;
// To get hold of the focused control:
IntPtr focusedHandle = GetFocus();
if(focusedHandle != IntPtr.Zero)
// Note that if the focused Control is not a .Net control, then this will return null.
focusedControl = Control.FromHandle(focusedHandle);
return focusedControl;
}
}
Решение Hinek мне подходит, за исключением того, что это ContainerControl , а не ControlContainer. (На случай, если вы почесали голову из-за этой красной волнистой линии.)
public static Control FindFocusedControl(Control control)
{
ContainerControl container = control as ContainerControl;
while (container != null)
{
control = container.ActiveControl;
container = control as ContainerControl;
}
return control;
}
ActiveControl в форме или контейнере будет возвращать активный элемент управления этой сущности, независимо от того, насколько глубоко он может быть вложен в другие контейнеры.
В вашем примере, если TextBox имеет Фокус: затем: для Form, TableLayoutPanel и FlowLayoutPanel: свойство ActiveControl всех из них будет TextBox!
Некоторые, но не все, «настоящие» типы ContainerControl ... например, Form и UserControl ... раскрывают ключевые события (в случае формы: только если Form.KeyPreview == true можно использовать).
Другие элементы управления, которые по своей конструкции содержат другие элементы управления, такие как TableLayOutPanel, GroupBox, Panel, FlowLayoutPanel и т. Д., Относятся к не типу ContainerControl и не предоставляют KeyEvents. , которого нет в самой Форме ... обычного неконтейнерного Элемент управления вложен на несколько произвольных уровней глубоко ... вы можете использовать некоторые из идей в ответ: но код можно значительно упростить.
Обычные элементы управления, элементы управления контейнерами, элементы управления пользователями и т. д. (но не формы!) все имеют свойство «Контейнер», к которому вы можете получить доступ, чтобы получить их непосредственный контейнер, но убедитесь, что у вас есть последний Контейнер в их пути наследования, не являющийся формой, требует некоторого кода для "обхода" дерева наследования, которое демонстрируется здесь.
Вы также можете проверить свойство HasChildren элемента управления, которое обычно полезен при решении проблем Focus, ActiveControl и Select в WinForms. Здесь может быть полезно изучить разницу между Select и Focus,