1

代表步骤:

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

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

因此,在应用程序之间移动不会触发 Enter/Leave

是否有另一种可供我使用的替代控制级事件,它会在这种情况下触发?

通常,我会使用Form.Activated。不幸的是,这在这里很麻烦,因为我的组件由一个停靠系统托管,该系统可以将我的组件取消停靠到一个新的表单中而无需通知我。

4

10 回答 10

3

你想在 Enter 事件中做什么?

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

有趣的问题,但它需要更多的上下文。

于 2008-10-01T01:40:27.047 回答
1

如果我尝试您的示例并在另一个窗口、桌面等上的控件外部单击,我可以触发 Got 和 Lost Focus 事件,但如果您只是尝试在表单或只有 1 个控件的控件内单击,这些事件永远不会被触发,因为它是唯一需要关注的事情。既不会进入也不会离开,除非你改变动态或超载控制,你不能让这种情况发生

于 2008-10-02T20:58:57.393 回答
0

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

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

于 2008-10-01T04:12:05.013 回答
0

谢谢,我会提供一些背景。

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

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

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

它会工作,除了对接和脱离...

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

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

但是,用户可以通过抓住选项卡标题并将其拖出主应用程序来“撕掉”选项卡。此时,应用程序创建一个新的“浮动表单”来承载控件。就 Control.Enter 和 Form.Activated 事件而言,在主应用程序和此浮动表单之间切换与在应用程序之间切换相同。

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

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

问题是我的 UserControl 与其父窗体的关系是流动的,使得解决方案有些复杂。我尝试连接到“this.ParentForm.Activated”,它工作正常。问题是你什么时候调用这个?当您取消停靠/重新停靠时会发生什么?我最终得到了一堆令人讨厌的代码,其中包含“previousParentForm”之类的东西,这样我就可以从旧表单中解脱出来,然后我仍然面临着当我的父表单被更改时对接系统没有通知我的问题,所以我也必须在那里做一些改变。

这些问题并非无法解决,但如果有一个更简单的控制级“父窗体被激活”事件,那就优雅多了。

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

于 2008-10-01T15:02:08.710 回答
0

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

Grid currentGrid = (Grid)sender;

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

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

于 2008-10-01T17:50:01.567 回答
0

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

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

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

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

于 2008-10-01T18:23:37.087 回答
0

听起来您遇到的问题与 Enter 事件没有直接关系,更重要的是,如果您有“与您的代码无关”的控件,那么您实际上并没有查看控件级别事件.

于 2008-10-01T19:09:59.550 回答
0

估计我不是很清楚。

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

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

维护这个“LastFocusedGrid”参考是我在 Enter 事件中所做的。

如果你想在 Visual Studio 中看到类似的功能,试试这个:

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

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

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

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

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

于 2008-10-01T20:25:00.960 回答
0

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

于 2008-10-01T21:36:17.747 回答
-2

在此示例中,如果您在单击文本框之间切换,则 enter 或 got focus 都不会按预期执行,但是如果您单击子表单,两者都会按预期运行。

    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();
            }
        }
    }
于 2015-08-24T16:35:45.760 回答