Delphi FMX下WndProc Hook

因爲FMX是一套跨平臺的組件,所以把消息過程移除掉了,不能愉快的像VCL那樣攔截消息。

現在提供一個簡單攔截消息過程的方法:

開源地址: https://github.com/ying32/FMXWndProcHook

  • 引用單元 FMX.WndProcHook

裏面提供了兩種方式,一是繼承自TWndProcForm或者使用TWndProcHook對象。

下面是繼承自TWndProcForm的演示,完成後就可以像VCL一樣使用攔截消息了(注:需要在Form的DoShow中調用Hook,如果在OnCreate中攔截後會被替換掉消息,造成消息HOOK失效。)。


unit Unit23;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.WndProcHook,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm23 = class(TWndProcForm)
    Button1: TButton;
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    { Public declarations }
    procedure WMMove(var msg: TWMMove); message WM_MOVE;
    procedure WMLButtonDown(var msg: TWMLButtonDown); message WM_LBUTTONDOWN;
  end;

var
  Form23: TForm23;

implementation

{$R *.fmx}

procedure TForm23.Button1Click(Sender: TObject);
begin
  Perform(WM_SYSCOMMAND, SC_MINIMIZE, 0);
end;

procedure TForm23.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  Log.d('mousedown: x=%f, y=%f', [x, y]);
end;

procedure TForm23.WMLButtonDown(var msg: TWMLButtonDown);
begin
  Log.d('鼠標按下: x=%d, y=%d', [Msg.XPos, msg.YPos]);
//  Msg.Result := 1;  // 攔截消息,這樣 FormMouseDown 就收不到這個消息了
end;

procedure TForm23.WMMove(var msg: TWMMove);
begin
  msg.Result := 1;
  Log.d('收到移動的消息');
end;

procedure TForm23.WndProc(var Message: TMessage);
begin
  inherited;
  if Message.Msg = WM_LBUTTONDOWN then
  begin
    Log.d('WndProc 鼠標按下: x=%d, y=%d', [TWMLButtonDown(Message).XPos, TWMLButtonDown(Message).YPos]);
    //Message.Result := 1;  // 攔截消息, WMLButtonDown  FormMouseDown 將都收不到消息
  end;
end;

end.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章