Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WinAPI.docx
Скачиваний:
49
Добавлен:
16.12.2018
Размер:
3.43 Mб
Скачать

8.1.10 Кнопки и фокус ввода

Как уже упоминалось в этой главе, нажимаемые кнопки, флажки, переключатели и кнопки, определяемые пользователем, получают фокус ввода при щелчке мыши на них. Признаком наличия фокуса ввода служит окружающая текст пунктирная линия. Когда дочерние окна управления получают фокус ввода, родительское окно теряет его; весь ввод с клавиатуры направлен теперь не на родительское окно, а на дочернее окно управления. Однако, дочернее окно управления реагирует только на клавишу <Spacebar>, которая в этот момент действует аналогично мыши. Такая ситуация создает очевидную проблему: ваша программа теряет контроль над обработкой сообщений клавиатуры. Давайте посмотрим, что можно с этим сделать.

Как говорилось в главе 5, когда Windows переключает фокус ввода с одного окна (например, родительского) на другое (например, дочернее окно управления), она первым делом посылает сообщение WM_KILLFOCUS окну, теряющему фокус ввода. Параметр сообщения wParam является описателем окна, которое должно получить фокус ввода. Затем Windows посылает сообщение WM_SETFOCUS окну, получающему фокус ввода, при этом параметр сообщения wParam является описателем окна, которое теряет фокус ввода. (В обоих случаях, wParam может быть равен NULL, который показывает, что нет окна, которое имеет или получает фокус ввода.)

Родительское окно, обрабатывая сообщения WM_KILLFOCUS, может предотвратить получение фокуса ввода дочерним окном. Предположим, что массив hwndChild содержит описатели всех дочерних окон. (Которые были помещены в массив при создании окон с помощью вызовов функций CreateWindow.) Пусть NUM — это число дочерних окон, тогда:

case WM_KILLFOCUS:

for(i = 0; i < NUM; i++)

if(hwndChild[ i ] ==(HWND) wParam)

{

SetFocus(hwnd);

break;

}

return 0;

Этот фрагмент кода показывает, что, если родительское окно определяет, что его фокус ввода переходит к одному из дочерних окон управления, оно вызывает функцию SetFocus и восстанавливает фокус ввода на себя.

Далее представлен более простой (но менее очевидный) способ добиться того же самого:

case WM_KILLFOCUS:

if(hwnd == GetParent((HWND) wParam))

SetFocus(hwnd);

return 0;

Однако, оба эти метода имеют недостатки: они не дают кнопкам возможности реагировать на клавишу <Spacebar>, поскольку кнопки никогда не получают фокус ввода. Лучше было бы дать кнопкам возможность получить фокус ввода, но при этом и пользователю обеспечить возможность переходить от кнопки к кнопке с помощью клавиши <Tab>. На первый взгляд это кажется невозможным, но далее будет показано, как это сделать с помощью приема названного "window subclassing" (установка новой оконной процедуры) в программе COLORS1, представленной далее в этой главе.

8.2 Дочерние окна управления и цвета

Кнопки, созданные программой BTNLOOK, выглядят не слишком привлекательно. Нажимаемые кнопки смотрятся неплохо, но остальные нарисованы в виде серого прямоугольника, которого здесь просто не должно быть. Так происходит потому, что кнопки предназначены для вывода на экран в окнах диалога, а окна диалога в Windows имеют серую поверхность. Поверхность нашего окна белая, поскольку так мы определили ее в структуре WNDCLASS:

wndclass.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH);

Мы это делали, поскольку часто занимались выводом текста в рабочую область, а GDI использует цвет текста и фона, которые определяются в задаваемом по умолчанию контексте устройства. Этими цветами всегда являются белый и черный. Чтобы кнопки выглядели привлекательней, мы должны либо изменить цвет рабочей области, согласовав его с цветом фона кнопок, либо как-то изменить цвет фона кнопок на белый.

Вначале необходимо понять, как Windows использует системные цвета (system colors).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]