Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.03.2017, 15:28   #11
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 272
По умолчанию

Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
последний исходник с embarcardo
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
  Icon: HICON;
begin
  Icon := ExtractSizedIcon('notepad.exe', 256, 0);
  DrawIconEx(Canvas.Handle, 10, 10, Icon, 0, 0, 0, 0, DI_NORMAL);
  DestroyIcon(Icon);
end;
Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
P.S. Здесь есть кнопка "Спасибо" ?
Есть весы

Последний раз редактировалось Filka; 16.03.2017 в 16:06.
Filka вне форума Ответить с цитированием
Старый 16.03.2017, 17:45   #12
Sabouter2017
Пользователь
 
Регистрация: 10.02.2017
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Filka Посмотреть сообщение
Есть весы
Я бы и не догадался про кнопку
Оставил отзыв Только вы и помогаете.

Как бы не было обидно, но код с embarcardo оказался хоть и рабочим, но из части exe-шников иконки экспоритуруются криво. Там, где имя ресурса не MAINICON, а например "201". Код красивый, но не срабатывает. Попробовал у себя применить такую функцию LookupIconIdFromDirectoryEx - не помогло.

Попробовал еще его аналог:
Код:
function LoadIconSize( ResName: PChar; X, Y: Integer ): HICON; 
var 
HG: HGLOBAL; 
ID, HRes, RS: Cardinal; 
PRes: Pointer; 
begin 
Result := 0; 
HRes := FindResource( hInstance, ResName, RT_GROUP_ICON ); 
HG := LoadResource( hInstance, HRes ); 
PRes := LockResource( HG ); 
ID := LookupIconIdFromDirectoryEx( PRes, True, X, Y, 
LR_DEFAULTCOLOR ); 
if ID < 1 then Exit; 

HRes := FindResource( hInstance, MakeIntResource( ID ), RT_ICON ); 
RS := SizeOfResource( hInstance, HRes ); 
HG := LoadResource( hInstance, HRes ); 
PRes := LockResource( HG ); 
Result := CreateIconFromResourceEx( PRes, RS, True, $30000, X, Y, 
LR_DEFAULTCOLOR ); 
end;
То же самое, там где "201" - не ту иконку сохраняет.

Вообщем, пока 2 рабочих: DBIconChanger и kicon.

По поводу велосипеда - нет, что вы. Не хочу изобретать. Но разобраться нужно же как это происходит. И понять в чем именно секрет сохранения именно нужной иконки, а не первой попавшейся. Сейчас уже знаю, что поиск нужного имени ресурса делается с помощью EnumResourceNames. Вся загвоздка сейчас у меня в понимании места между LockResource и получением HIcon (как я понимаю с помощью CreateIconFromResourceEx).

Но все дело в том, что в DBIconChanger и kicon не используется CreateIconFromResourceEx !!! Вместо них там происходят битовые операции в памяти (насколько я понял). Вот их видимо и нужно понять. А CreateIconFromResourceEx убрать.

P.S. Но чувствую, что возьму к себе в программу модуль DBIconChanger и буду просто его использовать, лишь переделав для работы с WideString. Так как устал уже над одной простейшей задачей столько сидеть. Никогда бы не подумал, что извлечь иконку будет так сложно и займет столько много времени для понимания этого кода. А еще странно, что в WinApi нет простой функции по извлечению иконки из файла. Точнее, они есть, но они все работают некорректно (типа ExtractIcon, ExtractAssociatedIcon). Иначе бы не было всех этих модулей для сохранения иконки высокого качества.

Последний раз редактировалось Sabouter2017; 16.03.2017 в 18:09.
Sabouter2017 вне форума Ответить с цитированием
Старый 16.03.2017, 18:19   #13
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 272
По умолчанию

Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
возьму к себе в программу модуль DBIconChanger и буду просто его использовать
Почему бы и нет...
Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
они есть, но они все работают некорректно
Это не функции работают некорректно, а TIcon разработчики не доделали...

Последний раз редактировалось Filka; 16.03.2017 в 18:22.
Filka вне форума Ответить с цитированием
Старый 17.03.2017, 06:38   #14
Sabouter2017
Пользователь
 
Регистрация: 10.02.2017
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Filka Посмотреть сообщение
Почему бы и нет...

Это не функции работают некорректно, а TIcon разработчики не доделали...
Вот это и удивляет. Ведь, иконки используются везде. В Эксплорере, в Винде, в Диалогах. Неужели, везде в коде такой изврат приходится делать?
Sabouter2017 вне форума Ответить с цитированием
Старый 17.03.2017, 13:24   #15
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 272
По умолчанию

Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
Неужели, везде в коде такой изврат приходится делать?
Почему везде? Только там, где необходимо.
Filka вне форума Ответить с цитированием
Старый 23.04.2017, 11:04   #16
Sabouter2017
Пользователь
 
Регистрация: 10.02.2017
Сообщений: 12
По умолчанию

Так как ответ, который мне помог был дан на этом форуме, то сюда и решил написать.

Помогло вот это:
HighQualityIconExtractor -> DBIconChanger.pas
из ссылки выше от Filka

Его и взял себе в проект, но позже оказалось возникает ошибка с извлечением иконки у файла audacity.exe (программы по работе со звуком). А также проблема с открытием этого файла ico другими процедурами. Получается файл не закрыт...
Попытался дебажить, нашел, что переменная цикла i и hFile сбиваются на 16 номере функции ExtractIconFromFileW цикла "for i := 0 to lpMemIcon^.idCount - 1 do". Сбой происходит после выполнения AdjustIconImagePointers.
Пытался делать разное, обнаружил, что если перенести переменную lpIR в глобальные, то проблема устраняется и иконка сохраняется вполне себе нормально. Но возникают другие ошибки...

И в итоге оказалось, что проблема в границе массива

TICONRESOURCE = packed record
nNumImages: UINT;
IconImages: Array[0..15] of TICONIMAGE;
end;

А мы пытаемся обратиться к 16-му элементу, которого нет... следовательно и сбой.

IconImages: Array[0..15] of TICONIMAGE;
idEntries: Array[0..15] of TMEMICONDIRENTRY;
ReservedArray: Array[0..15] of char;

Там где 15 поставил 128. Теперь хватает. Ошибок никаких нет.

Может кому поможет.

P.S. Еще, если кто знает как обратиться к стандартной иконке для конкретного расширения (например: .avi, mpg, mp3 .txt, .jpg) - напишите пожалуйста. У меня есть идея, что нужно в реестре находить программу, которая открывает этот файл и извлекать иконку из программы, которая там записана. Но может есть и более прямой способ?

Вот нашел:
для .pas:
uses ShellAPI, ...;
...
var
test_file: array[1..255] of Char;
FileInfo: TSHFileInfo;
test_icon: TIcon;
...
begin
StrPCopy(@test_file,'*.pas'#0);
SHGetFileInfo(@test_file,0,FileInfo ,SizeOf(FileInfo),SHGFI_ICON or SHGFI_USEFILEATTRIBUTES);
test_icon := TIcon.Create;
test_icon.Handle := FileInfo.hIcon;
test_icon.SaveToFile('Путь к нашей новой иконке.ico');
test_icon.Free;
...
end;

НО! Иконка опять кривая, не красивая. Почему так?

Последний раз редактировалось Sabouter2017; 23.04.2017 в 11:50.
Sabouter2017 вне форума Ответить с цитированием
Старый 23.04.2017, 11:48   #17
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 272
По умолчанию

Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
НО! Иконка опять кривая, не красивая.
Для сохранения hIcon в файл можно же воспользоваться KIcon или
Код:
uses
  ShellAPI,
  IconsToFile; // из #2

procedure TForm1.Button1Click(Sender: TObject);
const
  Flags = SHGFI_ICON or SHGFI_LARGEICON or SHGFI_USEFILEATTRIBUTES;
var
  FileInfo: TSHFileInfo;
begin
  SHGetFileInfo(PChar('*.mp3'), FILE_ATTRIBUTE_NORMAL, FileInfo, SizeOf(FileInfo), Flags);
  autoIconToFile('C:\Test\mp3.ico', FileInfo.hIcon);
  DestroyIcon(FileInfo.hIcon);
end;
Цитата:
Сообщение от Sabouter2017 Посмотреть сообщение
иконка одна и та же для всех видов расширений получается
В смысле?
Filka вне форума Ответить с цитированием
Старый 23.04.2017, 14:10   #18
Sabouter2017
Пользователь
 
Регистрация: 10.02.2017
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Filka Посмотреть сообщение
Для сохранения hIcon в файл ... или
Код:
uses
  ShellAPI,
  IconsToFile; // из #2

procedure TForm1.Button1Click(Sender: TObject);
const
  Flags = SHGFI_ICON or SHGFI_LARGEICON or SHGFI_USEFILEATTRIBUTES;
var
  FileInfo: TSHFileInfo;
begin
  SHGetFileInfo(PChar('*.mp3'), FILE_ATTRIBUTE_NORMAL, FileInfo, SizeOf(FileInfo), Flags);
  autoIconToFile('C:\Test\mp3.ico', FileInfo.hIcon);
  DestroyIcon(FileInfo.hIcon);
end;
Круто! Все работает и иконки красивые. Еще раз спасибо ОГРОМНОЕ!
Вопрос на засыпку (не сильно важно, но если ответите - будет хорошо):
У меня еще есть в программе icn: TIcon, в который я устанавливаю иконку
icn.Handle := FileInfo.hIcon; А потом добавляю в ImageList или заменяю с помощью ImageList1.Delete и ImageList1.InsertIcon(btnNum,icn) несколько раз по необходимости.

Вопрос о DestroyIcon(FileInfo.hIcon) - если не уничтожать иконку, будут ли они накапливаться в памяти? И нужно ли думать об этом. Правильно ли я мыслю, что если мы загружаем иконку еще в ImageList1.AddIcon(icn), у которого icn.Handle := FileInfo.hIcon; а потом делаем icn.free то уничтожать саму FileInfo.hIcon никогда и нигде не надо в данном случае. Ведь ее уничтожением будет заниматься уже ImageList, либо icn.free делает ту же работу!? Немного бред написал, но просто сомнения развеять хочется, чтобы потом не было переполнения буфера какого-нибудь.
Sabouter2017 вне форума Ответить с цитированием
Старый 23.04.2017, 14:41   #19
Filka
Форумчанин
 
Регистрация: 29.10.2015
Сообщений: 272
По умолчанию

Если сделать Icon.Handle := FileInfo.hIcon, а потом Icon.Free, то DestroyIcon(FileInfo.hIcon) можно не делать. А при использовании ImageList нужно.
Filka вне форума Ответить с цитированием
Старый 23.04.2017, 15:18   #20
Sabouter2017
Пользователь
 
Регистрация: 10.02.2017
Сообщений: 12
По умолчанию

Цитата:
Сообщение от Filka Посмотреть сообщение
Если сделать Icon.Handle := FileInfo.hIcon, а потом Icon.Free, то DestroyIcon(FileInfo.hIcon) можно не делать. А при использовании ImageList нужно.
А ImageList сам разве не умеет это делать? Правильно ли я понял, если просто загрузить в imagelist иконку FileInfo.hIcon, то DestroyIcon нужно будет делать? А данные иконки не удалятся? Или это нужно делать при выходе из программы?
Sabouter2017 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Большие иконки иконки exe файла Сидоров Паскаль, Turbo Pascal, PascalABC.NET 12 02.10.2014 17:41
Извлечение иконки из *.exe и вставка в TImage - убрать фон spirit-ua Общие вопросы Delphi 2 20.09.2013 10:25
Извлечение иконки файла и ее подгрузка в Image artemavd Общие вопросы Delphi 1 13.10.2012 22:28
Код не всегда выдает правильный результат Maxx Microsoft Office Excel 2 18.02.2010 15:59
Извлечение иконки из dll JSM Общие вопросы Delphi 2 29.06.2007 21:32