我正在使用Visual Studio Professional 2013编写Excel 2010插件。我已经创建了一个简单的CustomTaskPane,其中包含一个System.Windows.Forms.WebBrowser子文件。该插件工作正常,我可以通过单击并更改复选框的状态在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浏览器以某种方式阻止这些事件并阻止TaskPaneView理解它具有焦点。如果我还在浏览器旁边的TaskPaneView中添加了一个文本框表单控件,文本框工作正常,TaskPaneView理解它有焦点,然后浏览器中的输入文本字段开始工作。如果我直接在Web浏览器上调用焦点方法,则TaskPaneView会理解它具有焦点并且一切正常。很明显,问题并不是真的与键盘有关,而是在点击浏览器时没有告诉它有焦点的TaskPaneView问题所以键击会转到错误的区域。如果我能找到一种方法让TaskPaneView理解它有焦点,那么每个标志都应该有用。
答案 0 :(得分:8)
好的,我可以使用以下代码解决问题
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
让我以新的方式思考这个问题。
答案 1 :(得分:3)
问:提供更详细的说明,了解其原因,以便我更好地理解
很高兴你得到它的工作!要执行根本原因分析,我们需要查看528消息的发送位置,我们需要Microsoft Excel源代码才能执行此操作。
我认为不值得花时间进行故障排除或 弄清楚它为什么会发生,因为它是一个BUG!记录连接 帮助微软修复它的bug是你能做的最好的事情。我们只能解决它, 这是他们源代码中的一个问题。
很少见到你在VSTO中发现这些场景看到错误,你肯定找到了一个;用户将文本输入输入到加载项文本框中,并且消息流入工作表中的单元格!在我的情况下;消息未被提取到Calendars_SelectedChange()
事件的位置。因此,我们可以看到Hans在这里形成的行为的一个主题,很好地解释了(引自我在评论中链接到的Q& A):
什么永远不是问题(即通常可能有问题)是您依靠Excel中的消息泵来分派Windows消息,使这些控件响应输入的消息。 WPF和Winforms一样出错,它们有自己的调度循环,在消息传递到窗口之前过滤消息。当他们各自的调度员没有被使用时出现问题的关键事项就像tabbing和快捷键击。
然后一些,这种问题将由Excel在调度消息之前进行自己的过滤。我猜测反恶意软件的功能,微软总是担心乱搞Office应用程序的程序。
不要忘记VSTO WPF Connect case with menu's not receiving click events。解决方法涉及使用DispatcherFrame来提取消息并订阅菜单的 GotFocusEvent和LostFocusEvent 。
因此,该错误与响应输入的控件有关,而void WndProc(ref Message m)
消息在调度循环中被错误地过滤或重定向。