如何将标准 windows 信息图标很好地绘制到页面控件选项卡的索引
How to paint standard windows information icon nicely to the index of a pagecontrol's tab
我想要将标准 windows 信息(以及警告和错误)图标绘制到页面控件的选项卡索引中。但是,如果 windows 背景颜色不是白色,结果看起来很糟糕。
program Project111;
uses
Vcl.Forms,
Vcl.Controls,
Vcl.Graphics,
Winapi.Windows,
Vcl.ComCtrls,
Vcl.ImgList;
{$R *.res}
var
mainForm: TForm;
imageList: TImageList;
icon: TIcon;
pageControl: TPageControl;
tabSheet: TTabSheet;
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, mainForm);
imageList := TImageList.Create(mainForm);
imageList.ColorDepth := cd32bit;
icon := TIcon.Create;
try
icon.Handle := LoadImage( 0, IDI_INFORMATION, IMAGE_ICON, 16, 16, {LR_DEFAULTSIZE or} LR_SHARED );
imageList.AddIcon(icon);
finally
icon.Free;
end;
pageControl := TPageControl.Create(mainForm);
pageControl.Parent := mainForm;
pageControl.Images := imageList;
tabSheet := TTabSheet.Create(mainForm);
tabSheet.Parent := pageControl;
tabSheet.PageControl := pageControl;
tabSheet.ImageIndex := 0;
Application.Run;
end.
截图如下:
如您所见,白色边框模糊不清,我猜这是因为 TImageList 缺少适当的 alpha 透明度,但我不知道如何解决这个问题。
该解决方案不必使用 TImageList,我很乐意使用任何其他方法。请注意,还会有标题,并非所有索引都有图标,并且图标可能 changed/added/removed 随着上下文的变化。
我正在使用 Delphi XE-2,如果有帮助,我也有 DevExpress 组件。
您看到的不是因为 alpha 透明度损坏,而是因为调整了大小。
与 documented 一样,LoadImage
加载的图标的默认大小为 SM_CXICON
xSM_CYICON
,通常为 32x32。由于您正在请求系统共享的图标,因此这将是将要提供的图标的大小。
您可以验证您的代码是否属于这种情况:
..
try
icon.Handle := LoadImage( 0, IDI_INFORMATION, IMAGE_ICON, 16, 16, {LR_DEFAULTSIZE or} LR_SHARED );
Assert(icon.Width = GetSystemMetrics(SM_CXICON));
Assert(GetSystemMetrics(SM_CXICON) <> 16);
..
接下来是调整图标大小以适合图像列表,可能没有什么比 StretchBlt
和 COLORONCOLOR
模式更好。
不幸的是,无法加载非标准尺寸的系统图标,因为再次记录,
When loading a system icon or cursor, you must use LR_SHARED or the
function will fail to load the resource.
您需要做的是以默认大小加载共享图标,然后使用更好的算法自行将其调整为 16x16。 StretchBlt
和 HALFTONE
可能会更好,但使用更高级的图形库可能会产生最佳效果。
强烈建议不要使用的替代方法是直接从资源所在的位置加载资源。如果您不使用 LR_SHARED
标志,您将获得请求的大小。你需要做一些研究来找到图标的实际索引,因为这没有记录。并且需要考虑索引或它所在的位置可能会随时间发生变化。在这种情况下不要忘记自己销毁图标,因为系统不会为非共享资源这样做。
icon.Handle := LoadImage(GetModuleHandle(user32), Pointer(104), IMAGE_ICON, 16, 16, 0);
正如@Sertac 所说,您看到的是将 windows shell 图标从 32x32 调整为 16x16 的效果,作为从 Windows Vista 开始的解决方法,您可以使用 SHGetStockIconInfo
函数。
传递 SHGSI_SMALLICON
标志以检索由 SM_CXSMICON
和 SM_CYSMICON
.
指定的小版本图标
SM_CXSMICON
和 SM_CYSMICON
的值取决于当前的 DPI 设置。对于 DPI 96 是 16x16.
样本
LIcon := TIcon.Create;
try
LIcon.Handle := 0;
if TOSVersion.Check(6, 0) then
begin
ZeroMemory(@LSHStockIconInfo, SizeOf(LSHStockIconInfo));
LSHStockIconInfo.cbSize := sizeof(LSHStockIconInfo);
if SHGetStockIconInfo(SIID_INFO, SHGSI_ICON or SHGSI_SMALLICON, LSHStockIconInfo) = S_OK then
begin
LIcon.Handle := LSHStockIconInfo.hIcon;
imageList.AddIcon(LIcon);
end;
end;
finally
LIcon.Free;
end;
我想要将标准 windows 信息(以及警告和错误)图标绘制到页面控件的选项卡索引中。但是,如果 windows 背景颜色不是白色,结果看起来很糟糕。
program Project111;
uses
Vcl.Forms,
Vcl.Controls,
Vcl.Graphics,
Winapi.Windows,
Vcl.ComCtrls,
Vcl.ImgList;
{$R *.res}
var
mainForm: TForm;
imageList: TImageList;
icon: TIcon;
pageControl: TPageControl;
tabSheet: TTabSheet;
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, mainForm);
imageList := TImageList.Create(mainForm);
imageList.ColorDepth := cd32bit;
icon := TIcon.Create;
try
icon.Handle := LoadImage( 0, IDI_INFORMATION, IMAGE_ICON, 16, 16, {LR_DEFAULTSIZE or} LR_SHARED );
imageList.AddIcon(icon);
finally
icon.Free;
end;
pageControl := TPageControl.Create(mainForm);
pageControl.Parent := mainForm;
pageControl.Images := imageList;
tabSheet := TTabSheet.Create(mainForm);
tabSheet.Parent := pageControl;
tabSheet.PageControl := pageControl;
tabSheet.ImageIndex := 0;
Application.Run;
end.
截图如下:
如您所见,白色边框模糊不清,我猜这是因为 TImageList 缺少适当的 alpha 透明度,但我不知道如何解决这个问题。
该解决方案不必使用 TImageList,我很乐意使用任何其他方法。请注意,还会有标题,并非所有索引都有图标,并且图标可能 changed/added/removed 随着上下文的变化。
我正在使用 Delphi XE-2,如果有帮助,我也有 DevExpress 组件。
您看到的不是因为 alpha 透明度损坏,而是因为调整了大小。
与 documented 一样,LoadImage
加载的图标的默认大小为 SM_CXICON
xSM_CYICON
,通常为 32x32。由于您正在请求系统共享的图标,因此这将是将要提供的图标的大小。
您可以验证您的代码是否属于这种情况:
..
try
icon.Handle := LoadImage( 0, IDI_INFORMATION, IMAGE_ICON, 16, 16, {LR_DEFAULTSIZE or} LR_SHARED );
Assert(icon.Width = GetSystemMetrics(SM_CXICON));
Assert(GetSystemMetrics(SM_CXICON) <> 16);
..
接下来是调整图标大小以适合图像列表,可能没有什么比 StretchBlt
和 COLORONCOLOR
模式更好。
不幸的是,无法加载非标准尺寸的系统图标,因为再次记录,
When loading a system icon or cursor, you must use LR_SHARED or the function will fail to load the resource.
您需要做的是以默认大小加载共享图标,然后使用更好的算法自行将其调整为 16x16。 StretchBlt
和 HALFTONE
可能会更好,但使用更高级的图形库可能会产生最佳效果。
强烈建议不要使用的替代方法是直接从资源所在的位置加载资源。如果您不使用 LR_SHARED
标志,您将获得请求的大小。你需要做一些研究来找到图标的实际索引,因为这没有记录。并且需要考虑索引或它所在的位置可能会随时间发生变化。在这种情况下不要忘记自己销毁图标,因为系统不会为非共享资源这样做。
icon.Handle := LoadImage(GetModuleHandle(user32), Pointer(104), IMAGE_ICON, 16, 16, 0);
正如@Sertac 所说,您看到的是将 windows shell 图标从 32x32 调整为 16x16 的效果,作为从 Windows Vista 开始的解决方法,您可以使用 SHGetStockIconInfo
函数。
传递 SHGSI_SMALLICON
标志以检索由 SM_CXSMICON
和 SM_CYSMICON
.
SM_CXSMICON
和 SM_CYSMICON
的值取决于当前的 DPI 设置。对于 DPI 96 是 16x16.
样本
LIcon := TIcon.Create;
try
LIcon.Handle := 0;
if TOSVersion.Check(6, 0) then
begin
ZeroMemory(@LSHStockIconInfo, SizeOf(LSHStockIconInfo));
LSHStockIconInfo.cbSize := sizeof(LSHStockIconInfo);
if SHGetStockIconInfo(SIID_INFO, SHGSI_ICON or SHGSI_SMALLICON, LSHStockIconInfo) = S_OK then
begin
LIcon.Handle := LSHStockIconInfo.hIcon;
imageList.AddIcon(LIcon);
end;
end;
finally
LIcon.Free;
end;