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

发布于 2024-08-28 08:36:59 字数 381 浏览 10 评论 0原文

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

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

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

We have a Windows desktop application written in Delphi that works fine on Windows 7, except that the icon of the main form looks blurry in Windows' new taskbar. As long as the application has not been started the icon looks fine (i.e. when it's pinned to the taskbar). Once it has been started Windows uses the icon of the main form (instead of the .exe resource icon) and it's blurry (it looks like a 16x16 version of the icon is scaled up).

The icon that we use for the .exe and for the main form are exactly the same and it contains all kinds of resolutions, including 48x48 with alpha blending.

My theory is that Delphi ignores/deletes the extra resolutions of the icon when I import the .ico file for the main form in Delphi. Is there a way to prevent/fix this? What's the best way to ensure that an application written in Delphi uses the correct icon resolution in Windows 7's taskbar?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

去了角落 2024-09-04 08:36:59

问题在于 VCL 内的惰性编程不适合操作系统的行为变化。或多或少是这样的;

TCustomForm.CreateWnd,窗口句柄创建后,调用;

  SendMessage(Handle, WM_SETICON, 1, LPARAM(GetIconHandle)) else

注意“1”代替了 wParam,即 ICON_BIG。实际上VCL设置了窗体的大图标。但图标的请求大小 (TIcon.FRequestedSize) 是 16x16(默认情况下),因此窗体的 TIcon 返回小图标的句柄。这是系统小图标的大小,是在构造函数 CreateNew 中通过调用 GetSystemMetrics 确定的。

由于早期版本的 Windows 使用任务栏上的小图标,这没有问题。然而,Alt+Tab 对话框却有相反的问题;如果将图标分配给表单,则它在 Alt+Tab 对话框中显示为“模糊”。无论如何,Windows 7默认情况下仍然为小图标(SM_CXSMICON/SM_CYSMICON)返回16x16,为大图标(SM_CXICON/SM_CYICON)返回32x32,但是大任务栏显示大图标,如果有的话

..正确的方法是为大图标分配一张大图像(如果图标中有一个),为小图标分配一张小图像(如果有的话)。当然,由于尺寸不必完全匹配,因此这需要复杂的算法。相反,实施了一种更简单但破碎的设计。

作为解决方法,我没有为 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');

The problem lies within lazy programming within the VCL not fitting with the behavioral change of the OS. More or less it is like this;

TCustomForm.CreateWnd, after the window handle is created, calls;

  SendMessage(Handle, WM_SETICON, 1, LPARAM(GetIconHandle)) else

Notice the "1" in place of wParam, that's ICON_BIG. Actually the VCL sets the large icon of the form. But the icon's requested size (TIcon.FRequestedSize) is 16x16 (by default), and so the TIcon of the form returns a handle for the small icon. That's the size for the system small icon and is determined in the constructor CreateNew with calls to GetSystemMetrics.

Since earlier versions of Windows used the small icon on the taskbar this was no problem. Hovewer the Alt+Tab dialog had the problem other way around; if an icon was assigned to a form it showed "blurred" in the Alt+Tab dialog. Anyway, Windows 7, still, by default returns 16x16 for the small icon (SM_CXSMICON/SM_CYSMICON) and 32x32 for the large icon (SM_CXICON/SM_CYICON), but the large taskbar displays the large icon, if there is one that is..

The correct approach would be to assign a large image (if there is one in the icon) for the large icon and assign a small image (if there is one) to the small icon. Granted, since the sizes would not have to have exact matches, this would require a complex algorithm. Instead, a simpler but broken design is implemented.

For a workaround, I don't assign an icon to the forms in the OI and instead use this;

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;

and include an "icons.res" with named icons having 16x16 and 32x32 images, in the project. All the forms in their OnCreate call

 SetFormIcons(Handle, 'MYFORM', 'MYFORM');
Smile简单爱 2024-09-04 08:36:59

要做到这一点可能有点像一场噩梦。我发现最成功的策略是在主窗体和应用程序上放置一个非常简单的图标,然后将 ReplaceVistaIcon 程序合并到构建工作流程中,以便在构建完成后用多图标文件替换该图标(并且在签署 exe 之前)。这似乎正确放置了图标,以便 Windows 优先于任何其他图标资源选择它。必须这样做很麻烦,但是一旦设置(在我们的 FinalBuilder 项目中)它就对我们有用。

当您测试此功能时,令人烦恼的问题是您可能必须删除 Windows 图标缓存才能看到任何更改的效果。这涉及关闭资源管理器以允许您从命令会话中删除缓存文件。

It can be a bit of a nightmare getting this right. I have found that the most successful strategy is to place a very simple icon on the main form and application, and then to incorporate the ReplaceVistaIcon program into the build workflow to replace the icon with your multiple-icon file after the build is complete (and before signing the exe). This seems to place the icon correctly so that Windows picks it up in preference to any other icon resource. It's a nuisance to have to do this, but once set up (in our FinalBuilder project) it works for us.

The annoying problem, while you are testing this, is that you may have to delete the Windows icon cache to see the effect of any changes. This involves shutting down Explorer to allow you to delete the cache file from a command session.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文