将 Windows 主题应用到 Office Com 加载项
多年来,Delphi 一直支持“应用程序设置”选项卡上的“启用运行时主题”开关。但是,这仅适用于可执行文件。假定 DLL 从其父应用程序接管主题(和其他)设置。
不幸的是,Microsoft Office 在那里表现不佳。它们的“主题”外观是使用自定义控件实现的,而不是通过 Windows 自己的通用控件实现的。
在 MSDN 文章 830033 - 如何将 Windows XP 主题应用到 Office COM 加载项中 Microsoft 解释了如何将清单应用到 DLL,使其具有隔离感知功能,从而忽略父进程的设置。
基本上,它可以归结为两个步骤:
- 在您的进程中包含默认清单资源,使用 int-resource id 2(而不是您通常使用的 1)。
- 使用 ISOLATION_AWARE_ENABLED 定义进行编译。 **这在 Delphi 中不可用。**
我想我已经确定了 (1),尽管我不太确定 brcc32 是否将资源 ID 作为整数或文字字符串。真正的问题在于(2)。据推测,此定义更改了几个 DLL 函数绑定。
有人用Delphi解决过这个问题吗?我应该进一步研究这条路线,我应该尝试手动创建激活上下文,还是有其他优雅的解决方案来解决这个问题?
For ages, Delphi has supported the Enable runtime themes switch on the Application Settings tab. However, this only works for executables. DLLs are assumed to take over the theming (and other) setings from their parent application.
Unfortunately, Microsoft Office doesn't play nice there. Their 'themed' look is achieved using custom controls, not through Windows' own Common Controls.
In the MSDN article 830033 - How to apply Windows XP themes to Office COM add-ins
Microsoft explains how to apply a manifest to a DLL, making it Isolation Aware such that settings from the parent process are ignored.
Basically, it comes down to two steps:
- Include the default manifest resource in your process, using an int-resource id of 2 (as opposed to the 1 you'd normally use).
- Compile with the ISOLATION_AWARE_ENABLED define. **Which isn't available in Delphi.**
I think I've got (1) nailed down, although I'm never quite sure whether brcc32 picks up resource IDs as integers or as literal strings. The real problem lies with (2). Supposedly, this define changes several DLL function bindings.
Has anyone solved this problem in Delphi? Should I further investigate this route, should I try and manually creating activation contexts, or are there other elegant solutions to this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我已经为我的 COM 加载项完成了此操作。我使用了激活上下文。对于 COM 加载项来说这非常容易,因为加载项界面的表面积非常小。我可以发布代码,但直到明天我才会使用它。希望这有帮助!
更新
正如所承诺的,这是我使用的代码:
当您想使用它时,您只需编写如下代码:
您需要将每个执行 GUI 工作的入口点包装在此类代码中。
请注意,在我的 COM 加载项 DLL 中,我采取了特殊措施来避免在
DLLMain
期间运行代码,因此我对InitialiseActivationContext
和FinaliseActivationContext
的调用不在单元初始化/终结部分中。但是,我认为没有理由将这段代码放在那里不安全。I've done this for my COM add-in. I used activation contexts. It's pretty easy for a COM add-in because the surface area of the add-in interface is so small. I could post code but I won't be at a machine with it on until tomorrow. Hope this helps!
UPDATE
As promised, here is the code that I use:
When you want to use this, you simply write code like so:
You need each entry point that does GUI work to be wrapped in such code.
Note that in my COM add-in DLL I have taken special measures to avoid running code during
DLLMain
, and so my calls toInitialiseActivationContext
andFinaliseActivationContext
are not in unit initialization/finalization sections. However, I see no reason why this code would not be safe to place there.