Отображение рамок фокуса
В одном проекте для платформы .NET мне понадобилось принудительно отобразить рамки фокуса (они бывают у контролов Button
, RadioBox
, CheckBox
). При разработке приложений, которые в большинстве своем управляются с клавиатуры иногда бывает просто необходимо за кратчайшее время знать, на каком контроле находится текущий фокус. У кнопок, например, фокус может отображаться в двух состояниях:
На самом деле, Windows настроена так, чтобы автоматом включать режим отображения рамок по клавише TAB. Но у меня возникла проблема. Переходы надо было осуществлять по кнопке Enter и в форме, на которой куча контролов, было легко заблудиться без рамок фокуса.
Как оказалось, без использования Windows API обойтись было нельзя. Поэтому после некоторого поиска в гугле, я натолкнулся на описание сообщения WM_UPDATEUISTATE
, которое, как раз и отвечает за состояние контролов в окне. После родился следующий код:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public static IntPtr MakeLong(short lowPart, short highPart) {
return (IntPtr)(((ushort) lowPart) | (uint)(highPart << 16));
}
public static void ShowFocusCues(IntPtr Handle) {
const uint WM_UPDATEUISTATE = 0x0128;
//short UIS_SET = 1;
short UIS_CLEAR = 2;
//short UIS_INITIALIZE = 3;
short UISF_HIDEFOCUS = 0x1;
//short UISF_HIDEACCEL = 0x2;
//short UISF_ACTIVE = 0x4;
Common.SendMessage(Handle, WM_UPDATEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), (IntPtr) 0);
}
Используя функцию ShowFocusCues(this.Handle)
с параметром, указывающим на хендл активного окна, мы можем сменить режим отображения контролов на тот, что и требуется. То есть, принудительно отобразить рамки фокуса. Хендл окна описан в классе Form
.
Также, если понадобится принудительно спрятать рамки фокуса, то можно использовать немного иную реализацию отправки сообщения WM_UPDATEUISTATE
:
public static void HideFocusCues(IntPtr Handle) {
const uint WM_UPDATEUISTATE = 0x0128;
short UIS_SET = 1;
//short UIS_CLEAR = 2;
//short UIS_INITIALIZE = 3;
short UISF_HIDEFOCUS = 0x1;
//short UISF_HIDEACCEL = 0x2;
//short UISF_ACTIVE = 0x4;
SendMessage(Handle, WM_UPDATEUISTATE, MakeLong(UIS_SET, UISF_HIDEFOCUS), (IntPtr) 0);
}