Excel CustomTaskPane с управлением WebBrowser - проблемы с клавиатурой/фокусом
У меня такая точная проблема 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
Я пишу плагин Excel 2010 с помощью Visual Studio Professional 2013. Я создал простую CustomTaskPane с дочерним элементом System.Windows.Forms.WebBrowser. Плагин работает очень хорошо, и я могу перемещаться внутри веб-браузера щелчком и изменять состояние флажков.
![enter image description here]()
Когда я нажимаю на текстовое поле ввода, я получаю фокус, и я вижу, что курсор мигает, но когда я начинаю вводить текст, он отправляется в 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?
EDIT: Хорошо, я сделал еще несколько тестов.. Если я добавлю события в свой TaskPaneView для отслеживания ввода мыши и нажмите, они работают, но только если я удалю дочерний элемент веб-браузера. Значение веб-браузера каким-то образом блокирует эти события и не позволяет TaskPaneView понять, что у него есть фокус. Если бы я также добавил элемент управления текстовыми полями в TaskPaneView вместе с браузером, текстовое поле прекрасно работает, и TaskPaneView понимает, что он имеет фокус, а затем вводит текстовое поле внутри браузера, а затем начинает работу. Если я вызываю метод фокуса непосредственно в веб-браузере, TaskPaneView понимает, что он имеет фокус, и все работает отлично. Настолько ясно, что проблема не в том, что на клавиатуре, но вместо проблемы TaskPaneView не сказано, что она имеет фокус при щелчке браузера, поэтому нажатия клавиш идут в неправильную область. Если я смогу найти способ заставить TaskPaneView понять, что он должен фокусироваться, все должно работать.
Ответы
Ответ 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, который является просто UserControl с этим дочерним веб-браузером. У меня нет глубокого понимания того, почему или как это работает, но в основном я думаю, что происходит, я перехватываю WndProc, который является некоторой низкоуровневой функцией, которая обрабатывает сообщения, отправленные в окно. Я использую его, чтобы проверить, является ли сообщение 528, что, я думаю, означает notifyParent. Я не знаю, если это именно то сообщение, которое я должен слушать, но это похоже на работу.
Как только у меня появляется правильное сообщение, я проверяю, имеет ли TaskPaneView фокус, а если нет, я делаю его с помощью функции focus()
. Ранее я проводил тестирование, которое показывало, что если бы я вручную вызывал focus
на TaskPaneView, все работало нормально. Так что, если у меня нет фокуса, то вручную запросите фокус, и мы все в порядке
Я был бы признателен, если бы кто-то мог дать более подробное объяснение того, почему это работает, чтобы я мог понять это лучше, но, по крайней мере, я решил проблему. Спасибо Jeremy Thompson
за то, что он заставил меня по-новому взглянуть на эту проблему.
Ответ 2
Q: Предоставьте более подробное объяснение, почему это работает, чтобы я мог лучше понять его
Рад, что у вас это работает! Чтобы выполнить анализ основных причин, нам нужно будет увидеть, куда отправлено это сообщение 528, и для этого нам понадобится исходный код Microsoft Excel.
Я не думаю, что стоит потратить больше времени на устранение неполадок или почему это происходит, потому что это ОШИБКА! Вход в систему Connect ошибка, помогающая Microsoft исправить это лучшее, что вы можете сделать. Мы можем только обойти это, это проблема в исходном коде.
Очень редко вы обнаруживаете, что эти сценарии в VSTO видят ошибки, и вы наверняка нашли их; где пользователь вводит текстовый ввод в текстовое поле надстройки, и сообщение втекает в ячейку на листе! В моей ситуации; где сообщение не было перекачано в событие Calendars_SelectedChange()
. Таким образом, мы можем видеть немного темы поведения, формирующегося здесь, что Ханс объясняет хорошо (цитата из Q & A, с которой я связан в своем комментарии):
Что никогда не проблема (то есть часто бывает проблематично) заключается в том, что вы полагаетесь на насос сообщений в Excel для отправки сообщений Windows, сообщения, которые заставляют эти элементы управления реагировать на ввод. В WPF это происходит не так, как Winforms, у них есть собственный цикл отправки, который фильтрует сообщения до их доставки в окно. Ключевые вещи, которые идут не так, когда их диспетчер не используется , являются такими, как табуляция и короткие нажатия клавиш.
И затем некоторые, такая проблема будет вызвана тем, что Excel делает свою собственную фильтрацию перед отправкой сообщений. Я бы предположил, что функция защиты от вредоносных программ Microsoft навсегда беспокоится о программах, запутанных в приложениях Office.
И не забывайте VSTO WPF Connect с меню, не получающим события кликов. Обходной путь, связанный с использованием DispatcherFrame для накачки сообщений и подписки на GotFocusEvent и LostFocusEvent для меню.
Таким образом, ошибка связана с элементами управления, которые реагируют на ввод, а сообщения void WndProc(ref Message m)
неправильно фильтруются или перенаправляются в цикле отправки.