Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2009.08.09;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.005 c
15-1244082212
alert2006
2009-06-04 06:23
2009.08.09
Помогите решить задачу


4-1213710169
JetuS
2008-06-17 17:42
2009.08.09
Получение ID главного потока приложения


2-1244961097
Udrt
2009-06-14 10:31
2009.08.09
Указатель на класс по его Handle


15-1244387849
cyber-pilot
2009-06-07 19:17
2009.08.09
MapReduce на Delphi


8-1196410194
аа
2007-11-30 11:09
2009.08.09
формы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский