Delphi表单图标在Windows 7任务栏上模糊不清(启用MainFormOnTaskbar)

14

我们有一个用Delphi编写的Windows桌面应用程序,可以在Windows 7上正常运行,但在Windows新任务栏中主窗体的图标模糊。只要应用程序没有启动,图标就看起来很好(例如当它被固定到任务栏时)。一旦它被启动,Windows使用主窗体的图标(而不是.exe资源图标),并且它变得模糊了(看起来像16x16版本的图标被放大了)。

我们用于.exe和主窗体的图标完全相同,其中包含各种分辨率,包括48x48具有alpha混合。

我的理论是,在我将.ico文件导入Delphi的主窗体时,Delphi会忽略/删除图标的额外分辨率。有没有办法防止/修复这个问题?确保用Delphi编写的应用程序在Windows 7的任务栏中使用正确的图标分辨率的最佳方法是什么?

2个回答

12
问题在于VCL中的惰性编程与操作系统的行为变化不匹配。更准确地说,就像这样;
TCustomForm.CreateWnd,在窗口句柄创建后调用;
  SendMessage(Handle, WM_SETICON, 1, LPARAM(GetIconHandle)) else
注意,在wParam的位置上有个"1",这是ICON_BIG。实际上,VCL设置了窗体的大图标。但是,图标的请求大小(TIcon.FRequestedSize)默认为16x16,因此窗体的TIcon返回了一个小图标的句柄。这是系统小图标的大小,并在CreateNew构造函数中通过调用GetSystemMetrics来确定。
早期版本的Windows在任务栏上使用小图标,这不是问题。然而,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
有趣的是,我找到的解决方案是不为表单设置图标,而是使用应用程序的图标,这样似乎效果更好。现在我会检查一下在Win 7中的情况。 - mj2008
@mj2008 - 你的解决方案在W7上也可以正常工作。我忽略了Dennis提到他为应用程序和窗体分配了相同的图标。在这种情况下,这将是更简单的解决方案。我的解决方法只有在需要为窗体分配不同的图标时才有意义。 - Sertac Akyuz
很久以前有人提出了问题并得到了回答,但我想指出这个解决方案似乎不适用于使用VCL样式的人。关闭样式后,该解决方案可以正常工作。 - spurgeon
1
要修复VCL样式,请参见https://dev59.com/ImLVa4cB1Zd3GeqP1PXg - spurgeon
@spurgeon - 感谢提供链接。 - Sertac Akyuz

3
这个确实有点棘手。我发现最成功的策略是在主窗体和应用程序上放置一个非常简单的图标,然后将ReplaceVistaIcon程序纳入构建工作流中,在构建完成之后(签名exe之前),使用多重图标文件替换图标。这样似乎可以正确地放置图标,以便Windows优先选择它,而不是其他任何图标资源。虽然这样做有点麻烦,但一旦设置好了(在我们的FinalBuilder项目中),就可以为我们工作。
令人讨厌的问题是,在您测试时,您可能需要删除Windows图标缓存才能看到任何更改的效果。这涉及关闭Explorer,以允许您从命令会话中删除缓存文件。

谢谢您的建议,如果Sertac的方法不是那么有效,我们会使用这个方法。+1 - Dennis G.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接