Перехоплення WM_INPUT всіх вікон
Мені необхідно визначити яка з двох мишок підключених до комп'ютера зараз активна, знайшов в інтернеті приклад роботи через RawInput. Програма чудово працює тільки коли вікно моєї програми активно, якщо перейти на інше вікно, програма перестає отримувати повідомлення від мишок (WM_INPUT). Мені необхідно отримувати повідомлення про активність миші (WM_INPUT) завжди, активно моє вікно чи ні. Як це реалізувати я не знаю ( Ось код програми :
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, RawInput_h, AppEvnts, StdCtrls, ExtCtrls;
const ENUMERATE_EXISTING_MICE=0; MAX_DEVICES=2; MAX_DEVICE > type TForm1 = class(TForm) Memo1: TMemo; ApplicationEvents1: TApplicationEvents; процес ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); procedure FormCreate(Sender: TObject); private < Private declarations > public < Public declarations > end;
type RAW_INPUT_DATA = record num_mice: integer; AMouseHandle: array[0..MAX_DEVICES] of THandle; AMouseID: array[0..MAX_DEVICES,0..MAX_DEVICEID_LEN] of Cardinal; dataBuf: Pointer; data_buf_size: WORD; end;
TMouse_Info=record mouse: integer; mouseData: ^RAWMOUSE; end;
const WM_INPUT = WM_KEYFIRST-1;
var Form1: TForm1; rid: RAW_INPUT_DATA; mInfo: TMouse_Info;
function FindMouseNum(hdevice:THandle):integer; var i,j,k: integer; DevName: array[0..MAX_DEVICEID_LEN] of Cardinal; max: cardinal; begin max:=2048; for i:=0 to rid.num_mice-1 do if r > begin if r > GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, @rid.AmouseID[i], max); result:=i; exit; end; GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, @DevName, max); for i:=0 to rid.num_mice-1 do begin k:=0; for j:=0 to MAX_DEVICEID_LEN do if DevName[j] = rid.AmouseID[i,j] then inc(k); якщо k >= MAX_DEVICEID_LEN, тоді початок r > результат:=i; вихід; кінець; кінець; якщо rid.num_mice r > r > результат:=rid.num_mice-1; вихід; кінець; результат:=-1; кінець;
procedure RawInputInit; var nDevices: Cardinal; pRawIn: PRAWINPUTDEVICELIST; hRawIn: масив [1..100] RAWINPUTDEVICELIST; rawInDev: RAWINPUTDEVICE; begin r > r > if GetRawInputDeviceList(nil, nDevices, sizeof(RAWINPUTDEVICELIST)) <> 0 потім showMessage("Помилка 1"); pRawIn:=нуль; pRawIn:=@hRawIn; if GetRawInputDeviceList(pRawIn, nDevices, sizeof(RAWINPUTDEVICELIST)) = -1 then showMessage("Error 2"); r > rawInDev.usUsagePage:=1; rawInDev.usUsage:=2; rawInDev.dwFlags:=0; rawInDev.hwndTarget:=0; RegisterRawInputDevices(@rawInDev,1,sizeOf(rawInDev)); end;
функція HandleWMInput(wnd:HWND; lPar:LPARAM):TMouse_Info; var Raw: RAWINPUT; dwSize: UINT; res: TMouse_Info; hRawIn: HRAWINPUT; pRawIn: PRAWINPUT; миша: ціле число; початок res.mouse:=-1; res.mouseData:=ніль; hRawIn:=lPar; GetRawInputData(hRawIn,RID_INPUT, nil, dwSize, sizeof(RAWINPUTHEADER)); якщо dwSize = 0, то showMessage("Неможливо виділити пам'ять"); Новий(pRawIn); якщо GetRawInputData(hRawIn,RID_INPUT,pRawIn,dwSize,sizeof(RAWINPUTHEADER)) <> dwSize then showMessage("GetRawInputData does""не повертає правильний розмір!"); raw:=pRawIn^; res.mouse:=-1; if raw.header.dwType = RIM_TYPEMOUSE then begin mouse:=FindMouseNum(raw.header.hDevice); res.mouse:=миша; res.mouseData:[email protected]; результат:=рез; end; end;
function GetInfo(wnd:HWND; lPar:LPARAM):TMouse_Info; begin result:=HandleWMInput(wnd,lpar); end;
procedure TForm1.FormCreate(Sender: TObject); begin RawInputInit; end;
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean); var m: TMouse_Info; p: TPoint; Memo1.Lines.Add("Aktivna mishka : "+intToStr(m.mouse)); if m.mouse = 1 then begin //*** Працює миша 1 end else begin if m.mouse = 0 then begin //*** Працює миша 0 end; end; end; end;
Став глоб.хук типу WH_LL_MOUSE
←→DelphiN! (2009-05-11 11:01) [2]
Поставив WH_MOUSE_LL хук, проте тепер функція визначення миші (HandleWMInput) перестала працювати видає помилку:GetRawInputData doesn""t return correct size !
Ось як я її викликаю:
function SysMsgProc(code : integer; wParam : word; lParam : longint) : longint; stdcall; var m: TMouse_Info; Msg: TMsg; begin msg := TMsg(Pointer(lParam)^); m:=GetInfo(msg.hwnd,msg.lParam); bit.Canvas.TextOut(10,10,"mouse: "+inttostr(m.mouse)+" WND: "+inttostr(wparam)+" Lparam: "+inttostr(lparam)); Result:= CallNextHookEx(GlobalData^.SysHook, Code, wParam, lParam); end;
у чому може бути проблемма?
wParam: word було у Win16. Про це можна забути.
←→DelphiN! (2009-05-14 15:28) [4]
Зміна типу результату не дало.
> функція визначення миші (HandleWMInput) перестала працювати
Так ти ж їй тепер зовсім інше передаєш параметром.
Вона в тебе чекає на HRAWINPUT, а ти їй чомусьТикаєш покажчик на MSLLHOOKSTRUCT, який системою передається параметром lParam при виклику хук-функції.
←→DelphiN! (2009-05-15 22:48) [6]
А як отримати HRAWINPUT у хуку на мишу?
> як отримати HRAWINPUT у хуку на мишу?
А власне навіщо?
Чого тобі не вистачає у структурі MSLLHOOKSTRUCT?
←→DelphiN! (2009-05-18 20:52) [8]
Щоб передати його в HandleWMInput
> ?Чого тобі не вистачає у структурі MSLLHOOKSTRUCT ?
А що потрібно передати в HandleWMInput із MSLLHOOKSTRUCT щоб процедура HandleWMInput працювала правильно?
Я запитав - для ЧОГО тобі RAW-дані миші? Чого такого тобі не вистачає в MSLLHOOKSTRUCT? Там тобі і тек.координати, там тобі і інформація про натискання/відпускання мишачих кнопок ..
←→DelphiN! (2009-05-20 18:00) [10]
До одного комп'ютера підключений сенсорний екран як другий монітор, на основному моніторі працює оператор. Клієнт клацає по сенсорному екрану (щоб проголосувати як його обслужив оператор добре чи погано), при натисканні на сенсор покажчик миші переміщається на основному моніторі так ніби сенсорним є основний монітор і клацнули по ньому (особливість сенсорних екранів). Для цього мені необхідно визначити хто натиснув на екран (сенсор або основна миша) і якщо клік зробили з сенсорного монітора то перенести положення поточного положення покажчика на Screen.Width по координаті x і семулювати натискання миші. Тобто RAW дані миші мені потрібні для визначення хто клацнув по екрану миша або сенсорний екран.
> сенсорний екран як другий монітор, на основному моніторі > працює оператор
На обох екранахвиводиться одне й те вікно, яке бачить і оператор і користувач ?
←→DelphiN! (2009-05-22 16:26) [12]
Ні, другий екран - доповнення 1го. Бачать вони різне. Просто у сенсорного екрану така особливість, що якщо клацають по ньому, то клацання він робить на основному екрані, от і доводиться перекручуватися. Писали виробникам про цей "глюк", вони сказали, що вирішити це не можна, а сенсорний дисплей у них розрахований, що його використовують як основний монітор.
> 2й екран - доповнення 1го
Що означає "доповнення"?
←→DelphiN! (2009-05-22 18:17) [14]
Підключений як другий монітор. Зображення на них різне, на 1-му - вікна оператора, на 2-му розгорнуте на весь екран вікно для клієнта з атрибутом fsStayOnTop.
Тобто. ти хочеш сказати, що форма 2 твого додатка, показана на екрані сенсорного монітора, не має фокусу введення (фокус введення має інша форма 1 твого ж додатка, показана на екрані оператора), але тим не менш події сенсорного введення надходять як повідомлення про мишаче введення у чергу повідомлень вікна форми 1?
←→DelphiN! (2009-05-27 11:41) [16]
Оператор може працювати з не моїм вікном (наприклад з Wordом), в цей момент ні 1 форма ні 2 моя форма не має фокус. Однак у цей момент клієнт може клацнути по екрану сенсора і мені потрібно визначити чи було це клацання з сенсора і якщо так, то обробити його. Однак для постійного контролю мені потрібен глобальний хук, але на даному етапі я на жаль не можу визначити індекс пристрою з якого було зроблено клацання в глобальному хуку.
Мабуть, RegisterRawInputDevices слід викликати у процедурі ініціалізації dll-модуля глобального WH_GETMESSAGE-хуку.
←→DelphiN! (2009-06-04 13:50) [18]
Точно! Допомогло, дякую! Тільки тепер виникла інша проблема. Коли я рухаю або натискаю 1-ою або 2-ою мишкою програма відрізняє їх один від одного, на як тільки я емітую натискання миші на 2му моніторі програма визначає індекс пристрою при імітації як -1, після основна(1а) миша визначається як друга. Як вирішити цю проблему? Ось код імітації: SetCursorPos(X, Y); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)