gpt4 book ai didi

delphi - 将 Windows 主题应用到 Office Com 加载项

转载 作者:行者123 更新时间:2023-12-03 14:59:46 25 4
gpt4 key购买 nike

多年来,Delphi 一直支持“应用程序设置”选项卡上的启用运行时主题开关。但是,这仅适用于可执行文件。 DLL 被假定从其父应用程序接管主题(和其他)设置。

不幸的是,Microsoft Office 在那里运行得不太好。它们的“主题”外观是使用自定义控件实现的,而不是通过 Windows 自己的通用控件实现的。

在 MSDN 文章 830033 - How to apply Windows XP themes to Office COM add-ins 中Microsoft 解释了如何将 list 应用到 DLL,使其具有隔离感知能力,从而忽略父进程的设置。

基本上,可以归结为两个步骤:

  1. 在您的进程中包含默认 list 资源,使用 int-resource ID 2(而不是您通常使用的 1)。
  2. 使用 ISOLATION_AWARE_ENABLED 定义进行编译。 **这在 Delphi 中不可用。**

我想我已经确定了 (1),尽管我不太确定 brcc32 是否将资源 ID 作为整数或文字字符串。真正的问题在于(2)。据推测,此定义更改了几个 DLL 函数绑定(bind)。

有人用Delphi解决过这个问题吗?我应该进一步研究这条路线,我应该尝试手动创建激活上下文,还是有其他优雅的解决方案来解决这个问题?

最佳答案

我已经为我的 COM 加载项完成了此操作。我使用了激活上下文。对于 COM 加载项来说这非常容易,因为加载项界面的表面积非常小。我可以发布代码,但直到明天我才会使用它。希望这有帮助!

<小时/>

更新

正如所 promise 的,这是我使用的代码:

type
(* TActivationContext is a loose wrapper around the Windows Activation Context API and can be used
to ensure that comctl32 v6 and visual styles are available for UI elements created from a DLL .*)
TActivationContext = class
private
FCookie: LongWord;
FSucceeded: Boolean;
public
constructor Create;
destructor Destroy; override;
end;

var
ActCtxHandle: THandle=INVALID_HANDLE_VALUE;
CreateActCtx: function(var pActCtx: TActCtx): THandle; stdcall;
ActivateActCtx: function(hActCtx: THandle; var lpCookie: LongWord): BOOL; stdcall;
DeactivateActCtx: function(dwFlags: DWORD; ulCookie: LongWord): BOOL; stdcall;
ReleaseActCtx: procedure(hActCtx: THandle); stdcall;

constructor TActivationContext.Create;
begin
inherited;
FSucceeded := (ActCtxHandle<>INVALID_HANDLE_VALUE) and ActivateActCtx(ActCtxHandle, FCookie);
end;

destructor TActivationContext.Destroy;
begin
if FSucceeded then begin
DeactivateActCtx(0, FCookie);
end;
inherited;
end;

procedure InitialiseActivationContext;
var
ActCtx: TActCtx;
hKernel32: HMODULE;
begin
if IsLibrary then begin
hKernel32 := GetModuleHandle(kernel32);
CreateActCtx := GetProcAddress(hKernel32, 'CreateActCtxW');
if Assigned(CreateActCtx) then begin
ReleaseActCtx := GetProcAddress(hKernel32, 'ReleaseActCtx');
ActivateActCtx := GetProcAddress(hKernel32, 'ActivateActCtx');
DeactivateActCtx := GetProcAddress(hKernel32, 'DeactivateActCtx');
ZeroMemory(@ActCtx, SizeOf(ActCtx));
ActCtx.cbSize := SizeOf(ActCtx);
ActCtx.dwFlags := ACTCTX_FLAG_RESOURCE_NAME_VALID or ACTCTX_FLAG_HMODULE_VALID;
ActCtx.lpResourceName := MakeIntResource(2);//ID of manifest resource in isolation aware DLL
ActCtx.hModule := HInstance;
ActCtxHandle := CreateActCtx(ActCtx);
end;
end;
end;

procedure FinaliseActivationContext;
begin
if ActCtxHandle<>INVALID_HANDLE_VALUE then begin
ReleaseActCtx(ActCtxHandle);
end;
end;

initialization
InitialiseActivationContext;

finalization
FinaliseActivationContext;

当你想使用它时,你只需编写如下代码:

var
ActivationContext: TActivationContext;
....
ActivationContext := TActivationContext.Create;
try
//GUI code in here will support XP themes
finally
ActivationContext.Free;
end;

您需要将 GUI 工作的每个入口点包装在此类代码中。

请注意,在我的 COM 加载项 DLL 中,我采取了特殊措施来避免在 DLLMain 期间运行代码,因此我调用 InitialiseActivationContextFinaliseActivationContext 不在单元初始化/终结部分中。但是,我认为没有理由将此代码放在那里不安全。

关于delphi - 将 Windows 主题应用到 Office Com 加载项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5132679/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com