〜 オブジェクト 〜
エディットコンボの配置・文字列取得と設定 (要USER32.DLL)

ウェブブラウザのアドレスバーや、ファイル名を指定して実行コマンドで表示されるコントロールは、
テキストを入力できるインプットボックスのようなエディット機能と、
過去に打ち込んだものを入力せずに呼び出すことの出来るドロップダウン式の選択機能を併せ持っていますが、
HSPのコンボボックスはテキスト編集が出来ない選択のみのドロップダウンリストです。
inputcomboxを縦または横に並べれば済む問題かもしれませんが、
時には冒頭に書いた選択と編集2つの機能を併せ持ったオブジェクトを配置したいこともあることでしょう。
そこで今回は、API関数を使ってドロップダウンコンボボックスを配置してみます。

HSP3からはウィンドウオブジェクトを配置するwinobj命令を使って配置できますが、
HSP2以前は用意されてないのでAPI関数CreateWindowExを使って配置します。
HSP3から使えるwinobj命令で配置したオブジェクトはHSPのオブジェクトの一部として、
clrobj命令による除去、cls命令やscreen命令による初期化、objsel命令による選択は出来ますが、
objprm命令による更新処理は出来ませんし、
API関数CreateWindowExを使って配置したHSP2のオブジェクトは、
更新はおろか初期化しても消えませんし、標準命令では選択することも出来ませんので、
一連の処理をまとめてモジュールにしました。
配置後、追加や削除・取得等の処理は、メッセージ送受信によって実現させますが、
HSP3からは標準命令のsendmsg命令が使えるものの、
HSP2は標準オブジェクトではなくobjsend命令が使えないのでAPI関数SendMessageでやり取りします。

API関数SendMessageをHSP用に標準命令で使えるようにしたものがsendmsg命令なので、
sendmsg命令のパラメータ同様に「ハンドル, コード, wparam, lparam」で記述できます。
メッセージコードwparamlparam内容
WM_SETFONT(=0x0030)bmscr.38 (※後述)即時再描画(=1)配置オブジェクトのフォント変更
CB_LIMITTEXT(=0x0141)文字数不使用(=0)入力可能文字数を設定
CB_ADDSTRING(=0x0143)不使用(=0)テキスト格納先アドレスアイテムを追加登録
CB_DELETESTRING(=0x0144)削除行位置不使用(=0)アイテムを削除
CB_RESETCONTENT(=0x014B)不使用(=0)不使用(=0)アイテム全てを削除
CB_GETCURSEL(=0x0147)不使用(=0)不使用(=0)選択アイテム行を取得
CB_SETCURSEL(=0x014E)選択行位置不使用(=0)選択アイテム行を設定
CB_GETCOUNT(=0x0146)不使用(=0)不使用(=0)アイテム総数を取得
CB_GETLBTEXT(=0x0148)取得行位置格納先変数アドレスアイテムテキストを取得 (※後述)
WM_GETTEXT(=0x000D)変数サイズ格納先変数アドレスアイテムテキストを取得 (※後述)
winobj命令やAPI関数CreateWindowExで配置したオブジェクトのフォントは、 幾らobjmodeでオブジェクトのフォントをfont命令で指定したフォントに切り替えても適用されないため、 WM_SETFONTでは現在のフォントが格納されたBMSCR構造体の要素38(hfont)を指定します。 もし、デフォルトのシステムフォントに戻したい時はwparamに0を指定すればOKです。 コンボボックスのアイテムテキストを取得するCB_GETLBTEXTは登録済アイテムしか取得できません。 選択した既存アイテムではなく編集したテキストを取得するにはWM_GETTEXTを使いましょう。

comedit 最大文字数, 拡張Yサイズ
最大文字数入力できる最大文字数を指定する。
拡張Yサイズコンボボックスを開いた時に表示されるリストの高さを指定する。

comedit_cnt コンボID
コンボID操作対象エディットコンボIDを指定する。
オブジェクトIDとは別物で、1つ目のエディットコンボがID0となる。

comedit_destroy コンボID
コンボID削除するエディットコンボのコンボIDを指定する。

comedit_limit 最大文字数
最大文字数操作対象エディットコンボに入力できる最大文字数を指定する。

comedit_max 受取先変数
受取先変数操作対象エディットコンボのアイテム数の受取先変数を指定する。

comedit_index 受取先変数
受取先変数操作対象エディットコンボの現在選択中の行位置を受け取る変数を指定する。
入力変更されている場合は−1が入る。

comedit_sel 選択行
選択行操作対象エディットコンボの変更先選択アイテム行を指定する。

comedit_add 追加テキスト
追加テキスト操作対象エディットコンボに追加するテキストを指定する。
改行を区切りとして複数アイテムを一括追加することも可能。

comedit_get 取得行, 受取先変数, 取得サイズ
取得行取得するアイテム行を指定する。−1を指定すると表示テキストとなる。
受取先変数取得したアイテムテキストの受取先変数を指定する。
取得サイズ受取先変数に代入できる最大サイズを指定する。

comedit_del 削除行
削除行操作対象エディットコンボの削除アイテム行位置を指定する。

 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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
	ll_libload user, "user32.dll"
	ll_getproc CreateWindowEx, "CreateWindowExA", user
	ll_getproc SendMessage, "SendMessageA", user

#module
#deffunc comedit_limit int
	mref max, 0
	prm = comid.comid, 0x0141, (max = 0) * 64 + max, 0
	ll_callfunc prm, 4, SendMessage@
	return

#deffunc comedit int, int
	mref max, 0 : mref height, 1
	mref bmscr, 67
	prm = 0, 0, 0, 0x50000202, bmscr.27, bmscr.28, bmscr.29, height = 0 * 100 + height, bmscr.13, 0xFF00, bmscr.14, 0
	s = "combobox" : ll_getptr s : ll_ret prm.1
	ll_callfunc prm, 12, CreateWindowEx@ : ll_ret prm
	comid = 0
	repeat 15, 1
		if comid.cnt = 0 : comid = cnt : break
	loop
	if comid = 0 : return
	comid.comid = prm
	comedit_limit max
	prm = comid.comid, 0x0030, bmscr.38, 1
	ll_callfunc prm, 4, SendMessage@
	return

#deffunc comedit_destroy int
	mref id, 0
	id++
	if id > 0 | (id < 16) {
		prm = comid.id, 0x0010, 0, 0
		ll_callfunc prm, 4, SendMessage@
		comid.id = 0
	}
	return

#deffunc comedit_cnt int
	mref id, 0
	mref stt, 64
	if id < 0 | (id + 1 >= 16) : stt = comid.comid : else : comid = id + 1
	return

#deffunc comedit_max val
	mref max, 16
	prm = comid.comid, 0x0146, 0, 0
	ll_callfunc prm, 4, SendMessage@
	ll_ret max
	return

#deffunc comedit_index val
	mref index, 16
	prm = comid.comid, 0x0147, 0, 0
	ll_callfunc prm, 4, SendMessage@
	ll_ret index
	return

#deffunc comedit_sel int
	mref index, 0
	comedit_max max
	if index >= 0 & (index < max) : i = index : else : i = max - 1
	prm = comid.comid, 0x014E, i, 0
	ll_callfunc prm, 4, SendMessage@
	return

#deffunc comedit_add str
	mref msg, 32
	ll_getptr s : ll_ret i
	prm = comid.comid, 0x0143, 0, i
	repeat
		getstr s, msg
		if strsize = 0 : break
		strlen i, msg
		memcpy msg, msg, i - strsize, , strsize
		poke msg, i - strsize
		ll_callfunc prm, 4, SendMessage@
		if i - strsize <= 0 : break
	loop
	comedit_sel -1
	return

#deffunc comedit_get int, val, int
	mref index, 0 : mref msg, 25 : mref size, 2
	ll_getptr msg : ll_ret i
	if index = -1 {
		prm = comid.comid, 0x000D, size = 0 * 64 + size, i
	} else {
		prm = comid.comid, 0x0148, index, i
	}
	ll_callfunc prm, 4, SendMessage@
	return

#deffunc comedit_del int
	mref index, 0
	prm = comid.comid, index = -1 * 7 + 0x0144, index ! -1 * index, 0
	ll_callfunc prm, 4, SendMessage@
	return
#global

	font msmincho, 12 : objmode 2 : objsize 120, 20
	pos 10,  10 : comedit 10 // エディットコンボ配置
	pos 10,  40 : button "追加", *add
	pos 10,  70 : button "取得", *get
	pos 10, 100 : button "削除", *del
	comedit_add "abc\ndef\nghi\njkl\nmno" // アイテム追加
	sdim selrow, 64
	comedit_max max // アイテム総数取得
	repeat max
		if cnt : selrow += "\n"
		selrow += "" + cnt + "行目"
	loop
	comedit_sel 0 // 選択行変更
	pos 150, 10 : combox index, , selrow
	pos 150, 40 : button "選択", *sel
	stop

*add
	comedit_get -1, tmp // 表示テキスト取得
	comedit_add tmp // アイテム追加登録
	stop

*get
	comedit_index index // 選択行取得
	comedit_max max // アイテム総数取得
	if index ! -1 {
		comedit_get index, tmp // 選択テキスト取得
		objprm 3, index
		dialog "行数:" + max + "\n選択:" + index + "\n内容:" + tmp
	} else {
		comedit_get -1, tmp // 表示テキスト取得
		dialog "行数:" + max + "\n表示:\n" + tmp
	}
	stop

*del
	comedit_index index // 選択行取得
	comedit_max max // アイテム総数取得
	comedit_get index, tmp // 選択テキスト取得
	if index = -1 {
		dialog "削除行が選択されていません"
	} else {
		dialog "" + index + "行目「" + tmp + "」を削除しますか?", 2
		if stat = 6 {
			comedit_del index // 選択行削除
			if index >= max : index = max - 1
			comedit_sel index // 選択行変更
		}
		objprm 3, index
	}
	stop

*sel
	comedit_sel index // 選択行変更
	stop

comedit 最大文字数, 拡張Yサイズ
最大文字数入力できる最大文字数を指定する。
拡張Yサイズコンボボックスを開いた時に表示されるリストの高さを指定する。

comedit_cnt コンボID
コンボID操作対象エディットコンボIDを指定する。
オブジェクトIDとは別物で、1つ目のエディットコンボがID0となる。

comedit_destroy コンボID
コンボID削除するエディットコンボのコンボIDを指定する。

comedit_limit 最大文字数
最大文字数操作対象エディットコンボに入力できる最大文字数を指定する。

アイテム数 = comedit_max( )
アイテム数取得したアイテム数の受取先を指定する。
[パラメータなし]操作対象エディットコンボのアイテム数を取得するだけなのでパラメータは必要ない。

選択行 = comedit_index( )
選択行取得した現在選択中の行位置の受取先を指定する。入力変更した場合は−1が入る。
[パラメータなし]操作対象エディットコンボの選択アイテム行を取得するだけなのでパラメータは必要ない。

comedit_sel 選択行
選択行操作対象エディットコンボの変更先選択アイテム行を指定する。

comedit_add 追加テキスト
追加テキスト操作対象エディットコンボに追加するテキストを指定する。
改行を区切りとして複数アイテムを一括追加することも可能。

テキスト = comedit_get(取得行)
テキスト取得した操作対象エディットコンボのテキスト受取先を指定する。
取得行取得するアイテム行を指定する。−1を指定すると表示テキストとなる。

comedit_del 削除行
削除行操作対象エディットコンボの削除アイテム行位置を指定する。

 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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#module
#deffunc comedit_limit int max
	sendmsg comid.comid, 0x0141, (max = 0) * 64 + max
	return

#deffunc comedit int max, int height, local i, local h
	mref bmscr, 67
	winobj "combobox", "", 0, 0x50000202, , (height = 0) * 100 + height
	if stat = -1 : return 0
	objskip stat, 1
	comid = 0
	repeat length(comid) - 1, 1
		if comid.cnt = 0 : comid = cnt : break
	loop
	if comid = 0 : comid = length(comid)
	comid.comid = objinfo(stat, 2)
	comedit_limit max
	sendmsg comid.comid, 0x0030, bmscr.38, 1
	return comid - 1

#deffunc comedit_destroy int id
	mref bmscr, 67
	if bmscr.72 = 0 : return
	dupptr hspobjinfo, bmscr.71, bmscr.72 * 48
	repeat bmscr.72
		if comid.comid = hspobjinfo(cnt * 12 + 2) {
			clrobj cnt, cnt
			comid.comid = 0
			break
		}
	loop
	return

#deffunc comedit_cnt int id
	if id = -1 : return comid(comid)
	if id >= 0 && id + 1 < length(comid) : comid = id + 1
	return

#defcfunc comedit_max
	sendmsg comid.comid, 0x0146
	return stat

#defcfunc comedit_index
	sendmsg comid.comid, 0x0147
	return stat

#deffunc comedit_sel int index, local i
	if index >= 0 & index < comedit_max() : i = index : else : i = comedit_max() - 1
	sendmsg comid.comid, 0x014E, i
	return

#deffunc comedit_add str msg, local s
	s = msg
	repeat
		getstr s.1, s
		if s.1 = "" | strsize = 0 : break
		memcpy s, s, strlen(s) - strsize, , strsize
		poke s, strlen(s) - strsize
		sendmsg comid.comid, 0x0143, , varptr(s.1)
	loop
	comedit_sel -1
	return

#defcfunc comedit_get int index, local s
	sdim s, 4000
	if index = -1 {
		sendmsg comid.comid, 0x000D, 4000, varptr(s)
	} else {
		sendmsg comid.comid, 0x0148, index, varptr(s)
	}
	return s

#deffunc comedit_del int index
	if index = -1 {
		sendmsg comid.comid, 0x014B
	} else {
		sendmsg comid.comid, 0x0144, index
	}
	return
#global

	font msmincho, 12 : objmode 2 : objsize 120, 20
	pos 10,  10 : comedit 10 // エディットコンボ配置
	pos 10,  40 : button gosub "追加", *add
	pos 10,  70 : button gosub "取得", *get
	pos 10, 100 : button gosub "削除", *del
	comedit_add "abc\ndef\nghi\njkl\nmno" // アイテム追加
	sdim selrow, 64
	repeat comedit_max() // アイテム総数取得
		if cnt : selrow += "\n"
		selrow += str(cnt) + "行目"
	loop
	gosub *sel
	pos 140, 10 : combox index, , selrow
	pos 140, 40 : button gosub "選択", *sel
	stop

*add
	comedit_add comedit_get(-1) // 表示テキスト取得してアイテム追加登録
	return

*get
	if comedit_index() ! -1 {
		// アイテム数と選択テキストを取得して表示
		index = comedit_index()
		objprm 4, index
		dialog "行数:" + comedit_max() + "\n選択:" + index + "\n内容:" + comedit_get(index)
	} else {
		// アイテム数と表示テキストを取得して表示
		dialog "行数:" + comedit_max() + "\n表示:\n" + comedit_get(-1)
	}
	return

*del
	if comedit_index() = -1 {
		dialog "削除行が選択されていません"
		return
	}
	index = comedit_index()
	dialog str(index) + "行目「" + comedit_get(index) + "」を削除しますか?", 2
	if stat = 6 {
		comedit_del index // 選択行削除
		if index >= comedit_max() : index = comedit_max() - 1
		comedit_sel index // 選択行変更
	}
	objprm 4, index
	return

*sel
	comedit_sel index // 選択行変更
	return