Помощь - Поиск - Пользователи - Календарь
Полная версия: Кнопки WinAPI
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
TarasBer
Созднаю кнопку со стилем ws_Child or ws_Visible or bs_PushButton or ws_TabStop и заголовком &A
Буква подчёркивается, но реакции на альт+А нету. Если создать две кнопки, то переключатель по таб между ними не работает. Горячие клавиши реализуются системой, или надо самому их отдельно регистрировать?
volvo
Цитата
Если создать две кнопки, то переключатель по таб между ними не работает.
WM_TABSTOP работает в диалоговых окнах, то есть, если у родителя существует функция диалогового окна (а это совсем не то же самое, что простая функция окна) и присутствует (у родителя же) стиль WS_EX_CONTROLPARENT...
TarasBer
Так что мне делать для того, чтобы кнопки срабатывали от клавиатуры? RegisterHotKey и всё?
volvo
Можно - RegisterHotKey (это добавит данную комбинацию для всей системы). Если этого не хочется, а хочется - только когда свое приложение активно - можно создать файл ресурсов (*.RC), в нем описать ресурс типа ACCELERATORS, в котором перечислить все нужные горячие клавиши и связанные с ними сообщения, а в программе чуть-чуть изменить основной цикл обработки сообщений:
var hAccel: THandle;
// ...
hAccel := LoadAccelerators(hInstance, 'Accels'); // Accels - название таблицы акселераторов в RC-файле
while GetMessage (Msg, 0, 0, 0) do
if TranslateAccelerator(handleWnd, hAccel, Msg) = 0 then // Вот для чего все это делается
begin
TranslateMessage (Msg);
DispatchMessage (Msg);
end;
TarasBer
Но в глубине души эти акселлераторы всё равно являются хоткеями, которые каждый раз все регистрируются/разрегестрировываются в ответ на wm_Activate?
volvo
Ничего не регистрируется/разрегистрируется.

Для обработке Хоткея Windows проделывает дополнительную работу, и всем приложениям, установившим этот хоткей в очередь сообщений назначенного RegisterHotKey-ем приложения пишет WM_HOTKEY всегда, независимо от того активно это приложение или нет.

А если приложение, ждущее акселератор, активно - то код нажатой клавиши кроме всего прочего поступает в очередь сообщений этого приложения, и естественно обрабатывается TranslateAccelerator-ом. Если НЕактивно - то код нажатой клавиши в очередь не пишется.
TarasBer
> if TranslateAccelerator(handleWnd, hAccel, Msg) = 0

А тут в качестве handleWnd должно быть активное окно или главное? И тогда для каждого окна проекта нужна своя таблица акселераторов?
volvo
Цитата
для каждого окна проекта нужна своя таблица акселераторов?
Да. Техника описана у MS: How To Manage Per-Window Accelerator Tables

( для случая MDI-интерфейса существует также Функция TranslateMDISysAccel )
TarasBer
На пункты меню действует, на bs_PushButton - тоже, а вот на bs_AutoRadioButton - нет. Что делать?
volvo
В функции окна прописано, что при получении соответствующего сообщения надо включить AutoRadioButton?

TranslateAccelerator не занимается обработкой сообщений, он только переводит код нажатой клавиши в сообщение WM_COMMAND. Там его и надо обрабатывать...
TarasBer
> В функции окна прописано, что при получении соответствующего сообщения надо включить AutoRadioButton?

Не написано. Написал, заработало. Вот только как сделать, чтобы остальные элементы радиогруппы выключились? Я это сделал через ж
SendMessage(H, wm_LButtonDown, 0, 0);
SendMessage(H, wm_LButtonUp, 0, 0);
А как сделать нормально?
TarasBer
А, всё, сообщение bm_Click можно послать. Оно вроде не приводит к рекурсивной обработке wm_Comand?
volvo
Если создавать радио-кнопки так:
  (*
WS_GROUP - значит, началась новая группа радио-кнопок. Все последующие
AUTORADIOBUTTON-ы будут добавляться именно в эту группу. Нужна еще одна -
при создании первой кнопки, которая будет в новой группе, надо опять указать
WS_GROUP
*)
hRBtn_1 := CreateWindowEx(0, 'BUTTON', 'Опция &0',
WS_GROUP or BS_AUTORADIOBUTTON or WS_VISIBLE or WS_CHILD,
15, 132, 95, 25, handleWnd, RBTN_0, hInstance, nil);
hRBtn_2 := CreateWindowEx(0, 'BUTTON', 'Опция &1',
BS_AUTORADIOBUTTON or WS_VISIBLE or WS_CHILD,
15, 154, 155, 25, handleWnd, RBTN_1, hInstance, nil);
hRBtn_3 := CreateWindowEx(0, 'BUTTON', 'Опция &2',
BS_AUTORADIOBUTTON or WS_VISIBLE or WS_CHILD,
15, 176, 155, 25, handleWnd, RBTN_2, hInstance, nil);
CheckRadioButton(handleWnd, RBTN_0, RBTN_2, RBTN_0); // включаем любую кнопку в группе


, а WM_COMMAND обрабатывать так:
  case AMessage of
WM_COMMAND:
begin
case LoWord(WParam) of
RBTN_0 .. RBTN_2: // Смотрим только одну группу. Если есть еще одна - отдельно
begin
// В группе включить нужную. Естественно, остальные выключатся
CheckRadioButton(Window, RBTN_0, RBTN_2, LoWord(WParam));
end;
end

, то не надо никакой эмуляции нажатия на кнопку мыши. Радио-кнопки они на то и радио, что в одной группе может быть одновременно выбрана только одна такая кнопка...
TarasBer
> Если создавать радио-кнопки так:

Ну я так и делал.

> // Смотрим только одну группу. Если есть еще одна - отдельно

Каждую группу отдельно?
Мышкой сэмулировать проще... К тому же позволяет, ничего не меняя, вешать хоткеи на что угодно, например, на поля ввода.
volvo
Цитата
Мышкой сэмулировать проще...
Проще - не всегда правильнее... Дело твое, хочешь потом ловить баги из-за того, что не играл по правилам ОС - лови. Я предпочитаю писать программы по-другому.

Цитата
К тому же позволяет, ничего не меняя, вешать хоткеи на что угодно, например, на поля ввода.
Угу, вон оно, уже позволило тебе словить отсутствие работоспособности. Продолжай в том же духе. Ничего не меняя, главное...

P.S.
Цитата
Я это сделал через ж
, но
Цитата
Мышкой сэмулировать проще...
А потом удивляются, что 90% кода в интернете - говно
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.