AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

was macht AllocateHWND genau?

Ein Thema von snook · begonnen am 10. Aug 2011 · letzter Beitrag vom 10. Aug 2011
 
snook

Registriert seit: 25. Jun 2010
94 Beiträge
 
Delphi 2005 Professional
 
#4

AW: was macht AllocateHWND genau?

  Alt 10. Aug 2011, 12:00
okay, sry war wohl noch etwas zu früh am morgen , ich häng mal die unit rein
Delphi-Quellcode:
unit ExtDLLTimer;

interface

uses Windows, SysUtils, Classes, messages;

const
  CTI_MULT_FACTOR = 10000;
  CTI_MAXINTERVAL = $8000000000000000;
  CTI_MAXINTERVAL_MS = CTI_MAXINTERVAL div CTI_MULT_FACTOR;

// Timeout to wait for finishing timer-thread
  CTI_EXITTIMEOUT = 1000;

type
  TAPIWaitableTimer = class(TThread)
  private
    FOnTimer : TNotifyEvent;
    FTimer,
    FCloseEvent,
    FPauseEvent,
    FExitEvent : Cardinal;
    FInterval : Int64;
    FRunning,
    FContinuous : boolean;
    FHandle : HWND;
    procedure CLoseHandles;
    function GetEnabled: boolean;
    procedure ThrowTimerEvent;
    procedure SetEnabled(const Value: boolean);
    procedure SetInterval(const Value: Int64);
  protected
    procedure Execute; override;
    procedure StartTimer;
    procedure StopTimer;
  public
    constructor Create(AContinuous: boolean; ATimerObject: HWND;
      AExitEvent: Cardinal); reintroduce;
    destructor Destroy; override;
    property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
    property Enabled: boolean read GetEnabled write SetEnabled;
    property CloseEvent: Cardinal read FCloseEvent;
    property Interval: Int64 read FInterval write SetInterval;
  end;

  TDLLTimer = class(TObject)
  private
    FHandle : HWND;
    FExitEvent : Cardinal;
    FOnTimer : TNotifyEvent;
    FTimer : TAPIWaitableTimer;
    FContinuous: boolean;
    FInterval : Cardinal;
    function GetEnabled: boolean;
    procedure OnAPITimer(Sender: TObject);
    procedure APITimerTerminated(Sender: TObject);
  public
    constructor Create(AContinuous: boolean); reintroduce;
    destructor Destroy; override;
    procedure WndProc(var Msg: TMessage);
    procedure StartTimer(AInterval: Int64);
    procedure StopTimer;
    property OnTimer: TNotifyEvent read FOnTimer write FOnTimer;
    property Enabled: boolean read GetEnabled;
  end;

implementation

{ TAPIWaitableTimer }

constructor TAPIWaitableTimer.Create(AContinuous: boolean; ATimerObject: HWND;
  AExitEvent: Cardinal);
begin
  inherited create(false);
  FHandle := ATimerObject;
  FExitEvent := AExitEvent;
  FTimer := CreateWaitableTimer(nil, false, PChar(''));
  FCloseEvent := CreateEvent(nil, false, false, PChar(''));
  FPauseEvent := CreateEvent(nil, false, false, PChar(''));
  FRunning := false;
  FContinuous := AContinuous;
  FreeOnTerminate := true;
  SetInterval(1000);
end;

destructor TAPIWaitableTimer.Destroy;
begin
  CloseHandles;
  SetEvent(FExitEvent);
  inherited;
end;

procedure TAPIWaitableTimer.CloseHandles;
begin
  if FTimer > 0 then
    closehandle(FTimer);
  if FCLoseEvent > 0 then
    closehandle(FCloseEvent);
  if FPauseEvent > 0 then
    closehandle(FPauseEvent);
  FTimer := 0;
  FCloseEvent := 0;
end;

procedure TAPIWaitableTimer.Execute;
var objs : Array[0..2] of Cardinal;
    lQuit: boolean;
begin
  lQuit := false;
  if (FTimer > 0) and (FCloseEvent > 0) then
  begin
    objs[0] := FTimer;
    objs[1] := FCloseEvent;
    objs[2] := FPauseEvent;
    repeat

      case WaitForMultipleObjects(3, @objs, false, INFINITE) of
        WAIT_OBJECT_0 :
          begin
// synchronize(ThrowTimerEvent);
            PostMessage(FHandle, WM_TIMER, 0, 0);
            FRunning := false;
            if FContinuous then StartTimer;
          end;
        WAIT_OBJECT_0 + 1: lQuit := true;
        WAIT_OBJECT_0 + 2:
          case Enabled of
            true : StopTimer;
            false : StartTimer;
          end;
      end;
    until lQuit;
  end;
  Terminate;
end;

function TAPIWaitableTimer.GetEnabled: boolean;
begin
  result := (FTimer > 0) and (FCloseEvent > 0) and FRunning;
end;

procedure TAPIWaitableTimer.SetEnabled(const Value: boolean);
begin
  if Value <> Enabled then
    SetEvent(FPauseEvent);
  if suspended then
    resume;
end;

procedure TAPIWaitableTimer.SetInterval(const Value: Int64);
begin
  FInterval := Value;
  if Enabled then StartTimer;
end;

procedure TAPIWaitableTimer.StartTimer;
const WaitDur = 10;
var Duration: TLargeInteger;
    Per : Integer;
begin
  // not sure why have to wait, but else timer sometimes behaves corrupted
  sleep(WaitDur);
  if abs(FInterval) > abs(CTI_MAXINTERVAL_MS) then
    raise Exception.Create('Maximum Interval exceeded!');
  FInterval := FInterval - WaitDur;
  Duration := (-1) * FInterval * CTI_MULT_FACTOR;
  Per := 0;
  FRunning := SetWaitableTimer(FTimer, Duration, Per, nil, nil, true);
  if not FRunning then
    raise Exception.Create(SysErrorMessage(GetLastError));
  if suspended then
    resume;
end;

procedure TAPIWaitableTimer.StopTimer;
begin
  FRunning := false;
  if not CancelWaitableTimer(FTimer) then
    raise Exception.Create(SysErrorMessage(GetLastError));
end;

procedure TAPIWaitableTimer.ThrowTimerEvent;
begin
  if FRunning and Assigned(FOnTimer) then
    FOnTimer(self);
end;

{ TDLLTimer }

constructor TDLLTimer.Create(AContinuous: boolean);
begin
  inherited create;
{$IFDEF MSWINDOWS}
  FHandle := Classes.AllocateHWnd(WndProc);
{$ENDIF}
{$IFDEF LINUX}
  FHandle := WinUtils.AllocateHWnd(WndProc);
{$ENDIF}
  FContinuous := AContinuous;
  FExitEvent := CreateEvent(nil, false, false, '');
  FTimer := TAPIWaitableTimer.Create(AContinuous, FHandle, FExitEvent);
  FTImer.OnTimer := OnAPITimer;
  FTimer.OnTerminate := APITimerTerminated;
end;

destructor TDLLTimer.Destroy;
begin
{$IFDEF MSWINDOWS}
  Classes.DeallocateHWnd(FHandle);
{$ENDIF}
{$IFDEF LINUX}
  WinUtils.DeallocateHWnd(FHandle);
{$ENDIF}
  FTimer.OnTerminate := nil;
  ResetEvent(FExitEvent);
  SetEvent(FTimer.CloseEvent);
  case WaitForSingleObject(FExitEvent, CTI_EXITTIMEOUT) of
    WAIT_OBJECT_0: FTimer := nil;
    WAIT_TIMEOUT : raise Exception.Create('Error releasing DLLTimer');
  end;
  inherited;
end;

procedure TDLLTimer.APITimerTerminated(Sender: TObject);
var lEnabled: boolean;
begin
  lEnabled := FTimer.Enabled;
  if Assigned(FTimer.FatalException) then
    raise Exception.Create(Exception(FTimer.FatalException).Message)
  else
  begin
    ResetEvent(FExitEvent);
    FTimer := TAPIWaitableTimer.Create(FContinuous, FHandle, FExitEvent);
    FTImer.OnTimer := OnAPITimer;
    FTimer.OnTerminate := APITimerTerminated;
    FTimer.Interval := FInterval;
    if lEnabled then
      FTimer.StartTimer;
  end;
end;

function TDLLTimer.GetEnabled: boolean;
begin
  result := FTimer.Enabled;
end;

procedure TDLLTimer.OnAPITimer(Sender: TObject);
begin
  if Assigned(FOnTimer) then
    FOnTimer(Sender);
end;

procedure TDLLTimer.StartTimer(AInterval: Int64);
begin
  FInterval := AInterval;
  FTimer.Interval := AInterval;
  FTimer.Enabled := true;;
end;

procedure TDLLTimer.StopTimer;
begin
  FTimer.Enabled := false;
end;

procedure TDLLTimer.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    WM_TIMER: OnApiTimer(FTimer);
  end;
end;

en
d.
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:48 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz