具有Alpha混合图标的Imagelist丢失透明度 [英] Imagelist with alpha blend icons loses Transparency

查看:455
本文介绍了具有Alpha混合图标的Imagelist丢失透明度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是(或多或少)相关的问题:,但我真正想知道的是如何创建与系统图像列表相同的图像列表。



注意:我知道 TPngImageList 并且不想在这种情况下使用。






编辑:
@ David的答案(和评论)是准确的:


你会必须显式地链接到ImageList_Create(v6),因为
否则是impl
绑定到v5.8


示例代码(不使用激活上下文API ):

  function ImageList_Create_V6(CX,CY:Integer;标志:UINT;初始,成长:整数):HIMAGELIST; 
var
h:HMODULE;
_ImageList_Create:function(CX,CY:Integer; Flags:UINT;
Initial,Grow:Integer):HIMAGELIST;标准
begin
// TODO:以编程方式查找comctl32.dll v6路径
h:= LoadLibrary('C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x -ww_35d4ce83\comctl32.dll');
如果h 0然后
尝试
_ImageList_Create:= GetProcAddress(h,'ImageList_Create');
如果分配(_ImageList_Create)then
结果:= _ImageList_Create(CX,CY,Flags,Initial,Grow);
finally
FreeLibrary(h);
结束
结束

procedure TForm1.Button1Click(Sender:TObject);
begin
...
ImageList1.Handle:= ImageList_Create_V6(ImageList1.Width,ImageList1.Height,
ILC_COLOR32或ILC_MASK,0,ImageList1.AllocBy);
...
end;






Edi2: a href =http://pastebin.com/dvMiGJ78 =nofollow noreferrer> @David的示例代码,显示了如何通过激活上下文API正确完成。

解决方案

有两个版本的图像列表控件。 v5.8版本和v6版本。系统映像列表是系统拥有的共享共享,并使用v6版本。这不是特别的,它只是一个简单的v6图像列表。在您的应用程序中,您的图像列表是v5.8或v6,具体取决于是否包含清单。但是系统拥有的图像列表总是v6。



我不知道为什么你不想在你的应用程序中使用v6常用控件。但是,通过这种约束,您可以在创建图像列表时使用激活上下文API来本地使用v6通用控件。这将解决您的问题,并离开您的应用程序的其余部分与v5.8通用控件。


Here is (more or less) a related question: Delphi - Populate an imagelist with icons at runtime 'destroys' transparency.

I have tested @TOndrej answer. But it seems I need to have visual styles (XP Manifest) enabled for this to work (version 6.0 of Windows common controls will be used - which I don't want right now). I add the Icons at run-time via ExtractIconEx and ImageList_AddIcon.

Apparently setting ImageList.Handle to use System Image-List handle, does not require XP Manifest. so even an old program I wrote back in D3 is showing up with alpha blended icons correctly when I use the System image list to display file listing (with a TListView).

I was wandering What is special about the System Image List and how is it created, so that it supports alpha blending in all cases? I can't figure that out. Here is some sample code:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ImgList, StdCtrls, ShellAPI, ExtCtrls, Commctrl;

type
  TForm1 = class(TForm)
    ImageList1: TImageList;
    PopupMenu1: TPopupMenu;
    MenuItem1: TMenuItem;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    FileName: string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
// {$R WindowsXP.res}

procedure TForm1.FormCreate(Sender: TObject);
begin
  PopupMenu1.Images := ImageList1;
  FileName := 'C:\Program Files\Mozilla Firefox\firefox.exe';
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  IconPath: string;
  IconIndex: Integer;
  hIconLarge, hIconSmall: HICON;
begin
  IconPath := FileName;
  IconIndex := 0; // index can be other than 0

  ExtractIconEx(PChar(IconPath), IconIndex, hIconLarge, hIconSmall, 1);

  Self.Refresh; // erase form
  DrawIconEx(Canvas.Handle, 10, 10, hIconSmall, 0, 16, 16, 0,
    DI_IMAGE or DI_MASK); // this will draw ok on the form

  // ImageList1.DrawingStyle := dsTransparent;
  ImageList1.Handle := ImageList_Create(ImageList1.Width, ImageList1.Height,
    {ILC_COLORDDB} ILC_COLOR32 or ILC_MASK, 0, ImageList1.AllocBy);
  ImageList_AddIcon(ImageList1.Handle, hIconSmall);

  MenuItem1.ImageIndex := 0;

  DestroyIcon(hIconSmall);
  DestroyIcon(hIconLarge);

  PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;

procedure TForm1.Button2Click(Sender: TObject);
// using sys image-list will work with or without Manifest
type
  DWORD_PTR = DWORD;
var
  ShFileINfo :TShFileInfo;
  SysImageList: DWORD_PTR;
  FileName: string;
begin
  SysImageList := ShGetFileInfo(nil, 0, ShFileInfo, SizeOf(ShFileInfo),
    SHGFI_SYSICONINDEX OR SHGFI_SMALLICON);

  if SysImageList = 0 then Exit;
  ImageList1.Handle := SysImageList;
  ImageList1.ShareImages := True;

  if ShGetFileInfo(PChar(FileName), 0, ShFileInfo, SizeOf(ShFileInfo),
    SHGFI_SYSICONINDEX OR SHGFI_ICON OR SHGFI_SMALLICON) <> 0 then
  begin
    MenuItem1.ImageIndex := ShFileInfo.IIcon;
    Self.Refresh; // erase form
    DrawIconEx(Canvas.Handle, 10, 10, ShFileInfo.hIcon, 0, 16, 16, 0,
      DI_IMAGE or DI_MASK);
    DestroyIcon(ShFileInfo.hIcon); // todo: do I need to destroy here? 

    PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
  end;      
end;

end.


Visual Styles Disabled:

Visual Styles Enabled:


A Workaround is to use interposer class or subclass TImageList and override DoDraw as shown here, but what I really want to know is how to create my image list same as system Image list.

Note: I know about TPngImageList and don't want to use it in this case.


Edit: @David's answer (and comments) were accurate:

You'll have to explicitly link to ImageList_Create (v6) because otherwise it is implicitly linked at module load time and will be bound to v5.8

Sample code (no use of activation context API):

function ImageList_Create_V6(CX, CY: Integer; Flags: UINT; Initial, Grow: Integer): HIMAGELIST;
var
  h: HMODULE;
  _ImageList_Create: function(CX, CY: Integer; Flags: UINT;
    Initial, Grow: Integer): HIMAGELIST; stdcall;
begin
  // TODO: find comctl32.dll v6 path programmatically
  h := LoadLibrary('C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll');
  if h <> 0 then
  try
    _ImageList_Create := GetProcAddress(h, 'ImageList_Create');
    if Assigned(_ImageList_Create) then
      Result := _ImageList_Create(CX, CY, Flags, Initial, Grow);
  finally
    FreeLibrary(h);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ...
  ImageList1.Handle := ImageList_Create_V6(ImageList1.Width, ImageList1.Height,
    ILC_COLOR32 or ILC_MASK, 0, ImageList1.AllocBy);
  ...
end;


Edi2: A sample code by @David that shows how it's done correctly via Activation Context API.

解决方案

There are two versions of the image list controls. The v5.8 version and the v6 version. The system image list is a shared coonent owned by the system and uses the v6 version. It's not special in any other way, it's just a plain v6 images list. In your app, your image list is either v5.8 or v6 depending on whether or not you include the manifest. But the system owned image list is always v6.

I don't know why you don't want to use v6 common controls in your app. But with that constraint you could use the activation context API to locally use v6 common controls just while you create your image list. That would solve your problem and leave the rest of your app with v5.8 common controls.

这篇关于具有Alpha混合图标的Imagelist丢失透明度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆