понедельник, 3 августа 2009 г.

Отображение рамок фокуса

В одном проекте для платформы .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);
}

Комментариев нет:

Отправить комментарий