Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.08.09;
Скачать: CL | DM;

Вниз

Какая какая из мышек произвела действие?   Найти похожие ветки 

 
DelphiN!   (2009-06-05 09:25) [0]

Заказали у меня следующую программу:
К компьютеру подключено 2 монитора, за первым монитором работает оператор, на 2ом мониторе(сенсорном) во весь экран развернута программа для клиента с просьбой проголосовать за оператора "Хорошо ли он обслужил вас?" Да\Нет. У драйверов сенсора - особенность. Если клиент докоснулся до экрана, то клик производится по основному дисплею(рабочему пространству оператора), хотя сенсорный монитор подключен как второй. Соответственно форма клиента клик не получает.  
 У меня родилась идея как решить эту проблему - определить какая из мышек в системе произвела клик и если эта вторая мышь, то сдвинуть курсор по координате X на ширину экрана и сэмитировать клик, а после клика вернуть курсов обратно. Однако в данном решении возникла куча непонятных для меня проблем:
Определение какая из мышек произвела активность я сделал через Raw Input в хуке на WH_GETMESSAGE. Однако "иногда" определение через  RawInput путает мышки местами, либо же не определяет одну из мышек совсем(возвращает индекс устройства как -1). При каких условиях это происходит я понять не могу, эту случается неожиданно и после неожиданно прекращается.
 Может быть кто нибудь сможет помочь мне решить эту проблему или же поделится мыслями по поводу иного вида решения данной задачи.
 
Вот код .DLL модуля, в котором я произвожу определение какая из мышек произвела действие :


library Hook;

uses
 
 Windows,
 Constants in "Constants.pas", Graphics,Messages,RawInput_h,SysUtils, Forms,TLHelp32;

{$R *.res}

const
  ENUMERATE_EXISTING_MICE=0;
  MAX_DEVICES=2;
  MAX_DEVICEID_LEN=2048;

const
 WM_INPUT = WM_KEYFIRST-1;

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;

var

rid:   RAW_INPUT_DATA;

var
 MouseHook: HHOOK;
 bit: TBitmap;
 LastPoint: TPoint;
 b: Boolean;
 MyClicks,LastClick: Integer;

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
  bit.Canvas.TextOut(10,10,"Error 1");
pRawIn:=nil;
pRawIn:=@hRawIn;
if GetRawInputDeviceList(pRawIn, nDevices, sizeof(RAWINPUTDEVICELIST)) = -1 then
  bit.Canvas.TextOut(10,10,"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
  bit.Canvas.TextOut(10,10,"Can not allocate memory");
New(pRawIn);
if GetRawInputData(hRawIn,RID_INPUT,pRawIn,dwSize,sizeof(RAWINPUTHEADER)) <> dwSize then
  bit.Canvas.TextOut(10,10,"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;

function MouseProc(hCode: Integer; wParam: Longint; lParam: Longint): LRESULT; stdcall;
var
 Wnd: THandle;
 m: TMouse_Info;
 Msg: TMsg;
 p,tp: TPoint;
begin
 try
   if hCode = HC_ACTION then
   begin
     msg := TMsg(Pointer(lParam)^);
     if msg.message = WM_INPUT then
     begin
       m := GetInfo(msg.hwnd,msg.lParam);
       
       
 if m.Mouse = 0 then
   //Запоминаем положение основной мыши для возврата на эту позицию после клика по сенсору
   GetCursorPos(LastPoint)
 else
 if msg.WParam = 1 then
 begin
   //Кликнули по сенсору, эмулируем нажатие на 2ом рабочем столе
   GetCursorPos(tp);
   SetCursorPos(tp.X+Screen.Width, tp.Y);
   mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
   mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
   SetCursorPos(LastPoint.X, LastPoint.Y);
 end;


Модуль RawInput_h.pas можно скачать тут

     end;
   end;
 except
   Result := CallNextHookEx(MouseHook, hCode, wParam, lParam);
 end;
end;

function SetMouseHook: Boolean; stdcall; export;
begin
 MouseHook := SetWindowsHookEx(WH_GETMESSAGE, @MouseProc, HInstance, 0);
 Result := MouseHook <> 0;
end;

function RemoveMouseHook: Boolean; stdcall; export;
begin
 Result := UnhookWindowsHookEx(MouseHook);
end;

exports SetMouseHook, RemoveMouseHook;

begin
 bit := TBitmap.Create;
 bit.Canvas.Handle := GetDC(0);
 bit.Canvas.Font.Size := 15;
 b := false;
 MyClicks := 0;
 RawInputInit;
end.



Модуль RawInput_h.pas можно скачать тут
http://rapidshare.com/files/238044969/RawInput_h.rar


 
ANB   (2009-06-05 09:29) [1]

Главное, что непонятно - а зачем ЕЩЕ ОДНА программа ?
Клиент то не по черному экрану кликает и не по просто картинке, а по форме некой программы ? Не проще ее доработать, чем вешать хуки ?


 
DelphiN!   (2009-06-05 09:41) [2]


> ANB   (05.06.09 09:29) [1]
> Главное, что непонятно - а зачем ЕЩЕ ОДНА программа ?
> Клиент то не по черному экрану кликает и не по просто картинке,
>  а по форме некой программы ? Не проще ее доработать, чем
> вешать хуки ?


Дело в том что у сенсоров особенность, если сенсорный монитор подключен как не основной, то при нажатии на сенсор, курсор кликает на основном экране в той же позиции где кликнул клиент на сенсоре(как будто основной экран сенсорный и кликнули по нему) . Соответственно клиентское окно не приобретает фокус, а клик до него не доходит, из за того что во время клика может быть активно не извесное приложение я не могу перехватить щелчок без глобального хука....


 
vrem   (2009-06-05 09:51) [3]

подключить как основной :)


 
DelphiN!   (2009-06-05 09:52) [4]


> vrem   (05.06.09 09:51) [3]


:) В этом то и проблема, что нельзя так делать ...


 
@!!ex ©   (2009-06-05 10:51) [5]

> [4] DelphiN!   (05.06.09 09:52)
> :) В этом то и проблема, что нельзя так делать ...

почему?

P.S.
Для работы с несколькими мышами есть драйвера в гугле. Там все корректно работает.


 
Dennis I. Komarov ©   (2009-06-05 11:03) [6]


> Дело в том что у сенсоров особенность...

Это не особенность, это кривой драйвер какой-то...


 
DelphiN!   (2009-06-05 11:16) [7]


> @!!ex ©   (05.06.09 10:51) [5]
>
> почему?


Потому что за основным монитором работает оператор с обычными пользовательскими программами и он не должен чувствовать дискомфорта.


> P.S.
> Для работы с несколькими мышами есть драйвера в гугле. Там
> все корректно работает.


Я довольно долго искал, но найти не смог.


> Dennis I. Komarov ©   (05.06.09 11:03) [6]
>
> > Дело в том что у сенсоров особенность...
>
> Это не особенность, это кривой драйвер какой-то...


Другого драйвера нет. Спрашивали у производителей, они сказали что выход только 1 - поставить сенсорный монитор главным.


 
Dennis I. Komarov ©   (2009-06-05 11:31) [8]


> Другого драйвера нет. Спрашивали у производителей, они сказали
> что выход только 1 - поставить сенсорный монитор главным.
>

Это противоречит [4] :) А пляски с бубнами - это до первого сгоревшего монитора, его заменой более поздним и соответственно другими дровами со всеми вытекающими...


 
DelphiN!   (2009-06-05 11:35) [9]


> А пляски с бубнами - это до первого сгоревшего монитора,
>  его заменой более поздним и соответственно другими дровами
> со всеми вытекающими...


 Мониторов уже купили 50 штук, так что купить другие или поменять их не получится :(


 
DVM ©   (2009-06-05 11:37) [10]


> У меня родилась идея как решить эту проблему - определить
> какая из мышек в системе произвела клик

Это невозможно с обычным мышиным драйвером насколько я знаю. Или придется писать свой драйвер.


 
Dennis I. Komarov ©   (2009-06-05 11:42) [11]


> Мониторов уже купили 50 штук, так что купить другие или
> поменять их не получится :(

да хоть 1000. Через месяц два сдохли. С линейки производители такие сняли. Есть другие, с другими дровами, которые работают корректно. Дальше что?


 
DelphiN!   (2009-06-05 13:41) [12]


> Dennis I. Komarov ©   (05.06.09 11:42) [11]


Если купят те которые работают корректно переделаю или сделаю в настройках опцию "Правильный\Не правильный драйвер на сенсор" :) , а пока нам поставили задачу сделать чтобы все работало на этих мониторах...


> DVM ©   (05.06.09 11:37) [10]


Жаль что раньше я драйвера не писал и не имею представление как это делать. Может быть у кого-то есть пример как это реализовать?


 
DelphiN!   (2009-06-05 13:45) [13]


> DVM ©   (05.06.09 11:37) [10]


Да и мой способ описанный выше работает ведь(ну почти), только мышки местами по непонятным причинам иногда путает. Кстати по моему предположению на путаницу с мышками как-то влияет активное в данный момент окно. Иногда над какими-то окнами определяет правильно, а над другими - нет.



Страницы: 1 вся ветка

Текущий архив: 2009.08.09;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.012 c
15-1244484954
{RASkov}
2009-06-08 22:15
2009.08.09
Алгоритмы хеширования


15-1244320205
Юрий
2009-06-07 00:30
2009.08.09
С днем рождения ! 7 июня 2009 воскресенье


15-1244483958
User200902
2009-06-08 21:59
2009.08.09
Поиск лишних гиф и jpg


4-1213868141
Nil
2008-06-19 13:35
2009.08.09
Поясните пожалуйста работу WM_EXITSIZEMOVE


15-1244752206
Юрий
2009-06-12 00:30
2009.08.09
С днем рождения ! 12 июня 2009 пятница