Изобразяване на 32-битови икони с цената на нарушаване на контролното изобразяване

Ситуацията ми може да се нарече битка с UxTheme.dll. Във формуляра има лента с инструменти (VCL) с един бутон, назначен към падащото меню. В това меню трябва да покажа 32-битови икони, които зареждам в ImageList в движение. Трябваше леко да коригирам изходния код на TCustomImageList и да добавя манифест към програмата. Тъй като не се нуждая от нищо друго от Uxtheme (т.е. има странични ефекти, които са обсъдени по-долу), пиша SetThemeAppProperties (STAP_ALLOW_NONCLIENT) във Form.OnCreate.

Факт е, че също рисувам тази лента с инструменти чрез събитието OnCustomDrawButton (програмата поддържа кожи). Там, както се очаква, 3 състояния: горещо, натиснато и нормално. Така че, без манифест, програмата обикновено обработва изобразяването на лентата с инструменти, но не рисува правилно иконите (черна кутия вместо сенки) - всичко е точно тук, SDK на платформата предупреждава за това. И ако добавите манифест - започва, извинете, йок: по някаква причина бутонът на лентата с инструменти, когато се натисне, менюто се показва, но като се натисне не се рисува. Понякога се рисува - буквално за един момент, после пак се рисува нормално, не се натиска. (Тук трябва да кажа, че преди използването на SetThemeAppProperties, най-накрая беше пълен йок - размерът и характерът на изобразяването на бутоните бяха някак напълно неадекватни).

И цялото това страдание - в името на иконите с меки сенки. Кажете ми, добри хора, какво греша? Има ли алтернативни методи за изобразяване на 32-битови икони? В края на краищата Windows го прави по някакъв начин, въпреки че е опакован в Common Controls. Или може би има нещо нередно в процедурата за изчертаване на бутона на лентата с инструменти? За всеки случай код:

procedure TMyForm.ToolBar1CustomDrawButton(Sender: TToolBar; Button: TToolButton; State: TCustomDrawState; var DefaultDraw: Boolean);

// пропусната част от кода .

начало Ако (cdsHot вState) тогава DrawHot else if (cdsSelected в състояние) then DrawSelected else DrawNormal; end;

Където DrawHot, DrawSelected и DrawNormal са процедури, които работят с растерното изображение и след това просто го копират в платното на лентата с инструменти. Повтарям, работят коректно, само ако има манифест, DrawSelected не се извиква.

Така че изглежда, че е било трудно да го приключим.

Обяснявам накратко: трябва да се науча да рисувам икони, сред които може да има 32-битови (с алфа канал, за Windows XP). Трябва да направите това, без да използвате манифест.

Или трябва да обясните странното поведение на лентите с инструменти или по-скоро на техните бутони със зададеното падащо меню. Ако има манифест, натиснатото състояние се изобразява като ненатиснато.

Islander ( 2004-05-04 09:27 ) [2]

Няма нужда да се потите, мили мои. Проблемът не е в лентата с инструменти, лентата с инструменти държи алфа канала. Проблемът е в ImageList. ImageList не трябва да се приема като стандартен Delphi, а да се създаде с помощта на WinAPI манипулатори с флаг за поддръжка на 32-битови икони. И след това го присвоете на лентата с инструменти чрез SendMessage

Islander ( 2004-05-04 10:33 ) [3]

Между другото, менюто съдържа и алфа канал.

Всъщност DrawIconEx, ако не се лъжа, рисува иконата нормално, дори манифестът да не е свързан. Основното нещо е да имате XP. А писалките ImageList са по-добри.