Excel从VCL表单(在AddIn中)窃取了键盘焦点

时间:2019-05-09 11:38:26

标签: excel delphi ms-office add-in vcl

我有一个用Delphi编写的Excel加载项,该加载项具有VCL格式并带有TMemo。 当我尝试在记事中输入文本时,输入将转到Excel。

enter image description here

当我启动表单模式(ShowModal)时,一切正常,但显然无法同时使用excel主窗口和外接程序窗口。

问题似乎与以下问题完全相同:Modeless form cannot receive keyboard input in Excel Add-in developed by Delphi

answer建议处理WM_PARENTNOTIFY,因此我尝试了以下操作:

TMyForm = class(TForm)
...
 procedure OnParentNotify(var Msg: TMessage); message WM_PARENTNOTIFY;

在该过程中,尝试了SetFocusWinApi.Windows.SetFocus(self.Handle)SetForeGroundWindowsSetActiveWindow之类的操作,但这似乎不起作用。

我读过的其他建议是使用run the UI in a different thread(对于VCL当然是不可能的),并建议使用SetWindowsHookEx安装键盘挂钩。显然,这将为我们提供按键事件,但不确定如何处理这些事件。

我没有使用诸如Add-In Express之类的第三方工具,而只是实现了IDTExtensibility2

编辑:更多研究表明,Office使用称为IMsoComponentIMsoComponentManager的接口作为跟踪应用程序中活动组件的方式。 Visual Studio将它们用作IOleComponentIOleComponentManager

linkthis建议注册一个新的空IOleComponent / IMsoComponent。

编辑:可以提取here来获取MCVE,这是最小的Excel插件代码,它将启动带有TEdit的VCL表单。只要工作表处于活动状态,该编辑就会失去键盘焦点。

1 个答案:

答案 0 :(得分:2)

我遇到同样的问题。我也正在实现IDTExtensibility2,但是当我在C ++上执行操作时,我已经设法在另一个线程上运行UI。但是无论如何,我对这种解决方案并不完全满意。如果我想使用VBA用户窗体作为TaskPane窗口,我仍然会遇到这个问题。我确实尝试过,但是(我想,没有检查)VBA用户窗体将在本机Excel线程上运行,只是在另一个线程(用作TaskPane窗口)上对其进行了编组,但这并不意味着是在其他线程上创建的,因此,正如我尝试过的那样,存在这种问题。

我也确实阅读并尝试使用SetFocus ..在我的窗口上处理WM_PARENTNOTIFY消息,但是没有用。

这两个接口IOleComponent和IOleComponentManager对我来说都是新的。找不到头文件,但可以根据您共享的链接中的描述进行编写和实现。

对我来说,如何工作是在“窗体窗口”上的每个WM_SETCURSOR和WM_IME_SETCONTEXT上注册IOleComponent实现。 (我不确定这是否是最好的消息,但确实对我有用),并在每次单击EXCEL7窗口时撤消该组件。

我以前注册的MSOCRINFO选项是msocrfPreTranslateKey和msocadvfModal。

希望我的回答不会引起大量批评。我知道这是一个非常具体的问题,当我阅读该问题时,它的状态为-1,但这正是我完成这一点所需要的。所以我只是想诚实一点,分享一些东西。