На главную

25.10.2002

Автор: Нижегородцев Сергей

Как извлекать иконки из файлов exe или dll.

Исходники здесь

Не так часто появляется необходимость извлекать иконки из каких-либо других программ, чтобы потом использовать их в своих программах. Но вот когда вдруг понадобилась именно эта иконка, что делать? Ну конечно можно через проводник найти файл с иконкой и просто тупо скопировать весь экран в буфер обмена нажатием клавиши “Print Screen”. Затем вставить содержимое буфера обмена в любом графическом редакторе (например Paint.exe, входящий в поставку Windows) и отредактировать экран таким образом, чтобы осталась одна иконка. В таком методе есть недостатки. Это невозможность использовать иконки из dll-файлов (они не отображаются в проводнике) и невозможность извлечения более одной иконки из exe-файла. К тому же зачем упрощать данную задачу, ведь мы же русские, зачем нам искать простые пути? J

Я предлагаю вам простенькую программку, которую можно лишь слегка модифицировать получать ресурсы из любого файла ресурсов. Эта программа будет получать все иконки из указанного вами файла, и сохранять рисунки в bmp-файлы. Причем, все сохраняемые файлы будут иметь порядковые имена.

Итак, что нам нужно:

    1. Запустите Visual Basic и создайте проект “Standart Exe”.
    2. Сохраните этот проект в какую-нибудь папку.
    3. Затем обязательно создайте в папке проекта еще одну папку и назовите ее “Temp”. В эту папку будут складываться все извлеченные иконки, преобразованные в bmp-файлы.
    4. Бросьте на форму проекта компонент Picture и компонент Command (кнопка). У кнопки свойство Caption сделайте “Extract Icons”. Размеры этих компонент пока остаются на ваше усмотрение.

    В результате должна получиться подобная форма

    extract_icons_01.jpg (23526 bytes)

Ну все, теперь можно приступить к программированию как таковому.

Нам потребуется две API функции: ExtracIconA и DrawIcon. API–функция (Application Programming Interface) – это функция, входящая в операционную систему Windows. Подобные функции можно использовать практически в любом языке программирования под Windows будь то C++, Visual Basic, Delphi и т.д. Для использования вышеуказанных функций в нашей программе нужно их описать (или импортировать, как хотите называйте), нужно написать следующие строчки в модуле формы Form1:

Private Declare Function ExtractIcon Lib "shell32.dll" Alias _

"ExtractIconA" (ByVal hInst As Long, _

ByVal lpszExeFileName As String, _

ByVal nIconIndex As Long) As Long

Это первая функция, которая импортируется из shell32.dll. Эта функция будет извлекать из файла lpszExeFileName иконку по номеру (индексу) nIconIndex. Параметр hInst – это экземпляр программы, которая вызывает функцию. Функция возвращает дескриптор на иконку. Самое интересное, что мы еще раз будем использовать эту дллэльку.

Private Declare Function DrawIcon Lib "user32" (ByVal hdc As Long, _

ByVal x As Long, ByVal y As Long, ByVal hIcon As Long) As Long

Эта функция рисует иконку на элементе hdc. x и y это координаты верхнего левого угла с которого будет рисоваться иконка. Параметр hIcon – дескриптор иконки, который мы будем получать функцией ExtractIcon.

В нашей форме Form1 надо написать обработчик события нажатия на кнопку с именем Command1. Для этого щелкните дважды на кнопке формы, и вы попадете в окно редактирования кода.

Вставьте код:

Dim hIcon As Long, i As Long

Dim FilePath As String

 

i = 0

hIcon = -1

FilePath = "C:\Windows\System32\Shell32.dll"

Picture1.BorderStyle = 0

Picture1.BackColor = vbWhite

Picture1.Height = Screen.TwipsPerPixelY * 32

Picture1.Width = Screen.TwipsPerPixelY * 32

While hIcon <> 0

hIcon = ExtractIcon(App.hInstance, FilePath, i)

Set Picture1.Picture = LoadPicture("") ' Clear the picture box

Picture1.AutoRedraw = True

'?enoai eeiieo

Call DrawIcon(Picture1.hdc, 0, 0, hIcon)

Picture1.AutoRedraw = False

Picture1.Refresh

SavePicture Picture1.Image, App.Path & "\Temp\" & i & ".bmp"

i = i + 1

Wend

Разберем его по порядку. Переменная hIcon это дескриптор иконки, которую мы будем извлекать. Переменная i – счетчик. Мы будем в цикле стараться извлечь все иконки начиная от 0 и до тех пор пока не hIcon не будет равна 0. Это будет означать, что функция ExtractIcon не может извлечь иконку с индексом i. Переменная FilePath = "C:\Windows\System32\Shell32.dll". Этот файл содержит огромное количество иконок, которые использует Windows, например в проводнике. Именно из этого файла мы будем извлекать иконки.

Дальше мы делаем Picture1.BorderStyle = 0, что значит, что ободок нашего элемента не будет виден и, следовательно, не будет занимать место на форме. Именно поэтому мы сможем приравнять размеры большой стандартной иконки и компонент Picture1:

Picture1.Height = Screen.TwipsPerPixelY * 32

Picture1.Width = Screen.TwipsPerPixelY * 32

Как вы может быть знаете, что стандартная величина измерения форм и компонент на экране у VB – это Twip (не понимаю, зачем ее придумали). А стандартная величина в Windows – это Pixel. Поэтому мы и конвертируем размер иконки в пикселах в размер иконки в твипах. Можно еще поменять фон компонента для того, чтобы белый фон компонента, был белым фоном для bmp-рисунка

Picture1.BackColor = vbWhite

Затем мы в цикле проверяем hIcon на соответствие 0, на каждом шаге увеличивая индекс иконки на 1 (i = i + 1). Так как мы заранее не знаем сколько иконок в файле-ресурсе, то как только функция ExtractIcon вернет 0, будем предполагать, что больше нет иконок с другими индексами. Перед тем, как используем функцию DrawIcon для рисования на Picture1, надо сделать

Picture1.AutoRedraw = True

чтобы включить автоматическое прорисовывание компоненте, как только изменится содержимое его памяти. После того как иконка нарисовалась выключим автопрорисовывание и обновим компонент

Picture1.AutoRedraw = False

Picture1.Refresh

И наконец, запишем в файл все содержимое компонента Picture1 во временный каталог нашего проекта.

SavePicture Picture1.Image, App.Path & "\Temp\" & i & ".bmp"

После того как программа отработает, проверьте этот каталог.

Желаю удачи!

Hosted by uCoz