IPB
ЛогинПароль:

> 

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Контрол Hot Key
сообщение
Сообщение #1


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Возникли проблемы. Ситуация такова: при создании главного окна я связываю с ним комбинацию горячих клавиш (RegisterHotKey), с которой ассоциирую идентификатор HotKeyTId. Но позже, я предоставляю юзеру возможность, в случае необходимости, изменить комбинацию, использую Hot Key контрол, создаваемого на отдельном PopUp окне. Когда ввод Hot Keys закончен, пользователю необходимо подтвердить его нажатием на кнопку (еще один контрол окна PopUp), после чего оконная функция PopUp'a считывает ввод Hot Key контрола, посылая ему сообщение HKM_GETHOTKEY. В ответ я получаю слово (Word), в котором хранятся флаги специальных клавиш (HiWord(word)), а также код виртуальной клавиши (LoWord(Word)), введенных юзером. Это слово я посылаю главному окну, которое, в свою очередь, снимает предыдущею комбинацию горячих клавиш с HotKeyTId (UnregisterHotKey ) и ставит новую, считанную с контрола. Проблема в том, что HiWord(word)) всегда возвращает 0... Из-за чего у меня возникает сомнение что HKM_GETHOTKEY сообщения корректно, в моем случае, и что вместо строки с Hot Key контрола оно возвращает комбинацию горячих клавиш, при которых этот контрол будет активен. Так ли это?

Сообщение отредактировано: Bokul -


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


В случае необходимости могу предоставит код...


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Если не брать во внимание PopUp окно, а заменить его нормальным родительским, то это выглядит примерно так:

{$mode ObjFpc}
uses windows;
Const MainWndClass='MainWindowClass';
HotKeyId=$2;
HotKeyControlId=$5;
ButtonControlId=$6;
Wm_ChangeHotKeys=Wm_User+2;
var MainWnd,HotKeysWnd,ButtonWnd:hWnd;
HotKeysFlags,HotKeysLetter:word;
buf:word;
function MainProc(Wnd:hWnd; Msg:cardinal; wparam,lparam:longint):longint; stdcall;
begin
result:=0;
case Msg of
Wm_Create:begin//создаем кнопку и HotKey контрол
HotKeysWnd:=CreateWindowEx(0,HotKey_Class,'Hot Keys',
Ws_Child or Ws_Visible,
2,5,
150,
20,
Wnd,
HotKeyControlId,
system.mainInstance,
nil);
ButtonWnd:=CreateWindowEx(0,'Button','Change',
Ws_Child or Ws_Visible,
2,35,
70,
20,
Wnd,
ButtonControlId,
system.mainInstance,
nil);
//почему-то перестало работать.
SendMessage(HotKeysWnd,HKM_SetHotKey,MakeWParam(HotKeysLetter,HotKeysFlags),0);
end;
Wm_Destroy:begin
PostQuitMessage(0);
end;
Wm_HotKey:case wParam of//если нас вызывает через горячие клавиши, то...
HotKeyId: MessageBox(0,PChar('Main function'),PChar('Hot Keys!!!'),Mb_Ok);
end;
Wm_Command: case LoWord(wParam) of
ButtonControlId:case HiWord(wParam) of//нажали на кнопку - сообщаем
Bn_Clicked:begin
buf:=SendMessage(HotKeysWnd,HKM_GetHotKey,0,0);
if buf=0 then writeln('Error');
writeln('Flags: ',HiWord(buf));//почему 0?
writeln('Letter: ',LoWord(buf),' = ',chr(LoWord(buf)));
SendMessage(Wnd,Wm_ChangeHotKeys,buf,0);
end;
end;
end;
Wm_ChangeHotKeys:begin//меняем Hot Keys...
writeln('Flags Received: ',HiWord(wParam));//почему 0?
writeln('Letter Received: ',LoWord(wParam),' = ',chr(LoWord(wParam)));
if not(UnregisterHotKey(wnd,HotKeyId)) then
writeln('Hot key unregistering error');
HotKeysFlags:=HiWord(wParam);
HotKeysLetter:=LoWord(wParam);
if not(RegisterHotKey(Wnd,HotKeyId,HotKeysFlags,HotKeysLetter)) then
writeln('Cannot register new keys combination');
MessageBox(0,PChar('Receive'),PChar('Message was received'),Mb_Ok);
end;
else result:=DefWindowProc(Wnd,Msg,wparam,lparam);
end;
end;

function RegisterMainWndClass(ClassName:PChar):boolean;
var WndClass:PWndClassEx;
begin
WndClass:=new(PWndClassEx);
with WndClass^ do
begin
cbSize:=sizeof(WndClassEx);
style := CS_DBLCLKS or CS_HREDRAW or
CS_OWNDC or CS_VREDRAW or Cs_ParentDc;
LpfnWndProc:=@MainProc;
cbClsExtra:=0;
cbWndExtra:=0;
hInstance:=System.HInstance;
hIcon:=LoadIcon(0,Idi_Asterisk);
hCursor:=LoadCursor(0,Idc_Arrow);
hbrBackground:=Color_BtnFace+1;
lpszMenuName:=nil;
lpszClassName:=ClassName;
hIconSm:=0;
end;
result:=RegisterClassEx(WndClass)<>0;
end;

function CreateMainWnd(ClassName:PChar):hWnd;
begin
result:=CreateWindowEx(WS_EX_APPWINDOW,
ClassName,
'',
Ws_Border or Ws_Caption or Ws_ClipCHildren or
Ws_OverlappedWindow or Ws_SizeBox or
Ws_Visible,
CW_USEDEFAULT, CW_USEDEFAULT,
200, 130,
0,
0,
HInstance,
nil
);
HotKeysFlags:=Mod_Control;
HotKeysLetter:=ord('L');
writeln('Init Flags: ',HotKeysFLags);
writeln('Init Letter: ',HotKeysLetter);
writeln;
RegisterHotKey(result,HotKeyId,HotKeysFlags,HotKeysLetter);
end;

var Msg:TMsg;
begin
RegisterMainWndClass(MainWndClass);
MainWnd:=CreateMainWnd(MainWndClass);
UpdateWindow(MainWnd);
ShowWindow(MainWnd,Sw_ShowNa);
while GetMessage(Msg,0,0,0) do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end.




Сообщение отредактировано: volvo -


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
вместо строки с Hot Key контрола оно возвращает комбинацию горячих клавиш, при которых этот контрол будет активен
А что ты ожидал, что к тебе вернется, при таком описании:
Цитата(Msdn: HKM_GETHOTKEY)
Gets the virtual key code and modifier flags of a hot key from a hot key control
? О какой строке вообще речь?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Я выразился не правильно, на самом деле я читаю все как надо... скорее всего.. smile.gif


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гость






Кстати, проблема у тебя может быть еще в том, что ты делаешь:
var buf: WORD;
buf:=SendMessage(HotKeysWnd,HKM_GetHotKey,0,0);

а надо
var buf: DWORD; // <--- или var buf: LRESULT
buf:=SendMessage(HotKeysWnd,HKM_GetHotKey,0,0);
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Спасибо, действительно ошибка, но после исправления программа работает все-равно не верно...


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Так... Моя ошибка - надо все-таки работать при Buf: Word... Смотри:

var  MainWnd,HotKeysWnd,ButtonWnd:hWnd;
HotKeysFlags,HotKeysLetter:word;
buf:word; // <--- Все верно, нас интересует только одно слово

function MainProc(Wnd:hWnd; Msg:UINT; wparam:WPARAM;lparam:LPARAM):INT_PTR; stdcall;
begin
result:=0;
case Msg of
Wm_Create:
begin
HotKeysWnd:=CreateWindowEx(
0, HotKey_Class,'Hot Keys',
Ws_Child or Ws_Visible,
2,5,
150,
20,
Wnd,
HotKeyControlId,
system.mainInstance,
nil
);
ButtonWnd:=CreateWindowEx(
0,'Button','Change',
Ws_Child or Ws_Visible,
2,35,
70,
20,
Wnd,
ButtonControlId,
system.mainInstance,
nil
);
SendMessage(HotKeysWnd, HKM_SetHotKey,
MakeWParam(HotKeysLetter,HotKeysFlags), 0);
end;

Wm_Destroy:
begin
PostQuitMessage(0);
end;

Wm_HotKey:
case wParam of
HotKeyId:
MessageBox(0,PChar('Main function'),PChar('Hot Keys!!!'),Mb_Ok);
end;

Wm_Command:
case LoWord(wParam) of
ButtonControlId:
case HiWord(wParam) of
Bn_Clicked:
begin
buf:=SendMessage(HotKeysWnd,HKM_GetHotKey,0,0);
if buf=0 then writeln('Error');
writeln('Flags: ',Hi(buf)); // MSDN: the modifier flags are in the high-order __byte__
writeln('Letter: ',Lo(buf),' = ',chr(Lo(buf))); // ... The virtual key code is in the low-order __byte__
SendMessage(Wnd,Wm_ChangeHotKeys,buf,0);
end;
end;
end;

Wm_ChangeHotKeys:
begin
writeln('Flags Received: ',Hi(loword(wParam)));
writeln('Letter Received: ',Lo(loWord(wParam)),' = ',chr(Lo(loWord(wParam))));
if not(UnregisterHotKey(wnd,HotKeyId))
then writeln('Hot key unregistering error');
HotKeysFlags:=HiWord(wParam);
HotKeysLetter:=LoWord(wParam);
if not(RegisterHotKey(Wnd,HotKeyId,HotKeysFlags,HotKeysLetter))
then writeln('Cannot register new keys combination');
MessageBox(0,PChar('Receive'),PChar('Message was received'),Mb_Ok);
end;

else
result:=DefWindowProc(Wnd,Msg,wparam,lparam);
end;
end;


Ключевое слово взято в двойное подчеркивание... Попробуй, это - то, что тебе надо?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Цитата
Попробуй, это - то, что тебе надо?

Премного благодарен! good.gif


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Потестил... рабочии комбинации только Сtrl'a + виртуальный код клавиши, другое - лягает... хотя все передается как положено.

Сообщение отредактировано: Bokul -


Прикрепленные файлы
Прикрепленный файл  test.pas ( 5.41 килобайт ) Кол-во скачиваний: 219


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гость






Проблема в следующем: описаны константы вот так

     MOD_ALT = 1;
MOD_CONTROL = 2;
MOD_SHIFT = 4;
MOD_WIN = 8;

, а посмотри, что у тебя передается, когда ты жмешь Alt+ ... ? У Control+ ... код совпадает, поэтому работает только Control. Почему - пока не понял.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






Так, ну все понятно... Какой-то умник решил, что возвращаемые по сообщению HKM_GETHOTKEY флаги должны быть "перевернутыми":
  { HKM_GETHOTKEY message  }
HOTKEYF_ALT = 4;
HOTKEYF_CONTROL = 2;
HOTKEYF_EXT = 8;
HOTKEYF_SHIFT = 1;

blink.gif

Придется делать так:

Var
modif: Word;
...

WM_COMMAND:
case LoWord(wParam) of
ButtonControlId:
case HiWord(wParam) of
BN_CLICKED:
begin
buf := SendMessage(HotKeysWnd, HKM_GETHOTKEY, 0, 0);
if buf = 0 then writeln('Error');

modif := $0000;
if (hi(buf) and HOTKEYF_ALT) = HOTKEYF_ALT then modif := modif or MOD_ALT;
if (hi(buf) and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then modif := modif or MOD_CONTROL;
if (hi(buf) and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then modif := modif or MOD_SHIFT;
if (hi(buf) and HOTKEYF_EXT) = HOTKEYF_EXT then modif := modif or MOD_WIN;


writeln('Flags: ', modif);
writeln('Letter: ',Lo(buf),' = ',chr(Lo(buf)));

buf := (modif shl 8) or (buf and $00FF);
SendMessage(Wnd, WM_CHANGEHOTKEYS,
MakeWParam(buf, 0), 0);
end;
end;
end;
...

Должно работать...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


В принципе я разобрался, но из-за неопытности с работой над числами логическими операциями переспрошу.

{ HKM_GETHOTKEY message }
HOTKEYF_ALT = 4;
HOTKEYF_CONTROL = 2;
HOTKEYF_EXT = 8;
HOTKEYF_SHIFT = 1;


Такие значения позволяют контролировать значение определенного бита в байте.
1=2^0-младший бит
2=2^1
4=2^2
8=2^3 - старший бит
А так как не надо больше чем указать использовалась ли данная клавиша или нет, одного байта хватает с головой для кодирования четырех.

if (hi(buf) and HOTKEYF_ALT) = HOTKEYF_ALT then modif := modif or MOD_ALT;
if (hi(buf) and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then modif := modif or MOD_CONTROL;
if (hi(buf) and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then modif := modif or MOD_SHIFT;
if (hi(buf) and HOTKEYF_EXT) = HOTKEYF_EXT then modif := modif or MOD_WIN;


Тут мы переворачиваем, как ты сказал, так как байт специальных клавиш (hi(buf)) упакован, используя другие константы для клавиш. Разберем один из этих переворотов:
if (hi(buf) and HOTKEYF_ALT) = HOTKEYF_ALT then modif := modif or MOD_ALT;

Допустим, что hi(buf)=1101 тогда при выполнении логического "и" с HOTKEYF_ALT=0100, над каждой парой битов произойдет эта операция, а в случае совпадения третьей - результат будет тем самым HOTKEYF_ALT, так как другие нули (false) и вернуть также нули. И-так, если результат операции совпал со значением HOTKEYF_ALT добавляем необходимый бит в байт операцией
modif or MOD_ALT


Ну и последние
buf := (modif shl 8) or (buf and $00FF);

Так как buf это слово, но высший байт которого заполнен неправильно, надо обнулить его buf and $00FF и записать туда нормальное значение modif, предварительно сделав его высшим байтом слова, сдвигом на 8 бит (один байт) (modif shl 8). Все. Так?

PS а откуда узнал что есть разные константы кодирующие одно и то же.

Сообщение отредактировано: Bokul -


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Цитата
Все. Так?
yes2.gif

Цитата
откуда узнал что есть разные константы кодирующие одно и то же.
Посмотрел здесь: HKM_GETHOTKEY Message, увидел, что есть константы HOTKEYF_..., однако у тебя используется:

Цитата
     HotKeysFlags:=Mod_Control; // <--- MOD_... 
HotKeysLetter:=ord('L');


Вот и стал смотреть в исходниках FPC, что за константы...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Бессмысленный смысл путаницы стал ясен: этим разработчики хотели подчеркнуть разницу между WM_SETHOTKEY и RegisterHotKey. ИМХО.
WM_SETHOTKEY:
Цитата

HOTKEYF_ALT: ALT key
HOTKEYF_CONTROL: CTRL key
HOTKEYF_EXT: Extended key
HOTKEYF_SHIFT: SHIFT key


RegisterHotKey

Цитата

MOD_ALTE: ither ALT key must be held down.
MOD_CONTROL: Either CTRL key must be held down.
MOD_SHIFT: Either SHIFT key must be held down.
MOD_WIN: Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo. Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.


PS

Var
modif: Word;


А можно поменять тип modif на byte?


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Гость






Цитата
А можно поменять тип modif на byte?
А зачем? Для экономии места, что-ли? smile.gif

Теоретически - емкости типа Byte хватит для хранения нужной информации, значит можно. Практически - нежелательно: не очень хорошо FPC работает с байтами, лучше работать с Word-ами или Integer-ами...

Кроме всего прочего, не забудь (если все-таки будешь менять на Byte), изменить и тут:
...
buf := (Word(modif) shl 8) or (buf and $00FF); // <--- !!!
...

, иначе все время modif после сдвига будет превращаться в 0.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Гуру
*****

Группа: Пользователи
Сообщений: 1 117
Пол: Мужской
Реальное имя: Богдан

Репутация: -  11  +


Цитата
Кроме всего прочего, не забудь (если все-таки будешь менять на Byte), изменить и тут:

Ради этого и спросил.. smile.gif
Цитата
иначе все время modif после сдвига будет превращаться в 0.

А будит ли так? Теоретически значение modif после сдвига действительно выйдет за пределы емкости byte, но практически - для нас зарезервировано больше одного байта, так что если компилятор не проверяет выход за границы, все должно работать и так... практически smile.gif


--------------------
Лао-Цзы :
Знать много и не выставлять себя знающим есть нравственная высота. Знать мало и выставлять себя знающим есть болезнь. Только понимая эту болезнь, мы можем избавиться от нее.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Гость






Практически? Не уверен, что делать вот так:
var modif: byte;
buf := (modif shl 8) or (buf and $00FF); // без приведения к Word
будет правильно...

А знаешь, почему? Потому, что оно конечно понятно, что под результат отводится размер переменной, равный максимальному из размеров переменных, участвующих в выражении. Только вот какая штука получается: если сначала вычислится вторая часть выражения, т.е., (buf and $00FF), и только потом будет выполняться первая - то все в порядке, тогда первая часть будет уже выполняться в поле из 16 бит, а нам больше и не надо... Но если сначала выполнится (modif shl 8), то оно еще будет выполняться в байтовой сетке, ведь размер modif и размер 8 - один байт, как результат: выражение (modif shl 8) = 0... А какая из частей выражения будет вычисляться первой - не знает никто:

Цитата(ref.pdf @ Chapter 8)
Remark: The order in which expressions of the same precedence are evaluated is not guaranteed to be left-to-right. In general, no assumptions on which expression is evaluated first should be made in such a case. The compiler will decide which expression to evaluate first based on optimization rules. Thus, in the following expression:
a := g(3) + f(2);
f(2) may be executed before g(3).


Если же сделать приведение к Word-у, то при любом раскладе результат будет корректным... Дело твое, выбирай - или сократить программу на 6 символов и получить возможность возникновения бага, или не делать этого... rolleyes.gif
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 23.09.2020 17:15
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name