〜 グラフィック 〜
複数のアイコンを一括取得して描画 (要USER32.DLL, SHELL32.DLL)

実行ファイルやDLLに入っている複数のアイコンを一括でHSPウィンドウ内に描画するには、
API関数ExtractIconExを使うことで特定または全てのアイコンリソースを抽出できます。
ExtractIconExのパラメータには第1引数から順に「アイコンの入ったファイルパス」「インデクス」
「大アイコン格納先変数ポインタ」「小アイコン格納先変数ポインタ」「アイコン数」を指定します。
尚、API関数ExtractIconExはアイコンのハンドル(管理番号)を取得するだけのものであるため、
ウィンドウ内に描画するにはAPI関数DrawIconまたはDrawIconExを使う必要があります。
また、アイコンが不要になればAPI関数DestroyIconでハンドルを解放してください。
ココで紹介するAPI関数DrawIconExのパラメータには第1引数から順に
「デバイスコンテキスト」「描画基点X座標」「描画基点Y座標」「アイコンハンドル」「横幅」「縦幅」
「アニメーションフレームインデクス」「ブラシハンドル」「描画フラグ」をそれぞれ指定します。
デバイスコンテキストは描画先であるHSPのhdc(HSP2はBMSCR構造体要素4の値)を指定、
描画基点XY座標はウィンドウ左上を(0,0)としたpos同様の座標を指定、
アイコンハンドルにAPI関数ExtractIconExで取得したハンドルを指定、
横・縦幅はリソースの一部ではなくリソースサイズの伸縮を行ったアイコンの描画サイズを指定、
アニメーションフレームインデクスはアニメーションカーソルで使用するものなのでココでは0を指定、
ブラシハンドルはオフスクリーンビットマップに描画させてから指定のデバイスコンテキストにコピー、
直接デバイスコンテキストへ描画する場合はNULL指定と言うことでココでも0を指定、
描画フラグは以下のいずれかを指定します。
DI_MASK0x0001マスクを使ってアイコンまたはカーソルを描画
DI_IMAGE0x0002イメージを使ってアイコンまたはカーソルを描画
DI_NORMAL0x0003上記2つの組み合わせ
DI_COMPAT0x0004システム既定のイメージを描画
DI_DEFAULTSIZE0x0008デフォルトサイズで描画
コチラで紹介したAPI関数DrawIconだとサイズ指定、フレームインデクス、ブラシ、描画フラグがないので 当ページのAPI関数DrawIconExより設定すべきパラメータが少なくて使いやすい場合があります。 ただし、小さいアイコンを描画しようとしても通常アイコンサイズで表示されてしまうので、 ケースバイケースで使い分けると良いでしょう。 下記のサンプル命令は含まれているアイコン全てをカレントポジションに一括描画させるもので、 1列に表示させるアイコン数、縦横のアイコン間隔、1アイコンの表示サイズをそれぞれ指定可能です。 アイコン数を省略した場合は縦に並べます。 縦横のアイコン間隔にマイナス値を指定した場合はエクスプローラの大きいアイコン表示と同じ 水平間隔「SM_CXICONSPACING(=0x0026)」、垂直間隔「SM_CYICONSPACING(=0x0027)」が適用されます。 1アイコンの表示サイズを省略した場合、画面プロパティのデザインの詳細項目で設定できる 大きいアイコンサイズ「SM_CXICON(=0x000B)」「SM_CYICON(=0x000C)」が適用されます。 もし、小さなアイコンを描画するフラグを設定している場合は タイトルバーに表示するサイズ「SM_CXSMICON(=0x0031)」「SM_CYSMICON(=0x0032)」が適用されます。

gsm 取得項目
取得項目取得するシステムメトリクス(画面構成やシステム設定情報のオブジェクトサイズ)定数値を指定する

geticonnum アイコンパス
アイコンパス含まれているアイコン数の確認対象アイコンファイルのパスを指定する

drawicons アイコンパス, 列数, 横間隔, 縦間隔, 横幅, 高さ, フラグ
アイコンパス描画対象アイコンファイルのパスを指定する
尚、内部でgsm命令、geticonnum命令を使用しているため、
drawicons命令の前にgsm命令、geticonnum命令を定義すること!
列数1列に表示するアイコン数を指定する
尚、省略またはマイナス値を指定した場合は列数=1となる
横間隔複数列指定時に隣のアイコンとの間隔を指定する
尚、マイナス値を指定した場合はデスクトップ同様の間隔が適用される
縦間隔複数アイコン描画時に前のアイコンとの間隔を指定する
尚、マイナス値を指定した場合はデスクトップ同様の間隔が適用される
横幅表示するアイコンの横幅を指定する。指定サイズが実際のサイズと異なる場合は伸縮される
尚、省略した場合はデフォルトサイズが適用される
高さ表示するアイコンの縦幅を指定する。指定サイズが実際のサイズと異なる場合は伸縮される
尚、省略した場合はデフォルトサイズが適用される
フラグ大きいアイコン(=0)か小さいアイコン(=1)かを指定する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
	ll_libload user, "user32.dll"
	ll_getproc DestroyIcon, "DestroyIcon", user
	ll_getproc DrawIconEx, "DrawIconEx", user
	ll_getproc GetSystemMetrics, "GetSystemMetrics", user
	ll_libload shell, "shell32.dll"
	ll_getproc ExtractIconEx, "ExtractIconEx", shell

#module
#deffunc gsm int
	mref i, 0
	mref stt, 64
	ll_callfunc i, 1, GetSystemMetrics@
	ll_ret i : stt = i
	return

#deffunc geticonnum str
	mref file, 32
	mref stt, 64
	ll_getptr file : ll_ret prm
	prm.1 = 0, 0, 0, -1
	ll_callfunc prm, 5, ExtractIconEx@ : ll_ret prm
	stt = prm
	return

#deffunc drawicons str, int, int, int, int, int, int
	mref file, 32 : mref num, 1 : mref ix, 2 : mref iy, 3 : mref sx, 4 : mref sy, 5 : mref small, 6
	mref stt, 64
	mref bmscr, 67
	j = csrx, csry, 0, csrx, csry
	geticonnum file : j.2 = stat
	dim h, j.2
	ll_getptr h : ll_ret i
	prm = 0, 0, (small = 0) * i, (small ! 0) * i, j.2
	ll_getptr file : ll_ret prm
	ll_callfunc prm, 5, ExtractIconEx@
	if num < 1 : num = 1
	if sx = 0 {
		if small : gsm 0x0031 : else : gsm 0x000B // (small) SM_CXSMICON (big) SM_CXICON
		sx = stat
	}
	if sy = 0 {
		if small : gsm 0x0032 : else : gsm 0x000C // (small) SM_CYSMICON (big) SM_CYICON
		sy = stat
	}
	if ix < 0 : gsm 0x0026 : ix = stat // SM_CXICONSPACING
	if iy < 0 : gsm 0x0027 : iy = stat // SM_CYICONSPACING
	repeat j.2
		j.3 += sx + ix
		prm = bmscr.4, j.3, j.4, h.cnt, sx, sy, 0, 0, 0x0003
		ll_callfunc prm, 9, DrawIconEx@
		ll_callfunc h.cnt, 1, DestroyIcon@
		if cnt \ num = (num - 1) : j.3 = j.0, j.4 + sy + iy
	loop
	redraw 1
	stt = j.2
	return
#global

	columns = 3
	dialog "", 16, "描画アイコン"
	if stat {
		pos 50, 50
		drawicons refstr, columns, 10, 5 // 横に3個、横間隔10・縦間隔5ピクセルで並べる
		dialog "" + stat + "個のアイコンを描画しました"
	}
	stop

geticonnum アイコン
アイコン含まれているアイコン数の確認対象アイコンファイルのパスを指定する

drawicons アイコンパス, 列数, 横間隔, 縦間隔, 横幅, 高さ, フラグ
アイコンパス描画対象アイコンファイルのパスを指定する
内部でgeticonnum命令を使用しているため、drawicons命令の前にgeticonnum命令を定義すること!
列数1列に表示するアイコン数を指定する
尚、省略またはマイナス値を指定した場合は列数=1となる
横間隔複数列指定時に隣のアイコンとの間隔を指定する
尚、マイナス値を指定した場合はデスクトップ同様の間隔が適用される
縦間隔複数アイコン描画時に前のアイコンとの間隔を指定する
尚、マイナス値を指定した場合はデスクトップ同様の間隔が適用される
横幅表示するアイコンの横幅を指定する。指定サイズが実際のサイズと異なる場合は伸縮される
尚、省略した場合はデフォルトサイズが適用される
高さ表示するアイコンの縦幅を指定する。指定サイズが実際のサイズと異なる場合は伸縮される
尚、省略した場合はデフォルトサイズが適用される
フラグ大きいアイコン(=0)か小さいアイコン(=1)かを指定する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#uselib "shell32.dll"
#func  global ExtractIconEx "ExtractIconExA" str, int, int, int, int
#uselib "user32.dll"
#func  global DestroyIcon "DestroyIcon" int
#func  global DrawIconEx "DrawIconEx" int, int, int, int, int, int, int, int, int
#cfunc global GetSystemMetrics "GetSystemMetrics" int, int

#module
#defcfunc geticonnum str file
	ExtractIconEx file, , , , -1
	return stat

#deffunc drawicons str file, int num, int ix, int iy, int sx, int sy, int small, local i
	i = ginfo_cx, ginfo_cy, geticonnum(file), ginfo_cx, ginfo_cy
	dim h, i.2
	ExtractIconEx file, , (small = 0) * varptr(h), (small ! 0) * varptr(h), i.2
	if num > 0 : i.5 = num : else : i.5 = 1
	if sx : i.6 = sx : else : i.6 = GetSystemMetrics(0x0031) * (small ! 0) + GetSystemMetrics(0x000B) * (small = 0)
	if sy : i.7 = sy : else : i.7 = GetSystemMetrics(0x0032) * (small ! 0) + GetSystemMetrics(0x000C) * (small = 0)
	if ix : i.8 = GetSystemMetrics(0x0026) * (ix < 0) + ix * (ix > 0) : else : i.8 = 0
	if iy : i.9 = GetSystemMetrics(0x0027) * (iy < 0) + iy * (iy > 0) : else : i.9 = 0
	repeat i.2
		i.3 += i.6 + i.8
		DrawIconEx hdc, i.3, i.4, h.cnt, i.6, i.7, , , 0x0003
		DestroyIcon h.cnt
		if cnt \ i.5 = i.5 - 1 : i.3 = i.0, i.4 + i.7 + i.9
	loop
	redraw 1
	return i.2
#global

	columns = 3
	dialog "", 16, "描画アイコン"
	if stat {
		pos 50, 50
		drawicons refstr, columns, 10, 5 // 横に3個、横間隔10・縦間隔5ピクセルで並べる
		dialog str(stat) + "個のアイコンを描画しました"
	}