32×32アイコンの抽出方法

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/01/29(Tue) 23:35:16 No.2356

こんばんは。お世話になります。アークです。

画像描画機能の「アイコン画像」の取得機能は簡単に使えて便利ですが、
抽出されるのは16×16ピクセルのアイコンに限られるようです。
32×32のアイコンを抽出する方法も用意されているのでしょうか。
何方かご存知の方、よろしくお願いします。

Re: 32×32アイコンの抽出方法

投稿者:通り道 投稿日:2019/01/30(Wed) 09:33:09 No.2359

実際の動作は未確認で申し訳ないのですが、デザイナからアイコン画像の抽出の命令の雛形を見てみると、「[サイズ]で」 と言う引数も指定できるようです。
ここに、明示的に32や16を指定することで取得できないでしょうか?

Re^2: 32×32アイコンの抽出方法

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/01/31(Thu) 00:01:45 No.2360

通り道さん、こんばんは。アークです。

コメントありがとうございます。

ご教示頂いた方法で32×32アイコンの抽出ができました。
ありがとうございました。

通り道さんは何をご覧になっているのでしょうか。
私はリファレンスが検索できて便利なので使っているのですが、
アイコン画像の抽出命令の雛形に「[サイズ]で」という記述は発見できませんでした。

ところで、32×32アイコンは抽出できましたが色数が希望していた物では無いです。
ファイルのプロパティウィンドウに表示されるような綺麗なアイコンを抽出したかったのですが…。
一口にアイコンと言っても実際には色々と有るようで、
目的のアイコンを抽出するのは結構大変なのですね。

Re^3: 32×32アイコンの抽出方法

投稿者:通り道 投稿日:2019/01/31(Thu) 01:33:06 No.2362

こんにちは。

> 私はリファレンスが検索できて便利なので使っているのですが、
> アイコン画像の抽出命令の雛形に「[サイズ]で」という記述は発見できませんでした。

デザイナ(標準のエディタ)の右にある、「見出し」「機能」「リファレンス」というタブが並ぶ中の、「機能」のタブです。
今回の場合ですと、このタブで「画像処理部品(Produire.PGraphics.dll)」のノードを開いて、「アイコン画像」を選択すると、その下の手順と設定項目のところに、この種類に含まれる、変数や手順が一覧表示されます。ここのシグネチャには、実際の実装にもとづいて、表示されるようです。
ただし、注意書きにある通り、マニュアルに明記のない部分は、変更の可能性があるため、利用の際には注意が必要です。

> ところで、32×32アイコンは抽出できましたが色数が希望していた物では無いです。
> ファイルのプロパティウィンドウに表示されるような綺麗なアイコンを抽出したかったのですが…。
> 一口にアイコンと言っても実際には色々と有るようで、
> 目的のアイコンを抽出するのは結構大変なのですね。

アイコンには、おおよそ、「SMALL」(16)「LARGE」(32)「EXTRALARGE」(48)「JUMBO」(256)の4種類があるようです。アイコンの抽出では、「SMALL」と、「LARGE」が扱えるようです。
Windows自体のAPIとしては、前者2つは、旧来からあるAPIで取得できるのですが、後者2つは異なるAPIを用いる必要があるため、プロデルで前者2つしか取得できないとしたら、おそらくは、利用しているAPIが原因と思います(サイズ指定がマニュアルに記載がないのも、対応を迷っているのかもしれません)
アイコンの取得方法を、後者2つも取得できる方法にした場合、アイコンへのマークのオーバレイも対応できるようになるため、その辺をどう対応するかで実装を迷っているため、サイズ指定もマニュアルに載せてないのではないかな と思っています。
(ショートカット時とか、管理者権限要とかで、本来のアイコンの左下に表示されるマーク)
WIN32のNativeAPIと、COMを用いることでも取得できなくはなさそうなので、あとで少し試してみます。

Re^4: 32×32アイコンの抽出方法

投稿者:通り道 投稿日:2019/01/31(Thu) 22:33:45 No.2363

こんにちは。
ざっと実装すると、以下のような感じでしょうか。参考までに。
プロデル、結構、プロデル外の機能を使う命令が充実していますね。
本体側の命令でも取り出せるようになるのではと思います。
なお、アイコン抽出という名前なのですが、実際には、指定したファイルから
アイコンを抽出しているのではなく、指定したファイルやフォルダについて、
エクスプローラーが表示する際に使用するアイコンを取得する機能になります。
基本的に、実行ファイルは、その実行ファイル内の最初のアイコンになりますが、
フォルダやデータファイルは、関連付けられているアプリケーションのアイコンに
なります。
また、256サイズのアイコンは、古いOSでは取得できない可能性があります。
(48サイズは、XP以降ならば大丈夫のはず)
--------------------
アイコン抽出支援とは
 −IntPtr型
 −Icon型
 −SHGetFileInfo
 −SHGetImageList
 −UuidFromString
 −DestroyIcon
 −ImageList_GetIcon

 −SHGFI_LARGEICON:整数=0x000000000
 −SHGFI_SMALLICON:整数=0x000000001
 −SHGFI_ADDOVERLAYS:整数=0x000000020
 −SHGFI_OVERLAYINDEX:整数=0x000000040
 −SHGFI_ICON:整数=0x000000100
 −SHGFI_SYSICONINDEX:整数=0x000004000
 −SHGFI_LINKOVERLAY:整数=0x000008000
 −SHGFI_SELECTED:整数=0x000010000
 −SHIL_LARGE:整数=0x0
 −SHIL_SMALL:整数=0x1
 −SHIL_EXTRALARGE:整数=0x2
 −SHIL_SYSSMALL:整数=0x3
 −SHIL_JUMBO:整数=0x4
 −ILD_NORMAL:整数=0x0000
 −ILD_TRANSPARENT:整数=0x0001

 −IID_IImageList

 はじめの手順
  ' 使用するドットネット型を取得
  IntPtr型は、ドットネット型(「System.IntPtr」)を作る
  Icon型は、ドットネット型(「System.Drawing.Icon」)を作る
  ' 使用するネイティブ関数を取得
  SHGetFileInfoは、ネイティブ関数(ファイル名「Shell32.dll」、関数名「SHGetFileInfoA」)を作る
  SHGetFileInfoの引数型一覧は、{文字列,整数,SHFILEINFO,整数,整数}
  SHGetFileInfoの戻り値型は、整数

  SHGetImageListは、ネイティブ関数(ファイル名「Shell32.dll」、関数名「SHGetImageList」)を作る
  SHGetImageListの引数型一覧は、{整数,GUID,ポインタ}
  SHGetImageListの戻り値型は、整数

  UuidFromStringは、ネイティブ関数(ファイル名「Rpcrt4.dll」、関数名「UuidFromStringA」)を作る
  UuidFromStringの引数型一覧は、{文字列,GUID}
  UuidFromStringの戻り値型は、整数

  DestroyIconは、ネイティブ関数(ファイル名「user32.dll」、関数名「DestroyIcon」)を作る
  DestroyIconの引数型一覧は、{整数}
  DestroyIconの戻り値型は、整数

  ImageList_GetIconは、ネイティブ関数(ファイル名「Comctl32.dll」、関数名「ImageList_GetIcon」)を作る
  ImageList_GetIconの引数型一覧は、{整数,整数,整数}
  ImageList_GetIconの戻り値型は、整数
  
  IID_IImageListというGUIDを作る
  UuidFromStringを{「46EB5926-582E-4017-9FDF-E8998DAA0950」,IID_IImageList}で呼び出して結果とする
  もし、結果が0でなければ、
   「初期化に失敗しました」というエラーを発生させる
  もし終わり
 終わり
 自分で[ファイル名]から小アイコン取得する手順:プロデルアイコン
  【パラメータ】というSHFILEINFOを作る
  SHGetFileInfoを{ファイル名,0,パラメータ,SHFILEINFOの構造体バイト数, SHGFI_ICON+SHGFI_SMALLICON}で呼び出して【結果】とする
  もし、結果が0ならば、
   空を返す
  もし終わり
  もし、パラメータのhIconが0ならば、
   空を返す
  もし終わり
  【iconhandle】は、IntPtr型から{パラメータのhIcon}でインスタンスを作る
  Icon型から「FromHandle」を{iconhandle}で呼び出して【取得アイコン】とする
  もし、取得アイコンが0ならば、
   空を返す
  もし終わり
  取得アイコンを返す
 終わり
 自分で[ファイル名]から大アイコン取得する手順:プロデルアイコン
  【パラメータ】というSHFILEINFOを作る
  SHGetFileInfoを{ファイル名,0,パラメータ,SHFILEINFOの構造体バイト数, SHGFI_ICON+SHGFI_LARGEICON}で呼び出して【結果】とする
  もし、結果が0ならば、
   空を返す
  もし終わり
  もし、パラメータのhIconが0ならば、
   空を返す
  もし終わり
  【iconhandle】は、IntPtr型から{パラメータのhIcon}でインスタンスを作る
  Icon型から「FromHandle」を{iconhandle}で呼び出して【取得アイコン】とする
  もし、取得アイコンが0ならば、
   空を返す
  もし終わり
  取得アイコンを返す
 終わり
 自分で[ファイル名]から巨大アイコン取得する手順:プロデルアイコン
  【パラメータ】というSHFILEINFOを作る
  SHGetFileInfoを{ファイル名,0,パラメータ,SHFILEINFOの構造体バイト数, SHGFI_SYSICONINDEX}で呼び出して【imglist】とする
  もし、imglistが0ならば、
   空を返す
  もし終わり
  もし、パラメータのhIconが0でなければ、
   DestroyIconを{パラメータのhIcon}で呼び出す
  もし終わり
  【imglist参照】は、ネイティブ参照(型整数)を作る
  SHGetImageListを{SHIL_EXTRALARGE,IID_IImageList,imglist参照}で呼び出して【結果】とする
  もし、結果が0でなければ、
   空を返す
  もし終わり
  imglistは、imglist参照の値
  ImageList_GetIconを{imglist,パラメータのiIcon,ILD_TRANSPARENT}で呼び出して結果とする
  【iconhandle】は、IntPtr型から{結果}でインスタンスを作る
  Icon型から「FromHandle」を{iconhandle}で呼び出して【取得アイコン】とする
  もし、取得アイコンが0ならば、
   空を返す
  もし終わり
  取得アイコンを返す
 終わり
 自分で[ファイル名]から超大アイコン取得する手順:プロデルアイコン
  【パラメータ】というSHFILEINFOを作る
  SHGetFileInfoを{ファイル名,0,パラメータ,SHFILEINFOの構造体バイト数, SHGFI_SYSICONINDEX}で呼び出して【imglist】とする
  もし、imglistが0ならば、
   空を返す
  もし終わり
  【imglist参照】は、ネイティブ参照(型整数)を作る
  SHGetImageListを{SHIL_JUMBO,IID_IImageList,imglist参照}で呼び出して【結果】とする
  もし、結果が0でなければ、
   空を返す
  もし終わり
  もし、パラメータのhIconが0でなければ、
   DestroyIconを{パラメータのhIcon}で呼び出す
  もし終わり
  imglistは、imglist参照の値
  ImageList_GetIconを{imglist,パラメータのiIcon,ILD_TRANSPARENT}で呼び出して結果とする
  【iconhandle】は、IntPtr型から{結果}でインスタンスを作る
  Icon型から「FromHandle」を{iconhandle}で呼び出して【取得アイコン】とする
  もし、取得アイコンが0ならば、
   空を返す
  もし終わり
  取得アイコンを返す
 終わり

終わり

SHFILEINFOとは
 ネイティブ構造体を受け継ぐ
 +hIcon:整数
 +iIcon:整数
 +dwAttributes:整数
 +szDisplayName:文字列
 +szTypeName:文字列
 はじめの手順
  自分で初期化する
  「szDisplayName」を256文字設定する
  「szTypeName」を80文字設定する
 終わり
終わり

GUIDとは
 ネイティブ構造体を受け継ぐ
 +Data1:整数   ' 00000000-
+Data2:短整数 ' 0000-
+Data3:短整数 ' 0000-
+Data4A:整数  ' C000-0000
+Data4B:整数  ' 00000046
 はじめの手順
  自分で初期化する
 終わり
終わり

メイン画面を表示する
待機

メイン画面とは
 ウィンドウを継承
 はじめの手順
  この大きさを{400,370}に変える
  画像領域Aというピクチャーを作る
  その位置と大きさは、{0,0,16,16}
  その背景色を白に変える
  その表示を○に変える
  画像領域Bというピクチャーを作る
  その位置と大きさは、{20,0,32,32}
  その背景色を白に変える
  その表示を○に変える
  画像領域Cというピクチャーを作る
  その位置と大きさは、{60,0,48,48}
  その背景色を白に変える
  その表示を○に変える
  画像領域Dというピクチャーを作る
  その位置と大きさは、{120,0,256,256}
  その背景色を白に変える
  その表示を○に変える
  ファイルパスというテキストを作る
  その位置と大きさは、{10,270,360,18}
  その内容は、「C:\」
  テスト実行ボタンというボタンを作る
  その位置と大きさは、{150,290,100,20}
  その内容は、「テスト実行」
  そのクリックされた時の手順は、テスト実行
 終わり
終わり

[ファイル名]をサイズ確認する手順
 【結果】
 【結果画像】
 結果は、アイコン抽出支援でファイル名から小アイコン取得する
 もし、結果が空でなければ、
  メイン画面の画像領域Aの画像は、結果を画像化する
 もし終わり
 結果は、アイコン抽出支援でファイル名から大アイコン取得する
 もし、結果が空でなければ、
  メイン画面の画像領域Bの画像は、結果を画像化する
 もし終わり
 結果は、アイコン抽出支援でファイル名から巨大アイコン取得する
 もし、結果が空でなければ、
  メイン画面の画像領域Cの画像は、結果を画像化する
 もし終わり
 結果は、アイコン抽出支援でファイル名から超大アイコン取得する
 もし、結果が空でなければ、
  メイン画面の画像領域Dの画像は、結果を画像化する
 もし終わり
終わり

[ファイル名]をテスト実行する手順
 メイン画面のファイルパスの内容をサイズ確認する
終わり

凄過ぎます…

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/01/31(Thu) 23:36:48 No.2365

通り道さん、こんばんは。アークです。

超絶のコード、ありがとうございます。
これが同じプロデルのコードとは思えません。
凄すぎて直ぐには理解が追いつきませんので、
多少なりとも理解してから利用させて頂きます。

ありがとうございました。

P.S. 後日、結果をご報告します。

アイコン画像の取得を確認しました 

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/02/01(Fri) 22:24:05 No.2366

通り道さん、こんばんは。アークです。

お世話になります。

サンプル作成して頂いたビュアでアイコンの取得を確認しました。
私が抽出したかったのはこのアイコンです。
ありがとうございます。

コードの大部分は理解できていませんが、
親切に作成されていたので使う分には問題ありませんでした。
理解を深めるためにファイル選択機能を追加したり、
ドラッグ&ドロップに対応させたり、
ファイル保存機能を付けたりしています。

〉エクスプローラーが表示する際に使用するアイコンを取得する機能になります
確かに画像として取得しているようでアイコンファイルとしては保存できませんでした。
これはプロデルの機能によるのかも知れませんが…。
でも、pingなどでも問題ありません。
これでボタンに表示する画像を実行時に取得・設定する事ができそうです。

ところで、この難解なコードを汎用的に使用できるようにとライブラリ化を試みたのですが、
『「プラグイン型情報」種類に定義されていない「小アイコン取得する」手順を呼び出そうとしました。』というエラーになってしまいました。
ライブラリなど作成した事が無いので未熟なためと思われます。

[機能]タブ

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/01/31(Thu) 23:25:49 No.2364

通り道さん、こんばんは。アークです。

お世話になります。

〉デザイナ(標準のエディタ)の右にある、「見出し」「機能」「リファレンス」というタブが並ぶ中の、「機能」のタブです。
[機能]タブは使った事が有りませんでした。
[リファレンス]タブと同じ項目でも内容が微妙に違うのですね。
これからはこちらも利用するようにします。
ありがとうございます。

▲ページの先頭へ

- WebForum -