在Delphi上处理WM_SetFocus或WM_KillFocus

问题描述

| 我需要在delphi应用程序上处理WM_SetFocus或WM_KillFocus,我编写了一个消息处理程序,如下所示:
Procedure Focus(var Msg: TWMSetFocus); message WM_SetFocus;
但是它不起作用,不要在WM_SetFocus到达时触发消息处理程序,此后,我编写了一个应用程序消息处理程序,但是对它不起作用! 我认为此消息直接发送给控制者,是真的吗? 有人可以帮助我做到这一点吗?     

解决方法

        此答案假定您希望表单上的控件接收消息。 这些消息是非排队的,并直接发送到控件。这就解释了您两次尝试接收失败的原因。 接收它们的唯一方法是通过控件的窗口过程。您有以下选择。 子类化控件并处理消息。插入器类可能最容易做到这一点。 使用控件的
WindowProc
属性替换窗口过程,而无需派生新类。 您可能会发现
TForm.SetFocusedControl
会有所帮助。响应于控件接收到“ 3”消息而调用它,以及在某些其他情况下调用它(有关详细信息,请参见VCL代码)。 选项1:插入器
unit uWindowProc;

interface

uses
  Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls;

type
  TEdit = class(StdCtrls.TEdit)
  protected
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  end;

  TMyForm = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
  end;

var
  MyForm: TMyForm;

implementation

{$R *.dfm}

{ TEdit }

procedure TEdit.WMSetFocus(var Message: TWMSetFocus);
begin
  inherited;
  Beep;
end;

end.
选项2:WindowProc
unit uWindowProc;

interface

uses
  Windows,StdCtrls;

type
  TMyForm = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    procedure FormCreate(Sender: TObject);
  private
    FOriginalWindowProc: TWndMethod;
    procedure NewWindowProc(var Message: TMessage);
  end;

var
  MyForm: TMyForm;

implementation

{$R *.dfm}

procedure TMyForm.FormCreate(Sender: TObject);
begin
  FOriginalWindowProc := Edit1.WindowProc;
  Edit1.WindowProc := NewWindowProc;
end;

procedure TMyForm.NewWindowProc(var Message: TMessage);
begin
  if Message.Msg=WM_SETFOCUS then
    Beep;
  FOriginalWindowProc(Message);
end;

end.
    ,        @Mojtaba-是否将消息直接发送到控件取决于它是哪种控件。 正如Andrei K建议的那样,仅将消息直接发送到TWinControl派生的控件-其他控件是TControl派生的,但不是TWinControls。例如,TL​​abel不是TWinControl的后代,而TPanel是TWinnel的后代。 对于不是TWinControl的控件,消息将发送到内部处理消息的Delphi应用程序的默认消息处理程序(通常是应用程序的“主窗体”消息处理程序),具体取决于消息内容。 看到: TWinControl: http://docwiki.embarcadero.com/VCL/en/Controls.TWinControl TLabel: http://docwiki.embarcadero.com/VCL/en/StdCtrls.TLabel TPanel: http://docwiki.embarcadero.com/VCL/XE/en/ExtCtrls.TPanel     ,        或者您也可以在freepascal上使用此wich
var
  Form1: TForm1;
  OldProc : Pointer;
  counter : Integer = 0;
implementation

{$R *.dfm}

function WndProc1(hw:HWND;Msg:Cardinal;wparam:WPARAM;lparam:LPARAM):LResult;stdcall;
begin
  if Msg = WM_SETFOCUS then
  begin
    Inc(counter);
    Form1.Caption:=IntToStr(counter);
  end;
  Result := CallWindowProc(oldProc,hw,Msg,wparam,lparam);
end;

procedure TForm1.FormShow(Sender: TObject);
var
newproc:Pointer;
begin
  DWORD(OldProc) := GetWindowLong(Edit1.Handle,GWL_WNDPROC);
  newproc := @WndProc1;
  SetWindowLong(Edit1.Handle,GWL_WNDPROC,Integer(newproc));
end;