我想知道失去焦点的是谁,应该拦windows的哪个消息?(200分)

  • 主题发起人 主题发起人 WoDing
  • 开始时间 开始时间
W

WoDing

Unregistered / Unconfirmed
GUEST, unregistred user!
当焦点在控件之间进行切换时会产生哪个消息?<br>我首先要捕捉这个消息,并要通过这个消息得到失焦的控件名。
 
WM_KILLFOCUS
 
WM_KILLFOCUS Notification<br><br>--------------------------------------------------------------------------------<br><br>The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. <br><br>Syntax<br><br>WM_KILLFOCUS<br><br>&nbsp; &nbsp; WPARAM wParam<br>&nbsp; &nbsp; LPARAM lParam;<br>&nbsp; &nbsp; <br>Parameters<br><br>wParam<br>Handle to the window that receives the keyboard focus. This parameter can be NULL. <br>lParam<br>This parameter is not used. <br>Return Value<br><br>An application should return zero if it processes this message. <br><br><br><br><br>Remarks<br><br>If an application is displaying a caret, the caret should be destroyed at this point. <br><br>While processing this message, do not make any function calls that display or activate a window. This causes the thread to yield control and can cause the application to stop responding to messages. For more information, see Message Deadlocks. <br><br>Notification Requirements<br><br>Minimum DLL Version None <br>Header Declared in Winuser.h, include Windows.h <br>Minimum operating systems Windows 95, Windows NT 3.1 <br><br>See Also<br><br>Keyboard Input Overview, SetFocus, WM_SETFOCUS<br><br>--------------------------------------------------------------------------------<br><br>? 2003 Microsoft Corporation. All rights reserved.
 
weiwei81123,好像不太满足我的要求,这个好像要重新定义一个类。<br>而我要的是这种形式的:<br>&nbsp; &nbsp; procedure wmkillfocus(var msg:twmkillfocus);message wm_killfocus;<br><br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br>&nbsp;procedure tForm1.wmkillfocus(var msg:twmkillfocus);<br>&nbsp;begin<br>&nbsp; &nbsp;showmessage('');<br>&nbsp;end;<br>end.<br>而我这样写好像只能在form失焦的情况下才会触发!<br><br>
 
lcy 14:42:29<br>你试试onEnter和OnExit事件,消息我没研究过 <br>郭大路 14:44:16<br>用ONEXIT要在每一个控件中写,有点麻烦,因为每个控件的ONEXIT里就有输入检测的代码,又不能公用一个 <br>lcy 14:46:32<br>你控件的Tag属性不会用到吧 <br>lcy 14:50:03<br>将所有控件的OnExit事件指针保存到Tag属性中,在你写的OnExit函数执行完之前,判断一下Tag,如果非0的话,就运行TNotifyEvent(Tag)(Sender)就可以了 <br>lcy 14:50:47<br>就是在他们的事件前插入你的事件,在你的事件代码中再调用他们的事件 <br>
 
不用拦windows消息,以下程序可以满足你的要求。<br>unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, StdCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; Edit2: TEdit;<br>&nbsp; &nbsp; Edit3: TEdit;<br>&nbsp; &nbsp; ListBox1: TListBox;<br>&nbsp; private<br>&nbsp; &nbsp; FLastActive: TWinControl;<br>&nbsp; public<br>&nbsp; &nbsp; procedure ActiveChanged; override;<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TForm1.ActiveChanged;<br>begin<br>&nbsp; inherited;<br>&nbsp; if Assigned(FLastActive) then<br>&nbsp; &nbsp; ListBox1.Items.Append(FLastActive.Name);<br>&nbsp; FLastActive := ActiveControl;<br>end;<br><br>end.<br>
 
这个在Events列表里面的OnEnter 和OnExit函数里面就可以实现的啊<br>就是得到控件的焦点和逝去焦点函数
 
我采用 Application.OnMessage 事件来截取 WM_KILLFOCUS,但是无效?<br>可是我又能在 Spy++ 中看到 WM_KILLFOCUS,是哪里写错了?<br><br>主程序段:<br>&nbsp; Application.Initialize;<br>&nbsp; Application.CreateForm(TForm1, Form1);<br>&nbsp; Application.OnMessage := Form1.MyOnMessage;<br>&nbsp; Application.Run;<br><br>消息处理段:<br>procedure TForm1.MyOnMessage(var Msg: TMsg; var Handled: Boolean);<br>var<br>&nbsp; CurrControl: TWinControl;<br>begin<br>&nbsp; if Msg.message = WM_KILLFOCUS then<br>&nbsp; begin<br>&nbsp; &nbsp; CurrControl := FindControl(Msg.hwnd);<br>&nbsp; &nbsp; if CurrControl &lt;&gt; nil then<br>&nbsp; &nbsp; &nbsp; ShowMessage(CurrControl.Name);<br>&nbsp; end;<br>&nbsp; Handled := False; // 可以删除此句<br>end;
 
to savetime:<br>&nbsp; &nbsp; 你这样写,岂不所有其他消息就完了?[:)]
 
to qince,<br>这样只是应用程序的效率降低了,对其他消息有什么影响吗?<br>我是奇怪为什么拦截不到 WM_KILLFOCUS,但能在 SPY++ 中看到。
 
你前面的截获WM_KILLFOCUS的处理方法只能收到窗口失去焦点情况下的消息是很正常的<br>因为这个窗体上每个控件接收和发送的句柄不是主窗口,而是控件,所以你可以试试看<br>用GetMessage,PeekMessage然后再判断消息的发送窗口,要么就是用钩子钩出你想要的消息
 
简单的问题非要消息消息的,是不是沾了消息程序就高级点?[:D]
 
to 品梅小哥,用ONEXIT要在每一个控件中写,有点麻烦,因为每个控件的ONEXIT里就有输入检测的代码,又不能公用一个
 
东兰梦舞,我是菜鸟当然想用更简单的方法撤。
 
to 东兰梦舞,<br>我测试你的方法只能在按 TAB 键切换时有效,如果直接用鼠标点击就不行。:(
 
为什么不能公用一个?只要空间可以拥有焦点,一般情况下都有对应的焦点处理函数<br>在Events列里面都有OnExit函数啊,你把所有的Onexit指定到一个应该可以的啊
 
我刚用了几个常用的,只要后面有OnExit处理函数的都可以指定到同一个啊
 
to 品梅小哥,<br>Application.OnMessage 是拦截所有发给应用程序的消息,包括控件的消息。<br>控件的 WM_KEYDOWN WM_PAINT 都能拦截到,就是不能拦截 WM_KILLFOCUS?
 
unit Unit1;<br><br>interface<br><br>uses<br>&nbsp; Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br>&nbsp; Dialogs, StdCtrls;<br><br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Edit1: TEdit;<br>&nbsp; &nbsp; Edit2: TEdit;<br>&nbsp; &nbsp; Edit3: TEdit;<br>&nbsp; &nbsp; Edit4: TEdit;<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; Button2: TButton;<br>&nbsp; &nbsp; procedure ObjectExit(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br><br>var<br>&nbsp; Form1: TForm1;<br><br>implementation<br><br>{$R *.dfm}<br><br>procedure TForm1.ObjectExit(Sender: TObject);<br>begin<br>&nbsp; if (Sender is TButton) then<br>&nbsp; &nbsp; ShowMessage((Sender as TButton).Caption + ' losted focus!');<br>&nbsp; if (Sender is TEdit) then<br>&nbsp; &nbsp; ShowMessage((Sender as TEdit).Name + ' losted focus!');<br>&nbsp; // 你可以继续添加其它对象<br>end;<br><br>end.<br><br>窗体:<br>object Form1: TForm1<br>&nbsp; Left = 294<br>&nbsp; Top = 103<br>&nbsp; Width = 696<br>&nbsp; Height = 480<br>&nbsp; Caption = 'Form1'<br>&nbsp; Color = clBtnFace<br>&nbsp; Font.Charset = DEFAULT_CHARSET<br>&nbsp; Font.Color = clWindowText<br>&nbsp; Font.Height = -11<br>&nbsp; Font.Name = 'MS Sans Serif'<br>&nbsp; Font.Style = []<br>&nbsp; OldCreateOrder = False<br>&nbsp; PixelsPerInch = 96<br>&nbsp; TextHeight = 13<br>&nbsp; object Edit1: TEdit<br>&nbsp; &nbsp; Left = 128<br>&nbsp; &nbsp; Top = 56<br>&nbsp; &nbsp; Width = 121<br>&nbsp; &nbsp; Height = 21<br>&nbsp; &nbsp; TabOrder = 0<br>&nbsp; &nbsp; Text = 'Edit1'<br>&nbsp; &nbsp; OnExit = ObjectExit<br>&nbsp; end<br>&nbsp; object Edit2: TEdit<br>&nbsp; &nbsp; Left = 128<br>&nbsp; &nbsp; Top = 96<br>&nbsp; &nbsp; Width = 121<br>&nbsp; &nbsp; Height = 21<br>&nbsp; &nbsp; TabOrder = 1<br>&nbsp; &nbsp; Text = 'Edit2'<br>&nbsp; &nbsp; OnExit = ObjectExit<br>&nbsp; end<br>&nbsp; object Edit3: TEdit<br>&nbsp; &nbsp; Left = 128<br>&nbsp; &nbsp; Top = 128<br>&nbsp; &nbsp; Width = 121<br>&nbsp; &nbsp; Height = 21<br>&nbsp; &nbsp; TabOrder = 2<br>&nbsp; &nbsp; Text = 'Edit3'<br>&nbsp; &nbsp; OnExit = ObjectExit<br>&nbsp; end<br>&nbsp; object Edit4: TEdit<br>&nbsp; &nbsp; Left = 128<br>&nbsp; &nbsp; Top = 160<br>&nbsp; &nbsp; Width = 121<br>&nbsp; &nbsp; Height = 21<br>&nbsp; &nbsp; TabOrder = 3<br>&nbsp; &nbsp; Text = 'Edit4'<br>&nbsp; &nbsp; OnExit = ObjectExit<br>&nbsp; end<br>&nbsp; object Button1: TButton<br>&nbsp; &nbsp; Left = 128<br>&nbsp; &nbsp; Top = 216<br>&nbsp; &nbsp; Width = 75<br>&nbsp; &nbsp; Height = 25<br>&nbsp; &nbsp; Caption = 'Button1'<br>&nbsp; &nbsp; TabOrder = 4<br>&nbsp; &nbsp; OnExit = ObjectExit<br>&nbsp; end<br>&nbsp; object Button2: TButton<br>&nbsp; &nbsp; Left = 128<br>&nbsp; &nbsp; Top = 256<br>&nbsp; &nbsp; Width = 75<br>&nbsp; &nbsp; Height = 25<br>&nbsp; &nbsp; Caption = 'Button2'<br>&nbsp; &nbsp; TabOrder = 5<br>&nbsp; &nbsp; OnExit = ObjectExit<br>&nbsp; end<br>end
 
因为我的ONEXIT本来就有检测输入合法的代码,除非再显式的调用一个公用过程,发帖子就是不想显式的调用,看看有没有其它的方法。<br>to 东兰梦舞,<br>我也是这样,我还认为是自己什么地方错了。:)<br>to ALL,谢谢大家!<br>请继续
 
后退
顶部