如何找到关注哪个控件?

时间:2009-10-27 14:24:59

标签: .net winforms mdi

我有一个用vb.net编写的.net MDI应用程序。我正在尝试编写一个表单,允许用户选择一个特殊字符,如°,μ,²,³,ɑ等,并将该字符插入到通过以下方式启动表单之前聚焦的任何控件中热键或MDI父级的主菜单。

执行此操作的简单方法是在调用字符选择表单时确定哪个控件关注哪个MDI子窗体,但我找不到有关如何执行此操作的任何信息。

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

看起来WM_SETFOCUS消息没有通过....我的坏。我很确定他们会使用Control.WndProc方法。作为一种解决方法,我不得不暂时调用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);
        }
    }
}

答案 1 :(得分:1)

添加IMessageFilter并监控Windows消息,例如WM_SETFOCUSWM_ACTIVATE。您可以使用Control.FromHandle将IntPtrs转换为.NET控件。

答案 2 :(得分:1)

找到一种更简单的方法 -

[Parent Form].ActiveMdiChild.ActiveControl

答案 3 :(得分:0)

您可以在项目中添加这样的类:

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事件添加此处理程序,但肯定会有想要这样的控件(例如Buttons)。您可以改为迭代并仅添加TextBoxes的处理程序。