СообЧа > База Знаний > Программирование > Delphi

Вопрос

Как установить комбинацию клавиш для команды и процедуры?

Ответ

Здесь можно предложить несколько вариантов:
1. Большинство «логически законченных» программ имеют главное меню. Итак, добавляете главное меню (палитра Standard — MainMenu) Так вот: каждый пункт главного меню имеет свойство ShortCut — это ни что иное как горячая клавиша. Если не знаете как работать с главным меню, смотрите в конце. В общем, добавляем пункт, допустим, «Закрыть Файл». Назначаем ему ShortCut «Ctrl+W». Делаем событие OnClick для этого пункта меню и пишем там код, который надо выполнить, например,
Close;
После этого и Ctrl+W, и Ctrl+Ц будут приводить к закрытию формы (или выполнению вашего кода).

Но на случай, если вы не захотите делать главное меню, существует второй вариант:
2. Обрабатываем событие OnKeyUp, т.к. оно содержит как параметр переменную Shift: TShiftState, которая даст нам информацию о нажатых системных клавишах:
— у формы есть параметр KeyPreview: делаете его True.
— пишете обработчик события ДЛЯ ФОРМЫ OnKeyUp:
if (key = vkkeyscan('w')) and (shift = [ssCtrl]) then close;
Здесь функция vkkeyscan возвращает код символа, переданного ей в качестве параметра. Нам это надо, т.к. параметр Key поступает к нам в «виде» типа Word, поэтому надо узнать код самого символа. Переменная Shift типа TShiftState является по сути множеством и может принимать значения:
(ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble)
Хоть одно значение, хоть два, хоть все вместе. Так мы и проверяем: если переменная представляет собой множество из одного элемента [ssCtrl], то значит была нажата клавиша Control. Например, если эта переменная равна [ssCtrl, ssShift], то были нажаты обе клавиши Control и Shift.
Естественно, вместо Close; можете поставить все, что хотите: свой оператор, вызов процедуры, операторные скобки begin..end и набор операторов между ними, …

3. Будем обрабатывать сообщения:
— в объявлении класса вашей формы (по умолчанию TForm1) в разделе private добавляете:
procedure ProcMess(var Msg: TWMKEYUP);
message WM_KEYUP;

этим мы определяем процедуру, которая будет реагировать на сообщение WM_KEYUP, т.е. отпущена клавиша
— в самой процедуре пишем (шаблон нам в этом случае не делают, поэтому в любом месте программы сами пишите следующее):
procedure TForm1.ProcMess(var Msg: TWMKEYUP);
begin
if (msg.CharCode = vkkeyscan('w')) then
if (getkeystate(vk_control) < 0) then
close; //или вызов вашей процедуры, или сама
//процедура
end;

Здесь функция vkkeyscan возвращает код символа, переданного ей в качестве параметра. Нам это надо, т.к. msg.CharCode поступает к нам в «виде» типа Word, поэтому надо узнать код самого символа.

Итак, если, допустим, «отжата» клавиша w, то при этом вычисляется следующее выражение:
getkeystate(vk_control) < 0
Здесь getkeystate — функция Windows API, которая возвращает состояние какой-либо клавиши. Нам надо состояние, например, клавиши Control, которая имеет код, содержащийся в константе vk_control. Также это может быть и Shift с кодом vk_shift. Вот на счет Alt ничего конкретного сказать не могу (ее код — vk_menu): она определяется как-то неправильно, точнее ее нажатие не всегда определяется, можете сами поэкспериментировать.

PS Вариант с получением кода буквы w также срабатывает и с буквой ц, т.е. не надо отдельно получать код буквы ц. И еще: всегда ставьте маленькие буквы в качестве параметра.

PPS Про меню:
— щелкайте дважды на палитре компонентов Standard по компоненту MainMenu — он появляется на форме
— дважды щелкайте уже по компоненту, появившемуся на форме — перед вами редактор главного меню и по умолчанию выделен первый раздел
— идете в Object Inspector и изменяете свойство Caption на, допустим, строку «Файл» — появляется (в редакторе) раздел с именем «Файл»
— щелкаете по этому разделу («Файл») — выпадает первый элемент, пока пустой
— щелкаете по этому пустому пункту и опять же изменяете свойство Caption на, допустим, «Закрыть»
— теперь если два раза щелкнуть на пунктике «Закрыть», то вы попадаете в редактор кода с готовым шаблоном для написания обработчика события OnClick для пункта «Закрыть» и пишите там все, что хотите

Герун Данил

ДЕЛАЕМ СЛЕДУЮЩЕЕ:

1. Запустить WinSight;
2. Зайти в его настройки: Меню Messages — Options …;
3. В окне настроек ВКЛючить галочку "Interpret Values", а "HEX Values" — ВЫКЛючить. Нажать OK! ;-);
4. Запустить программу-"пациента", которой мы хотим посылать комбинацию клавиш;
5. Выбрать в дереве процессов WinSight эту программу-"пациента" и тот ее объект, которому надо "посылать";
6. Включить WinSight в режим слежения: "Start!" и переключиться на программу-"пациента";
7. Активировать (если надо) нужный объект щелчком мыши и нажать требуемую комбинацию клавиш;
8. Должна выполниться та функция программы-"пациента", вызов которой мы хотим эмулировать программно;
9. Закрываем программу-"пациента" (не обязательно, можно свернуть ;-);
10. Переходим к WinSight и смотрим, какие сообщения он у нас поймал;
11. Если ничего нет (или нет того, что нужно), значит вы выбрали не тот процесс или объект программы.

Коли так, возвращайтесь к пункту 4 и делайте заново… Удачи…;

12. Если вы все-таки получили "какие то" сообщения и среди них попадаются слова WM_KEYDOWN,

значит, возможно, это то, что нужно… ;-);

13. Выбираем (визуально) участок сообщений, в котором содержатся сообщения WM_KEYDOWN

и/или WM_KEYUP. Например:

000160:00000710 {Internet Ex} WM_TIMER Dispatched id 4096 lpfn 00000000
000161:00000710 {Internet Ex} WM_NCHITTEST Sent (236,258)
+ 000162:00000710 {Internet Ex} WM_KEYDOWN Dispatched 11h 17d VK_CONTROL Scan 1Dh Down
000163:00000710 {Internet Ex} WM_NCHITTEST Sent (236,258)
+ 000164:00000710 {Internet Ex} WM_KEYDOWN Dispatched 46h 70d VK_F Scan 21h Down
+ 000165:00000710 {Internet Ex} WM_COMMAND Sent Accelerator 0043h 67d
+ 000166:00000710 {Internet Ex} WM_KEYUP Dispatched 46h 70d VK_F Scan 21h Up
000167:00000710 {Internet Ex} WM_TIMER Dispatched id 4096 lpfn 00000000
000168:00000710 {Internet Ex} wm_systimer Dispatched wp=0000FFFF lp=177F12DC

// Плюсами я мысленно пометил те сообщения, которые нужны (в моем случае) для эмуляции нажатия.

14. Отделите (мысленно) "мусор" от "нормальных", нужных сообщений (чтобы выбрать, можно прогнать процесс отслеживания сообщений несколько раз и сравнить полученные результаты)
15. Допустим Вы получили список "нужных" сообщений, повторяющихся всегда при нажатии комбинации:

000162:00000710 {Internet Ex} WM_KEYDOWN Dispatched 11h 17d VK_CONTROL Scan 1Dh Down
000164:00000710 {Internet Ex} WM_KEYDOWN Dispatched 46h 70d VK_F Scan 21h Down
000165:00000710 {Internet Ex} WM_COMMAND Sent Accelerator 0043h 67d
000166:00000710 {Internet Ex} WM_KEYUP Dispatched 46h 70d VK_F Scan 21h Up
16. Далее, нужно зайти в настройки WinSight: Меню Messages — Options …
17. В окне настроек ВЫКЛючить галочку "Interpret Values", а "HEX Values" — ВКЛючить. Нажать OK! ;-)

Ваши сообщения преобразуются в несколько другой вид:

000162:00000710 {Internet Ex} WM_KEYDOWN (10004X) Dispatched wp=00000011 lp=001D0001
000164:00000710 {Internet Ex} WM_KEYDOWN (10004X) Dispatched wp=00000046 lp=00210001
000165:00000710 {Internet Ex} WM_COMMAND (11104X) Sent wp=00010043 lp=00000000
000166:00000710 {Internet Ex} WM_KEYUP (10104X) Dispatched wp=00000046 lp=C0210001

18. А вот это, девочки и мальчики — уже и есть готовые команды! Надо только переписать в Дельфю!
19. Преобразуем в нормальный Дельфевый вид:

// Эмуляция нажатия CTRL+F. ( HWND — соответственно хендл объекта, которому будем посылать комбинацию)
// PostMessage применяется, если сообщение Dispatched (см. выше — перехваченные сообщения)
// SendMessage применяется, если сообщение Sent (см. выше — перехваченные сообщения)

PostMessage(HWND, WM_KEYDOWN, $00000011, $001D0001); // Эмулирует нажатие и задержку CTRL (Код-&H11)
PostMessage(HWND, WM_KEYDOWN, $00000046, $00210001); // Эмулирует нажатие клавиши F (Код-&H46)
SendMessage(HWND, WM_KEYDOWN, $00010043, $00000000); // Акселератор
PostMessage(HWND, WM_KEYUP, $00000046, $C0210001); // Эмулирует отпускание клавиши F (Код-&H46)

20. Вот собственно и все! Компилируйте, запускайте свою прогу, запускайте программу-"пациента" и проверяйте!
Если не работает, значит вы чего то не учли… Попробуйте еще поискать WinSight'ом… А у меня все работает!

BioHazard



Copyright © 2000-2004 Сообщество Чайников
Контактная информация