有没有办法检测Winform文本框的离开事件是由Tab或Shift-Tab或其他事件触发的

本文关键字:事件 Tab Shift-Tab 其他 离开 检测 Winform 文本 有没有 | 更新日期: 2024-10-30 14:27:33

我现在跳过我的代码;用语言描述应该更容易。

到目前为止,我有以下逻辑在工作:

    我有一个输入文本框,
  1. 当用户输入错误文本时,我会显示一条错误消息并将焦点返回到文本框。
  2. 当用户不输入任何内容或删除其中的内容并离开文本框时,它会执行一些处理,但其他行为会像它一样 - 按 Tab 键顺序跳转到下一个控件。
  3. 如果我按 Tab 关闭,则在按 Shift-Tab 或将焦点放在我用鼠标单击的任何内容上时跳转到上一个控件。
  4. 如果我为某些可以自动完成的文本输入唯一的前缀,例如可以自动完成为"artichoke"的"articho",则代码会自动填充旁边的另一个只读文本框,并跳到只读文本框的下一个邻居。注意:如果我使用相同的输入 Shift-Tab,那么它会做同样的事情,但在这种情况下我想执行不同的逻辑。
  5. 就像 4. 但是如果我通过单击鼠标离开,那么代码确实会自动填充文本框 - 很棒,但它也会选择我想要的控件。

现在被打破的是 4 的秃头部分; 如果我尝试使用 Shift-Tab 向后循环所有交互式(而不是标签或禁用的)控件,我不能 - 我的自定义逻辑每 4. 启动并将焦点向前发送。只有当我手头的文本框中填写了一些东西时,这只是一个问题,但我仍然想修复这个边缘情况。

有什么想法吗?问题?

附言我不知道如何回答"你试过什么?"类型的问题,只能说我使用了WinForms几个月,我不确定如何在这里进行。谢谢。

有没有办法检测Winform文本框的离开事件是由Tab或Shift-Tab或其他事件触发的

您可能想尝试文本框的 PreviewKeyDown 事件,您可以在其中识别正在按下的组合键,如果是 Shift + Tab 键按下,则执行不同的逻辑。

这是我的做法。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace LeaveTest {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }
        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);
            textBox2.LostFocus += new EventHandler(textBox2_LostFocus);
        }
        void textBox2_LostFocus(object sender, EventArgs e) {
            Control newControl = GetCurrentControl();
            Control prevControl = GetPrevControl(textBox2);
            Control nextControl = GetNextControl(textBox2);
            if (newControl.Handle == prevControl.Handle) {
                MessageBox.Show("Case 4");
            }
        }
        [DllImport("user32.dll")]
        static extern IntPtr GetFocus();
        [DllImport("user32.dll")]
        static extern IntPtr GetNextDlgTabItem(IntPtr hDlg, IntPtr hCtl,
           bool bPrevious);
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
        enum GetWindow_Cmd : uint {
            GW_HWNDFIRST = 0,
            GW_HWNDLAST = 1,
            GW_HWNDNEXT = 2,
            GW_HWNDPREV = 3,
            GW_OWNER = 4,
            GW_CHILD = 5,
            GW_ENABLEDPOPUP = 6
        }

        private Control GetCurrentControl() {
            IntPtr hWnd = GetFocus();
            Control control = Control.FromHandle(hWnd);
            return control;
        }
        private Control GetNextControl(Control ctrl) {
            // I know the last parameter looks wierd, but it works
            IntPtr hWnd = GetNextDlgTabItem(ctrl.Parent.Handle, ctrl.Handle, true);
            Control control = Control.FromHandle(hWnd);
            return control;
        }
        private Control GetPrevControl(Control ctrl) {
            // I know the last parameter looks wierd, but it works
            IntPtr hWnd = GetNextDlgTabItem(ctrl.Parent.Handle, ctrl.Handle, false);
            Control control = Control.FromHandle(hWnd);
            return control;
        }
    }
}