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

标签 excel delphi ms-office add-in vcl

我有一个用 Delphi 编写的 Excel AddIn,它有一个带有 TMemo 的 VCL 表单。 当我尝试在备忘录中输入文本时,输入会转至 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 安装键盘钩子(Hook)。显然,这将为我们提供按键事件,但不知道如何处理这些事件。

我没有使用 Add-In Express 等第 3 方工具,而只是实现 IDTExtensibility2

编辑:更多研究表明 Office 使用名为 IMsoComponent 的界面和和IMsoComponentManager作为跟踪应用程序中事件组件的一种方式。 Visual Studio 将它们用作 IOleComponentIOleComponentManager .

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

编辑:可以获取 MCVE here ,它是最小的 Excel AddIn 代码,将启动带有 TEdit 的 VCL 表单。一旦工作表处于事件状态,编辑就会失去键盘焦点。

最佳答案

我也遇到了同样的问题。我也在实现 IDTExtensibility2,但当我在 C++ 上实现时,我已经设法在不同的线程上运行 UI。但无论如何,我对这个解决方案并不完全满意。如果我想使用 VBA 用户窗体作为任务 Pane 窗口,我仍然会遇到这个问题。我确实尝试过,但(我猜,没有检查)VBA 用户窗体将在 native Excel 线程上运行,只是在不同的线程上调用它(用作 TaskPane 窗口)只是编码它,并不意味着它是在不同的线程上创建的,所以当我尝试时,存在这种问题。

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

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

它对我的工作原理是在我的表单窗口的每个 WM_SETCURSOR e WM_IME_SETCONTEXT 上注册我的 IOleComponent 实现。 (我不确定这是否是最好的消息,但确实对我有用)并在每次点击 EXCEL7 窗口时撤销该组件。

我用来注册的 MSOCRINFO 选项是 msocrfPreTranslateKey 和 msocadvfModal。

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

关于Excel 从 VCL 表单中窃取键盘焦点(在 AddIn 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56058580/

相关文章:

sql-server - 我可以与 ADO 一起使用的最简单的数据库类型是什么?

delphi - 如何使用 CryptoAPI 加载 OpenSSL 生成的 RSA1024 纯文本公钥?

正则表达式 : Remove line breaks if lookbehind shows a lowercase

python - Excel python COM 对象的文档?

php - Laravel 内存不足

excel - 带有 For 循环 VBA 的多维数组

excel - 将用户名(数组)与电子邮件(数组)匹配

delphi - 如何避免通用容器中的非无参数构造函数出现不兼容的类型错误?

windows - 运行多个版本的 Microsoft Office 的最佳方式是什么?

ms-office - 在对话框中打开另一个页面