我有一个.net MDI应用程序在vb.net编写。我试图编写一个表单,允许用户选择一个特殊的字符,如°,μ,²,³,ɑ等,并将这个字符插入到通过热键或MDI父级的主菜单。如何找到关注哪个控件?
执行此操作的简单方法是找出在调用字符选择表单时哪个控件集中在哪个MDI子表单上,但我找不到任何有关如何执行此操作的信息。
任何想法?
我有一个.net MDI应用程序在vb.net编写。我试图编写一个表单,允许用户选择一个特殊的字符,如°,μ,²,³,ɑ等,并将这个字符插入到通过热键或MDI父级的主菜单。如何找到关注哪个控件?
执行此操作的简单方法是找出在调用字符选择表单时哪个控件集中在哪个MDI子表单上,但我找不到任何有关如何执行此操作的信息。
任何想法?
找到一个更简单的方法 -
[Parent Form].ActiveMdiChild.ActiveControl
添加一个IMessageFilter并监视窗口消息,如WM_SETFOCUS或WM_ACTIVATE。您可以使用Control.FromHandle将IntPtrs转换为.NET控件。
它通过添加的Application.AddMessageFilter应用程序消息循环。有关示例,请参阅http://blogs.msdn.com/csharpfaq/archive/2004/10/20/245412.aspx。 – 2009-10-27 15:03:32
试图 如果m.Msg = H7或m.Msg = H6然后“WM SetFocus的 FocusedControl = Control.FromHandle(m.WParam) 结束如果 它简化版,似乎永远被触发。我收到各种消息,只是没有与这些消息相匹配的消息 - 我在做什么错了? – 2009-10-27 15:07:52
我会在一些例子中发布 – 2009-10-27 15:11:13
你可以像这样添加一个类项目:
public class FocusWatcher
{
private static System.Windows.Forms.Control _focusedControl;
public static System.Windows.Forms.Control FocusedControl
{
get
{
return _focusedControl;
}
}
public static void GotFocus(object sender, EventArgs e)
{
_focusedControl = (System.Windows.Forms.Control)sender;
}
}
然后,你希望成为“最近为重点控制”候选人的任何形式的任何控制,你可以这样做:
textBox1.GotFocus += FocusWatcher.GotFocus;
,然后访问FocusWatcher.FocusedControl
获得最近为重点的控制。监控消息将起作用,但您必须忽略不需要的消息(例如Mdi表单中的WM_ACTIVATE)。
您可以遍历每个窗体上的所有控件,并为GotFocus事件添加此处理程序,但肯定有控件不需要(例如按钮)。您可以改为迭代并仅添加TextBoxes的处理程序。
看起来像WM_SETFOCUS消息没有通过....我的坏。我很确定他们会通过Control.WndProc的方法。作为一种解决方法,我不得不通过p/invoke GetFocus来传递消息并存储具有焦点的控件的句柄。
第一个代码段是过滤器类,第二个代码段是测试代码。
public class LastFocusedControlFilter : IMessageFilter
{
[DllImport("user32")]
private static extern IntPtr GetFocus();
private IntPtr? _lastCtrl;
private readonly Control _ctrlToIgnore;
public LastFocusedControlFilter(Control controlToIgnore)
{
_ctrlToIgnore = controlToIgnore;
}
public bool PreFilterMessage(ref Message m)
{
if (!_ctrlToIgnore.IsHandleCreated || _ctrlToIgnore.Disposing || _ctrlToIgnore.IsDisposed)
{
return false;
}
IntPtr handle = GetFocus();
if (handle != _ctrlToIgnore.Handle)
{
_lastCtrl = handle;
}
return false;
}
public Control GetLastFocusedControl()
{
return _lastCtrl.HasValue ? Control.FromHandle(_lastCtrl.Value) : null;
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Form form = new Form())
{
Action resetBackColor = null;
for (int i = 0; i < 10; i++)
{
TextBox textBox = new TextBox();
resetBackColor += delegate { textBox.BackColor = Color.White; };
textBox.Text = ((char)('a' + i)).ToString();
textBox.Location = new Point(0, textBox.Height * i);
form.Controls.Add(textBox);
}
Button showTextButton = new Button();
LastFocusedControlFilter msgFilter = new LastFocusedControlFilter(showTextButton);
showTextButton.Dock = DockStyle.Bottom;
showTextButton.Text = "Show text of last selected control";
showTextButton.Click += delegate(object sender, EventArgs e)
{
resetBackColor();
Control lastControl = msgFilter.GetLastFocusedControl();
if (lastControl == null)
{
MessageBox.Show("No control previous had focus.");
}
else
{
lastControl.BackColor = Color.Red;
MessageBox.Show(string.Format("Control of type {0} had focus with text '{1}'.", lastControl.GetType(), lastControl.Text));
}
};
form.Controls.Add(showTextButton);
Application.AddMessageFilter(msgFilter);
Application.Run(form);
}
}
}
很棒的答案!感谢你付出的努力! – 2009-10-27 18:02:17
那么确定,如果你认为*一行代码*是“更容易”。 :) – MusiGenesis 2009-10-27 20:39:53
只是更容易,哈哈。 虽然这种方法对于非MDI应用程序来说非常棒,所以我仍然投票赞成。 – 2009-10-29 15:22:23