Значки формы Delphi размыты на панели задач Windows 7 (с включенным MainFormOnTaskbar)

У нас есть настольное приложение Windows, написанное на Delphi, которое отлично работает в Windows 7, за исключением того, что значок основной формы выглядит размытым в новой панели задач Windows. Пока приложение не запускается, значок выглядит хорошо (т.е. Когда он прикреплен к панели задач). После того, как он был запущен, Windows использует значок основной формы (вместо значка ресурса .exe), и она размыта (похоже, что версия 16x16 значка масштабируется).

Значок, который мы используем для .exe и для основной формы, абсолютно одинаковый и содержит все виды разрешений, включая 48x48 с альфа-смешиванием.

Моя теория заключается в том, что Delphi игнорирует/удаляет дополнительные разрешения значка при импорте файла .ico для основной формы в Delphi. Есть ли способ предотвратить/исправить это? Какой лучший способ убедиться, что приложение, написанное в Delphi, использует правильное разрешение значка в панели задач Windows 7?

Ответы

Ответ 1

Проблема заключается в ленивом программировании в VCL, не соответствующем поведенческой смене ОС. Более или менее это так:

TCustomForm.CreateWnd, после создания дескриптора окна, вызывает

  SendMessage(Handle, WM_SETICON, 1, LPARAM(GetIconHandle)) else

Обратите внимание на "1" вместо wParam, это ICON_BIG. Фактически VCL устанавливает большой значок формы. Но запрошенный размер значка (TIcon.FRequestedSize) равен 16x16 (по умолчанию), и поэтому TIcon формы возвращает дескриптор маленькой иконки. Это размер для маленькой иконки системы и определяется в конструкторе CreateNew с вызовами GetSystemMetrics.

Поскольку более ранние версии Windows использовали маленький значок на панели задач, это не было проблемой. У Hovewer диалог Alt + Tab имел другую проблему; если значок был присвоен форме, он показал "размытый" в диалоговом окне "Alt + Tab". Во всяком случае, Windows 7 по-прежнему по умолчанию возвращает 16x16 для небольшого значка (SM_CXSMICON/SM_CYSMICON) и 32x32 для большого значка (SM_CXICON/SM_CYICON), но на большой панели задач отображается большой значок, если есть тот, который...

Правильный подход - назначить большое изображение (если оно есть в значке) для большого значка и назначить небольшое изображение (если оно есть) маленькому значку. Конечно, поскольку размеры не должны иметь точных совпадений, для этого потребуется сложный алгоритм. Вместо этого реализуется более простой, но сломанный дизайн.


Для обходного пути я не назначаю значок формам в OI и вместо этого использую это:

procedure SetFormIcons(FormHandle: HWND; SmallIconName, LargeIconName: string);
var
  hIconS, hIconL: Integer;
begin
  hIconS := LoadIcon(hInstance, PChar(SmallIconName));
  if hIconS > 0 then begin
    hIconS := SendMessage(FormHandle, WM_SETICON, ICON_SMALL, hIconS);
    if hIconS > 0 then
      DestroyIcon(hIconS);
  end;
  hIconL := LoadIcon(hInstance, PChar(LargeIconName));
  if hIconL > 0 then begin
    hIconL := SendMessage(FormHandle, WM_SETICON, ICON_BIG, hIconL);
    if hIconL > 0 then
      DestroyIcon(hIconL);
  end;
end;

и включите в проект значок icons.res с именованными значками с изображениями 16x16 и 32x32. Все формы в вызове OnCreate

 SetFormIcons(Handle, 'MYFORM', 'MYFORM');

Ответ 2

Это может быть немного кошмар, и это правильно. Я обнаружил, что наиболее успешной стратегией является размещение очень простой иконки в основной форме и приложении, а затем включение программы ReplaceVistaIcon в рабочий процесс сборки для замены значка с помощью файла с несколькими значками после завершения сборки (и перед подписанием exe). Кажется, что значок правильно размещен, так что Windows выбирает его, предпочитая любой другой ресурс значка. Это неудобно делать это, но после настройки (в нашем проекте FinalBuilder) это работает для нас.

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