Archive

Archive for November 14, 2013

Handle messages without forms?

November 14, 2013 Leave a comment

Want to handle messages without creating an actual form? Send messages between a thread and your main app? Or just impress your friends by using messages to communicate between forms? This is a very handy class that i’ve used over the years. Just override “HandleMessage” to intercept and process your own messages (ps: dispatch is your friend).

  TMessageHandler = Class(TObject)
  private
    FHandle:    HWND;
  protected
    Property    Handle:HWND read FHandle;
    Procedure   HandleMessage(var message:TMessage);virtual;
  public
    Constructor Create;virtual;
    Destructor  Destroy;Override;
  End;

constructor TMessageHandler.Create;
begin
  inherited Create;
  FHandle:=AllocateHWnd(HandleMessage);
end;

destructor TMessageHandler.Destroy;
begin
  DeallocateHWnd(FHandle);
  inherited;
end;

procedure TMessageHandler.HandleMessage(var Message:TMessage);
begin
  Message.Result := DefWindowProc(FHandle, Message.Msg,
  Message.wParam, Message.lParam);
end;

Delayed non-blocking callback function

November 14, 2013 1 comment

In my previous post regarding a delayed callback function under Delphi I should have pointed out that it was coded for a form-based environment. Meaning that it allows the GUI to remain responsive and other events to fire by calling application.processmessages at a regular intervals. It was indeed “blocking” in the sense that it also functions as a friendly alternative to the sleep API function.

For a complete non-blocking solution, one that truly “calls back later”, more or less a replica of the Smart Pascal callback (which essentially is the JavaScript callback), we have to add a bit more. Here is a minimalistic version of a OS friendly callback function:

  unit w3callback;

  interface

  uses System.SysUtils, Winapi.Windows, System.Generics.Collections;

  procedure w3_callback(const aCallback:TProc;ms:Integer);

  implementation

  var
  _LUT: TDictionary<UINT,TProc>;

  procedure w3_callback(const aCallback:TProc;ms:Integer);
    procedure w3_invoke(hwnd: HWND; uMsg: UINT;
              idEvent: UINT_PTR;dwTime: DWORD);stdcall;
    var
      mProc:  TProc;
    begin
      KillTimer(0,idEvent);
      if assigned(_LUT) then
      begin
        mproc:=_lut.Items[idEvent];
        _lut.Remove(idEvent);
        if assigned(mProc) then
        mproc;
      end;
    end;
  begin
    if Assigned(_LUT) then
    _LUT.add(SetTimer(0,0,ms,@w3_invoke),aCallback);
  end;

  initialization
  _LUT:=TDictionary<UINT,TProc>.Create;

  finalization
  if Assigned(_LUT) then
  FreeAndNil(_LUT);

  end.