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 с альфа-прозрачностью:
Это правда, что я сделал это в D2010, но мой вышеупомянутый обходной путь будет работать для D7 - я использовал этот механизм до недавнего времени с D6. Я просто показываю это, чтобы доказать, что список изображений может содержать иконки 48 пикселей. поскольку TImageList
Я просто обертка вокруг компонента списка системных образов, я думаю, то, что вы пытаетесь сделать, должно быть вполне осуществимым.
TImageList выдает ошибку "Неверный размер изображения" только при 2 условиях:
1) Свойство Height или Width TImageList меньше 1 или свойство Height больше 32768, когда TImageList изначально создается с помощью конструктора CreateSize() (таких ограничений нет, налагаемых установщиками свойств Height и Width).
2) вы пытаетесь добавить / вставить новый TBitmap или TIcon, размеры которого не вписываются во внутреннее изображение TImageList.