通过在运行时添加应用程序清单,可以在运行时进行“运行时主题"的可选切换吗? [英] Possible to do runtime optional toggling of **runtime themes** by adding an application manifest at runtime?

查看:125
本文介绍了通过在运行时添加应用程序清单,可以在运行时进行“运行时主题"的可选切换吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:
如何在两个应用程序之间切换应用程序主题而不是主题在运行时?

Possible Duplicate:
How to switch an Application between Themed and not Themed at run-time?

我创建了一个运行时主题选项设置为未启用的GUI应用程序,并且需要该选项来在应用程序初始化期间手动启用嵌入式清单.

I create a GUI App with runtime themes option set to not enabled and need the option to manually enable an embedded Manifest during App initialization.

问题:

VCL是否允许扩展点实现这一点?

Does the VCL allow an extension point to implement that?

让我解释一下:

  • 自定义清单作为字符串常量嵌入在二进制文件中.
  • 使用命令行参数开关启用运行时主题,例如:MyApp.exe -themeOn

我已经深入研究Forms.TApplication,希望找到一个句柄,但是没有发现任何指向前进方向的有趣信息.

I have delved into Forms.TApplication in hope to find a handle but found nothing of interest pointing to a direction to go.

推荐答案

我会反过来做.我将通过在项目设置中启用运行时主题来包括标准comctl v6清单.然后,我会在启动时从 SetThemeAppProperties .dpr文件,以在必要时禁用运行时主题.

I would do this the other way around. I would include the standard comctl v6 manifest by enabling runtime themes in the project settings. Then I would call SetThemeAppProperties at startup, from the .dpr file, to disable runtime themes if necessary.

procedure DisableRuntimeThemes;
begin
  InitThemeLibrary;
  if Assigned(SetThemeAppProperties) then
    SetThemeAppProperties(STAP_ALLOW_NONCLIENT);
end;

begin
  if not FindCmdLineSwitch('themeOn') then
    DisableRuntimeThemes;
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;
end.

您需要确保UxTheme在.dpr使用子句中,或者甚至更好地将该函数移至其自己的专用单元中.

You'll need to make sure that UxTheme is in the .dpr uses clause, or even better move that function to its own dedicated unit.

将清单文件作为正常名称包含进去,然后禁用运行时主题会更容易.启用运行时主题的另一种方法是涉及激活上下文,而不是这种方法.

It's easier to include the manifest as normal and then disable runtime themes. The alternative of enabling runtime themes involves activation contexts which is rather more involved than this approach.

说过比使用激活上下文要容易,我决定看看其中涉及了什么.这是我想出的:

Having said it was easier than using the activation context, I decided to see what was involved in that. And here's what I came up with:

unit ActivateRuntimeThemes;

interface

implementation

uses
  Windows, SysUtils;

type
  TActivationContext = class
  private
    FActCtxHandle: THandle;
    FCreateActCtx: function(var pActCtx: TActCtx): THandle; stdcall;
    FActivateActCtx: function(hActCtx: THandle; var lpCookie: LongWord): BOOL; stdcall;
    FDeactivateActCtx: function(dwFlags: DWORD; ulCookie: LongWord): BOOL; stdcall;
    FReleaseActCtx: procedure(hActCtx: THandle); stdcall;
    FCookie: LongWord;
    FSucceeded: Boolean;
  public
    constructor Create;
    destructor Destroy; override;
  end;

constructor TActivationContext.Create;
var
  ActCtx: TActCtx;
  hKernel32: HMODULE;
begin
  inherited;
  hKernel32 := GetModuleHandle(kernel32);
  FCreateActCtx := GetProcAddress(hKernel32, 'CreateActCtxW');
  if Assigned(FCreateActCtx) then
  begin
    FReleaseActCtx := GetProcAddress(hKernel32, 'ReleaseActCtx');
    FActivateActCtx := GetProcAddress(hKernel32, 'ActivateActCtx');
    FDeactivateActCtx := GetProcAddress(hKernel32, 'DeactivateActCtx');
    ZeroMemory(@ActCtx, SizeOf(ActCtx));
    ActCtx.cbSize := SizeOf(ActCtx);
    ActCtx.lpSource := 'C:\desktop\comctlv6.manifest.txt';
    FActCtxHandle := FCreateActCtx(ActCtx);
    FSucceeded := (FActCtxHandle<>INVALID_HANDLE_VALUE) and FActivateActCtx(FActCtxHandle, FCookie);
  end
  else
    FActCtxHandle := INVALID_HANDLE_VALUE;
end;

destructor TActivationContext.Destroy;
begin
  if FSucceeded then
    FDeactivateActCtx(0, FCookie);
  if FActCtxHandle<>INVALID_HANDLE_VALUE then
    FReleaseActCtx(FActCtxHandle);
  inherited;
end;

var
  ActivationContext: TActivationContext;

procedure FinaliseActivationContext;
begin
  ActivationContext.Free;
end;

initialization
  if FindCmdLineSwitch('themeOn') then
    ActivationContext := TActivationContext.Create;

finalization
  ActivationContext.Free;

end.

您应尽早在.dpr文件中包括该单元.在任何内存管理器之后,但在任何RTL/VCL单元之前.在项目设置中将运行时主题设置为.您可能希望将清单文件包含为资源,但是为了方便起见,我在此处将其作为文件包含.

You should include this unit as early as possible in your .dpr file. After any memory managers, but before any RTL/VCL units. Set runtime themes to None in the project settings. You'd probably want to include the manifest file as a resource, but I've done it as a file here for my convenience.

这篇关于通过在运行时添加应用程序清单,可以在运行时进行“运行时主题"的可选切换吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆