LazarusでPrivateExtractIcons関数の使用について

解決


caballero  2020-11-22 16:32:02  No: 149389

こちらの環境は、Lazarus2.0.8+windows10(64bit)です。
48x48サイズのアイコンを取得したいおもい、PrivateExtractIcons関数を使用しようと試みていますがうまくいきません。
原因を調べるためサンプルプログラムを素のまま実行しようと思い、Mr.XRAY氏の"Delphi Library"のDelphi サンプルプログラム集-908_EXE や DLL ファイル内のアイコンの取得(http://mrxray.on.coocan.jp/Delphi/plSamples/908_ExtractIcon.htm)にある908_ExtractIcon.zipより該当の04_PrivateExtractIconsフォルダ以下のコードを使用しました
若干の修正でコンパイルは通り、実行したところ(ターゲットは”c:\windows\system32\shell32.dll”を指定しました)、エラーは出ないのですが、image1に何も表示されません。
確認のため、
  showmessage(IntToStr(PrivateExtractIcon(PChar(LSrcFileName),
                        LIconIndex,
                        LIconSize,
                        LIconSize,
                        @LhIcon,
                        @LnIconId,
                        LnIcons,
                        LR_LOADFROMFILE))); 
のコードを入れて実行したところ、何をしても4294967295(32ビット値の-1)が表示されます。

PrivateExtractIcons関数が、エラーにはならないものも適切に動作していないようです。
この現象に関してなにか情報をお持ちの方がいましたらご教示ください。

//別のノートPC(Windows10(64bit))にdelphi5をいれて試したところ、無事ビルドでき問題なく動作しました。
 


HFUKUSHI  2020-11-22 18:51:05  No: 149390

PrivateExtractIconsA function (winuser.h) - Win32 apps | Microsoft Docs
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-privateextracticonsa
によると、
> If the phicon parameter is not NULL and the function succeeds, then the return value is the number of icons extracted. Otherwise, the return value is 0xFFFFFFFF if the file is not found.
となってますね。


Mr.XRAY  2020-11-22 21:18:37  No: 149391

PrivateExtractIcons 関数の戻り値は UINT 型ですから.
符号付き整数では -1 です.32 ビットの場合 $FFFFFFFF ですね.
ということは HFUKUSHI さんのレスにあるようにファイルが見つからない時の戻り値です.

ところで,PrivateExtractIcons 関数に渡すファイル名に,
日本語の文字 (いわゆる全角文字) は含まれているのでしょうか ?


caballero  2020-11-23 04:39:23  No: 149392

 HFUKUSHIさま、Mr.XRAYさま
回答ありがとうございます。

>ところで,PrivateExtractIcons 関数に渡すファイル名に,
>日本語の文字 (いわゆる全角文字) は含まれているのでしょうか ?

動作確認の段階なので質問の文中にあるように"c:\windows\system32\shell32.dll”を対象にしているので全角文字は含まれていません。
最終的な実装のときはUTF8ToCP932を入れる予定です。


Mr.XRAY  2020-11-23 07:48:50  No: 149393

質問の書き込みで関数の定義は確認できます.実際の使用コードは確認できませんが,
日本語を使用していないということですので・・・

提示された関数の定義の場合,その関数は Ansi 版となります.
それは HFUKUSHI さんがリンクを貼っているページの関数です (末尾が A です).
Ansi 版の関数では,文字列は AnsiString 型を使用します.
そのあたりの処理を確認されてはどうでしょうか ?

参考]
[ Lazarus における Windows API の関数の日本語文字列 ]
http://mrxray.on.coocan.jp/Delphi/Others/Lazarus_WindowsAPI.htm


Mr.XRAY  2020-11-23 07:59:01  No: 149394

> 質問の書き込みで関数の定義は確認できます.実際の使用コードは確認できませんが,

失礼しました.
使用例のコードを掲載されているのですね.
提示の関数名の場合,Ansi 版となりますから,AnsiString 型を使用します.
Ansi 版を使用するのであれば関数の定義文も変更が必要です.


Mr.XRAY  2020-11-23 14:55:49  No: 149395

もし以下のコードの PrivateExtractIcon 関数の定義コードを使用しているのであれば,

http://mrxray.on.coocan.jp/Delphi/plSamples/908_ExtractIcon.htm#list5

もしかしたら,推測ですが,
以下の部分を変更するだけで,アイコンが取得できるようになるかも知れません.
私の Lazarus の環境では取得できまました.

name 'PrivateExtractIconsW'
  ↓
name 'PrivateExtractIconsA'


caballero  2020-11-24 04:17:11  No: 149396

Mr.XRAYさま

回答ありがとうございます。
ご指摘のようにWをAに変更したら、問題なく取得できました。
こういうところもDelphiとLazarusの違いなんですね。
助かりました。


HFUKUSHI  2020-11-24 10:27:42  No: 149399

> こういうところもDelphiとLazarusの違いなんですね。
そうではなく、使用している文字コード系の違いです。
(Delphi 2009以降はUTF-16、Delphi5はANSI=Shift_JISで、LazarusもANSIなのかな?)


Mr.XRAY  2020-11-24 14:21:16  No: 149406

> そうではなく、使用している文字コード系の違いです。 

ですね.
ASCII 文字 (半角の英数字) のコードポイントは,
UTF-8も Ansi (Shift_JIS) も同じで,Delphi 2007 までは Ansi 版でしたから.


caballero  2020-11-25 03:24:50  No: 149409

文字コード系の違いですか。
delphi/lazarusから離れていた期間が長いので、文字コードの扱いはよくわかっていません。
研究してみようと思います。


Mr.XRAY  2020-11-27 23:02:34  No: 149413

ずっと考えていたのですか,念のため追加しておきます.

http://mrxray.on.coocan.jp/Delphi/plSamples/908_ExtractIcon.htm#list5

 ↑ のコードを Ansi 版の Delphi で実行した場合,アイコンは取得できません.
結果と原因と対策は,既にレスにある通りです.
Ansi 版の Delphi とは,Delphi 4 / 5 / 6 / 7 / 2007 です.
質問された方は,Delphi 5 で『無事ビルドでき問題なく動作しました。 』と書いています.
これが,実際にアイコンが取得できたことを意味するのかは不明です.
もし,アイコンが取得できたということであっても,何故なのかは私には分かりません.


Mr.XRAY  2020-11-27 23:03:22  No: 149414

ついでいに.
エラーを調べる時,以下のように GetLastError 関数を使用すると便利なことがあります.

  // GetLastError はエラー番号をリセットするので変数に退避
  // LErrCode は UINT 型 (DWORD でも同じ) の変数
  LErrCode := GetLastError;
  ShowMessage('$ ' + IntToHex(LErrCode, 8) + sLineBreak + SysErrorMessage(LErrCode));
    
[参考]
http://mrxray.on.coocan.jp/Delphi/Others/RunError.htm#fig22


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加