问题描述
|
我需要在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。例如,TLabel不是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;