【问题标题】:Excel CustomTaskPane with WebBrowser control - keyboard/focus issues带有 WebBrowser 控件的 Excel CustomTaskPane - 键盘/焦点问题
【发布时间】:2019-05-23 17:38:18
【问题描述】:

我遇到了这个确切的问题https://social.msdn.microsoft.com/Forums/vstudio/en-US/e417e686-032c-4324-b778-fef66c7687cd/excel-customtaskpane-with-webbrowser-control-keyboardfocus-issues?forum=vsto

这里也提到了https://connect.microsoft.com/VisualStudio/feedback/details/521465/the-focus-issue-between-excel-cells-and-excel-customtaskpane-with-webbrowser-control

我正在使用 Visual Studio Professional 2013 编写一个 Excel 2010 插件。我创建了一个简单的 CustomTaskPane,其中包含一个 System.Windows.Forms.WebBrowser 子文件。该插件工作正常,我可以通过单击在网络浏览器中导航并更改复选框的状态。

当我点击输入文本框时,我获得焦点并且看到光标闪烁,但是当我开始输入时,文本会发送到 Excel 并写入单元格而不是浏览器内的文本框。

我在功能区加载时添加自定义任务窗格。

private void Ribbon_Load(object sender, RibbonUIEventArgs e)
{
  TaskPaneView taskPaneView = new TaskPaneView();
  Microsoft.Office.Tools.CustomTaskPane myTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(taskPaneView, "Title");
  myTaskPane.Visible = true;
}

当我点击文本框然后点击F6 它可以正常工作。 customtaskpane 标题稍微变暗,文本被捕获在文本框中。

我该如何解决这个问题,以便当我点击输入文本框时,文本会进入框中而不是 Excel?

编辑:好的,我做了更多测试。如果我在我的 TaskPaneView 上添加事件以跟踪鼠标输入并单击它们会起作用,但前提是我删除了 Web 浏览器子项。这意味着 Web 浏览器会以某种方式阻止这些事件并阻止 TaskPaneView 理解它具有焦点。如果我还在浏览器旁边的 TaskPaneView 中添加了一个文本框表单控件,则文本框工作得很好,TaskPaneView 理解它有焦点,然后浏览器内的输入文本字段开始工作。如果我直接在 Web 浏览器上调用 focus 方法,TaskPaneView 会理解它有焦点并且一切正常。很明显,问题不在于键盘,而是当单击浏览器时,TaskPaneView 没有被告知它具有焦点,因此击键进入了错误的区域。如果我能找到一种方法让 TaskPaneView 理解它有焦点,那么一切都应该工作。

【问题讨论】:

标签: c# excel winforms excel-2010 vsto


【解决方案1】:

好的,我可以使用以下代码解决此问题

protected override void WndProc(ref Message m)
{
  const int WM_PARENTNOTIFY = 528;
  if(m.Msg == WM_PARENTNOTIFY && !this.Focused)
  {
    this.Focus();
  }
  base.WndProc(ref m);
}

我将此功能添加到我的 TaskPaneView 中,它只是一个带有该 webbrowser 子级的 UserControl。我对它为什么或如何工作没有深入的了解,但基本上我认为正在发生的事情是我正在拦截 WndProc,这是一些处理发送到窗口的消息的低级函数。我用它来检查消息是否为 528,我认为这意味着 notifyParent。我不知道这是否正是我应该收听的消息,但它似乎有效。

一旦我得到正确的消息消息,我会检查 TaskPaneView 是否有焦点,如果没有,我会使用 focus() 函数将其焦点。我之前进行了测试,表明如果我在 TaskPaneView 上手动调用 focus 一切正常。所以如果我没有焦点,然后手动请求焦点,我们都很好。

如果有人能提供更详细的解释说明为什么这样可以让我更好地理解它,我将不胜感激,但至少我解决了这个问题。感谢 Jeremy Thompson 让我以新的方式思考这个问题。

【讨论】:

  • 搜索了几天并尝试了各种不成功的修复(包括令人印象深刻的 globalmousekeyhook 库@@github.com/gmamaladze/globalmousekeyhook),但没有什么比这更令人印象深刻了。它就像一个魅力。非常感谢。
【解决方案2】:

问:请提供更详细的解释说明为什么会这样,以便我更好地理解它

很高兴你让它工作了!要执行根本原因分析,我们需要查看 528 消息的发送位置,并且我们需要 Microsoft Excel 源代码来执行此操作。

我认为不值得再花时间对其进行故障排除或 找出它发生的原因,因为它是一个错误!记录连接 帮助微软修复它的错误是你能做的最好的事情。我们只能解决它, 这是他们源代码的问题。

您在 VSTO 中发现这些场景的错误非常少见,而且您肯定已经找到了;用户在加载项文本框中输入文本输入,消息流入工作表中的单元格!在我的情况下;消息未发送到Calendars_SelectedChange() 事件的位置。所以我们可以看到汉斯很好地解释了这里形成的行为主题(引用我在评论中链接到的问答)

永远不会有问题(即经常有问题)是您依赖 Excel 中的消息泵来发送 Windows 消息,这些消息使这些控件响应输入。这在 WPF 中和 Winforms 一样出错,它们有自己的调度循环,可以在消息传递到窗口之前对其进行过滤。不使用各自的调度程序时出现的关键问题是跳格键和快捷键

然后一些,这种问题将由 Excel 在发送消息之前进行自己的过滤引起。我猜是反恶意软件功能,微软一直担心程序会干扰 Office 应用程序。

别忘了VSTO WPF Connect case with menu's not receiving click events。解决方法涉及使用 DispatcherFrame 来泵送消息并为菜单订阅 GotFocusEvent 和 LostFocusEvent

因此,该错误与响应输入的控件以及在调度循环中被错误过滤或重定向的 void WndProc(ref Message m) 消息有关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多