Delphi Programming / Object Pascal
[掲載 2021年09月29日] [更新 2021年09月29日] Delphi 一般・その他 |
先頭が @ の文字列は文字列のリソース |
動作確認等 |
Windows 10 ビルド 19042 + Delphi XE5(UP2) Pro VCL-32 |
レジストリに,先頭が @ の文字列データがあります.これは,文字列のリソースを意味する文字列です.Windows API の SHLoadIndirectString 関数を使用すれば,リソースとしての文字列を取り出せます.
先頭が @ の文字列を間接文字列とも言います. |
|
図1
DLL から文字列のリソースを取り出す |
function SHLoadIndirectString(pszSource, psuOutBuf: PWideChar; const ccOutBuf:
UINT; var ppvReserved: Pointer): HRESULT; stdcall; external 'ShLwApi.dll';
function GetDirectStr(ArgText: WideString): string;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// 先頭が @ の文字列は文字列のリソース
// DLL 内の文字列リソースを取り出す例
// Windows API の SHLoadIndirectString 関数を使用して取得できる
//
// 取得した文字列は,必ずしもテキストとは限らない
// 画像ファイル,音楽ファイル等,他のオブジェクトのパス名のこともある
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LRegItem : string;
LResText : string;
begin
Memo1.Lines.Clear;
LRegItem := '@%SystemRoot%\system32\shell32.dll,-31361';
LResText := GetDirectStr(LRegItem);
Memo1.Lines.Add(LResText);
end;
//-----------------------------------------------------------------------------
// SHLoadIndirectString 関数を利用するための関数
//-----------------------------------------------------------------------------
function GetDirectStr(ArgText: WideString): string;
var
LBuffer : array [0..4095] of WideChar;
LPointer : Pointer;
begin
Result := '';
if ArgText = '' then Exit;
FillChar(LBuffer[0], SizeOf(LBuffer), #0);
if SHLoadIndirectString(PWideChar(ArgText),
LBuffer,
Length(Lbuffer),
LPointer) = S_OK then begin
Result := Lbuffer;
end;
end;
先頭に @ がない,以下のような文字列データがあります.この場合,ほとんどアイコン画像のリソースを意味します.文字列の最初の部分がリソースを格納している DLL 等のファイル名です.カンマの後の数字はリソースの ID 値です.
CSV (カンマ区切り) 文字列になっていますから,分解して Windows API の ExtractIcon 関数の引数に渡せばアイコンのハンドルが取得できます.ExtractIcon 関数の引数には,環境変数も使用可能です. |
%systemRoot%\system32\shell32.dll,-13
C:\Windows\system32\shell32.dll,-13 |
|
図2
DLL からアイコン画像を取り出す |
リスト2
「DLL のパス名,数字」形式の文字列は,主にいアイコン画像のリソースを意味する |
implementation
uses
System.StrUtils,
Winapi.ShellAPI;
{$R *.DFM}
//=============================================================================
// 「DLL のパス名,数字」形式の文字列
// アイコン画像のリソースを意味する
// 例 :
// %systemRoot%\system32\shell32.dll,-13
// C:\Windows\system32\shell32.dll,-13
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LRegItem : string;
LPos : Integer;
LFilePath : string;
LResID : Integer;
LIcon : TIcon;
begin
Image1.Picture.Assign(nil);
LRegItem := '%systemRoot%\system32\shell32.dll,-13';
LPos := Pos(',', LRegItem);
LFilePath := Copy(LRegItem, 1, LPos - 1);
LResID := Abs(StrToInt(Copy(LRegItem, LPos + 1, Length(LRegItem))));
LIcon := TIcon.Create;
try
LIcon.Handle := ExtractIcon(hInstance, PChar(LFilePath), LResID);
Image1.Picture.Assign(LIcon);
finally
FreeAndNil(LIcon);
end;
end;
//=============================================================================
// 「DLL のパス名,数字」形式の文字列
// アイコン画像のリソースを意味する
// 例 :
// %systemRoot%\system32\shell32.dll,-13
// C:\Windows\system32\shell32.dll,-13
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LRegItem : string;
LStrList : TStringList;
LFilePath : string;
LResID : Integer;
LIcon : TIcon;
begin
Image1.Picture.Assign(nil);
LRegItem := '%systemRoot%\system32\shell32.dll,-13';
LStrList := TStringList.Create;
LIcon := TIcon.Create;
try
LStrList.Text := ReplaceText(LRegItem, ',-', sLineBreak);
LFilePath := LStrList[0];
LResID := StrToInt(LStrList[1]);
LIcon.Handle := ExtractIcon(hInstance, PChar(LFilePath), LResID);
Image1.Picture.Assign(LIcon);
finally
FreeAndNil(LIcon);
FreeAndNil(LStrList);
end;
end;
ExtractIcon 関数の第 3 引数の値を -1 にすると,DLL 内のアイコンの数を知ることががきます. |
|
図3
DLL 内のアイコン数を調べる |
implementation
uses
Winapi.ShellAPI;
{$R *.DFM}
//=============================================================================
// DLL 内のアイコンの数を取得
// RT_GROUP_ICON リソースの数
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LFilePath : string;
LIconCnt : Integer;
begin
LFilePath := '%systemRoot%\system32\shell32.dll';
LIconCnt := ExtractIcon(hInstance, PChar(LFilePath), Cardinal(-1));
MessageBox(Handle, PChar(IntToStr(LIconCnt)), 'アイコン数', MB_ICONINFORMATION);
end;
[備考]
ExtractIcon 関数の説明には,取得したアイコンのハンドルを DestroyIcon 関数で解放するように書いてありますが,TIcon.Handle に代入した場合は必要ありません.TIcon が処理します. |
|