Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Управление "чужим таймером"?


Антон ©   (2004-06-15 18:52:00) 

Как найти и управлять "чужим" таймером.
Суть: нашел я чужое окно, нашел его child window (собственно оно и нужно) при его работе используется таймер (нажали кнопку время пошло) надо остановить сие действо. Или бред?


Rouse_   (2004-06-18 11:15:00) [1]

Ну раз уж тут разгорелся такой жаркий спор, тогда поясню:
Управлять таймером можно через
SetTimer, KillTimer
Вся проблема в том что нужно узнать Handle окна куда посылаются сообщения и ID таймера.
Узнать это до банального просто:
Ставим Hook на WH_GETMESSAGE и ловим WM_TIMER
в данном сообщении HWND будет содержать Handle окна а WParam - ID таймера.

Код ниже:

Библиотека

library Hook;

uses
 Windows,
 Messages;

const
 MapID = 'Timer Global Hook Demo';
 WM_HOOK_NOTIFY = WM_USER + 1234;

type
 PData = ^TData;
 TData = record
   AppWnd: HWND;
   OldHook: HHOOK
 end;

var
 HMap: THandle = 0;
 Data: PData = nil;

procedure DLLEntryPoint(dwReason: DWORD); stdcall;
begin
 case dwReason of
   DLL_PROCESS_ATTACH:
   begin
     HMap := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TData), MapID);
     Data := MapViewOfFile(HMap, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TData))
   end;
   DLL_PROCESS_DETACH:
   begin
     UnMapViewOfFile(Data);
     CloseHandle(HMap)
   end
 end
end;

function TimerHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
begin
 Result:=CallNextHookEx(Data^.OldHook, Code, WParam, LParam);
 if Code = HC_ACTION then
   if TMsg(Pointer(LParam)^).message = WM_TIMER then
     SendMessage(Data^.AppWnd, WM_HOOK_NOTIFY,
       TMsg(Pointer(LParam)^).WParam, TMsg(Pointer(LParam)^).hwnd);
end;

function SetTimerHook(Wnd: HWND): BOOL; stdcall;
begin
 if Assigned(Data) then
 begin
   Data^.AppWnd := Wnd;
   Data^.OldHook := SetWindowsHookEx(WH_GETMESSAGE, @TimerHook, HInstance, 0);
   Result := Data^.OldHook <> 0
 end
 else
   Result := False
end;

function RemoveTimerHook: BOOL; stdcall;
begin
 Result := UnhookWindowsHookEx(Data^.OldHook)
end;

exports
 SetTimerHook,
 RemoveTimerHook;

begin
 DLLProc := @DLLEntryPoint;
 DLLEntryPoint(DLL_PROCESS_ATTACH)
end.


Программа:

unit uMain;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

const
 WM_HOOK_NOTIFY = WM_USER + 1234;

type
 TTimerStruct = packed record
   WindowName: ShortString;
   WindowHandle: Cardinal;
   TimerID: Cardinal;
 end;
 TTimerArray = array of TTimerStruct;

 TForm1 = class(TForm)
   ListBox1: TListBox;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   TimersList: TStringList;
   TimerArray: TTimerArray;
   Hooked: Boolean;
 public
   procedure HookNotify(var Message: TMessage); message WM_HOOK_NOTIFY;
 end;

 function SetTimerHook(Wnd: HWND): BOOL; stdcall; external 'Hook' name 'SetTimerHook';
 function RemoveTimerHook: BOOL; stdcall; external 'Hook' name 'RemoveTimerHook';

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 TimersList := TStringList.Create;
 Hooked := SetTimerHook(Handle);
end;

procedure TForm1.HookNotify(var Message: TMessage);
var
 Buf: array of Char;
 Size: Cardinal;
 TmpStr: String;
begin  
 with Message do
 begin
   Result := 0;
   if TimersList.IndexOfName(IntToStr(LParam)) > -1 then Exit;
   TimersList.Values[IntToStr(LParam)] := IntToStr(WParam);
   SetLength(TimerArray, Length(TimerArray) + 1);
   Size := GetWindowTextLength(LParam);
   SetLength(Buf, Size);
   Inc(Size);
   GetWindowText(LParam, @Buf[0], Size);
   TmpStr := String(Buf);
   if TmpStr = '' then TmpStr := 'Без заголовка';
   while TmpStr[Length(TmpStr)] = #0 do Delete(TmpStr, Length(TmpStr), 1);
   with TimerArray[Length(TimerArray) - 1] do
   begin
     WindowName := TmpStr;
     WindowHandle := LParam;
     TimerID := WParam;
   end;
   ListBox1.Items.Add(Format('Окно: %s, хэндл окна: %d, ID таймера: %d',
       [TmpStr, LParam, WParam]));
 end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 if Hooked then RemoveTimerHook;
 TimersList.Free;
end;

end.


---
Желаю успехов


Cobalt   (2004-06-17 23:11:00) [2]

1) Ловить сообщение WM_Timer
2) KillTimer для всех окон со всеми идентификаторами
3) Ловить callback-функцию довольно-таки затруднительно. Я даже не представляю себе, как.


Mim1   (2004-06-17 21:57:00) [3]

Вообщем генерится не хендл, а окно с этим хендлом. А найти его можно стандартными функциями. Вот только если например есть два таких окна, то одно от другово отличить будет сложно.


}{enon   (2004-06-17 18:17:00) [4]


> Rouse_ ©   (15.06.04 20:29) [2]
> > Таймер не является визуальным объектом, у него нет Handle
> Сам понял что сказал?

Ладно, у него почтинет хэндла. Если залезть в ExtCtrls (там описан класс TTimer), то можно заметить, что handle таймера объявляется в разделе private. При создании таймера handle генерируется так:
FWindowHandle := Classes.AllocateHWnd(WndProc);
а потому я не знаю, откудаможно его выдрать (стандартные функции не найдут таймер).

Постараюсь откапать еще что-нибудь, но уверенности в успехе нет...

P.S. Если что-то найете - напишите (самому стало интересно).


Антон   (2004-06-16 18:23:00) [5]

Точно бред. :(


Антон   (2004-06-15 21:43:00) [6]

2}{enon  
Из Help Win32 Dev.. Reference:


The SetTimer function creates a timer with the specified time-out value.

UINT SetTimer(

   HWND hWnd, // handle of window for timer messages
   UINT nIDEvent, // timer identifier
   UINT uElapse, // time-out value
   TIMERPROC lpTimerFunc  // address of timer procedure
  );

Так что по идее, таймер можно найти по его идентификатору. Ищу дальше.


Rouse_   (2004-06-15 20:29:00) [7]

> Таймер не является визуальным объектом, у него нет Handle
Сам понял что сказал?


}{enon   (2004-06-15 20:27:00) [8]

Скорее уж "или". Таймер не является визуальным объектом, у него нет Handle, а потому к нему не применимо абсолютное большинство Windows'ских функций. Хотя по идее как-то это можно сделать, т.к. где-то в памяти хранится процедура OnTimer и ее можно каким-либо образом вызвать (DLL?)


Наверх

Титульная страница Поиск, карта сайта Написать письмо