Re[5]: Загрузка иконок высокого разрешения - как ?
От: programmater  
Дата: 13.12.06 16:15
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, IvanM, Вы писали:


IM>>Здравствуйте, Аноним, Вы писали:


А>>>Да, конечно. Все они позволяют загрузить не более 32х32.

А>>>Как ни странно, но проверенный факт.
А>>>Даже 48х48 — после этого радость =)

IM>>Ты, конечно, не поверишь. У меня LoadImage загружает любые разрешения вплоть до 128х128. Дальше просто не проверял. Примерно вот так делаю.

IM>>
IM>>HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 128, 128, LR_DEFAULTCOLOR);
IM>>

IM>>Win2k SP4

А>Так проблема в том, что сделать это нужно не в моём модуле, а в файле лежащем на диске. Т.е. не загруженном в память.

А>При этом CreateProcess делать не хочется, — т.к. задача программы просто собрать картинки и пользователи могут не
А>понять, если мы будем их запускать...
А заменить AfxGetInstanceHandle() на hLoadedFromDiskModule слабО?
Загрузка иконок высокого разрешения - как ?
От: tacit_one Россия  
Дата: 13.12.06 14:34
Оценка:
Всем привет,

Пытаюсь загрузить иконку из PE файла.
Задача — вытащить иконку самого высокого разрешения из содержащихся в файле.

На данный момент максимум того, что получилось сделать — достать иконку 48х48 при
работе в WindowsXP.

Делается на данный момент это через SHGetImageList
и получаемый посредством ней интерфейс IImageList.

Проблема в том, что даже SHIL_EXTRALARGE иконка в XP — это 48х48.

Подскажите,
как достать разрешения 96х96/128х128/256х256 и т.п. ?

Варианты со всякими LoadIcon(Ex) естесственно проверены и не работают.

Спасибо!
Макс.


// Код на данный момент (принципиально)
SHGetImageList( SHIL_EXTRALARGE, IID_IImageList, (IImageList**) &SysImageList );
// ...
SHGetFileInfo()
// ...
SysImageList->GetIcon()
// ...
Re: Загрузка иконок высокого разрешения - как ?
От: IvanM Россия  
Дата: 13.12.06 14:37
Оценка:
Здравствуйте, tacit_one, Вы писали:

_>Подскажите,

_>как достать разрешения 96х96/128х128/256х256 и т.п. ?

_>Варианты со всякими LoadIcon(Ex) естесственно проверены и не работают.


А варианты с LoadImage проверены?
Re[2]: Загрузка иконок высокого разрешения - как ?
От: Аноним  
Дата: 13.12.06 14:43
Оценка:
Здравствуйте, IvanM, Вы писали:

IM>Здравствуйте, tacit_one, Вы писали:


_>>Подскажите,

_>>как достать разрешения 96х96/128х128/256х256 и т.п. ?

_>>Варианты со всякими LoadIcon(Ex) естесственно проверены и не работают.


IM>А варианты с LoadImage проверены?


Да, конечно. Все они позволяют загрузить не более 32х32.
Как ни странно, но проверенный факт.
Даже 48х48 — после этого радость =)
Re[3]: Загрузка иконок высокого разрешения - как ?
От: IvanM Россия  
Дата: 13.12.06 15:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Да, конечно. Все они позволяют загрузить не более 32х32.

А>Как ни странно, но проверенный факт.
А>Даже 48х48 — после этого радость =)

Ты, конечно, не поверишь. У меня LoadImage загружает любые разрешения вплоть до 128х128. Дальше просто не проверял. Примерно вот так делаю.
HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 128, 128, LR_DEFAULTCOLOR);

Win2k SP4
Re[4]: Загрузка иконок высокого разрешения - как ?
От: Аноним  
Дата: 13.12.06 16:06
Оценка:
Здравствуйте, IvanM, Вы писали:

IM>Здравствуйте, Аноним, Вы писали:


А>>Да, конечно. Все они позволяют загрузить не более 32х32.

А>>Как ни странно, но проверенный факт.
А>>Даже 48х48 — после этого радость =)

IM>Ты, конечно, не поверишь. У меня LoadImage загружает любые разрешения вплоть до 128х128. Дальше просто не проверял. Примерно вот так делаю.

IM>
IM>HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 128, 128, LR_DEFAULTCOLOR);
IM>

IM>Win2k SP4

Так проблема в том, что сделать это нужно не в моём модуле, а в файле лежащем на диске. Т.е. не загруженном в память.
При этом CreateProcess делать не хочется, — т.к. задача программы просто собрать картинки и пользователи могут не
понять, если мы будем их запускать...
Re[5]: Загрузка иконок высокого разрешения - как ?
От: IvanM Россия  
Дата: 13.12.06 16:25
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Так проблема в том, что сделать это нужно не в моём модуле, а в файле лежащем на диске. Т.е. не загруженном в память.

А>При этом CreateProcess делать не хочется, — т.к. задача программы просто собрать картинки и пользователи могут не
А>понять, если мы будем их запускать...

Примерно так делается.
HMODULE hResModule = LoadLibraryEx("PathToBinaryModuleWithIcon", NULL, LOAD_LIBRARY_AS_DATAFILE);
Re[6]: Загрузка иконок высокого разрешения - как ?
От: Аноним  
Дата: 13.12.06 16:28
Оценка:
Здравствуйте, programmater, Вы писали:

P>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, IvanM, Вы писали:


IM>>>Здравствуйте, Аноним, Вы писали:


А>>>>Да, конечно. Все они позволяют загрузить не более 32х32.

А>>>>Как ни странно, но проверенный факт.
А>>>>Даже 48х48 — после этого радость =)

IM>>>Ты, конечно, не поверишь. У меня LoadImage загружает любые разрешения вплоть до 128х128. Дальше просто не проверял. Примерно вот так делаю.

IM>>>
IM>>>HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 128, 128, LR_DEFAULTCOLOR);
IM>>>

IM>>>Win2k SP4

А>>Так проблема в том, что сделать это нужно не в моём модуле, а в файле лежащем на диске. Т.е. не загруженном в память.

А>>При этом CreateProcess делать не хочется, — т.к. задача программы просто собрать картинки и пользователи могут не
А>>понять, если мы будем их запускать...
P>А заменить AfxGetInstanceHandle() на hLoadedFromDiskModule слабО?

ну почему слабО ?
HINSTANCE по идее представляет собой загруженный модуль ?
Но если я его загружу (и это будет, скажем, DLL) — то не спровацирую ли я славшейшим образом вызов DLLEntry() ?
Этого хочется избежать, если честно.
Re[6]: Загрузка иконок высокого разрешения - как ?
От: programmater  
Дата: 13.12.06 16:34
Оценка:
Здравствуйте, IvanM, Вы писали:

IM>Здравствуйте, Аноним, Вы писали:


А>>Так проблема в том, что сделать это нужно не в моём модуле, а в файле лежащем на диске. Т.е. не загруженном в память.

А>>При этом CreateProcess делать не хочется, — т.к. задача программы просто собрать картинки и пользователи могут не
А>>понять, если мы будем их запускать...

IM>Примерно так делается.

IM>
IM>HMODULE hResModule = LoadLibraryEx("PathToBinaryModuleWithIcon", NULL, LOAD_LIBRARY_AS_DATAFILE);
IM>


Хрена с два! При загрузке ДЛЛ-ки с флагом LOAD_LIBRARY_AS_DATAFILE "specialized resource management functions" не работают! Правда это касается только Win95/98. На 2000 и выше вроде бы можно:

LOAD_LIBRARY_AS_DATAFILE: If this value is used, the system maps the file into the calling process's virtual address space as if it were a data file. Nothing is done to execute or prepare to execute the mapped file. Use this flag when you want to load a DLL only to extract messages or resources from it.
Windows NT/2000: You can use the resulting module handle with any Win32 functions that operate on resources.

Windows 95/98: You can use the resulting module handle only with resource management functions such as EnumResourceLanguages, EnumResourceNames, EnumResourceTypes, FindResource, FindResourceEx, LoadResource, and SizeofResource.

You cannot use this handle with specialized resource management functions such as LoadBitmap, LoadCursor, LoadIcon, LoadImage, and LoadMenu.

Тем не менее я бы в данном случае не стал бы связываться с LOAD_LIBRARY_AS_DATAFILE и загрузил бы ДЛЛ-ку нормально. Ну если это exe, тогда попробуй LOAD_LIBRARY_AS_DATAFILE, может прокатит. В крайнем случае (ну в очень крайнем) соберешь иконку самостоятельно из изображения и маски.
Re[7]: Загрузка иконок высокого разрешения - как ?
От: Аноним  
Дата: 13.12.06 16:40
Оценка:
Здравствуйте, programmater, Вы писали:

P>Здравствуйте, IvanM, Вы писали:


IM>>Здравствуйте, Аноним, Вы писали:


А>>>Так проблема в том, что сделать это нужно не в моём модуле, а в файле лежащем на диске. Т.е. не загруженном в память.

А>>>При этом CreateProcess делать не хочется, — т.к. задача программы просто собрать картинки и пользователи могут не
А>>>понять, если мы будем их запускать...

IM>>Примерно так делается.

IM>>
IM>>HMODULE hResModule = LoadLibraryEx("PathToBinaryModuleWithIcon", NULL, LOAD_LIBRARY_AS_DATAFILE);
IM>>


P>Хрена с два! При загрузке ДЛЛ-ки с флагом LOAD_LIBRARY_AS_DATAFILE "specialized resource management functions" не работают! Правда это касается только Win95/98. На 2000 и выше вроде бы можно:


P>

P>LOAD_LIBRARY_AS_DATAFILE: If this value is used, the system maps the file into the calling process's virtual address space as if it were a data file. Nothing is done to execute or prepare to execute the mapped file. Use this flag when you want to load a DLL only to extract messages or resources from it.
P>Windows NT/2000: You can use the resulting module handle with any Win32 functions that operate on resources.

P>Windows 95/98: You can use the resulting module handle only with resource management functions such as EnumResourceLanguages, EnumResourceNames, EnumResourceTypes, FindResource, FindResourceEx, LoadResource, and SizeofResource.

P>You cannot use this handle with specialized resource management functions such as LoadBitmap, LoadCursor, LoadIcon, LoadImage, and LoadMenu.

P>Тем не менее я бы в данном случае не стал бы связываться с LOAD_LIBRARY_AS_DATAFILE и загрузил бы ДЛЛ-ку нормально. Ну если это exe, тогда попробуй LOAD_LIBRARY_AS_DATAFILE, может прокатит. В крайнем случае (ну в очень крайнем) соберешь иконку самостоятельно из изображения и маски.

Спасибо огромное за помошь!
Простая загрузка DLL без LOAD_LIBRARY_AS_DATAFILE не подходит в нашем случае однозначно...
Мне временами уже кажется, что гораздо проще вручную вытащить иконку из ресурсов PE
Немножко поисследую этот вопрос — я обязательно напишу о работающем варианте.
Re[7]: Загрузка иконок высокого разрешения - как ?
От: IvanM Россия  
Дата: 13.12.06 17:02
Оценка:
Здравствуйте, programmater, Вы писали:

Windows NT/2000: You can use the resulting module handle with any Win32 functions that operate on resources.

Windows 95/98: You can use the resulting module handle only with resource management functions such as EnumResourceLanguages, EnumResourceNames, EnumResourceTypes, FindResource, FindResourceEx, LoadResource, and SizeofResource.

You cannot use this handle with specialized resource management functions such as LoadBitmap, LoadCursor, LoadIcon, LoadImage, and LoadMenu.


P>Тем не менее я бы в данном случае не стал бы связываться с LOAD_LIBRARY_AS_DATAFILE и загрузил бы ДЛЛ-ку нормально.


Я думаю, надежнее грузить именно как LOAD_LIBRARY_AS_DATAFILE. А если так нужна поддержка Win95/98, то загружать иконку через FindResource, LoadResource, CreateIconFromResource.
Re[7]: Загрузка иконок высокого разрешения - как ?
От: programmater  
Дата: 13.12.06 17:16
Оценка:
Здравствуйте, Аноним, Вы писали:


А>ну почему слабО ?

А>HINSTANCE по идее представляет собой загруженный модуль ?
А>Но если я его загружу (и это будет, скажем, DLL) — то не спровацирую ли я славшейшим образом вызов DLLEntry() ?
А>Этого хочется избежать, если честно.
Спровоцируешь. Если нужно избежать вызова DLLMain и загрузки всязанных DLL-ей, то единственный вариант — загрузка с флагом LOAD_LIBRARY_AS_DATAFILE. Далее в зависимости от требований твоей программы к системе. Если ориентируешься на Win2k и выше, то все ок, юзай LoadImage. Если же планируется использовать прогу на более ранних версиях, то тут начинается самое интересное. Придется собирать иконку самостоятельно. Здесь тебе помогут функции FindResource/LoadResource. Процесс в двух словах такой: сначала находишь RT_GROUP_ICON. Получаешь индекс интересующей тебя иконки (integer resource identifier) используя LookupIconIdFromDirectoryEx. Далее загружаешь этот ресусрс
FindResource(hLoadedAsDataFileModule , RT_ICON , ResourceIndex);

Далее зовешь CreateIconFromResource(Ex) для создания иконки из этого ресурса.
Точного кода приводить не буду, т.к. лень проверять. Такой вариант годится в том случае, если ты знаешь точный размер нужной тебе иконки (иначе функция LookupIconIdFromDirectoryEx вернет тебе нулл). В качестве альтернативы можешь вручную распарсивать RT_GROUP_ICON. Это не так уж сложно. Под рукой документации нет, а то привел бы примерчик, как это делать. Плюс в том, что ты сам выбираешь наиболее "понравившуюся" иконку (например, самую большую).Но в любом случае это проще, чем выковыривать из заголовка PE-файла. Хотя для тренировки можно и этим заняться — тоже ничего сверхъестественного . В любом случае удачи.
Re[8]: Загрузка иконок высокого разрешения - как ?
От: Аноним  
Дата: 14.12.06 07:20
Оценка:
Здравствуйте, programmater, Вы писали:

В общем и целом, после исследования получилось что (почти) идеальный способ для
загрузки иконок из произвольного файла является

PrivateExtractIcons() MSDN

Попробовал — почти отлично работает. В ней можно задать желаемый размер иконки.
Однако с ней есть проблемы:
1. Она сама по собственному желанию внутри себя может растянуть иконку, сделав её ужасными квадратиками, если указать несуществующее разрешение.
Т.е. говоришь ей "дай картинку 128х128 — она может дать её увеличив из 32х23" ... А существующее разрешения иконки через API узнать я не нашёл как.
2. It is recommended that you do not use it in new programs because it might be altered or unavailable in subsequent versions of Windows
Без комментариев...

Сильный в очередной раз.

Итого, я пришёл к выводу, что самое разумное — это руками загрузить иконку из PE. Благо это не сложно на самом деле...
Единственное жалко, что адекватного API для работы с иконками нет.

В процессе поиска я наткнулся на статью. Парень бился с теми же проблемами и пришел к тому же решению:
CodeProject
Спасибо дяде ejor'у за наше счастливое детство!

В общем, имхо, в области упревления иконками Win32 API не самая удобная и правильная система ...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.