绘制主题按钮我使用此代码:
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,DFC_CAPTION,DFCS_CAPTIONCLOSE or GetClassicState) end;
此代码工作正常但绘制的按钮看起来像是从Windows 7主题,甚至在Windows 8或10上.这可以使用Windows 10或8主题绘制关闭按钮?
解决此问题的方法之一:手动解析活动的* .msstyles文件.通常这是aero.msstyles.存储在STREAM部分中的不同窗口控件的位图.对于Windows 7 ResId = 971,Windows 8:Id = 1060,Windows 10:Id = 1194.但这是手动工作,这个位图是不同的.
更新:
我发现,即使对于一个版本的Windows(测试为8),我们也可以为此Bitmap(png图像)提供不同的资源ID值,现在我可以提供代码以在任何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'),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,PBuf,BufSize,hInstance); finally CloseThemeData(h); end;
我可以为最小化按钮获取Rect,但是不明白如何使用GetThemeStream?应该使用PBuf还是PPBuf?