我已經完成了我的COM加載項。我使用了激活上下文。 COM插件非常容易,因爲插件接口的表面區域非常小。我可以發佈代碼,但明天之前我不會在機器上使用它。希望這可以幫助!
UPDATE
正如所承諾的,這裏是我使用的代碼:
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工作的入口點進行包裝d在這樣的代碼中。
請注意,在我的COM加載項DLL中,我採取了特殊措施以避免在DLLMain
期間運行代碼,因此我對InitialiseActivationContext
和FinaliseActivationContext
的調用不在單元初始化/結束部分。但是,我沒有看到爲什麼這個代碼不安全放置在那裏。
我不知道任何優雅的解決方案。在WinSDK頭文件中快速瀏覽顯示ActivateActCtx和DeactivateActCtx似乎很重要 - 它們在加載CommCtrl API函數時將調用包裝爲LoadLibrary和GetProcAddress。 WinSDK頭文件包含所有的代碼AFAICS,但由於它們似乎已被重命名以避免衝突(例如IsolationAwarePrivatezltRgCebPnQQeRff,CommctrlIsolationAwarePrivatetRgCebPnQQeRff_pbZPgYQP_QYY等),因此需要進行一些反混淆處理。 – 2011-02-27 11:31:15
@Barry:謝謝您的探索!我是否正確地假設Delphi RTL/VCL沒有使用激活上下文_anything_,並完全依賴於生成的清單? – 2011-02-27 13:11:49
我沒有任何特別的知識,我只是看着SDK標題來幫助提供線索。 – 2011-02-27 16:36:01