2012-04-09 44 views
1

可能重複:
How to switch an Application between Themed and not Themed at run-time?可能通過在運行時添加應用程序清單來執行運行時可選的切換**運行時主題**。

我創建了一個GUI應用程序與運行時主題選項設置爲未啓用和需要選擇手動啓用應用程序初始化過程中嵌入清單。

問題:

VCL是否允許擴展點來實現它?

讓我解釋一下:

  • 定製清單是嵌入在二進制爲字符串常量。
  • 運行的主題是使用命令行參數開關,例如:MyApp.exe -themeOn

我已經鑽研Forms.TApplication在希望找到一個手柄,但沒有發現任何興趣指點的方向去實現。

+2

試試這個問題[如何在運行時切換應用程序之間的主題和非主題?](http://stackoverflow.com/questions/4393723/how-to-switch-an-application-between-themed-而不是主題在運行時) – RRUZ 2012-04-09 14:51:19

+1

@RRUZ:謝謝你指出它。 – menjaraz 2012-04-09 15:06:32

+0

它不會是一個確切的重複的唯一原因是因爲這個問題規定你想做一些愚蠢的事情(不包括清單)。艾爾戈,這是一個騙局。 – 2012-04-09 18:21:23

回答

4

我會這樣做的另一種方式。我會通過在項目設置中啓用運行時主題來包含標準的comctl v6清單。然後,我會在啓動時從.dpr文件中調用SetThemeAppProperties,以根據需要禁用運行時主題。

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使用條款,甚至更好的移動,其功能是其自己的專用單元。

正常情況下包含清單,然後禁用運行時主題會更容易。啓用運行時主題的替代方法涉及激活上下文,這種方法比這種方法更爲複雜。


說到這比使用激活情況下,我決定去看看是什麼參與在更容易。這裏是我想出的:

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

我想這是不可能的['在運行時'](http://stackoverflow.com/q/7526665/960757)? – TLama 2012-04-09 14:49:05

+1

@TLama當然,您可以使用激活上下文,但它比上面概述的方法更難。我總是喜歡簡單的選擇! – 2012-04-09 14:50:20

+1

@ RRUZ在該問題中的鏈接將帶您到一個有很多SetThemeAppProperties答案的問題。 – 2012-04-09 14:54:45

相關問題