我需要在delphi应用程序上处理WM_SetFocus或WM_KillFocus,我写了一个这样的消息处理程序:
Procedure Focus(var Msg: TWMSetFocus); message WM_SetFocus;
但它不起作用&不要在WM_SetFocus到达时触发消息处理程序,之后我写了一个应用程序消息处理程序,但反对它不起作用!
我认为此消息直接发送给控件,是真的吗?
任何人都可以帮我这么做吗?
答案 0 :(得分:3)
此答案假设您希望表单上的控件接收消息。
这些消息未排队,直接发送给控件。这就解释了为什么你的两次尝试都失败了。
接收它们的唯一方法是通过控件的窗口过程。您有以下选择。
WindowProc
属性替换窗口过程而不派生新类。您可能会发现TForm.SetFocusedControl
可以提供帮助。它被调用以响应接收WM_SetFocus
消息的控件,以及在其他一些情况下被调用(有关详细信息,请参阅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, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, 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.
答案 1 :(得分:0)
@Mojtaba - 是否将消息直接发送到控件取决于它是什么类型的控件。
正如Andrei K建议的那样,消息只会直接发送给来自TWinControl的控件 - 还有其他控件来自TControl,但它们不是TWinControls。例如,TLabel不是TWinControl的后代,而是TPanel。
对于不是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
答案 2 :(得分:0)
或者你可以使用这个也适用于freepascal
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;