Windows 7任务栏中的模糊Delphi窗体图标 [英] Blurred Delphi Form Icon in Windows 7 Taskbar

查看:211
本文介绍了Windows 7任务栏中的模糊Delphi窗体图标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含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; 

接口

使用
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);
程序BitBtn01MouseEnter(发件人:TObject);
程序BitBtn02MouseEnter(发件人:TObject);
procedure BitBtn01MouseDown(Sender:TObject; Button:TMouseButton;
Shift:TShiftState; X,Y:Integer);
程序BitBtn02MouseDown(Sender:TObject; Button:TMouseButton;
Shift:TShiftState; X,Y:Integer);
程序BitBtn01MouseLeave(发件人:TObject);
程序BitBtn02MouseLeave(发件人:TObject);
程序BitBtn02Click(发件人:TObject);
程序BitBtn01Click(发件人:TObject);
private
{私人声明}
public
{公开声明}
end;

var
Form01:TForm01;

实现

{$ R * .dfm}

使用KoushikHalder02;

程序TForm01.BitBtn01Click(Sender:TObject);
begin
Doublebuffered:= True;
Form02.Show;
如果Form01.Visible = true则Form01.BringToFront;
结束

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

程序TForm01.BitBtn01MouseEnter(发件人:TObject);
begin
BitBtn01.Font.Color:= 16711825;
结束

程序TForm01.BitBtn01MouseLeave(发件人:TObject);
begin
BitBtn01.Font.Color:= 15756035;
结束

程序TForm01.BitBtn02Click(发件人:TObject);
begin
Form01.Close;
结束

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

程序TForm01.BitBtn02MouseEnter(发件人:TObject);
begin
BitBtn02.Font.Color:= 16711825;
结束

程序TForm01.BitBtn02MouseLeave(发件人:TObject);
begin
BitBtn02.Font.Color:= 15756035;
结束

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

程序TForm01.FormCreate(发件人:TObject);
begin
Doublebuffered:= True;
结束

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

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

结束。


解决方案

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



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



现在,如果应用程序仅提供所需图标之一,系统将缩放需要绘制的图标未提供的图标尺寸。如果您只提供一个大图标,一般来说,生成的缩放小图标看起来不错。如果您仅提供一个小图标,那么扩大难度就越大,通常情况下,小图标(标题栏上显示)看起来不错,但是大图标是pixellated。


$ b $事实上,你所发生的事情并不是这些问题。 VCL代码意味着您始终在Windows中指定大图标。但是,你显然是提供一个小图标,几乎肯定是16px。这与调用 WM_SETICON ICON_SMALL 相同的结果,32像素图标是pixellated。



最简单的解决方案是在 Form.Icon Application.Icon ,无论你在哪里设置图标。这可以在很多时间工作。



但是,如果您的应用程序运行时使用字体缩放活动,那么您将再次遇到pixellation。使用字体缩放,可以增加两个图标大小。为了正确处理,您必须向底层的Windows框架提供正确大小的图标。如果你不这样做会有pixellation。您可以通过调用 GetSystemMetrics

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

现在通常只需提供一个大图标,并依靠内置缩放来生成小图标。如果您真的关心视觉效果,您当然应该使用专门为这种小尺寸准备的图标。缩小到16像素的32像素图标将不会像熟练的视觉设计师制作的16像素图标一样有效。要使VCL使用您提供的小图标需要额外的工作。具体来说,您需要为 ICON_SMALL 发送 WM_SETICON 。在我的代码库中,我这样做,实际上避免使用 TForm.Icon ,并为两个图标大小调用 WM_SETICON 。为了获得正确的细粒度控制,VCL机制就会干扰。


I have an application having 2 Forms, each Form and Application have individual Icon. On Form1BitBtn1.Click Form2 is Shown-Nonmodaly and on Form1BitBtn2.Click Form1 is closed. On Form2BitBtn1.Click Form2 is Closed and Form2BitBtn2.Click Form1 is closed. It works fine. But the problem is that in Windows 7 Taskbar the Form1 Icon is Blurred and another problem is that when Form2 is shown using Form1BitBtn1.Click the application shows only Form1 Icon but not Form2 Icon. Please help me.

Here is the download link for my project file is "http://hotfile.com/dl/140219264/04ce49c/Delphi_XE2_Form_Handler.7z.html"

My code is as below :

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.

解决方案

What is happening here is, in my view, due to a design flaw in the VCL framework. The underlying windows framework maintains not one, but two icons for each top-level window. These icons are associated with a window either via the window class (see WNDCLASSEX) or through WM_SETICON messages.

The VCL framework always calls WM_SETICON passing ICON_BIG and so only the large icon is assigned. For Windows 7 the large icon is used on the taskbar and the small icon is used on the window's caption bar. On earlier versions of Windows, which had smaller taskbars, the small icon was used on the taskbar. For 100% font scaling the large icon is 32px and the small icon is 16px. For large fonts, the required icon sizes change.

Now, if an application only supplies one of the required icons, the system will scale the icon provided when it needs to draw the icon size which has not been supplied. If you supply a large icon only then, generally, the resulting scaled small icon looks fine. If you supply a small icon only then it's much harder to scale and what typically happens is that the small icon (shown on the caption bar) looks fine, but the large icon is pixellated.

In fact what is happening to you is neither of these problems. The VCL code means that you are always specifying, to Windows, the large icon. However, you are clearly supplying a small icon, almost certainly 16px. This has the same result as calling WM_SETICON with ICON_SMALL and the 32px icon is pixellated.

The simplest solution for you is to use the 32px icon in for Form.Icon or Application.Icon, wherever it is that you set the icon. This will work fine for much of the time.

However, if your application ever runs with font scaling active then you will encounter pixellation again. With font scaling, both icon sizes can be increased. In order to handle this properly you must provide to the underlying Windows framework an icon of the correct size. If you don't then there will be pixellation. You can find out the icon sizes by calling GetSystemMetrics.

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

Now it is often sufficient just to supply a large icon and rely on the built in scaling to produce the small icon. If you really care about visuals you should of course use an icon specifically prepared for such small sizes. A 32px icon down-scaled to 16px will not be as effective visually as a 16px icon produced by a skilled visual designer. To make the VCL use the small icon you provide requires extra work. Specifically you need to send the WM_SETICON for ICON_SMALL. In my code base I do this and in fact avoid using TForm.Icon at all and call WM_SETICON for both icon sizes. In order to get the fine-grained control needed to do this right the VCL mechanisms just interfere.

这篇关于Windows 7任务栏中的模糊Delphi窗体图标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆