Здравствуйте, __serj, Вы писали:
__>Здравствуйте!
__>Кто-нибудь знаком со стандартным механизмом загрузки иконок из ЕХЕ, которым пользуется windows? Я использовал много вариантов, все они работают, но одного варианта, который бы работал всегда и везде я так и не нашел. У windows похоже вообще нет никаких средств для того чтобы достать из файла самую крупную иконку. Приходится либо просматривать все ресурсы (RT_GROUP_ICON) либо вообще брутфорсом запрашивать все размеры иконок через PrivateExtractIcons... Если кто-то сталкивался с этой проблемой, подскажите пожалуйста как она решается правильно.
Вот старая дока от MS:
Icons in Win32, больше ничего в свое время я не нашел.
Не знаю, может с тех пор что-то изменилось.
Which Icon?
If an .EXE or .DLL file has only one RT_GROUP_ICON resource, the first step is trivial; Windows simply uses that resource. However, if more than one such group resource exists in the file, Windows must decide which one to use. Windows NT simply chooses the first resource listed in the application's RC script. On the other hand, Windows 95's algorithm is to choose the alphabetically first named group icon if one exists. If one such group resource does not exist, Windows chooses the icon with the numerically lowest identifier. So, to be sure that a particular icon is used for an application, the developer should insure that both of the following criteria are met:
1. The icon is placed before all other icons in the RC file.
2. If the icon is named, its name is alphabetically before any other named icon, otherwise its resource identifier is numerically smaller than any other icon.
Which Image?
Once an RT_GROUP_ICON is chosen, the individual icon image, or RT_ICON resource, must be selected and extracted. Again, if there exists only one RT_ICON resource for the group in question, the choice is trivial. However, if multiple images are present in the group, the following selection rules are applied:
1. The image closest in size to the requested size is chosen.
2. If two or more images of that size are present, the one that matches the color depth of the display is chosen.
3. If none exactly match the color depth of the display, Windows chooses the image with the greatest color depth without exceeding the color depth of the display.
4. If all the size-matched images exceed the color depth of the display, the one with the lowest color depth is chosen.
5. Windows treats all color depths of 8 or more bpp as equal. For example, it is pointless to have a 16x16 256 color image and a 16x16 16bpp image in the same resource—Windows will simply choose the first one it encounters.
6. When the display is in 8bpp mode, Windows will prefer a 16 color icon over a 256 color icon, and will display all icons using the system default palette.
Здравствуйте, Baskak, Вы писали:
B>Вот старая дока от MS: Icons in Win32, больше ничего в свое время я не нашел.
B>Не знаю, может с тех пор что-то изменилось.
Спасибо, я натыкался как раз на этот документ.
Но вот сейчас понял в чем было дело.
Ошибка была в имени которое я использовал для поиска ресурса.
Сейчас у меня работает вот так:
class Resource
{
static HRSRC hRes;
static BOOL CALLBACK EnumNames(HMODULE hModule, wchar_t const * lpszType, wchar_t * lpszName, LONG_PTR lParam )
{
hRes = IS_INTRESOURCE(lpszName) ? FindResourceW(hModule, MAKEINTRESOURCEW(lpszName), MAKEINTRESOURCEW(RT_GROUP_ICON)):
FindResourceW(hModule, lpszName, MAKEINTRESOURCEW(RT_GROUP_ICON));
return FALSE;
}
public:
static HRSRC GetFirstIconGroup(HMODULE hModule)
{
hRes = NULL;
EnumResourceNamesW(hModule, RT_GROUP_ICON, EnumNames, NULL);
return hRes;
}
};
и
HRSRC hRsrc = Resource::GetFirstIconGroup(hModule);
И похоже что задача решена
Здравствуйте, Carc, Вы писали:
C>Здравствуйте, __serj, Вы писали:
__>>Здравствуйте!
__>>Кто-нибудь знаком со стандартным механизмом загрузки иконок из ЕХЕ, которым пользуется windows? Я использовал много вариантов, все они работают, но одного варианта, который бы работал всегда и везде я так и не нашел. У windows похоже вообще нет никаких средств для того чтобы достать из файла самую крупную иконку. Приходится либо просматривать все ресурсы (RT_GROUP_ICON) либо вообще брутфорсом запрашивать все размеры иконок через PrivateExtractIcons... Если кто-то сталкивался с этой проблемой, подскажите пожалуйста как она решается правильно.
C>Зачем так печально? Есть ExtractIconEx — там можно получить маленькую и большую иконку. Но будет ли она самой большой из имеющихся, не уверен... По-моему это настроек Shell будет зависеть.
Да, конечно ExtractIconEx не даст иконку, скажем, 256х256х16bpp. Зачастую результат всех функций автоматизирующих получение иконок из модулей выглядит жутко.
Т.к. готового решения судя по всему в инете нету (за долгое время не нашел ничего), вот код который работает у меня сейчас. Он не идеален, но общий алгоритм из него можно понять.
class Resource
{
static HRSRC hRes;
static BOOL CALLBACK EnumNames(HMODULE hModule, wchar_t const * lpszType, wchar_t * lpszName, LONG_PTR lParam )
{
hRes = IS_INTRESOURCE(lpszName) ? FindResourceW(hModule, MAKEINTRESOURCEW(lpszName), MAKEINTRESOURCEW(RT_GROUP_ICON)):
FindResourceW(hModule, lpszName, MAKEINTRESOURCEW(RT_GROUP_ICON));
return FALSE;
}
public:
static HRSRC GetFirstIconGroup(HMODULE hModule)
{
hRes = NULL;
EnumResourceNamesW(hModule, RT_GROUP_ICON, EnumNames, NULL);
return hRes;
}
};
HRSRC Resource::hRes = NULL;
HICON GetOptimizeIcon(char const* exename, UINT& xSize) //exename - путь к файлу, в xSize - возвращается размер стороны иконки
{
UINT mode = SetErrorMode(SEM_FAILCRITICALERRORS);
HICON hicon = NULL;
UINT index = 0;
HMODULE hModule = LoadLibraryExA(exename, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (hModule != NULL)
{
HRSRC hRsrc = Resource::GetFirstIconGroup(hModule);
if (hRsrc != NULL)
{
HGLOBAL hGlobal = LoadResource(hModule, hRsrc);
if (hGlobal != NULL)
{
LPMEMICONDIR lpIconDir = static_cast<LPMEMICONDIR>(LockResource(hGlobal));
if (lpIconDir != NULL)
{
size_t MaxIcon = 0;
for (size_t i = 0; i < lpIconDir->idCount; i++)
{
UINT t = lpIconDir->idEntries[i].bWidth;
LPMEMICONDIRENTRY tmp = &lpIconDir->idEntries[i];
if (lpIconDir->idEntries[i].dwBytesInRes > lpIconDir->idEntries[MaxIcon].dwBytesInRes)
MaxIcon = i;
}
xSize = lpIconDir->idEntries[MaxIcon].bWidth ? lpIconDir->idEntries[MaxIcon].bWidth : 256;
HRSRC hRsrcIcon = FindResource(hModule, MAKEINTRESOURCE(lpIconDir->idEntries[MaxIcon].nID), MAKEINTRESOURCE(RT_ICON));
if (hRsrcIcon != NULL)
{
HGLOBAL hIconMem = LoadResource(hModule, hRsrcIcon);
if (hIconMem)
{
HANDLE lpResource = LockResource(hIconMem);
if (lpResource)
{
hicon = CreateIconFromResourceEx((PBYTE) lpResource, SizeofResource(hModule, hRsrcIcon), true, 0x00030000, xSize, xSize, 0);
UnlockResource(hRsrcIcon);
}
}
}
UnlockResource(lpIconDir);
}
}
}
FreeLibrary(hModule);
}
SetErrorMode(mode);
return hicon;
}