2012-04-09 13 views
1

可能性の重複:
How to switch an Application between Themed and not Themed at run-time?実行時にアプリケーションマニフェストを追加することで、**ランタイムテーマ**のランタイムオプションのトグル切り替えが可能ですか?

私はに設定ランタイムテーマにしたGUIアプリケーションオプションがを有効にし、手動でアプリの初期化中に埋め込まれたマニフェストを有効にするオプションを必要としない作成。

質問:

拡張ポイントでこれを実装することはできますか?

私に説明してみましょう:

  • マニフェスト定数文字列としてバイナリに埋め込まれたカスタム。
  • ランタイムテーマは例えば、コマンドラインパラメータスイッチを使用して有効になっている。:MyApp.exe -themeOn

私がハンドルを見つけることを期待してForms.TApplication掘り下げなく、どこへ行く方向に関心のポインティングのものは認められません。

+2

この質問をお試しください[実行時にテーマとテーマ以外の間でアプリケーションを切り替える方法は?](http://stackoverflow.com/questions/4393723/how-to-switch-an-application-between-themed-実行時テーマではありません) – RRUZ

+1

@RRUZ:ありがとうございます。 – menjaraz

+0

これは正確な重複ではない唯一の理由は、この質問が愚かなこと(マニフェストを含まない)をしたいと規定しているからです。エルゴ、それは詐欺です。 –

答えて

4

私はこれを逆にします。プロジェクト設定でランタイムテーマを有効にすることで、標準のcomctl v6マニフェストを追加します。その後、起動時に.dprファイルからSetThemeAppPropertiesを呼び出して、必要に応じてランタイムテーマを無効にします。あなたはUxThemeが.DPRであることを確認する必要があります

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. 

は句を使用して、またはより良い、独自の専用ユニットにその機能を移動します。

通常の方法でマニフェストを組み込み、ランタイムテーマを無効にする方が簡単です。ランタイムテーマを有効にする代わりに、このアプローチよりもむしろ関与するアクティベーションコンテキストが必要です。


は、アクティベーションコンテキストを使用するよりも簡単だったと述べた、私はそれに関与していたものを見ることにしました。ここで私が思いついたのは次のとおりです:

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ユニットの前。プロジェクトの設定でランタイムテーマをなしに設定します。マニフェストファイルをリソースとして含めることをお勧めしますが、私の便宜のためにここにファイルとして作成しました。

+0

これは['at runtime'](http://stackoverflow.com/q/7526665/960757)ではできないと思いますか? – TLama

+1

@TLamaもちろん、アクティベーションコンテキストを使用することはできますが、上記のアプローチよりも難しいことです。私はいつも簡単なオプションが好きです! –

+1

その質問のRRUZのリンクは、多くのSetThemeAppPropertiesの回答がある質問にあなたを連れて行きます。 –

関連する問題