Размытый значок формы Delphi в панели задач Windows 7 - PullRequest
1 голос
/ 07 января 2012

enter image description here У меня есть приложение, имеющее 2 формы, каждая форма и приложение имеют индивидуальный значок. На Form1BitBtn1.Click Form2 показывается немодально, а на Form1BitBtn2.Click форма Form1 закрыта. На Form2BitBtn1.Click Form2 закрывается, а Form2BitBtn2.Click Form1 закрывается. Работает нормально. Но проблема в том, что в панели задач Windows 7 значок формы Form1 размыт, а другая проблема заключается в том, что когда форма Form2 отображается с помощью Form1BitBtn1.Click, приложение отображает только значок формы Form1, но не значок формы Form2. Пожалуйста, помогите мне.

Вот ссылка для скачивания файла моего проекта: "http://hotfile.com/dl/140219264/04ce49c/Delphi_XE2_Form_Handler.7z.html"

Мой код указан ниже:

unit KoushikHalder01;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, Vcl.ExtCtrls,
  Vcl.ComCtrls;
type
  TForm01 = class(TForm)
    BitBtn01: TBitBtn;
    BitBtn02: TBitBtn;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormShow(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure BitBtn01MouseEnter(Sender: TObject);
    procedure BitBtn02MouseEnter(Sender: TObject);
    procedure BitBtn01MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure BitBtn02MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure BitBtn01MouseLeave(Sender: TObject);
    procedure BitBtn02MouseLeave(Sender: TObject);
    procedure BitBtn02Click(Sender: TObject);
    procedure BitBtn01Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form01: TForm01;

implementation

{$R *.dfm}

uses KoushikHalder02;

procedure TForm01.BitBtn01Click(Sender: TObject);
begin
   Doublebuffered := True;
   Form02.Show;
   if Form01.Visible = true then Form01.BringToFront;
end;

procedure TForm01.BitBtn01MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   BitBtn01.Font.Color :=10379745;
end;

procedure TForm01.BitBtn01MouseEnter(Sender: TObject);
begin
   BitBtn01.Font.Color :=16711825;
end;

procedure TForm01.BitBtn01MouseLeave(Sender: TObject);
begin
   BitBtn01.Font.Color :=15756035;
end;

procedure TForm01.BitBtn02Click(Sender: TObject);
begin
  Form01.Close;
end;

procedure TForm01.BitBtn02MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   BitBtn02.Font.Color :=10379745;
end;

procedure TForm01.BitBtn02MouseEnter(Sender: TObject);
begin
   BitBtn02.Font.Color :=16711825;
end;

procedure TForm01.BitBtn02MouseLeave(Sender: TObject);
begin
   BitBtn02.Font.Color :=15756035;
end;

procedure TForm01.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   Doublebuffered := True;
end;

procedure TForm01.FormCreate(Sender: TObject);
begin
   Doublebuffered := True;
end;

procedure TForm01.FormHide(Sender: TObject);
begin
   Doublebuffered := True;
end;

procedure TForm01.FormShow(Sender: TObject);
begin
   Doublebuffered := True;
end;

end.

Ответы [ 4 ]

7 голосов
/ 17 июня 2012

Я знаю, как это исправить ... и все просто. Не предоставляйте значок для Form1.Icon.

Введите информацию о значке в

Проект> Параметры> Приложение> Настройки значков приложения> Загрузить Icon.

Обязательно выберите лучшее разрешение для своей иконки.

Запустите приложение и шазан!

6 голосов
/ 08 января 2012

То, что здесь происходит, на мой взгляд, связано с недостатком дизайна в среде VCL. Базовая структура Windows поддерживает не один, а два значка для каждого окна верхнего уровня. Эти значки связаны с окном либо через класс окна (см. WNDCLASSEX), либо через сообщения WM_SETICON.

Платформа VCL всегда вызывает WM_SETICON, передавая ICON_BIG, поэтому назначается только большой значок. В Windows 7 большой значок используется на панели задач, а маленький значок - на панели заголовков окна. В более ранних версиях Windows, которые имели меньшие панели задач, на панели задач использовался маленький значок. Для 100% масштабирования шрифта большой значок составляет 32 пикселя, а маленький значок - 16 пикселей. Для больших шрифтов требуемые размеры значков меняются.

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

Фактически, то, что происходит с вами, не является ни одной из этих проблем. Код VCL означает, что вы всегда указываете для Windows большой значок. Тем не менее, вы явно предоставляете маленькую иконку, почти наверняка 16px. Это имеет тот же результат, что и вызов WM_SETICON с ICON_SMALL, а значок 32px имеет пикселизацию.

Самое простое решение для вас - использовать значок 32px для Form.Icon или Application.Icon, где бы вы ни устанавливали значок. Это будет хорошо работать большую часть времени.

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

SmallIconSize := GetSystemMetrics(SM_CXSMICON);
LargeIconSize := GetSystemMetrics(SM_CXICON);

Теперь часто достаточно просто поставить большую иконку и положиться на встроенное масштабирование, чтобы создать маленькую иконку. Если вы действительно заботитесь о визуальных эффектах, вам, конечно, следует использовать значок, специально подготовленный для таких небольших размеров. Значок в 32 пикселя, уменьшенный до 16 пикселей, визуально не будет столь же эффективным, как значок в 16 пикселей, созданный опытным визуальным дизайнером. Чтобы заставить VCL использовать маленький значок, который вы предоставляете, требуется дополнительная работа. В частности, вам нужно отправить WM_SETICON для ICON_SMALL. В моей кодовой базе я делаю это и фактически избегаю вообще использовать TForm.Icon и вызываю WM_SETICON для обоих размеров значков. Чтобы получить детальный контроль, необходимый для правильной работы, механизмы VCL просто вмешиваются.

1 голос
/ 07 января 2012

Мое лучшее предположение заключается в том, что размер иконки вашей формы составляет 16x16 и растягивается с 16x16 до 48x48, что приводит к тому, что вы бы назвали «размытым внешним видом», но это стандартное поведение Windows при вводе (значок на вашем форма или приложение) очень низкого разрешения.

Значки могут иметь несколько разрешений в одном файле .ico. Поэтому, пожалуйста, замените ваш текущий значок размером 16x16, 32x32 и 48x48. Затем окна смогут показывать правильное изображение в полном разрешении. Современная иконка для использования в Windows может также включать в себя некоторые большие значки Vista / Win7 размером до 256x256. Обновление ОП сообщает, что значок уже имеет все правильные размеры, и из другого ответа здесь следует, что у вас возникла проблема с внутренней обработкой VCL, как Дэвид упоминает в своем ответе.

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

0 голосов
/ 28 января 2016

TL; версия DR: Не устанавливайте для свойства Icon любое значение, отличное от значения, полученного при загрузке из ресурса Win32, который содержит несколько размеров значков. Например, используйте только TIcon.LoadFromResourceName. Если вы установите свойство Icon в конструкторе форм, будет использоваться только один размер значка, что приведет к артефактам масштабирования.

В течение многих лет VCL не поддерживал концепцию графического значка с иконками нескольких размеров: TIcon всегда предполагалось представлять собой один отдельный графический объект, а не набор графических изображений с различными размерами и разрешениями. Это все еще верно, и проблему с дизайном, вероятно, нелегко исправить в VCL.

VCL установит значок формы с помощью сообщения WM_SETICON. VCL всегда устанавливает wParam на ICON_BIG: проверка источников VCL показывает, что он никогда не использует ICON_SMALL при установке значка. Кроме того, переменные-члены hIcon и hIconSm структуры WNDCLASSEX всегда равны NULL при создании класса окна. Поэтому ясно, что VCL даже не пытается установить маленькую иконку. Обычно, если приложение никогда не устанавливает маленький значок, Windows изменит размер большого значка, чтобы получить маленький размер, что довольно уродливо. Однако есть важное исключение из этого правила.

Обратите внимание, что ресурс ICON файла ресурсов Windows фактически будет хранить так называемую группу значков 1027 *, которая представляет собой набор отдельных изображений значков из исходного * 1028. * файл. API LoadIcon утверждает, что будет загружен только большой значок 32x32. Однако на самом деле это не совсем так. Кажется, что сама Windows поддерживает связь между HICON и исходным ресурсом, поэтому, если требуются значки других размеров, Windows может загрузить их по мере необходимости.

Этот факт недостаточно документирован, но есть одно место в MSDN, в котором говорится об этом: WNDCLASSEX структура , hIconSm переменная:

Дескриптор маленькой иконки, связанной с классом окна. Если этот элемент имеет значение NULL, система ищет в значке ресурса, указанном членом hIcon, значок соответствующего размера, который будет использоваться в качестве маленького значка.

Поэтому, даже несмотря на то, что VCL не поддерживал маленькие значки должным образом с помощью общедоступного класса TForm.Icon (например, назначая его из редактора свойств во время разработки), все еще можно было заставить все работать правильно, используя один из этих два метода:

  • Оставьте свойство TForm.Icon неустановленным (без значка). В этом случае форма получит значок от TApplication.Icon. Значением по умолчанию для этого является ресурс приложения MAINICON. От TApplication.Create:

    FIcon := TIcon.Create;
    FIcon.Handle := LoadIcon(MainInstance, 'MAINICON');
    
  • Если вы не хотите использовать значок приложения по умолчанию, вы можете загрузить другой ресурс значка во время выполнения; в C ++:

    myForm->Icon->LoadFromResourceName(FindHInstance(...), L"OtherResource");
    

Таким образом, VCL обеспечивает базовую поддержку маленьких значков, поскольку он поддерживает загрузку значков из ресурсов, а Windows поддерживает загрузку маленьких значков из больших значков, которые были загружены из ресурса.

Если вы используете стили VCL, см. Мой ответ на связанную ошибку здесь: https://stackoverflow.com/a/35067909/562766

...