2012-01-07 64 views
1

enter image description here我有一个应用程序有2个窗体,每个窗体和应用程序都有单独的图标。在Form1BitBtn1.Click Form2上显示Nonmodaly和Form1BitBtn2.Click Form1已关闭。在Form2BitBtn1.Click Form2已关闭和Form2BitBtn2.Click Form1已关闭。它工作正常。但问题是,在Windows 7任务栏中,Form1图标是模糊的,另一个问题是使用Form1BitBtn1.Click显示Form2时,应用程序只显示Form1图标而不显示Form2图标。 请帮帮我。Windows 7中的模糊Delphi窗体图标任务栏

这里是下载链接为我的项目文件是“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

请编辑您的问题包括** **小屏幕捕获或东西给你在问什么。 “Windows 7任务栏中的模糊Delphi窗体图标”很难从模糊描述和一些完全不相关的代码中理解,你希望人们编译和运行以便甚至(可能)知道你在问什么。这里的人想要帮助,但你需要真正解释你想要帮助什么,才能使之成为可能。 :)(你发布的代码只能在几个事件中重复几件事;它们都是'DoubleBuffered:= True' /'Font.Color:= '没有理由完成。) – 2012-01-07 03:49:40

+3

澄清,'DoubleBuffered: = True'可以在Object Inspector中执行一次*(或者甚至在FormCreate中执行一次),并且在您每次执行操作时都会浪费精力。在你问的任何问题的范围内改变Font.Color是没有意义的(不管它是什么,它与字体颜色的改变无关)。这些代码都不适用于与应用程序或窗口图标相关的任何问题。 – 2012-01-07 03:54:12

+0

@Koushik - 这个问题是[this one](http://stackoverflow.com/q/2621814/243614)的重复,尽管您发布了所有代码? – 2012-01-08 15:21:59

回答

6

在我看来,这里发生的事情是由于VCL框架中的设计缺陷。基础的Windows框架不为每个顶级窗口维护一个,而是两个图标。这些图标通过窗口类(参见WNDCLASSEX)或通过WM_SETICON消息与窗口关联。

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

现在,如果应用程序只提供其中一个所需的图标,系统将缩放当需要绘制未提供的图标大小时提供的图标。如果您只提供一个大图标,通常,缩放后的小图标看起来很好。如果只提供一个小图标,那么缩放将变得更加困难,通常情况下,小图标(显示在标题栏上)看起来不错,但大图标是像素化的。

实际上发生在你身上的事情并不是这些问题。 VCL代码意味着您总是向Windows指定大图标。但是,你显然提供了一个小图标,几乎可以肯定是16px。这与调用WM_SETICONICON_SMALL的效果相同,并且32像素图标是像素化的。

对于你来说最简单的解决方案是使用32px图标作为Form.IconApplication.Icon,无论你在哪里设置图标。这在很多时候都能正常工作。

但是,如果您的应用程序运行时字体缩放活跃,那么您将再次遇到像素化。随着字体缩放,图标大小可以增加。为了正确处理此问题,您必须向底层Windows框架提供正确大小的图标。如果你不那么会有像素化。您可以致电GetSystemMetrics找出图标大小。

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

现在通常只要提供一个大图标并依靠内置的缩放来产生小图标就足够了。如果你真的关心视觉效果,你当然应该使用专门为这种小尺寸准备的图标。缩小到16px的32像素图标在视觉上不如有经验的视觉设计师制作的16像素图像有效。为了使VCL使用您提供的小图标,需要额外的工作。具体而言,您需要发送WM_SETICONICON_SMALL。在我的代码库中,我这样做,实际上完全避免使用TForm.Icon,并且为图标大小调用WM_SETICON。为了获得所需的细粒度控制,VCL机制正好干涉。

+0

+1同意。如有必要,最好提供一个大图标(32x32或48x48),让Windows缩小而不是提供这两个图标,并让VCL错误地选择小图标。 – 2012-01-09 15:59:51

+0

我不知道是否有一个额外的“LargeIcon”属性的自定义TForm后裔将是一个很好的事情,在一个人的工具箱。然后,TForm.Icon的内置行为无需再担忧。 – 2012-01-09 16:07:30

+0

@WarrenP事实上,你需要一个SmallIcon属性! – 2012-01-09 16:14:47

1

我最好的猜测是,你的窗体图标尺寸为16×16,并且正在从拉伸16x16到48x48,导致你称之为“模糊的外观”,但当输入(表单或应用程序中的图标)分辨率很低时,这是标准的Windows行为。

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

总之,窗户这样做是因为你无法避免它。这是一个模糊或像素化的选择。窗口内的“拉伸”代码会导致模糊,这正是为了避免您在不模糊它时会看到的块状外观。

+0

我已添加屏幕截图。请帮帮我。 – 2012-01-08 06:21:09

+0

我的项目已经有16x16,32x32和48x48大小的图标。 – 2012-01-08 06:34:46

+2

据我所知,德尔福只设置小图标,并没有提供内置的方式来设置大图标 – 2012-01-08 08:26:52

7

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

项目>选项>应用程序>应用程序图标设置>加载 图标提供您的图标信息。

一定要为您的图标选择最佳分辨率。

运行应用程序和shazan!

+0

thanx,为我工作...'+ 1' – 2014-05-12 09:06:58

+1

此答案不解决被问到的问题。特别是在被问到的问题中,提问者明确指出:“我有一份申请有2份表格,每份表格和申请都有单独的图标。”换句话说,所提出的解决方案根本不适用。使用'TForm.Icon'和'TApplication.Icon'看到不同行为的原因是,当您使用IDE设置图标时,最终会在'TForm.Icon'中出现一个小图标,在TApplication中出现一个大图标。 Icon'。 – 2014-05-12 09:16:31

0

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

多年来,VCL一直不支持多图标大小的图标图形的概念:TIcon总是被认为是一个单一的图形 - 而不是一组尺寸和分辨率不同的图形。这仍然是事实,并且VCL中的设计问题可能不容易纠正。

VCL将通过WM_SETICON消息设置窗体图标。 VCL始终将wParam设置为ICON_BIG:对VCL源进行的检查表明,在设置图标时它从不使用ICON_SMALL。此外,创建窗口类时,hIconhIconSm成员变量WNDCLASSEX结构始终为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

相关问题