设置应用程序图标的问题

发布于 2024-07-17 04:33:27 字数 1995 浏览 9 评论 0原文

(我使用的是 Visual Studio 2008,尽管我记得旧版本也有类似的问题。)

我尝试了几种不同的方法(其中许多方法在 这个其他问题),但我仍然遇到一些奇怪的问题:

  1. 当包含图标作为资源时,它确实立即显示为可执行文件的图标,但为了使图标显示在任务栏上,我必须重新启动计算机。 在此之前,它会继续显示为之前的图标。 清理溶液,重启VS,没有任何效果。 这不是一个真正的大问题,因为它不会影响已发布的 exe,但如果知道它在哪里缓存旧图标以及如何删除它,那就太好了。

  2. 无论我做什么,按 alt-tab 键时显示的图标都是默认应用程序图标(方形、白色和通用)。 这包括将图标嵌入到可执行文件中,以及使用 WM_SETICON 设置 ICON_BIG

至于第二件事,我的代码看起来像这样:

   hIcon = (HICON)(
      LoadImage( NULL, szFilename, IMAGE_ICON, 32, 32, LR_LOADFROMFILE ) );
   if( hIcon )
      SendMessage( hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );

但是,在发送 WM_SETICON 后,GetLastError() 返回 6,“句柄无效。”。 hWnd 是一个有效的窗口句柄,hIcon 似乎是一个有效的图标句柄。 我尝试寻找 WM_SETICON 可能导致该错误的原因,并且至少找出它认为无效的句柄,但还没有运气。 我在调用 SendMessage() 之前立即清除了错误代码,因此必须在消息处理过程中的某个位置设置它。

我尝试了另一种方法,从 exe 本身加载图标,其中资源的 ID 为 101 (它是第一个也是唯一包含的资源):

   hIcon = (HICON)(
      LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( 101 ),
      IMAGE_ICON, 48, 48, 0 ) );
   if( hIcon )
      SendMessage( hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );

...但同样的事情发生了; 调用 SendMessage() 后,GetLastError() 给出相同的错误状态。

我尝试过不同的尺寸(例如 48x48,所有这些都存在于图标文件中),但没有不同的效果。 我知道它肯定会查找并加载图像,因为如果我指定不存在的大小或无效的资源 ID 或错误的文件名(取决于我如何加载它),它会在 SendMessage( )

奇怪的是,如果我指定 ICON_SMALL 而不是 ICON_BIG,调用会成功且没有错误状态,但来自 文档,我需要使用 ICON_BIG 设置 alt-tab 键切换时使用的图标。 另外,如果我使用 ICON_BIG 但加载 16x16 图标,我不会收到错误状态,但没有任何变化。

关于可能导致 WM_SETICON 失败的任何想法? 我发布的任何代码有什么严重错误吗(除了格式/样式/转换问题,因为它已简化为基础知识)?

(I'm using Visual Studio 2008, though I remember having similar problems with older versions as well.)

I've tried several different methods (many of them mentioned in this other question), but I am still having some strange issues:

  1. When including an icon as a resource, it does show up as the executable file's icon immediately, but for the icon to show up on the taskbar, I have to restart the computer. Until then, it continues to show up as whatever the previous icon was. Cleaning the solution, restarting VS, doesn't have any effect. Not a really big issue, as it won't affect a released exe, but it would be nice to know where it's keeping the old icon cached and how to get rid of it.

  2. No matter what I do, the icon displayed when alt-tabbing is the default app icon (square and white and generic). This includes embedding the icon in the executable, as well as setting ICON_BIG with WM_SETICON.

As for the second matter, my code looks something like:

   hIcon = (HICON)(
      LoadImage( NULL, szFilename, IMAGE_ICON, 32, 32, LR_LOADFROMFILE ) );
   if( hIcon )
      SendMessage( hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );

However, after sending WM_SETICON, GetLastError() returns 6, "The handle is invalid.". hWnd is a valid window handle, and hIcon appears to be a valid icon handle. I've tried searching for reasons why WM_SETICON could cause that error, and at the very least, to figure out WHICH handle it thinks is invalid, but no luck yet. I've cleared the error code immediately before calling SendMessage(), so it has to be set somewhere in the processing of the message.

I tried an alternate method, loading the icon from the exe itself, where the ID of the resource is 101 (it's the first and only resource included):

   hIcon = (HICON)(
      LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( 101 ),
      IMAGE_ICON, 48, 48, 0 ) );
   if( hIcon )
      SendMessage( hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );

... but the same thing happens; after calling SendMessage(), GetLastError() gives the same error status.

I've tried different dimensions (such as 48x48, all of which are present in the icon file), but to no different effect. I know it's definitely finding and loading the images, because if I specify a size that doesn't exist or an invalid resource ID or the wrong filename (depending on how I am loading it), it fails out long before SendMessage().

Strangely, if I specify ICON_SMALL instead of ICON_BIG, the call succeeds with no error status, but from the docs, I need to use ICON_BIG to set the icon used while alt-tabbing. Also, if I use ICON_BIG but load the 16x16 icon, I get no error status, but nothing changes.

Any ideas about what could be causing WM_SETICON to fail? Anything terribly wrong with any of the code I've posted (aside from formatting/style/casting issues, as it's simplified to just the basics)?

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

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

发布评论

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

评论(5

清引 2024-07-24 04:33:27

我重新审视了这个问题,看看是否可以结束我的问题。 我无法仅通过将应用程序的图标嵌入到可执行文件中来使其显示在 alt-tab 列表中; 它将显示在任务栏中,作为资源管理器中的文件图标,以及其他地方都很好。

我想我应该尝试一些更简单的方法来手动设置图标,并使用 LoadIcon() 代替,如下面的代码所示:

HICON hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1) );
if( hIcon )
{
   SendMessage( GetHandle(), WM_SETICON, ICON_BIG, (LPARAM)hIcon );
   DestroyIcon( hIcon );
}
// ... Same for ICON_SMALL

这似乎已经成功了。 我真的不知道为什么,但到目前为止,这是唯一有影响的改变。 这确实不是我应该花更多时间的问题,所以我就继续吧。

I've revisited this to see if I can close out my question. I have been unable to get the app's icon to show up in the alt-tab list just through embedding it in the executable; it will show up in the taskbar, as the file's icon in Explorer, and elsewhere just fine.

I figured I'd try something simpler for setting the icon manually, and went with LoadIcon() instead, as the code below shows:

HICON hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1) );
if( hIcon )
{
   SendMessage( GetHandle(), WM_SETICON, ICON_BIG, (LPARAM)hIcon );
   DestroyIcon( hIcon );
}
// ... Same for ICON_SMALL

This seems to have done the trick. I really don't know why, but so far it's the only change that had any effect. It's really not an issue I should spend any more time on, so I'll just go with this.

驱逐舰岛风号 2024-07-24 04:33:27

好的,这对我来说是一种享受:

HICON hIconSmall =(HICON)LoadImage(handleToYourApplicationInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON,16, 16, 0);

HICON hIconLarge =(HICON)LoadImage(handleToYourApplicationInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON,256, 256, 0); // Big for task bar, small loaded otherwise.

SendMessage(yourWindowHandle, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall) ;

SendMessage(yourWindowHandle, WM_SETICON, ICON_BIG, (LPARAM)hIconLarge) ;

OK, this worked a treat for me :

HICON hIconSmall =(HICON)LoadImage(handleToYourApplicationInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON,16, 16, 0);

HICON hIconLarge =(HICON)LoadImage(handleToYourApplicationInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON,256, 256, 0); // Big for task bar, small loaded otherwise.

SendMessage(yourWindowHandle, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall) ;

SendMessage(yourWindowHandle, WM_SETICON, ICON_BIG, (LPARAM)hIconLarge) ;
不及他 2024-07-24 04:33:27

我使用多个分辨率 16x16、32x32、48x48、96x96 的单个 .ico 文件作为应用程序图标,没有任何问题。 然后窗口将选择正确的大小。

Windows shell 有一个 图标缓存,有一个 技巧重新启动它,而无需重新启动或从当前会话注销,或终止来自任务管理器的explorer.exe。

I've used a single .ico file with multiple resolutions 16x16, 32x32, 48x48, 96x96 without problems, as application icon. Then windows will pick up the right size.

The windows shell have an icon cache, there is a trick to restart it without rebooting or logout from the current session, or killing explorer.exe from task manager.

我一向站在原地 2024-07-24 04:33:27

对于遇到同样困难的任何人,如果您要更改 ICON_BIG,则必须首先发送带有 ICON_SMALL 的 WM_SETICON,然后继续更改 ICON_BIG。

例如:

SetLastError(0);
SendMessage(windowHandle, WM_SETICON, ICON_SMALL, (LPARAM)iconsmallHandle);
[do error handling]
SetLastError(0);
SendMessage(windowHandle, WM_SETICON, ICON_BIG, (LPARAM)iconbigHandle);
[do error handling]

您需要在第一个 SendMessage 之后使用 SetLastError 来清除任何返回的错误。

如果您只是设置 ICON_SMALL,则可以忽略 ICON_BIG。 无论出于何种原因,在我的所有测试中,无论该图标是否需要更改,您都必须在尝试更改 ICON_BIG 之前设置 ICON_SMALL,否则您将始终收到错误代码 0x6(无效句柄)。

For anyone coming to this same difficulty if you are going to change ICON_BIG you must first send WM_SETICON with ICON_SMALL and then proceed to ICON_BIG.

For example:

SetLastError(0);
SendMessage(windowHandle, WM_SETICON, ICON_SMALL, (LPARAM)iconsmallHandle);
[do error handling]
SetLastError(0);
SendMessage(windowHandle, WM_SETICON, ICON_BIG, (LPARAM)iconbigHandle);
[do error handling]

You will need to use SetLastError after the first SendMessage to clear any returned error.

If you are just setting ICON_SMALL you can ignore ICON_BIG. For whatever reason in all of my tests you must set ICON_SMALL regardless if that icon needs to change or not, before attempting to change ICON_BIG, otherwise you will always get error code 0x6 (invalid handle).

风铃鹿 2024-07-24 04:33:27

如果找到适合我的解决方案。 我创建了一个不可见的 CFrameWnd 应用程序窗口,然后创建了一些其他主窗口(它们是对话框窗口)。 神奇的未记录规则是:您必须更改第一个创建的 CFrameWnd 中的大图标。 虽然每个窗口都保留它自己的 ICON_BIG 实例,但它不使用它们。 因此,似乎不可能在一个应用程序内的不同窗口显示不同的任务栏图标。

If found the solution for me. I created an invisible CFrameWnd application window and then a few other main windows (which are dialog windows). The magic undocumented rule is: You have to change the big icon in the first created CFrameWnd. While each window keeps it's own ICON_BIG instance, it does not use them. So it seems not possible to show different taskbar icons for different windows inside one application.

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