-
Мне необходимо определить какая из двух мышек поключенных к компьютеру в данный момент активна, нашел в интернете пример работы через RawInput. Программа замечательно работает только когда окно моей программы активно, если перейти на другое окно, программа перестает получать сообщения от мышек(WM_INPUT). Мне необходимо получать сообщения об активности мыши (WM_INPUT) всегда, активно мое окно или нет. Как это реализовать я не знаю ( Вот код программы :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, RawInput_h, AppEvnts, StdCtrls, ExtCtrls;
const
ENUMERATE_EXISTING_MICE=0;
MAX_DEVICES=2;
MAX_DEVICEID_LEN=2048;
type
TForm1 = class(TForm)
Memo1: TMemo;
ApplicationEvents1: TApplicationEvents;
procedure ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
procedure FormCreate(Sender: TObject);
private
public
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;
implementation
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 rid.AMouseHandle[i] = hdevice then
begin
if rid.AMouseID[i,0] = 0 then
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);
if k >= MAX_DEVICEID_LEN then
begin
rid.AMouseHandle[i]:=hdevice;
result:=i;
exit;
end;
end;
if rid.num_mice < MAX_DEVICES then
begin
for j:=0 to MAX_DEVICEID_LEN do
rid.AmouseID[rid.num_mice,j]:=devName[j];
rid.AMouseHandle[rid.num_mice]:=hDevice;
rid.num_mice:=rid.num_mice+1;
result:=rid.num_mice-1;
exit;
end;
result:=-1;
end;
procedure RawInputInit;
var
nDevices: Cardinal;
pRawIn: PRAWINPUTDEVICELIST;
hRawIn: array[1..100] of RAWINPUTDEVICELIST;
rawInDev: RAWINPUTDEVICE;
begin
rid.dataBuf:=nil;
rid.data_buf_size:=0;
if GetRawInputDeviceList(nil, nDevices, sizeof(RAWINPUTDEVICELIST)) <> 0 then
showMessage('Error 1');
pRawIn:=nil;
pRawIn:=@hRawIn;
if GetRawInputDeviceList(pRawIn, nDevices, sizeof(RAWINPUTDEVICELIST)) = -1 then
showMessage('Error 2');
rid.num_mice:=0;
rawInDev.usUsagePage:=1;
rawInDev.usUsage:=2;
rawInDev.dwFlags:=0;
rawInDev.hwndTarget:=0;
RegisterRawInputDevices(@rawInDev,1,sizeOf(rawInDev));
end;
function HandleWMInput(wnd:HWND; lPar:LPARAM):TMouse_Info;
var
Raw: RAWINPUT;
dwSize: UINT;
res: TMouse_Info;
hRawIn: HRAWINPUT;
pRawIn: PRAWINPUT;
mouse: integer;
begin
res.mouse:=-1;
res.mouseData:=nil;
hRawIn:=lPar;
GetRawInputData(hRawIn,RID_INPUT, nil, dwSize, sizeof(RAWINPUTHEADER));
if dwSize = 0 then
showMessage('Can not allocate memory');
New(pRawIn);
if GetRawInputData(hRawIn,RID_INPUT,pRawIn,dwSize,sizeof(RAWINPUTHEADER)) <> dwSize then
showMessage('GetRawInputData doesn''t return correct size !');
raw:=pRawIn^;
res.mouse:=-1;
if raw.header.dwType = RIM_TYPEMOUSE then
begin
mouse:=FindMouseNum(raw.header.hDevice);
res.mouse:=mouse;
res.mouseData:=@raw.mouse;
result:=res;
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;
begin
if msg.message = WM_INPUT then
begin
m:=GetInfo(msg.hwnd,msg.lParam);
Memo1.Lines.Add('Aktivna mishka : '+intToStr(m.mouse));
if m.mouse = 1 then
begin
end
else
begin
if m.mouse = 0 then
begin
end;
end;
end;
end;
end.
-
Ставь глоб.хук типа WH_LL_MOUSE
-
> Сергей М. © (10.05.09 20:44) [1]
Поставил 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: integer;
wParam: word было в Win16. Об этом можно забыть.
-
> Юрий Зотов © (11.05.09 12:29) [3]
Изменение типа результата не дало ...
-
> функция определения мыши (HandleWMInput) перестала работать
Так ты же ей теперь совсем другое передаешь параметром.. Она у тебя ожидает HRAWINPUT, а ты ей почему-то тычешь указатель на MSLLHOOKSTRUCT, который системой передается параметром lParam при вызове хук-функции.. Читать сюда: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
-
> Сергей М. © (14.05.09 16:36) [5]
А как получить HRAWINPUT в хуке на мышь?
-
> как получить HRAWINPUT в хуке на мышь?
А собссно зачем ?
Чего тебе не хватает в структуре MSLLHOOKSTRUCT ?
-
> Сергей М. © (16.05.09 10:10) [7] А собссно зачем ?
Чтобы передать его в HandleWMInput
> ?Чего тебе не хватает в структуре MSLLHOOKSTRUCT ?
А что нужно передать в HandleWMInput из MSLLHOOKSTRUCT чтобы процедура HandleWMInput работала правильно?
-
)
Я спросил - для ЧЕГО тебе RAW-данные мыши ? ЧЕГО такого тебе не хватает в MSLLHOOKSTRUCT ? Там тебе и тек.координаты, там тебе и информация о нажатиях/отпусканиях мышиных кнопок ..
-
> Сергей М. © (18.05.09 21:28) [9]
К одному компьютеру подключен сенсорный экран как второй монитор, на основном мониторе работает оператор. Клиент щелкает по сенсорному экрану(чтобы проголосовать как его обслужил оператор хорошо или плохо), при щелчке по сенсору указатель мыши перемещается на основном мониторе так будто бы сенсорным является основной монитор и щелкнули по нему(особенность сенсорных экранов). Для этого мне необходимо определить кто произвел щелчок по экрану(сенсор или основная мышь) и если клик произвели с сенсорного монитора то перенести положение текущего положения указателя на Screen.Width по координате x и сэмулировать нажатие мыши. То есть RAW данные мыши мне нужны для определения кто щелкнул по экрану мышь или сенсорный экран ...
-
> сенсорный экран как второй монитор, на основном мониторе > работает оператор
На обоих экранах выводится одно и то же окно, которое видит и оператор и юзер ?
-
Нет, 2ой экран - дополнение 1го. Видят они разное. Просто у сенсорного экрана такая особенность, что если щелкают по нему то щелчок он делает на основном экране, вот и приходится извращаться. Писали производителям об этом "глюке", они сказали что решить это нельзя, а сенсорный дисплей у них рассчитан что его используют как основной монитор...
-
> 2ой экран - дополнение 1го
Что значит "дополнение" ?
-
> Сергей М. © (22.05.09 16:45) [13]
Подключен как 2ой монитор. Изображение на них разное, на 1ом - окна оператора, на 2ом развернутое во весь экран окно для клиента с атрибутом fsStayOnTop ...
-
Т.е. ты хочешь сказать, что форма 2 твоего приложения, показанная на экране сенсорного монитора, не имеет фокуса ввода (фокус ввода имеет другая форма 1 твоего же приложения, показанная на экране оператора), но тем не менее события сенсорного ввода поступают как сообщения о мышином вводе в очередь сообщений окна формы 1 ?
-
> Сергей М. © (24.05.09 19:45) [15]
Оператор может работать с не моим окном(например с Wordом), в этот момент ни 1ая форма ни 2ая моя форма не имеет фокус. Однако в этот момент клиент может щелкнуть по экрану сенсора и мне нужно определить был ли этот щелчок с сенсора и если да, то обработать его. Однако для постоянного контроля мне нужен глобальный хук, но на данном этапе я к сожалению не могу определить индекс устройства с которого был произведен щелчок в глобальном хуке.
-
Видимо, RegisterRawInputDevices следует вызывать в процедуре инициализации dll-модуля глобального WH_GETMESSAGE-хука .
-
> Сергей М. © (28.05.09 12:51) [17]
Точно! Помогло, спасибо! Только теперь появилась другая проблема. Когда я двигаю или нажимаю 1ой или 2ой мышкой программа отличает их друг от друга, на как только я эмитирую нажатие мыши на 2ом мониторе программа определяет индекс устройства при имитации как -1, после основная(1ая) мышь определяется как вторая. Как решить эту проблему? Вот код имитации :
SetCursorPos(X, Y);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
-
Для того, что бы окно получала WM_INPUT в неактивном состоянии надо значение rawInDev.dwFlags установить в $00000100 (RIDEV_INPUTSINK), кроме того, с помощью флагов можно даже установить фильтр по значению UsagePage и Usage.
|