Вверх ↑
Этот топик читают: Гость
Ответов: 3349
Рейтинг: 233
#1: 2011-06-16 20:45:09 ЛС | профиль | цитата
code_24404.txt
карма: 1

1
файлы: 1code_24404.txt [2.1KB] [580]
Голосовали:hitman249
vip
#1.1контекстная реклама от партнеров
Гость
Ответов: 17029
Рейтинг: 0
#2: 2011-06-16 21:50:49 правка | ЛС | профиль | цитата


Редактировалось 8 раз(а), последний 2021-06-21 04:15:41
карма: 0

0
Ответов: 3349
Рейтинг: 233
#3: 2011-06-17 06:39:20 ЛС | профиль | цитата
г. dendy писал(а):
можно без InlineCode

Нельзя. Твоя схема производит опрос клавиш, а мой IC устанавливает низкоуровневый хук на клавиатуру.
г. dendy писал(а):
нажатие (одиночное) и отпускание

Как раз там есть и нажатие и отпускание.
------------ Дoбавленo в 06.39:
Add(MainForm,13376086,147,203)
{
Point(onClose)
Point(onKeyDown)
link(onCreate,2317400:SetHook,[])
link(onClose,2317400:UnHook,[])
}
Add(InlineCode,2317400,189,217)
{
WorkPoints=#7:SetHook|6:UnHook|
EventPoints=#7:onKeyUp|9:onKeyDown|10:onSysKeyUp|12:onSysKeyDown|8:onRepeat|
Code=#15:unit HiAsmUnit;|0:|9:interface|0:|38:uses kol,Share,Debug,Windows,Messages;|0:|4:type|28: THiAsmClass = class(TDebug)|10: private|40: procedure onKey(param,code:integer);|9: public|65: onKeyUp,onKeyDown,onSysKeyUp,onSysKeyDown,onRepeat:THI_Event;|4: |46: procedure SetHook(var dt:TData; Idx:WORD);|45: procedure UnHook(var dt:TData; Idx:WORD);|5: end;|0:|14:implementation|0:|5:const|21: WH_KEYBOARD_LL = $D;|22: KBH_KEYREPEAT = $DD;|4:var |12: Hook:HHOOK;|45: ret:procedure(param,code:integer) of object;|0:|4:type|24: LLKBH_STRUCT = record|11: vkCode,|13: ScanCode,|10: Flags,|15: Time:DWORD;|23: dwExtraInfo:PDWORD;|7: end;|33: PLLKBH_STRUCT = ^LLKBH_STRUCT;|1: |28:var kbh_struct:LLKBH_STRUCT;|0:|82:function HookProc(Code: integer; wParam:integer;lParam: LongInt): HRESULT;stdcall;|21:var kbh:LLKBH_STRUCT;|5:begin|44: kbh:=LLKBH_STRUCT(PLLKBH_STRUCT(lParam)^); |122: if (kbh_struct.vkCode = 0) and (kbh_struct.ScanCode = 0) and (kbh_struct.Flags = 0) then ret(wParam,kbh_struct.vkCode); |44: if kbh.Flags <> kbh_struct.Flags then begin|37: kbh_struct:=PLLKBH_STRUCT(lParam)^; |31: ret(wParam,kbh_struct.vkCode);|51: end else ret(KBH_KEYREPEAT,kbh_struct.vkCode); |55: result := CallNextHookEx(Hook, Code, wParam , lParam);|4:end;|0:|30:procedure THiAsmClass.SetHook;|5:begin|25: with kbh_struct do begin|12: vkCode:=6;|14: ScanCode:=6;|11: Flags:=5;|5: end;|12: ret:=onKey;|64: Hook := SetWindowsHookEx(WH_KEYBOARD_LL,@HookProc,HInstance,0);|4:end;|0:|28:procedure THiAsmClass.onKey;|5:begin|16: Case Param of|45: WM_KEYDOWN :_hi_OnEvent(onKeyDown,code);|43: WM_KEYUP :_hi_OnEvent(onKeyUp,code);|48: WM_SYSKEYDOWN:_hi_OnEvent(onSysKeyDown,code);|46: WM_SYSKEYUP :_hi_OnEvent(onSysKeyUp,code);|44: KBH_KEYREPEAT:_hi_OnEvent(onRepeat,code);|9: end; |4:end;|0:|29:procedure THiAsmClass.UnHook;|5:begin|27: UnhookWindowsHookEx(Hook);|4:end;|0:|4:end.|
link(onKeyUp,3658577:doWork1,[])
link(onKeyDown,3658577:doWork2,[])
link(onSysKeyUp,3658577:doWork3,[])
link(onSysKeyDown,3658577:doWork4,[])
link(onRepeat,3658577:doWork5,[])
}
Add(ListBox,11565061,413,182)
{
Left=125
Top=35
Width=205
Height=180
}
Add(StrList,4095676,315,175)
{
Strings=#15:Опущена клавиша|14:Нажата клавиша|25:Опущена системная клавиша|24:Нажата системная клавиша|20:Удерживается клавиша|
Point(doGetString)
Point(onGetString)
link(onGetString,9575750:doString,[])
}
Add(ChanelToIndex,3658577,238,217)
{
Count=5
Point(Data)
link(onIndex,4095676:doGetString,[])
}
Add(FormatStr,9575750,357,182)
{
link(onFString,11565061:doAdd,[])
link(Str2,3658577:Data,[(370,170)(307,170)(307,261)(244,261)])
}
Теперь возможности идентичны KeyHook
карма: 1

4
Голосовали:Netspirit, 1nd1g0, andrestudio, filyaxxxcom
Ответов: 4612
Рейтинг: 746
#4: 2011-06-17 14:53:23 ЛС | профиль | цитата
А каким образом это работает? Ведь MSDN везде подчеркивает, что глобальные хуки должны ставиться в DLL?
------------ Дoбавленo в 14.38:
Видимо, потому, что WH_KEYBOARD_LL всегда глобальная
------------ Дoбавленo в 14.53:
И ещё интересно было бы поработать с RawInput.
Думаю, например, было бы возможно избегать эмуляции нажатий на клавиатуру в окно своей программы (при выдаче всяких NAG-скринов, проверке ввода серийника и т.п.), а также получать ввод от различных HID-устройств.
карма: 26

0
Ответов: 3889
Рейтинг: 362
#5: 2011-06-17 15:24:01 ЛС | профиль | цитата
Netspirit писал(а):
ввод от различных HID-устройств

Netspirit, глобальное обсуждение на тему, тогда же в ЛС с Nesco мы говорили и про RawInput. Но не хватило времени и желания.
------------ Дoбавленo в 15.20:
Netspirit писал(а):
А каким образом это работает? Ведь MSDN везде подчеркивает, что глобальные хуки должны ставиться в DLL?

Трюк заключается в том, что Callback для функций вида *_LL выполняется в контексте приложения, поставившего хук и работает через очередь сообщений (соответственно, в потоке должен быть прописан обработчик).
------------ Дoбавленo в 15.24:
Netspirit писал(а):
И ещё интересно было бы поработать с RawInput.

Равно как и с DirectInput.

Кстати, сам Microsoft рекомендует использовать RawInput вместо LL хуков (обе технологии работают на сообщениях, хотя RI экзотичнее, но значительно мощнее в умелых руках, кроме того, есть простейший метод случайноспециально заблокировать LL хуки в системе со всеми вытекающими). Лично меня очень интересует раздельный опрос нескольких однотипных средств ввода (две мышки, две клавиатуры на одном ПК без доп. фильтр. драйверов)

карма: 1

0
Ответов: 5227
Рейтинг: 585
#6: 2011-06-17 21:45:23 ЛС | профиль | цитата
1nd1g0 писал(а):
интересует раздельный опрос нескольких однотипных средств ввода (две мышки, две клавиатуры на одном ПК без доп. фильтр. драйверов
и ещё два рабочих стола с мониторами (причём разных марок и разрешения, а то иногда такой облом встать чтобы босу помочь )
карма: 4
Мой форум - http://hiasm.bbtalk.me/ схемы, компоненты...
0
Ответов: 3349
Рейтинг: 233
#7: 2011-06-17 22:01:03 ЛС | профиль | цитата
С RI не разу не работал, посмотрю может когда нибудь.
карма: 1

0
Ответов: 3889
Рейтинг: 362
#8: 2011-06-17 23:02:25 ЛС | профиль | цитата
andrestudio писал(а):
два рабочих стола с мониторами

Это уже пройденый этап, проверенный на практике (работали вдвоём, даже играть могли иногда), сейчас не редкость компьютер с двумя видеокартами, иили с двумя видеовыходами, доп. клавиатуры и мышки - вообще без проблем. Но требовало спец. драйверов-фильтров ввода (с новыми 64хбитными ОС это не есть хорошо дружить). Потом на тонких клиентов перешли, до 30 человек на одном ПК)

Тут ориентированность именно на одного человека там, где недопустимы блокировки клавиш из-за ограничений разводки клавиатур (ограничение на кол-во одновременных клавиш). Нужно много где, музыка, игра вдвоём, альтернативные интерфейсы (доп. клавиатура на внешних устройствах, например, для набора личного кода на проходной). Джойстики и т.п. само собой, тоже через RI при желании)

Ivann писал(а):
С RI не разу не работал, посмотрю может когда нибудь.

Страна не забудет своих героев)
карма: 1

0
Ответов: 3349
Рейтинг: 233
#9: 2011-06-19 09:58:55 ЛС | профиль | цитата
Первый эксперимент с RawInput.Перечисляет устройства
Add(MainForm,5093709,161,154)
{
Width=600
Height=437
link(onCreate,4674337:doEnum,[])
}
Add(InlineCode,4674337,210,168)
{
WorkPoints=#6:doEnum|
EventPoints=#8:onDevice|
Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses kol,Share,Debug,Windows;|0:|4:type|31: tagRAWINPUTDEVICELIST = record|18: hDevice:THandle;|15: dwType:DWORD;|5: end;|0:|32: tagRID_DEVICE_INFO_HID = record|22: dwVendorId: DWORD;|23: dwProductId: DWORD;|27: dwVersionNumber: DWORD;|22: usUsagePage: WORD;|18: usUsage: WORD;|6: end;|0:|37: tagRID_DEVICE_INFO_KEYBOARD = record|18: dwType: DWORD;|21: dwSubType: DWORD;|26: dwKeyboardMode: DWORD;|34: dwNumberOfFunctionKeys: DWORD;|32: dwNumberOfIndicators: DWORD;|31: dwNumberOfKeysTotal: DWORD;|7: end; |1: |34: tagRID_DEVICE_INFO_MOUSE = record|16: dwId: DWORD;|29: dwNumberOfButtons: DWORD;|24: dwSampleRate: DWORD;|7: end; |2: |52: RID_DEVICE_INFO_HID = tagRID_DEVICE_INFO_HID;|58: RID_DEVICE_INFO_KEYBOARD = tagRID_DEVICE_INFO_KEYBOARD; |54: RID_DEVICE_INFO_MOUSE = tagRID_DEVICE_INFO_MOUSE;|0:|28: tagRID_DEVICE_INFO = record|18: cbSize: DWORD;|18: dwType: DWORD;|19: case Integer of|38: 0: (mouse: RID_DEVICE_INFO_MOUSE);|44: 1: (keyboard: RID_DEVICE_INFO_KEYBOARD);|34: 2: (hid: RID_DEVICE_INFO_HID);|6: end;|38: RID_DEVICE_INFO = tagRID_DEVICE_INFO;|1: |45: TRAWINPUTDEVICELIST = tagRAWINPUTDEVICELIST;|44: PRAWINPUTDEVICELIST = ^TRAWINPUTDEVICELIST;|0:|78: TGetRawInputDeviceList = function (pRawInputDeviceList: PRAWINPUTDEVICELIST;|58: var puiNumDevices: UINT; cbSize: UINT): UINT; stdcall;|4: |87: TGetRawInputDeviceInfo = function (hDevice: THANDLE; uiCommand: UINT; pData: POINTER;|38: var pcbSize: UINT): UINT; stdcall;|0:|4:type|28: THiAsmClass = class(TDebug)|10: private|28: User32DllHandle:THandle;|49: GetRawInputDeviceList:TGetRawInputDeviceList;|52: RAWINPUTDEVICELIST:array of TRAWINPUTDEVICELIST;|49: GetRawInputDeviceInfo:TGetRawInputDeviceInfo;|9: public|23: onDevice:THI_Event;|3: |45: procedure doEnum(var dt:TData; idx:word);|5: end;|0:|14:implementation|0:|40:const USER32 = 'User32.DLL';|29: RIM_TYPEHID = 2;|29: RIM_TYPEKEYBOARD = 1;|29: RIM_TYPEMOUSE = 0;|37: RIDI_DEVICENAME = $20000007;|37: RIDI_DEVICEINFO = $2000000b;|37: RIDI_PREPARSEDDATA = $20000005;|0:|31:function IsWindowsNt():boolean;|33:var OSVersionInfo:TOSVersionInfo;|5:begin|15: Result:=false;|50: FillChar(OSVersionInfo,SizeOf(TOSVersionInfo),0);|61: OSVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);|29: GetVersionEx(OSVersionInfo);|69: result := OSVersionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT; |14: result:=true;|4:end;|0:|29:procedure THiAsmClass.doEnum;|13:var c,s:UINT;|14: i:integer;|33: n:array[0..1023] of AnsiChar;|17: t,name:TData;|5:begin|20: if IsWindowsNt then|7: begin|47: User32DllHandle := GetModuleHandle(USER32);|31: if User32DllHandle = 0 then|9: begin|45: User32DllHandle := LoadLibrary(USER32);|14: end; |87: @GetRawInputDeviceList := GetProcAddress(User32DllHandle, 'GetRawInputDeviceList');|88: @GetRawInputDeviceInfo := GetProcAddress(User32DllHandle, 'GetRawInputDeviceInfoA');|11: c := 0;|61: GetRawInputDeviceList(nil,c,SizeOf(TRAWINPUTDEVICELIST));|92: SetLength(RAWINPUTDEVICELIST,c); |80: GetRawInputDeviceList(@RAWINPUTDEVICELIST[0],c,SizeOf(TRAWINPUTDEVICELIST));|30: for i:=0 to c - 1 do begin|79: GetRawInputDeviceInfo(RAWINPUTDEVICELIST[i].hDevice,RIDI_DEVICENAME,@n,s);|41: case RAWINPUTDEVICELIST[i].dwType of|42: RIM_TYPEHID: dtString(t,'HID');|44: RIM_TYPEMOUSE: dtString(t,'MOUSE');|53: RIM_TYPEKEYBOARD: dtString(t,'KEYBOARD'); |9: end;|22: dtString(name,n);|22: t.ldata := @name;|29: _hi_OnEvent(onDevice,t);|8: end;|6: end;|4:end;|0:|4:end.|
link(onDevice,4274780:doStr,[])
}
Add(StringTable,12067686,322,168)
{
Top=25
Width=600
Height=375
Columns=#8:type=100|8:name=495|
}
Add(MT_String,4274780,266,168)
{
link(onResult,12067686:doAdd,[])
}


карма: 1

1
файлы: 1code_24419.txt [4KB] [483]
Голосовали:1nd1g0
Ответов: 3889
Рейтинг: 362
#10: 2011-06-19 13:02:29 ЛС | профиль | цитата
Ivann, хорошее начало, осталось научить программу оптимальному выбору среди дубликатов ,(например, PS2 тачпад и клавиатура на ноутбуке, по крайней мере, под NT6.x, прописались по двум путям, как корневые, и как ACPI. А складная USB клавиатура оказалась основанной на чипе, который заявляет себя как два устройства - клавиатура и нечто дополнительное)
Пример того, что число виртуальных устройств ввода может превышать число реальных
------------ Дoбавленo в 13.02:
Кстати, функция GetRawInputDeviceList - один из лучших примеров индийского кода, порождённого в Microsoft. При её использовании приходится помнить о некоторых подводных камнях, описанных тут. Теперь понятно, почему практическое использование RI встречается достаточно редко - надо быть либо очень внимательным и дотошным человеком, либо ... индусом.
карма: 1

0
Разработчик
Ответов: 26061
Рейтинг: 2120
#11: 2011-06-19 13:29:35 ЛС | профиль | цитата
1nd1g0 писал(а):
Теперь понятно, почему практическое использование RI встречается достаточно редко - надо быть либо очень внимательным и дотошным человеком, либо ... индусом.

Либо, тот кто писал этот API -- индус
карма: 22

0
Ответов: 5227
Рейтинг: 585
#12: 2011-06-19 13:47:21 ЛС | профиль | цитата
[flood]кстати индусы одни из самых продвинутых программистов считаются [/flood]
карма: 4
Мой форум - http://hiasm.bbtalk.me/ схемы, компоненты...
0
Разработчик
Ответов: 26061
Рейтинг: 2120
#13: 2011-06-19 14:23:13 ЛС | профиль | цитата
[flood]
andrestudio писал(а):
кстати индусы одни из самых продвинутых программистов считаются

Вот только не в области опимизации кодов. Хотя, наш Hiasm на стандартном пакете такой код лепит, что любой индус позавидует [/flood]
карма: 22

0
Ответов: 3349
Рейтинг: 233
#14: 2011-06-20 15:45:23 ЛС | профиль | цитата
Демонстрация работы RawInput в перехвате нажатий клавиш

Собственно схема с IC
code_24434.txt
И служебный юнит RInput(Поместить в папку %HiAsm%ElementsDelphiCode) c именем RInput.pas
code_24435.txt
карма: 1

3
файлы: 2code_24434.txt [2.6KB] [476], code_24435.txt [8.7KB] [998]
Голосовали:1nd1g0, ser_davkin, login
Ответов: 3889
Рейтинг: 362
#15: 2011-06-20 16:27:25 ЛС | профиль | цитата
Ivann, молодец, пока не могу проверить, будет возможность, погоняю под WOW64 на двух клавиатурах, отличать нажатия на первой и второй. То же с мышками и джойстиками всякими.
карма: 1

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)