How can we know if the user has moved a form?

Determining if a form has moved

Copyright © 2000 Ernesto De Spirito

EurekaLog - Catch and log every exception!

We can know if a form has resized with the Resize event (OnResize property), but how do we know if a form has moved? Simply by capturing the WM_MOVE Windows message:

interface

...

type
  TForm1 = class(TForm)
    ...
  private
    { Private declarations  }
    procedure FormMove(var Msg: TWMMove); message WM_MOVE;
    ...
  end;

...

implementation

...

procedure TForm1.FormMove(var Msg: TWMMove);
begin
  inherited;
  Label1.Caption := Format('(%d,%d)', [Left, Top]);
end;

...

We call "inherited" to let the ancestors of TForm process the message. This will update the Left and Top properties. In the above example we simply displayed them, but we can use this kind of Move event for example to guarantee that the form is always placed within the limits of the screen's work area (the portion of the screen not used by the system taskbar or by application desktop toolbars).

procedure TForm1.FormMove(var Msg: TWMMove);
var
  WorkArea: TRect;
begin
  inherited;
  if SystemParametersInfo(SPI_GETWORKAREA, 0, @WorkArea, 0) then begin
    if Left < WorkArea.Left then
      Left := WorkArea.Left
    else if Left + Width > WorkArea.Right then
      Left := WorkArea.Right - Width;
    if Top < WorkArea.Top then
      Top := WorkArea.Top
    else if Top + Height > WorkArea.Bottom then
      Top := WorkArea.Bottom - Height;
  end;
end;

You can find the full source code of this article in the archive that accompanies the Pascal Newsletter #20

JfControls Library - for Delphi and C++ Builder