Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Как отловить двойной клик на рабочем столе


Автор: DriveSoftware 30.12.2004, 11:01
Как можно отловить двойной клик мышью на рабочем столе без хука с DLL ???

Состояние мыши можно проверить так
GetAsyncKeyState(VK_LBUTTON)

но как это реализовать, не соображу )
Может есть другой способ? главное чтоб без DLL

Автор: Bes 30.12.2004, 11:19
Дак, я думаю, что проблема еще в том, что таким образом ты сможешь отлавливать двойной щелчек в принципе, а где будет этот двойной щелчек?.... Хотя вроде есть способ узнать окно фокуса и по-моему даже где-то здесь обсуждалось.
Кроме того если бы я пользовался такой функцией, то вычислял бы время м/у двумя щелчками, а т.к. скорость двойного щелчка настраивается в виндовс, то нужно еще откуда-то выдернуть эту константу....
Короче, надо искать способ по-проще... :-) правда не уверен, что он есть.

Щас сделал таймер с одной миллисекундой и в мемо результат твойе функции заносил - двойной клик выглядит так
0
0
0
0
0
-32767
-32768
-32768
-32768
0
0
0
0
0
0
-32767
-32768
-32768
0
0
0

т.е. 0-отпущена видимо само нажатие -32767, а -32768 - это нажатое состояние. - период м/у щелчками получился примерно 6 мс. Ща еще че-нить попробую.

Автор: Bes 30.12.2004, 11:34
Вот еще один примерчик - не мой может поможет решить вторую часть задачи. - там все написано. взято из кулибы.



Работа с другим приложением без Hook и DLL на примере GetFocus

Своим опытом делится SottNick:
На стандартной форме (Form1):

Form1.FormStyle=fsStayOnTop - форма поверх остальных окон

Объекты:

ТАЙМЕР (Timer1) с периодом 1000 или меньше,
3 метки (Label1, Label2, Label3). назначение их см. в тексте процедуры
У таймера событие OnTimer. а вот для нее обработчик:

--------------------------------------------------------------------------------
procedure TForm1.Timer1Timer(Sender: TObject);

var
dwTargetOwner :DWORD;//указатель на подключаемый процесс
dwThreadID :DWORD;//указатель на текущий процесс
Result:longbool;
begin

{В первой метке отображается Handle активного окна}
Label1.Caption:=IntToStr(GetForegroundWindow);//указатель на подключаемое приложение


// Подключение потока другого окна
dwTargetOwner := GetWindowThreadProcessId(GetForegroundWindow,nil);//указатель на подключаемый процесс
dwThreadID := GetCurrentThreadId();//указатель на текущий процесс
if (dwTargetOwner <>dwThreadID) then // если не один и тот же процесс
Result := AttachThreadInput(dwThreadID, dwTargetOwner, TRUE);//подключение


{Во второй метке отображается Handle объекта 'в фокусе' в активном окне}
Label2.Caption:=IntToStr(GetFocus);//фокус в другом приложении


if (Result) then
AttachThreadInput(dwThreadID, dwTargetOwner, FALSE);//отключение


{В третей метке отображается Handle объекта 'в фокусе' в активном окне,
но если это окно другого приложения, то Handle будет равен нулю,
т.к. попытка получения Handle происходит после отключения потока}
Label3.Caption:=inttostr(GetFocus);//проверка после отключения


{Эффект можно посмотреть, если запустить полученное приложение
и сделать активным другое приложение}
{Ясно, что полученный Handle объекта можно использовать
по своему разумению. Например, считать из объекта текст и т.п.}


// © SottNick 2000
end;

Автор: <Spawn> 30.12.2004, 11:42
Почему только вот хук не устраивает?

Автор: DriveSoftware 30.12.2004, 11:44
Bes

Спасибо, вроде решил проблему, не знаю на скока это рационально, закрутить в таймере GetAsyncKeyState(VK_LBUTTON) но работает, исходник:

Timer.Interval:=50;

Код

procedure TfrmMain.TimerMouseTimer(Sender: TObject);
var
 MS: word;
 P: TPoint;
 S: array[0..255] of Char;
begin
 MS:=300; {Время, в период которого должен произойти дабл клик}

 GetCursorPos(P);
 GetClassName(WindowFromPoint(P), S, 255);
 if S<>'SysListView32' then Exit;

 if (ClickCount=0) and (GetAsyncKeyState (VK_LBUTTON)<>0) then
 begin
   FirstClick:=GetTickCount;
   ClickState:=True;
 end;

 if FirstClick > (GetTickCount - MS) then
 begin
   if (ClickState) and ( GetAsyncKeyState (VK_LBUTTON)=0 ) then
   begin
     Inc(ClickCount);
     ClickState:=False;
   end;

   if (not ClickState) and ( GetAsyncKeyState (VK_LBUTTON)<>0 ) then
   begin
     Inc(ClickCount);
     ClickState:=True;
   end;

 end else
 begin
   ClickCount:=0;
   ClickState:=False;
 end;

 if ClickCount>2 then {Таким образом можно сделать и Трабл клик или хоть 10-клик)}
 begin
   ClickCount:=0;
   FirstClick:=0;
   ShowMessage('Double Click');
 end;


end;


Автор: Bes 30.12.2004, 11:48
Да согласен, на счет рациональности - тут большой вопрос, но как говриться на безрыбьи и рыбу... Хотя я бы тоже хотел увидеть какое-нить красивое решение.

Автор: DriveSoftware 30.12.2004, 11:48
А время дабл клика можно выяснить с помощью GetSystemMetrics

либо в реестре:
HKEY_CURRINT_USER\Control Panel\Mouse - DoubleClickSpeed

у меня там 500, т.е. для этого кода нужно будет присвоить переменной MS=500

и еще, забыл упомянуть про глобальные перменные:

Код

var  
 FirstClick: Cardinal;
 ClickCount: integer=0;
 ClickState: Boolean=False;

Добавлено @ 11:51
<Spawn>

Честно, просто не хочеться вазиться с DLL
я пишу шароварный проект, и просто нуу не хочеться smile

да и слышал я где то, что хуки с DLL напригают систему и в MSDK их использоваться не рекомендуется.

Автор: Bes 30.12.2004, 11:52
2DriveSoftware: во, тоже спасибо - буду знать. :-)

Автор: <Spawn> 30.12.2004, 11:55
Цитата(DriveSoftware @ 30.12.2004, 03:48)
Добавлено @ 11:51
<Spawn>

Честно, просто не хочеться вазиться с DLL
я пишу шароварный проект, и просто нуу не хочеться smile

да и слышал я где то, что хуки с DLL напригают систему и в MSDK их использоваться не рекомендуется.

Я не думаю, что таймер с периодом в 50 мс, будет меньше нагружать системуsmile

Автор: DriveSoftware 30.12.2004, 11:59
<Spawn>

памерю патом каким нить монитором на загрузку процессора smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)