我有一个用Delphi编写的Excel加载项,该加载项具有VCL格式并带有TMemo。 当我尝试在记事中输入文本时,输入将转到Excel。
当我启动表单模式(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;
在该过程中,尝试了SetFocus
,WinApi.Windows.SetFocus(self.Handle)
,SetForeGroundWindows
,SetActiveWindow
之类的操作,但这似乎不起作用。
我读过的其他建议是使用run the UI in a different thread(对于VCL当然是不可能的),并建议使用SetWindowsHookEx
安装键盘挂钩。显然,这将为我们提供按键事件,但不确定如何处理这些事件。
我没有使用诸如Add-In Express之类的第三方工具,而只是实现了IDTExtensibility2
。
编辑:更多研究表明,Office使用称为IMsoComponent和IMsoComponentManager的接口作为跟踪应用程序中活动组件的方式。 Visual Studio将它们用作IOleComponent和IOleComponentManager。
此link和this建议注册一个新的空IOleComponent / IMsoComponent。
编辑:可以提取here来获取MCVE,这是最小的Excel插件代码,它将启动带有TEdit的VCL表单。只要工作表处于活动状态,该编辑就会失去键盘焦点。
答案 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,但这正是我完成这一点所需要的。所以我只是想诚实一点,分享一些东西。