Control.Enter 事件在切换任务时不触发.有没有其他选择

本文关键字:有没有 选择 其他 任务 事件 Enter Control | 更新日期: 2023-09-27 17:47:22

代表步骤:

  1. 创建示例 .NET 表单应用程序
  2. 在窗体上放置一个文本框
  3. 将函数连接到文本框的 Enter 事件

运行此应用程序时,当焦点首次转到文本框时,将触发 Control.Enter 事件。 但是,如果单击另一个应用程序,然后单击返回到测试应用程序,则不会再次触发该事件。

因此,在应用程序之间移动不会触发进入/离开

是否有另一个可以使用的替代控件级事件,该事件将在此方案中触发?

通常,我会使用 Form.Active。 不幸的是,这很麻烦,因为我的组件由停靠系统托管,该系统可以在不通知我的情况下将我的组件取消停靠到新表单中。

Control.Enter 事件在切换任务时不触发.有没有其他选择

你想在

Enter 事件中做什么?

我找不到在您的示例程序中触发的另一个控件级事件,但是当我的测试应用确实重新获得焦点时,上次具有焦点的控件仍然具有该焦点。

有趣的问题,但它需要更多的背景。

如果我尝试您的示例并在另一个窗口、桌面等上的控件外部单击,我可以触发 Got 和 Lost Focus 事件,但是如果您只尝试在只有一个控件的窗体或控件内单击,则永远不会触发这些事件,因为它是唯一需要关注的事情。 输入或离开都不会,除非您更改动态或重载控件,否则您无法发生这种情况

在您的示例中,我认为您需要另一个控件。 原因是第一个控件 (tabIndex 0) 是具有焦点的控件。 如果没有其他控件可以切换焦点,则此控件将始终处于焦点状态,因此永远无法进入。 切换到另一个应用程序或窗体不会更改此窗体中的焦点或活动控件,因此当您返回时,您仍然不会触发事件。

添加控件后,输入控件应该可以正常工作。 如果这是您唯一的控件,为什么不在窗体获得焦点时调用 formLoad 或 TextChange 上的事件?

谢谢,我会给出一些背景。

我的控件是包含网格和工具栏的用户控件。 用户通常会启动其中的几个控件来查看系统数据的不同切片。

有几个键盘快捷键可以从当前网格中的选定行启动操作。 但是,要求这些键盘快捷键不仅应应用于当前聚焦的网格。 如果用户当前专注于应用程序的许多其他区域之一,则此键盘快捷方式仍应有效,并且应路由到最后一个焦点网格

所以我将一个函数连接到我的UserControl的Control.Enter事件,基本上说LastFocusedGrid = this。

它会起作用,除了对接和取消对接...

请参阅,这些控件托管在具有停靠功能的应用程序内,有点类似于 Visual Studio。

默认情况下,控件作为应用程序主工作区内的选项卡启动,类似于源文件在 Visual Studio 中打开的方式。

但是,用户可以通过抓取选项卡标题并将其拖出主应用程序来"撕掉"选项卡。 此时,应用程序创建一个新的"浮点窗体"来承载控件。 在主应用程序和此浮动窗体之间切换与在应用程序之间切换相同,以便用于 Control.Enter 和 Form.Activated 事件。

此时,我们有了使用原始帖子中描述的示例应用程序模拟的"表单中的一个控件"场景。

现在,有一些方法可以解决这个问题。 我可以利用 Form.Activated 事件,该事件在窗体之间切换时会触发。 如果将测试应用程序中的事件添加到窗体的已激活事件,您将看到它工作得很好。

问题是我的 UserControl 与其父窗体的关系是流动的,这使得解决方案有些复杂。 我试着连接到"这个。ParentForm.Active",工作正常。 问题是你什么时候称呼这个? 当您断开停靠/重新停靠时会发生什么? 我最终得到了一堆令人讨厌的代码,其中包含"previousParentForm"之类的东西,以便我可以从旧表单中解脱出来,然后我仍然面临对接系统在我的父表单被更改时不通知我的问题,所以我将不得不在那里进行一堆更改, 太。

这些问题并非无法解决,但如果有一个更简单的控件级"父窗体已激活"事件,那么这将更加优雅。

这相当长,但我希望它能澄清情况。

那么在创建网格时,您不能设置按键或 KeyUp 等事件吗? 如果是这样,则所有网格都可以使用相同的事件处理程序。 只需确保在进入事件处理程序时执行以下操作:

Grid currentGrid = (Grid)sender;

然后,您应该能够将该代码块应用于发送的任何网格,而不必担心跟踪。

由于所有事件处理程序都是,因此它的位置实际上是一个静音点,只要执行它所需的所有内容都是可访问的。

Frye,问题是无论用户在应用程序中的哪个位置,键盘快捷键都应该工作。 它们是全局命令,在顶层处理,然后路由到"最后一个聚焦网格"。

因此,在网格级别处理击键将无济于事。

更具体地说,假设用户启动网格 A、B 和 C。 但他也启动了其他与我的代码无关的控件 X、Y 和 Z。

用户单击A,然后单击C。 然后他点击Y,然后点击Z。 专注于Z,他点击了我的键盘快捷键。 在这种情况下,网格 C 应该响应,因为它是用户关注的最后一个网格。

听起来您遇到的问题与 Enter 事件没有直接关系,更重要的是,如果您有"与您的代码无关"的控件,那么您真的没有查看控件级别事件。

猜我不清楚。

我的控件位于容器应用程序中。 其他团队的其他不相关的控件也是如此。 把它想象成Visual Studio - 我的控件是代码编辑选项卡,但也有挂起的更改列表和属性窗口,它们与源文件共存,但没有直接关系。

键盘快捷方式由容器应用程序处理。 然后,它应该路由到用户关注的最后一个控件。

维护这个"LastFocusedGrid"引用是我在 Enter 事件中所做的。

如果你想在Visual Studio中看到类似的功能,请尝试以下操作:

  1. 打开几个源文件
  2. 导航到"起始页"选项卡。
  3. 按 Ctrl-F 并在"当前文档"中搜索一些字符串
  4. 请注意,serach 功能会自动导航到"最后焦点"源文件以执行搜索。

因此,即使您没有聚焦于源文件,ctrl-F 命令也会由 Visual Studio 处理并路由到最后一个聚焦的源文件选项卡。

现在用 Ctrl-G 尝试同样的事情。 除非您直接专注于源文件,否则它不起作用。

我的键盘命令需要像 Ctrl-F 一样工作,而不是像 Ctrl-G。 这就是为什么我不只是直接在我的控件中捕获键盘事件。

这是否澄清或使事情变得更糟?

您是否尝试过一个简单的 Control.GotFocus?

在此

示例中,如果您在单击文本框之间切换,则 Enter 或 Get 焦点都不会按预期执行,但是,如果您单击子窗体,则两者都将按预期运行。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    namespace EnterBrokenExample
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Form Form1 = new Form();
                Form c1 = new Form();
                Form c2 = new Form();
                Form1.IsMdiContainer = true;
                c1.MdiParent = Form1;
                c2.MdiParent = Form1;
                c1.Show();
                c2.Show();
                TextBox tb1 = new TextBox();
                c1.Controls.Add(tb1);
                tb1.Enter += ontbenter;
                tb1.Text = "Some Text";
                tb1.GotFocus += ongotfocus;
                TextBox tb2 = new TextBox();
                c2.Controls.Add(tb2);
                tb2.Enter += ontbenter;
                tb2.Text = "some other text";
                tb2.GotFocus += ongotfocus;
                Application.Run(Form1);
            }
            static void ontbenter(object sender, EventArgs args)
            {
                if (!(sender is TextBox))
                    return;
                TextBox s = (TextBox)sender;
                s.SelectAll();
            }
            static void ongotfocus(object sender, EventArgs args)
            {
                if (!(sender is TextBox))
                    return;
                TextBox s = (TextBox)sender;
                s.SelectAll();
            }
        }
    }