
- •Глава 8 Дочерние окна управления
- •Класс кнопок
- •Создание дочерних окон
- •Сообщения дочерних окон родительскому окну
- •Сообщения родительского окна дочерним окнам
- •Нажимаемые кнопки
- •Переключатели
- •Окна группы
- •Изменение текста кнопки
- •Видимые и доступные кнопки
- •Кнопки и фокус ввода
- •Дочерние окна управления и цвета
- •Системные цвета
- •Цвета кнопок
- •Сообщение wm_ctlcolorbtn
- •Кнопки, определяемые пользователем
- •Класс статических дочерних окон
- •Класс полос прокрутки
- •Программа colors1
- •Интерфейс клавиатуры, поддерживаемый автоматически
- •Введение новой оконной процедуры
- •Закрашивание фона
- •Окрашивание полос прокрутки и статического текста
- •Класс редактирования
- •Стили класса редактирования
- •Коды уведомления управляющих окон редактирования
- •Использование управляющих окон редактирования
- •Сообщения управляющему окну редактирования
- •Класс окна списка
- •Стили окна списка
- •Добавление строк в окно списка
- •Выбор и извлечение элементов списка
- •Получение сообщений от окон списка
- •Простое приложение, использующее окно списка
- •Список файлов
- •Использование атрибутов файлов
- •Упорядочивание списков файлов
- •Утилита Head для Windows
Кнопки и фокус ввода
Как уже упоминалось в этой главе, нажимаемые кнопки, флажки, переключатели и кнопки, определяемые пользователем, получают фокус ввода при щелчке мыши на них. Признаком наличия фокуса ввода служит окружающая текст пунктирная линия. Когда дочерние окна управления получают фокус ввода, родительское окно теряет его; весь ввод с клавиатуры направлен теперь не на родительское окно, а на дочернее окно управления. Однако, дочернее окно управления реагирует только на клавишу <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, показанные здесь несколько кнопок выглядят не слишком привлекательно. Нажимаемые кнопки смотрятся неплохо, но остальные нарисованы в виде серого прямоугольника, которого здесь просто не должно быть. Так происходит потому, что кнопки предназначены для вывода на экран в окнах диалога, а окна диалога в Windows 95 имеют серую поверхность. Поверхность нашего окна белая, поскольку так мы определили ее в структуре WNDCLASS:
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
Мы это делали, поскольку часто занимались выводом текста в рабочую область, а GDI использует цвет текста и фона, которые определяются в задаваемом по умолчанию контексте устройства. Этими цветами всегда являются белый и черный. Чтобы кнопки выглядели привлекательней, мы должны либо изменить цвет рабочей области, согласовав его с цветом фона кнопок, либо как-то изменить цвет фона кнопок на белый.
Вначале необходимо понять, как Windows использует системные цвета (system colors).