How to detect docking / undocking  Download
This is a Delphi function that waits for docking/undocking event. It utilizes TWmiSystemEvents component to wait for the event. As noted in the help file, this will only work under Windows XP and higher. Writing an event handler for the UI type application is pretty straight forward: drop TWmiSystemEvents component on the form, go to the Events tab of Object Inspector, double click on the OnDocking event.

The code below demonstrates how to create an event handler in the console application. The function WaitForDocking returns true if docking or undocking happened, and false if the specified time elapsed.


type
  // this object is required only in console applications.
  // In UI applications the TWmiSystemEvents component can be
  // dropped on the form, the event handler will be the form's method.
  TWaitObject = class
  private
    FEventHappend: boolean;
  private
    procedure EventHandler(AObject: TObject);
  public
    property EventHappend: boolean read FEventHappend;
  end;

procedure TWaitObject.EventHandler(AObject: TObject);
begin
  FEventHappend := true;
end;

// this is needed to avoid blocking in the tight loop.
// it only needed in console application.
// UI type application is normally event-driven and does not have
// the tight loops. 
procedure ProcessMessage;
var
  Msg: TMsg;
begin
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end;

// this function waits for docking/undocking event for specified time.
// it returns true if the event happed and false if the specified
// time elapsed.
function WaitForDocking(WaitTimeMillisec: integer): boolean;
var
  vWmiEvents: TWmiSystemEvents;
  vDeadline: TDateTime;
  vWaitObject: TWaitObject;
  vTime: double;
const
  SECOND = 1/24/60/60;  
begin
  Result    := false;
  vTime     := WaitTimeMillisec;
  vDeadline := Now + (vTime/1000) * SECOND;

  // setup: create and link the components together
  vWaitObject := TWaitObject.Create;
  vWmiEvents  := TWmiSystemEvents.Create(nil);
  try
     vWmiEvents.PoolingInterval := 100;
     vWmiEvents.OnDocking := vWaitObject.EventHandler;
    // try to activate. It may fail if the computer does not have
    // WMI (like windows 95, 98, NT without WMI core installed)
    try
      vWmiEvents.Active := true;
    except
      Exit;
    end;

    while  Now < vDeadline do
      if vWaitObject.EventHappend then
      begin
        Result := true;
        Exit;
      end else
      begin
        Sleep(100);
        ProcessMessage; // avoids tight loop.
      end;

  finally
    vWmiEvents.Free;
    vWaitObject.Free;
  end;
end;