我需要處理WM_SETFOCUS或WM_KILLFOCUS在Delphi應用程序,我寫了這樣一個消息處理程序:處理WM_SETFOCUS或WM_KILLFOCUS德爾福
Procedure Focus(var Msg: TWMSetFocus); message WM_SetFocus;
,但它不工作&別,叔火消息處理程序時WM_SetFocus到達後,我寫了一個應用程序消息處理程序,但對它沒有工作!
我覺得這個消息直接發送來控制,這是真的嗎?
任何人都可以幫助我做到這一點?
我需要處理WM_SETFOCUS或WM_KILLFOCUS在Delphi應用程序,我寫了這樣一個消息處理程序:處理WM_SETFOCUS或WM_KILLFOCUS德爾福
Procedure Focus(var Msg: TWMSetFocus); message WM_SetFocus;
,但它不工作&別,叔火消息處理程序時WM_SetFocus到達後,我寫了一個應用程序消息處理程序,但對它沒有工作!
我覺得這個消息直接發送來控制,這是真的嗎?
任何人都可以幫助我做到這一點?
此答案假設您希望消息被窗體上的控件接收。
這些消息是非排隊的,並直接發送到控件。這就解釋了爲什麼你的兩次嘗試接收它們失敗了。
接收它們的唯一方法是通過控件的窗口過程。您有以下選項。
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.
但是他控制了控件的「子類」(可能是任何類型的控件):他爲該類添加了自己的消息處理程序。每個TObject後代自動調用消息處理程序,但是從TControl開始,消息只有在WndProc允許它們通過時纔會到達處理程序。所以如果他的處理程序從不開火,我想他或者別的WndProc會阻止這個信息。這就是爲什麼我認爲「控制」是MainForm的原因。 – NGLN 2011-05-28 07:15:41
@NGLN我敢打賭,OP的問題中的消息處理程序與窗體而不是控件相關聯。 – 2011-05-28 07:16:47
我的觀點正確:他在他的表格上嘗試這一點。我甚至認爲這是設計。 – NGLN 2011-05-28 07:24:21
@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
更正:如果消息未排隊(即,使用SendMessage發送),則直接向控件發送消息。如果郵件是排隊郵件(即使用PostMessage發佈),則通過郵件隊列發送郵件(對Application.OnMessage可見)。 – 2011-05-28 06:27:50
更正2:非窗口控件不會收到輸入焦點,因此甚至從未與這些消息關聯 – 2011-05-28 06:39:50
@David - 1)「消息直接發送到控件...」 - 我假設您正在討論TWinControls。 2)「非窗口控件沒有獲得輸入焦點」:我一般說話,但是我遵循你的優越知識,在非窗口控件的情況下,焦點消息是不相關的(這非常合理)。我收集OP顯然是在談論一個窗口控件,因爲問題是關於WM_SETFOCUS,WM_KILLFOCUS和setFocus,但也許這不是他們的代碼執行的地方。 – Vector 2011-05-28 07:17:36
或者您可以使用此至極適用於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;
你應該真的把全局變量移動到類 – 2011-05-28 07:20:42
任何特定的原因? – opc0de 2011-05-28 07:21:53
這是行不通的,因爲您正在設置窗體的窗口過程而不是感興趣的控件。這是複製OP已經嘗試過的一種混亂方式。這與重寫TForm1.WndProc並無不同。 – 2011-05-28 07:24:54
你爲什麼寫了一個消息處理程序?它是TWinControl的下降嗎? – 2011-05-28 06:01:24
等一下!再次,您希望哪些窗口收到這些通知? – 2011-05-28 06:46:49
該控件的'OnEnter' /'OnExit'將不起作用? – 2011-05-28 08:27:22