Перейти к содержанию
Fire Monkey от А до Я
  • 0

[Windows] Как поменять иконку формы без стилизованной рамки?


DirtyBorov

Вопрос

Подскажите как можно изменить иконку окна в runtime? 

Суть проблемы в том, что мне надо поддерживать приложение для разных заказчиков. Каждый из них хочет иметь собственную иконку в приложении. Очевидное решение - создать несколько проектов и каждому задать требуемую иконку. Однако на практике это весьма утомительное занятие. Хотелось бы сделать одно приложение, а иконки подгружать динамически на основании настроек приложения.

Вспоминая практику VCL и WinAPI, подменить иконку Application оказалось задачей тривиальной:

NewAppIcon := TIcon.Create;
NewAppIcon.LoadFromFile(AIconFile);
SendMessage(ApplicationHWND, WM_SETICON, 1, NewAppIcon.Handle);

А вот дальше начались проблемы. Окна уже прогрузили иконку по умолчанию и добраться до них у меня не получается. 

Добраться через стиль не получается, потому что TForm не является наследником TStyledObject и не имеет StylesData. Через FindStyleResource тоже не получается добраться.

 

Может кто знает как?

 

Изменено пользователем Brovin Yaroslav
Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Администраторы

Добрый день,

 

У вас все правильно написано. В вашем коде вы меняете иконку самого приложения в трее. А вот чтобы поменять иконку у формы, нужно отправлять сообщение WM_SETICON окну а не приложению:

uses
  VCL.Graphics, Winapi.Windows, Winapi.Messages, FMX.Platform.Win;


procedure TForm3.Button1Click(Sender: TObject);
var
  NewAppIcon: TIcon;
begin
  NewAppIcon := TIcon.Create;
  NewAppIcon.LoadFromFile('c:\icon.ico');

  SendMessage(ApplicationHWND, WM_SETICON, 1, NewAppIcon.Handle);
  SendMessage(WindowHandleToPlatform(Handle).Wnd, WM_SETICON, 1, NewAppIcon.Handle);
end;
Ссылка на комментарий
  • 0
SendMessage(WindowHandleToPlatform(Handle).Wnd, WM_SETICON, 1, NewAppIcon.Handle);

 

Это первое что попробовал.  Забыл об этом сказать. К сожалению этот трюк не работает.  Именно потому я и обратился за помощь. 

Верней он работает, только если не используется стиль но рамку окна.  

 

Если же используется стиль, то тут уже либо не работает (самодельный стиль на основе стандартных):

 

post-594-0-60220900-1431787253_thumb.png

 

Либо вот такие глюки (стиль jet). Причем если подвигать окно, то окно  восстановит рамку из стиля и... вернет иконку по умолчанию.

 

post-594-0-99522100-1431787972_thumb.png 

 

Очевидно что проблема связана именно с использованием стилей. Я пробовал расширенные стили для XE7 - у всех такая проблема в XE8. У стилей, где нет стилизации окна - проблем нет. Надеюсь что данная проблема связана именно с использованием стилей от ХЕ7 в ХЕ8. Насколько я понял, стили подверглись изменениям в связи с TImageList (картинки не будут отображаться в старых стилях).  К сожалению премиум стилей для ХЕ8 у меня нет и проверить истинность своих догадок я не могу.

В любом случае - спасибо за помощь. По крайней мере я теперь знаю что был на верном пути. :)

Изменено пользователем DirtyBorov
Ссылка на комментарий
  • 0
  • Администраторы

Вас понял. При стилизованной рамке окна, иконка кэшируется. Первый раз она запрашивается в момент первой отрисовки формы. Поэтому в вашем случае ее нужно задать сразу после создания хендла, а именно в CreateHandle.

  TForm15 = class(TForm)
    StyleBook1: TStyleBook;
  protected
    procedure CreateHandle; override;
  end;

implementation

uses
  VCL.Graphics, Winapi.Windows, Winapi.Messages, FMX.Platform.Win;

{ TForm15 }

procedure TForm15.CreateHandle;
var
  NewAppIcon: TIcon;
begin
  inherited;
  NewAppIcon := TIcon.Create;
  NewAppIcon.LoadFromFile('c:\icon.ico');

  SendMessage(ApplicationHWND, WM_SETICON, 1, NewAppIcon.Handle);
  SendMessage(WindowHandleToPlatform(Handle).Wnd, WM_SETICON, 1, NewAppIcon.Handle);
end;
Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...