Созднаю кнопку со стилем ws_Child or ws_Visible or bs_PushButton or ws_TabStop и заголовком &A Буква подчёркивается, но реакции на альт+А нету. Если создать две кнопки, то переключатель по таб между ними не работает. Горячие клавиши реализуются системой, или надо самому их отдельно регистрировать?
volvo
28.05.2010 14:44
Цитата
Если создать две кнопки, то переключатель по таб между ними не работает.
WM_TABSTOP работает в диалоговых окнах, то есть, если у родителя существует функция диалогового окна (а это совсем не то же самое, что простая функция окна) и присутствует (у родителя же) стиль WS_EX_CONTROLPARENT...
TarasBer
28.05.2010 15:07
Так что мне делать для того, чтобы кнопки срабатывали от клавиатуры? RegisterHotKey и всё?
volvo
28.05.2010 15:36
Можно - 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
28.05.2010 15:48
Но в глубине души эти акселлераторы всё равно являются хоткеями, которые каждый раз все регистрируются/разрегестрировываются в ответ на wm_Activate?
volvo
28.05.2010 16:51
Ничего не регистрируется/разрегистрируется.
Для обработке Хоткея Windows проделывает дополнительную работу, и всем приложениям, установившим этот хоткей в очередь сообщений назначенного RegisterHotKey-ем приложения пишет WM_HOTKEY всегда, независимо от того активно это приложение или нет.
А если приложение, ждущее акселератор, активно - то код нажатой клавиши кроме всего прочего поступает в очередь сообщений этого приложения, и естественно обрабатывается TranslateAccelerator-ом. Если НЕактивно - то код нажатой клавиши в очередь не пишется.
TarasBer
31.05.2010 14:34
> if TranslateAccelerator(handleWnd, hAccel, Msg) = 0
А тут в качестве handleWnd должно быть активное окно или главное? И тогда для каждого окна проекта нужна своя таблица акселераторов?
volvo
31.05.2010 15:23
Цитата
для каждого окна проекта нужна своя таблица акселераторов?
На пункты меню действует, на bs_PushButton - тоже, а вот на bs_AutoRadioButton - нет. Что делать?
volvo
31.05.2010 16:25
В функции окна прописано, что при получении соответствующего сообщения надо включить AutoRadioButton?
TranslateAccelerator не занимается обработкой сообщений, он только переводит код нажатой клавиши в сообщение WM_COMMAND. Там его и надо обрабатывать...
TarasBer
31.05.2010 17:03
> В функции окна прописано, что при получении соответствующего сообщения надо включить AutoRadioButton?
Не написано. Написал, заработало. Вот только как сделать, чтобы остальные элементы радиогруппы выключились? Я это сделал через ж SendMessage(H, wm_LButtonDown, 0, 0); SendMessage(H, wm_LButtonUp, 0, 0); А как сделать нормально?
TarasBer
31.05.2010 17:25
А, всё, сообщение bm_Click можно послать. Оно вроде не приводит к рекурсивной обработке wm_Comand?
volvo
31.05.2010 17:32
Если создавать радио-кнопки так:
(* 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
31.05.2010 17:39
> Если создавать радио-кнопки так:
Ну я так и делал.
> // Смотрим только одну группу. Если есть еще одна - отдельно
Каждую группу отдельно? Мышкой сэмулировать проще... К тому же позволяет, ничего не меняя, вешать хоткеи на что угодно, например, на поля ввода.
volvo
31.05.2010 17:51
Цитата
Мышкой сэмулировать проще...
Проще - не всегда правильнее... Дело твое, хочешь потом ловить баги из-за того, что не играл по правилам ОС - лови. Я предпочитаю писать программы по-другому.
Цитата
К тому же позволяет, ничего не меняя, вешать хоткеи на что угодно, например, на поля ввода.
Угу, вон оно, уже позволило тебе словить отсутствие работоспособности. Продолжай в том же духе. Ничего не меняя, главное...