Проблемы с настройкой иконки приложения - PullRequest
6 голосов
/ 01 апреля 2009

(я использую Visual Studio 2008, хотя я помню, что у меня были похожие проблемы и со старыми версиями.)

Я пробовал несколько разных методов (многие из них упомянуты в этот другой вопрос ), но у меня все еще есть некоторые странные проблемы:

  1. При включении значка в качестве ресурса он сразу отображается как значок исполняемого файла, но для того, чтобы значок появился на панели задач, я должен перезагрузить компьютер. До тех пор он продолжает отображаться как любой предыдущий значок. Очистка раствора, перезапуск VS, не дает никакого эффекта. Не очень большая проблема, поскольку она не повлияет на выпущенный exe-файл, но было бы неплохо узнать, где хранится старый значок в кэше и как от него избавиться.

  2. Независимо от того, что я делаю, значок, отображаемый при alt-tabbing, является значком приложения по умолчанию (квадратный, белый и общий). Это включает в себя встраивание значка в исполняемый файл, а также установку ICON_BIG с WM_SETICON.

Что касается второго вопроса, мой код выглядит примерно так:

   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-файла, где идентификатор ресурса равен 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, все они присутствуют в файле значков), но без разницы. Я знаю, что он определенно находит и загружает изображения, потому что, если я укажу несуществующий размер или неверный идентификатор ресурса или неправильное имя файла (в зависимости от того, как я его загружаю), произойдет сбой задолго до SendMessage().

Странно, если я укажу ICON_SMALL вместо ICON_BIG, вызов завершится успешно без состояния ошибки, но из документов мне нужно будет использовать ICON_BIG, чтобы установить значок, используемый при alt -tabbing. Кроме того, если я использую ICON_BIG, но загружаю значок 16x16, я не получаю статус ошибки, но ничего не меняется.

Есть идеи о том, что может вызвать сбой WM_SETICON? Что-нибудь ужасно не так с любым кодом, который я выложил (кроме вопросов форматирования / стиля / приведения, так как он упрощен только до основ)?

Ответы [ 5 ]

3 голосов
/ 27 апреля 2010

Я снова посетил это, чтобы посмотреть, смогу ли я закрыть свой вопрос. Мне не удалось отобразить значок приложения в списке 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

Кажется, это сработало. Я действительно не знаю почему, но пока это единственное изменение, которое оказало какое-либо влияние. Это действительно не проблема, на которую я должен тратить больше времени, так что я просто пойду с этим.

2 голосов
/ 18 августа 2012

ОК, для меня это сработало:

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) ;
2 голосов
/ 02 апреля 2009

Я использовал один файл .ico с несколькими разрешениями 16x16, 32x32, 48x48, 96x96 без проблем, как значок приложения. Тогда окна подберут нужный размер.

Оболочка Windows имеет кэш значков , есть трюк для его перезапуска без перезагрузки или выхода из текущего сеанса или убийства explorer.exe из диспетчера задач.

0 голосов
/ 28 февраля 2018

Для тех, кто сталкивается с такой же трудностью, если вы собираетесь изменить ICON_BIG, вы должны сначала отправить WM_SETICON с ICON_SMALL, а затем перейти к 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]

Вам потребуется использовать SetLastError после первого SendMessage, чтобы очистить любую возвращенную ошибку.

Если вы просто устанавливаете ICON_SMALL, вы можете игнорировать ICON_BIG. По какой-либо причине во всех моих тестах вы должны установить ICON_SMALL независимо от того, нужно ли менять этот значок, прежде чем пытаться изменить ICON_BIG, в противном случае вы всегда получите код ошибки 0x6 (неверный дескриптор).

0 голосов
/ 06 февраля 2012

Если нашел решение для меня. Я создал невидимое окно приложения CFrameWnd, а затем несколько других основных окон (которые являются диалоговыми окнами). Волшебное недокументированное правило таково: вы должны изменить большую иконку в первом созданном CFrameWnd. Хотя каждое окно хранит свой собственный экземпляр ICON_BIG, оно не использует их. Так что кажется невозможным показывать разные значки панели задач для разных окон в одном приложении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...