Windows 7任务栏中的模糊Delphi表单图标

时间:2012-01-07 03:46:18

标签: delphi delphi-xe2

enter image description here我的应用程序有2个表单,每个表单和应用程序都有单独的图标。在Form1BitBtn1.Click Form2上显示 - 非模式和Form1BitBtn2.Click Form1已关闭。在Form2BitBtn1.Click Form2已关闭,Form2BitBtn2.Click Form1已关闭。它工作正常。但问题是在Windows 7任务栏中,Form1图标是模糊的,另一个问题是当使用Form1BitBtn1显示Form2时。单击该应用程序仅显示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 个答案:

答案 0 :(得分:7)

我知道如何解决这个问题......而且很简单。 不要为Form1.Icon提供图标。

中提供您的图标信息
  

项目>选项>申请>应用程序图标设置>加载   图标。

请务必为您的图标选择最佳分辨率。

运行应用程序并使用shazan!

答案 1 :(得分:6)

在我看来,由于VCL框架中的设计缺陷,这里发生了什么。底层的Windows框架不会为每个顶级窗口维护一个,而是两个图标。这些图标通过窗口类(请参阅WNDCLASSEX)或WM_SETICON消息与窗口相关联。

VCL框架总是调用WM_SETICON传递ICON_BIG,因此只分配了大图标。对于Windows 7,任务栏上使用大图标,窗口标题栏上使用小图标。在具有较小任务栏的早期版本的Windows上,任务栏上使用了小图标。对于100%字体缩放,大图标为32px,小图标为16px。对于大字体,所需的图标大小会更改。

现在,如果应用程序仅提供所需图标之一,系统将在需要绘制尚未提供的图标大小时缩放提供的图标。如果您只提供一个大图标,通常,生成的缩放小图标看起来很好。如果你只提供一个小图标,那么它就难以扩展,通常会发生的是小图标(显示在标题栏上)看起来很好,但是大图标是像素化的。

事实上,发生在你身上的不是这些问题。 VCL代码意味着您始终在Windows中为大图标指定。但是,你显然提供了一个小图标,几乎可以肯定是16px。这与使用WM_SETICON调用ICON_SMALL并且像素化的32px图标具有相同的结果。

最简单的解决方案是在Form.IconApplication.Icon中使用32px图标,无论您在何处设置图标。这在大多数情况下都可以正常工作。

但是,如果您的应用程序运行时字体缩放处于活动状态,那么您将再次遇到像素化。通过字体缩放,可以增加两个图标大小。为了正确处理这个问题,您必须向底层Windows框架提供正确大小的图标。如果没有,则会出现像素化现象。您可以致电GetSystemMetrics了解图标大小。

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

现在通常只需提供一个大图标并依靠内置缩放来生成小图标。如果你真的关心视觉效果,你当然应该使用专为这么小的尺寸准备的图标。缩小到16px的32px图标在视觉上不如熟练的视觉设计师生成的16px图标有效。要使VCL使用您提供的小图标需要额外的工作。具体而言,您需要发送WM_SETICON ICON_SMALL。在我的代码库中,我执行此操作,实际上完全避免使用TForm.Icon并为两个图标大小调用WM_SETICON。为了获得所需的细粒度控制,VCL机制只是干涉。

答案 2 :(得分:1)

我最好的猜测是你的表单图标大小为16x16,并且从16x16扩展到大约48x48,导致你所谓的“模糊外观”,但这是输入时的标准Windows行为(你的图标)形式或应用)分辨率非常低。

图标在同一.ico文件中可以有多种分辨率。因此,请将当前图标替换为尺寸为16x16,32x32和48x48的图标。这个窗口将能够显示正确的全分辨率图像。 Windows使用的现代图标还可能包括一些较大的Vista / Win7图标,大小高达256x256。 更新 OP报告图标已经具有所有正确的尺寸,并且在此处的其他答案中确实显示您正在遇到VCL内部处理问题,正如David在回答中提到的那样。

简而言之,Windows就是这样做的,因为你没有办法避免它。它是模糊或像素化的选择。窗口内的“拉伸”代码会导致模糊,正是为了避免在不模糊时产生的块状外观。

答案 3 :(得分:0)

TL; DR版本:不要将Icon属性设置为除通过从包含多个图标大小的Win32资源加载获得的值之外的任何值。例如,仅使用TIcon.LoadFromResourceName。如果在表单设计器中设置Icon属性,则只会使用一个图标大小,从而导致缩放工件。

多年来,VCL一直不支持具有多种图标大小的图标图形的概念:TIcon始终被认为是一个单独的图形 - 而不是一组不同尺寸和分辨率的图形。这仍然是正确的,在VCL中可能不容易纠正设计问题。

VCL将通过WM_SETICON消息设置表单图标。 VCL始终将wParam设置为ICON_BIG:对VCL来源的检查表明,在设置图标时,它永远不会使用ICON_SMALL。此外,创建窗口类时,hIcon结构的hIconSmWNDCLASSEX成员变量始终为NULL。因此,很明显,VCL甚至都没有试图设置一个小图标。通常情况下,如果应用程序从不设置小图标,Windows会将大图标调整为小尺寸,这非常难看。但是,该规则有一个重要的例外。

请注意,Windows资源文件的ICON资源实际上会存储所谓的图标组,这是一组来自原始.ico的单个图标图像文件。 LoadIcon API声明只会加载大型32x32图标。然而,这实际上并不严格。似乎Windows本身在HICON和原始资源之间保持链接,因此如果需要其他大小的图标,Windows可以根据需要加载它们。

这个事实没有详细记录,但MSDN中有一个地方陈述了这一事实:WNDCLASSEX structurehIconSm变量:

  

与窗口类关联的小图标的句柄。如果此成员为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