Извлечение иконок из файлов

Все вы наверное знаете, что во многих EXE- и DLL-файлах запрятано много иконок. Примером может являться ну хотябы shell32.dll в папке Windows\System, в котором запиханы иконки, применяющиеся для большинства стандартных расширений и системных значков типа папок, дисков и т. п.

Также, главные EXE-шники всех уважающих себя программ содержат свои иконки, которые будут ассоциированы с нужными им типами файлов.

Сделать подобное в своей программе просто - надо скомпилировать файл ресурсов (как - это уже другая тема) и подключить к своему проекту. В результате, exe-шник вашей программы будет содержать все иконки, которые вы запихали в файл ресурсов, плюс иконки, которые ассоциированы с формами проекта.

Так вот, чтобы произвести обратный процесс, я обычно пользовался программкой Icon Digger 2000 (есть еще масса подобных программ) и меня мало волновало, как она работает. Пока самому не потребовалось получить доступ к иконкам, зашитым в файле. И что же?
Оказалось, что это не легко, а очень легко! С помощью парочки API функций можно сваять собственный Icon Digger!
Сейчас объясню как:

"В дело" пойдут две API функции - ExtractIcon и DrawIcon вот их объявления:

Private Declare Function DrawIcon Lib "user32" (ByVal hdc As Long, _
ByVal X As Long, ByVal Y As Long, ByVal hIcon As Long) As Long

Private Declare Function ExtractIcon Lib "shell32.dll" Alias _
"ExtractIconA" (ByVal hInst As Long, ByVal lpszExeFileName As String, _
ByVal nIconIndex As Long) As Long

Чтобы отобразить иконки, нам потребуется объект PictureBox. Именно Picture, а не Image! Установите его свойство AutoRedraw как False (Ох и долго же я намучался с этим. Наконец, методом научного тыка я вычислил, что если это свойство стоит как True, после выполнения функции DrawIcon необходимо выполнить метод PictureBox.Refresh)
Начнем извлекать:

Dim hIcon As Long, hModule as Long
'В следующей строке мы получим хэндл вытащеной иконки из Shell32
hIcon = ExtractIcon(hModule, "c:\windows\system\shell32.dll", 2)
'Поменяйте путь к файлу на ваш. 2 - означает вторую иконку по порядку
'из набора, содержащегося в файле.
'Теперь, рисуем иконку на PictureBox
Call DrawIcon(Picture1.hdc, 10, 10, hIcon)
'10,10 - означает координаты на PBox'е, где будет нарисована иконка

Вроде бы все. Можете написать даже специальную функцию. Не забудьте про заморочки с AutoRedraw.

Интересная вещь: чтобы узнать количество "зашитых" иконок в файле, выполните следующее

Num = ExtractIcon(hModule, "c:\windows\system\shell32.dll", -1)
'Обратите внимание на параметр nIconIndex

После этого, Num (As Long) будет содержать количество иконок в файле.

И последнее. Наверняка вы захотите получить иконку, ассоциированную с неким файлом, например txt, doc или еще что. Так вот: вам не надо лазить за эти в реестр! Есть еще одна функция, подобная ExtractIcon - ExtractAssociatedIcon. Эта функция делает то же самое, только возвращает не иконку, содержащуюся в файле, а иконку, ассоциированную с файлом.

(А вот тут я нашел багу в Win32 API Loader. На объявление функции ExtractAssociatedIcon бейсик при выполнении матюкается. Поэтому Declare функции не привожу, а советую воспользоваться библиотекой Win.tlb)

Пример:

hIcon = ExtractAssociatedIcon(hModule, "c:\windows\win.ini", 0)
Call DrawIcon(Picture1.hdc, 10, 10, hIcon)

Ну вот вроде и все! Судьба IconDigger'а на VB в ваших руках! :)))

Приятного программирования, Antiloop


>>> Реклама <<<