Delphi и 48x48 (или больше) списки изображений - есть ли обходной путь?

Я получаю системный список изображений (с SHGetFileInfo и SHGFI_LARGEICON), добавляю два моих собственных значка и присоединяю его к TListView.

Проблема заключается в том, что если размер значка пользователя не установлен в 32x32 (как, например, он установлен в 48x48), Delphi7 TImageList завершается с ошибкой "Неверный размер изображения".

Кто-нибудь знает, есть ли обходной путь? Я пытался использовать TPngImageList, но это приводит к другим проблемам.

Также обратите внимание, что я бы хотел сохранить альфа-канал иконок. Обычной 1-битной прозрачности недостаточно, так как иконки выглядят ужасно.

Спасибо!

3 ответа

Решение

Когда я уже собирался сдаться, эта страница привела меня к решению: http://delphihaven.wordpress.com/2010/09/06/custom-drawing-on-glass-2/

Очевидно, что если вы попытаетесь добавить иконку размером более 32x32 в список изображений в Delphi7, VCL выдаст вам ошибку "Недопустимый размер изображения", в то время как он может просто вызвать API -интерфейс himagelist - который легко справится с этим.

Вот полное решение:

unit ImageListFix;

interface

uses CommCtrl, Graphics, ImgList;

type
  TImageListFixer = class(TCustomImageList)
  public
    function AddIcon(Image: TIcon): Integer;
  end;

implementation

function TImageListFixer.AddIcon(Image: TIcon): Integer;
begin
  if Image = nil then
    Result := Add(nil, nil)
  else
  begin
    Result := ImageList_AddIcon(Handle, Image.Handle);
    Change;
  end;
end;

end.

И код для добавления иконок в системный список изображений:

DocumentImgList:=TImageListFixer(GetSystemLargeIconsList);

IconToAdd:=TIcon.Create;
try
  IconToAdd.Handle := LoadImage(0, 'c:\Ico1.ico', IMAGE_ICON, DocumentImgList.Width, DocumentImgList.Height, LR_LOADFROMFILE);
  DocumentImgList.AddIcon(IconToAdd);

  IconToAdd.Handle := LoadImage(0, 'c:\Ico2.ico', IMAGE_ICON, DocumentImgList.Width, DocumentImgList.Height, LR_LOADFROMFILE);
  DocumentImgList.AddIcon(IconToAdd);
finally
  IconToAdd.Free;
end;

Я не знаю каких-либо ограничений по размеру изображений, которые TImageList может держать. Мне кажется, что ваша проблема в том, что у вас есть значки разных размеров, и вы не можете держать значки разных размеров в одном списке изображений.

Если вы работаете с иконками разных размеров, вам нужно будет увеличить меньшие по размеру. Вам придется создать его в коде, используя растровое изображение. Вы заполняете растровое изображение чистым прозрачным альфа-каналом и затем перетаскиваете меньший значок в центр растрового изображения.

Другим вариантом может быть сохранение двух отдельных списков изображений, но если вам нужно нарисовать значки в одном и том же виде списка, то я думаю, что работа не будет выполнена. Я думаю, что вам нужно вырастить маленькие иконки.

Для альфы вам понадобится создать дескриптор списка изображений самостоятельно, так как свойство ColorDepth не существует в D7. Из-за этого ваниль D7 TImageList просто не может поддерживать иконки с альфа-каналами.

Вы работаете над этим ограничением, звоня ImageList_Create, проходя ILC_COLOR32 и присвоение результата ImageList.Handle, Сделайте это, прежде чем добавлять какие-либо изображения. Вам придется заполнять список во время выполнения, а не во время разработки, но, похоже, вы уже это делаете.

Вот снимок экрана кнопки инструмента 48x48 со значком 32bpp с альфа-прозрачностью:

Значок 48px из списка изображений

Это правда, что я сделал это в D2010, но мой вышеупомянутый обходной путь будет работать для D7 - я использовал этот механизм до недавнего времени с D6. Я просто показываю это, чтобы доказать, что список изображений может содержать иконки 48 пикселей. поскольку TImageList Я просто обертка вокруг компонента списка системных образов, я думаю, то, что вы пытаетесь сделать, должно быть вполне осуществимым.

TImageList выдает ошибку "Неверный размер изображения" только при 2 условиях:

1) Свойство Height или Width TImageList меньше 1 или свойство Height больше 32768, когда TImageList изначально создается с помощью конструктора CreateSize() (таких ограничений нет, налагаемых установщиками свойств Height и Width).

2) вы пытаетесь добавить / вставить новый TBitmap или TIcon, размеры которого не вписываются во внутреннее изображение TImageList.

Другие вопросы по тегам