2015-11-30 108 views
7

畫爲主題的按鈕,我用這個代碼:的Windows 10關閉,最小化和最大化按鍵

var 
    h: HTHEME; 
begin 
    if UseThemes then begin 
    SetWindowTheme(Handle, 'explorer', nil); 
    h := OpenThemeData(Handle, 'WINDOW'); 
    if h <> 0 then 
    try 
     DrawThemeBackground(h, Canvas.Handle, WP_CLOSEBUTTON, GetAeroState, ClientRect, nil); 
    finally 
     CloseThemeData(h); 
    end; 
    end 
    else 
    DrawFrameControl(Canvas.Handle, ClientRect, DFC_CAPTION, DFCS_CAPTIONCLOSE or GetClassicState) 
end; 

此代碼工作正常,但是畫按鈕看起來就像從Windows 7的主題,即使是在Windows 8或10這是可以使用Windows 10或8主題繪製關閉按鈕?

enter image description here

+1

是什麼版本的Delphi的作者你在用嗎? –

+0

添加了delphi-xe7標籤,這對我來說並不重要,我也是在Window 8下開發的,但是它的繪製方式類似於Windows 7 –

+0

問題不是很清楚。我理解它的方式,你試圖繪製一個匹配Windows版本的主題。這應該在沒有任何編碼的情況下發生。這聽起來像你使用的是一個非常老的Delphi版本,沒有運行時主題。你能提供你所期望的和你看到的東西的截圖嗎? –

回答

1

可行的解決方案,從主題得到位圖:

var 
    h: HTHEME; 
    Rect: TRect; 
    BufSize: Cardinal;  

h := OpenThemeData(Handle, 'DWMWINDOW'); 
if h <> 0 then 
try 
    GetThemeRect(h, WP_MINCAPTION, MNCS_ACTIVE, TMT_ATLASRECT, Rect); 
    ... 
    GetThemeStream(...); 
finally 
    CloseThemeData(h); 
end; 

以及如何使用這裏描述GetThemeStream:GetThemeStream usage,非常感謝安德烈亞斯·範霍文,程序Vista的樣式構建

2

一個方法來解決這個問題:手工解析活躍* .msstyles文件。通常這是aero.msstyles。存儲在STREAM部分中的不同窗口控件的位圖。對於Windows 7 ResId = 971,Windows 8:Id = 1060,Windows 10:Id = 1194。但這是手動工作,此位圖不同。

更新:

我發現,在Windows(8測試)即使對於一個版本中,我們可以有資源ID的不同值此位圖(PNG圖像),現在我可以提供代碼獲取任何Windows資源ID(測試7,8,10):

function EnumStreamProc(hModule: HMODULE; AType, AName: PChar; Params: LPARAM): BOOL; stdcall; 
var 
    Id: NativeInt; 
begin 
    PNativeInt(Params)^ := Integer(AName); 
    Result := False; 
end; 

function GetStyleResourceId(AModule: HMODULE): Integer; 
begin 
    Result := 0; 
    EnumResourceNames(AMODULE, 'STREAM', @EnumStreamProc, LPARAM(@Result)); 
end; 

var 
    hLib: HMODULE; 
    ResId: Integer; 
    RS: TResourceStream; 
    Png: TPngImage; 

begin 
    hLib := LoadLibraryEx(PChar(GetWindowsPath + 'Resources\Themes\Aero\aero.msstyles'), 
         0, LOAD_LIBRARY_AS_DATAFILE); 
    ResId := GetStyleResourceId(hLib); 
    RS := TResourceStream.CreateFromID(hLib, ResId, 'STREAM'); 
    Png := TPngImage.Create; 
    Png.LoadFromStream(RS); 
    ... 
end; 

更新2:

發現不破解方法,使用官方的API:

var 
    h: HTHEME; 
    Rect: TRect; 
    PBuf, PPBuf: Pointer; 
    BufSize: Cardinal; 
    Buf: array[0..1024*1024] of Byte; 


h := OpenThemeData(Handle, 'DWMWINDOW'); 
if h <> 0 then 
try 
    GetThemeRect(h, WP_MINCAPTION, MNCS_ACTIVE, TMT_ATLASRECT, Rect); 
    PBuf := @Buf[0]; 
    PPBuf := @PBuf; 
    GetThemeStream(h, WP_MINCAPTION, MNCS_ACTIVE, TMT_ATLASRECT, PBuf, BufSize, hInstance); 
finally 
    CloseThemeData(h); 
end; 

我可以得到最小化按鈕的矩形,但不明白如何使用GetThemeStream?應該使用PBuf還是PPBuf?

+0

攻擊實現細節並不是真正可行的。這是一個非常糟糕的主意。 –

+0

爲什麼這是一個壞主意?爲了解決這個問題,我們有三種可能:1.使用官方API(未提供); 2.創建按鈕的屏幕截圖(這很容易但不支持其他主題); 3。提供了讀取主題png內容的代碼(目前我準備解析這個PNG,這將支持不同的主題)。我很樂意聽到另一個更方便的解決方案 –

+0

因爲即使你已經發現了 –

相關問題