代码之家  ›  专栏  ›  技术社区  ›  tom.dietrich

我如何找到集中在哪个控件上?

  •  1
  • tom.dietrich  · 技术社区  · 17 年前

    我有一个用vb.net编写的.NET MDI应用程序。我正在尝试编程一个表单,该表单允许用户选择一个特殊字符,如_?、?、?、?、?、等等,并在通过热键或MDI父级中的主菜单启动表单之前,将该字符插入到所关注的任何控件中。

    实现这一点的简单方法是,在调用字符选择窗体时,找出哪个控件集中在哪个MDI子窗体上,但我找不到有关如何实现这一点的任何信息。

    有什么想法吗?

    4 回复  |  直到 17 年前
        1
  •  2
  •   Hasani Blackwell    17 年前

    看起来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);
            }
        }
    }
    
        2
  •  1
  •   Hasani Blackwell    17 年前

    添加一个 IMessageFilter 和监视Windows消息,如 WM_SETFOCUS 或 WM_ACTIVATE . 你可以使用 Control.FromHandle 将Intprs转换为.NET控件。

        3
  •  1
  •   tom.dietrich    17 年前

    找到一个更简单的方法-

    [Parent Form].ActiveMdiChild.ActiveControl
    
        4
  •  0
  •   MusiGenesis    17 年前

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

    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_)。

    您可以遍历每个窗体上的所有控件,并为gotfocus事件添加此处理程序,但确实有一些控件 不要 希望这样做(例如按钮)。您可以迭代并只添加文本框的处理程序。

    推荐文章