이 문제로 거의 한달간 끙끙대구 있습니다... ㅠ.ㅠ
Dll 에서 Timer를 사용하려 하고 있는데 왕처보인 저로서는 엄청 어렵네여...
ㅠ.ㅠ
고수님들 조언좀 부탁드립니다...
소스를 보시면 아시겠지만 현재 Timer의 OnTimer 를 지정하기 위한 이벤트를 생성하지 못해서 헤매고 있습니다..
Dll 내부에서 Timer를 동적생성하여 사용하려 하는데 OnTimer 이벤트 처리를 어떻게 해야할지...6-.-
지난번에도 질문을 올렸었는데 조언을 받아도 헤매이게 되네여... ㅠ.ㅠ
고수님들 조언좀 부탁드립니다....
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Dialogs,
ExtCtrls, Registry;
type
TMyTimer = class(TTimer)
private
FOnTimer : TNotifyEvent;
{private declarations}
protected
{protected declarations}
public
{public declarations}
published
property OnTimer : TNotifyEvent read FOnTimer write FOnTimer;
{published declarations}
end;
var
Time : TTimer;
Reg : TRegistry;
{$R *.RES}
function HookSHELL : Boolean; external 'HookDll.dll';
function UnHookSHELL : Boolean; external 'HookDll.dll';
procedure OnTimer(Sender : Tobject; OnTimer : TNotifyEvent);
begin
ShowMessage('11');
Reg := TRegistry.Create;
ShowMessage('12');
Reg.RootKey := HKEY_CURRENT_USER;
ShowMessage('13');
Reg.OpenKey('SOFTWAREMJ', True);
ShowMessage('14');
if Reg.ValueExists('suc') then
begin
ShowMessage('15');
UnHookSHELL;
ShowMessage('16');
Sleep(1000);
ShowMessage('17');
Reg.DeleteValue('suc');
ShowMessage('18');
Sleep(1000);
ShowMessage('19');
Reg.CloseKey;
ShowMessage('20');
Sleep(1000);
ShowMessage('21');
Reg.Free;
ShowMessage('22');
HookSHELL;
ShowMessage('23');
end;
end;
begin
Time := TTimer.Create(nil);
Showmessage('1');
Time.Enabled := False;
ShowMessage('2');
Time.Interval := 1000;
ShowMessage('3');
Time.OnTimer := OnTimer;
// 이곳에서 [Error] NZDll.dpr(84): Incompatible types: method pointer and regular procedure 가 나고 있습니다.. Type이 안맞는거는 알겠는뎅..ㅠ.ㅠ
ShowMessage('4');
Time.Enabled := True;
ShowMessage('5');
end.
잘 알고 계시네요... 타입이 안맞아서 그럽니다.
님이 작성하신거는 그냥 함수이고, OnTimer이벤트는 메소드포인터입니다. 객체 내부에 있는 함수를 쓸수 있는 포인터죠...
메소드포인터는 함수포인터에 객체의 Self값이 들어가 있습니다. 당근 호환이 안됩니다. 메소드포인터 형선언부분을 보시면 뒤에 of object가 들어가 있죠..
형변환하시면 되지만 아래거 사용해보세요...
그리고 델파이에 있는 TTimer는 OnTimer이벤트가 nil이 아닐때만 작동하도록 되어 있습니다. 그러니까 이부분만 바꾸시면 되겠네요.
걍 델파이의 TTimer소스보고 대강 작성했는데 DLL에서도 잘 작동하네요...
TMyTimer의 Timer메소드에다 원하시는 코딩을 해주시면 됩니다...
이것보다는 멀티미디어타이머를 쓰시라고 권하고 싶군요. 멀티미디어타이머쓰는 방법은 팁모아나 강의실에 찾아보시면 있을겁니다...
type
TMyTimer = class(TComponent)
private
FInterval: Cardinal;
FWindowHandle: HWND;
FOnTimer: TNotifyEvent;
FEnabled: Boolean;
procedure UpdateTimer;
procedure SetEnabled(Value: Boolean);
procedure SetInterval(Value: Cardinal);
procedure SetOnTimer(Value: TNotifyEvent);
procedure WndProc(var Msg: TMessage);
protected
procedure Timer; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Enabled: Boolean read FEnabled write SetEnabled default True;
property Interval: Cardinal read FInterval write SetInterval default 1000;
property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
end;
implementation
constructor TMyTimer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabled := True;
FInterval := 1000;
FWindowHandle := AllocateHWnd(WndProc);
end;
destructor TMyTimer.Destroy;
begin
FEnabled := False;
UpdateTimer;
DeallocateHWnd(FWindowHandle);
inherited Destroy;
end;
procedure TMyTimer.WndProc(var Msg: TMessage);
begin
with Msg do
if Msg = WM_TIMER then
try
Timer;
except
Application.HandleException(Self);
end
else
Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
end;
procedure TMyTimer.UpdateTimer;
begin
KillTimer(FWindowHandle, 1);
if (FInterval <> 0) and FEnabled then
if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
raise EOutOfResources.Create('Not enough timers available');
end;
procedure TMyTimer.SetEnabled(Value: Boolean);
begin
if Value <> FEnabled then
begin
FEnabled := Value;
UpdateTimer;
end;
end;
procedure TMyTimer.SetInterval(Value: Cardinal);
begin
if Value <> FInterval then
begin
FInterval := Value;
UpdateTimer;
end;
end;
procedure TMyTimer.SetOnTimer(Value: TNotifyEvent);
begin
FOnTimer := Value;
UpdateTimer;
end;
procedure TMyTimer.Timer;
begin
// 여기에서 OnTimer 내용 쓰시면 됩니다...
ShowMessage('Timer event...');
end;
^^ 항상 즐코하세요...