Форум: "Прочее";
Текущий архив: 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