オブジェクトの隠し機能?
標準命令でスイッチ系リスト系エディット系の3種のコントロールを配置できると紹介しましたが、
例えば、スイッチ系にはbutton命令で設置するボタンや、chkbox命令で設置するチェックボックスの他の、
ラジオボタンや3ステートチェックボックスといったコントロールを直接配置する命令は用意されてません。
既存のbuttonchkboxと別の命令とを組み合わせることで配置できるようになるので、
今回は隠し技とも言えるその別の命令を使って実際に配置してみましょう。
予め断っておきますが、今回紹介する命令や関数は「通常は使わないので覚えておかなくて良い」と
ヘルプで但し書きされる程のもので、
ソレらを説明する為には専門用語も多く必要となる為に理解しにくい内容となっている可能性があります。

さて、隠し技とも言えるその命令はというと、
Windowsがプログラマ向けに公開しているSendMessageというAPI関数のラッパーファンクション。
C言語等の別言語で利用可能なAPI関数をHSPでも利用できるようにしたもので、
操作対象のオブジェクトはobjselclrobj等で使用するオブジェクトIDでは指定できず、
ウィンドウハンドルと呼ばれるオブジェクト毎に割り当てられた識別番号で指定する必要があります。
HSPで配置したオブジェクトにもオブジェクトIDとは別にウィンドウハンドルは割り当てられ、
C言語等で利用できるAPI関数を利用する時はこのウィンドウハンドルを使うことになります。
まずは、このウィンドウハンドルを取得する関数から先に紹介します。

情報 = objinfo(オブジェクトID, 取得タイプ)
情報指定した取得タイプにより取得した情報の受取先を指定する。
オブジェクトID取得対象とするオブジェクトのオブジェクトIDを指定する。
取得タイプ 0:モードとオプションデータ(値 = オプションデータ << 16 | モード)
1:対象オブジェクトが配置されているウィンドウのBMSCR構造体ポインタ
2:オブジェクトのハンドル
3:内部汎用データ(owid)
4:内部汎用データ(owsize)
5-8:代入変数の情報
9-11:コールバックの情報
objinfo関数は「通常の私用では使う必要はないもの」とヘルプに書かれてある通り、 取得タイプが幾つか用意されているようですが、 それぞれが何を意味するものなのかヘルプからは一切読み取ることができません。 一応軽く説明しますが、入門者向けに紹介しても仕方のない情報で、 ハッキリ言って見る価値ないものなのでココまで読み飛ばしてもらって構いません。 objinfo関数で取得するのはオブジェクト情報が詰まったHSPOBJINFO構造体というもの。 コレを調べることで、それぞれの取得タイプが何を表しているのか知ることが可能です。 SDKによると、HSPOBJINFO構造体は次のように定義されています。
typedef struct HSPOBJINFO {
    short       owmode;
    short       option;
    void        *bm;
    HWND        hCld;
    int         owid;
    int         owsize;
    HSP3VARSET  varset;
    void        (*func_notice)( struct HSPOBJINFO *, int );
    void        (*func_objprm)( struct HSPOBJINFO *, int, void * );
    void        (*func_delete)( struct HSPOBJINFO * );
}
owmodeはタブキースキップする等のモードがセットされています。 optionは未使用で内部オブジェクトは0がセットされています。 *bmはBMSCR構造体と呼ばれるオブジェクトを配置元のウィンドウ情報を指し示し先、 コレは後の章で紹介するもので同一ウィンドウのオブジェクトは全て同じものになってます。 hCldobjinfo関数で使える唯一と言ってもいい程の情報で後で改めて説明します。 owidはオブジェクトの汎用値…オブジェクトに使ってる変数の値と言う意味ではありません。 owsizeはオブジェクトの汎用サイズ…オブジェクトのサイズと言う意味ではありません。 varsetは次に載せるHSP3VARSET構造体になっています。 最後の3つはコールバック関数に関するもので、 外部DLLを作成する時しか使えるものではないので説明しません。
typedef struct HSP3VARSET {
    int type;
    PVal *pval;
    APTR aptr;
    void *ptr;
}
typeはオブジェクトと関連付けてる変数の型コードが入ってます。 変数の型コードはまた後の章で新たなHSPの関数と共に説明をする予定で、この場は割愛します。 *pvalも後の章で説明することになるPVal構造体というもので、この場は割愛します。 aptrは配列データのオフセット…使用してる配列変数の要素番号を示すものです。 *ptrはポインタが格納されます。 objinfo関数で取得するタイプが5〜8と4つあるのは、 4種あるHSP3VARSET構造体のそれぞれの情報を示しているわけですね。 …と、ココまでが「覚えておく必要のない小難しい補足情報」です。 先に「読み飛ばして良い」と書いておいたので見てない方も多いと思いますが、 他のDLL等と連携させることなくHSPだけで完結する人にとって ほとんど遣う価値のないobjinfo関数で唯一利用できると言ってもいい情報がハンドル値。 HSPOBJINFO構造体の4つ目(objinfo関数のタイプ2)にあるこの情報こそが C言語等で利用するのに必要なウィンドウハンドルであり、 後に紹介する命令を使うときに必要な情報であると言う訳です。 オブジェクトIDは0から順に割り当てられ、 削除して歯抜けになった後に新しくオブジェクトを配置すると抜けていた番号が再利用されましたが、 ウィンドウハンドルは歯抜けのものが再度使われるのではなく新たなハンドルが割り当てられます。 今回はハンドル値を表示するだけなので載せておくほどの価値はありませんが、 入門講座のサンプルとして載せておきます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
	s = "abc", "def", "ghi"
	input s.0
	mes "オブジェクトID0=" + objinfo(0, 2)
	input s.1
	mes "オブジェクトID1=" + objinfo(1, 2)
	input s.2
	mes "オブジェクトID2=" + objinfo(2, 2)
	clrobj 1, 1
	input s.1
	mes "オブジェクトID1=" + objinfo(1, 2) // 別のハンドルが割り当てられている
利用する時は「受取先 = objinfo(オブジェクトID, 2)」というようにするワケですが、 毎回タイプ2を指定せずにイケるようhspdef.asobjinfo_hwndマクロが定義されてます。 objinfo_hwndマクロは自動的に読み込まれているものなので、 タイプ2がなんだか分かりにくいと思う人は下記のように書くと良いでしょう。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
	s = 123, 456, 789
	input s.0
	mes "オブジェクトID0=" + objinfo_hwnd(0)
	input s.1
	mes "オブジェクトID1=" + objinfo_hwnd(1)
	input s.2
	mes "オブジェクトID2=" + objinfo_hwnd(2)
	clrobj 1, 1
	input s.1
	mes "オブジェクトID1=" + objinfo_hwnd(1)
さて、ソレでは次に上記のハンドルを使って、 今回のメインであるオブジェクトの可能性を広げる命令の説明に移りましょう。
sendmsg ハンドル, メッセージID, wParam, iParam
ハンドル操作対象のウィンドウハンドルを指定する。
メッセージID送信するメッセージコードを指定する。
wParam送信メッセージ特有の1つ目の追加情報を指定する。
iParam送信メッセージ特有の2つ目の追加情報を指定する。
1つ目のパラメータにはobjinfo関数で取得したオブジェクトのハンドルを渡しましょう。 ウィンドウハンドルという表記にしてるのは、ウィンドウ自体も1つのオブジェクトであり、 逆に、配置するオブジェクト…コントロールもまたウィンドウの1つだからなんですね。 ワケわからないと思いますが、形は違えど「ウィンドウもオブジェクトも同じもの」なんだと、 今はそう考えておくだけで良いでしょう。 2つ目のパラメータが操作対象オブジェクトの動作内容になるもので、 ヘルプには全く書かれてない為に知らない人にとっては何を書くべきか分からないと思います。 書かれてない理由は、objinfo関数同様に「通常は覚える必要ないものだから」ということもありますが、 何より、対象となるオブジェクトのタイプ毎に膨大な量のメッセージが用意されていて、 どれを載せるべきか載せるべきでないのか、載せるに載せられない状態と言うこともあるのでしょう。 3つ目、4つ目のパラメータについても然り。 例えば、ヘルプのサンプル逆引きにあるgroupbox.hspで使われている 「sendmsg objinfo_hwnd(2), $f4, 7, 0」の$f4がメッセージ部分ですが、 何をしているのか、何を意味しているのかコメントすらないしサッパリ理解できません…。 $f4とはC言語等で利用できるコード定数名で書くとBM_SETSTYLEのことで、 オブジェクトのスタイルを変更する時に送信するメッセージになります。 この時の追加情報がどのように変更するかを示す部分になり、をコード定数名にするとBS_GROUPBOX。 「オブジェクトのスタイルをグループボックスに変更するよ」という意味のメッセージになっているワケです。 このように解説されていると、ある程度は「あぁ、なるほど」と理解されるかもしれませんが、 「じゃあ、ラジオボタンや3ステートチェックボックスの時はどう書くの?」となりますね。 昔は分厚い書籍を引っ張り出してきて、アレでもないコレでもないと探すしかなかったのですが、 今はネットで検索すれば簡単に探し出すことができるほど便利な時代になりましたから、 「ボタンをラジオボタンに変えるわけだから、『BM_SETSTYLE』と『ラジオボタン』がキーだな」と、 ソレら2つをキーワードに検索するとソレらしきコード定数名BS_AUTORADIOBUTTONがヒットします。 そのページにBS_AUTORADIOBUTTONのコード値が載ってなければ、 再度サーチエンジンで「『BS_AUTORADIOBUTTON』と『define』」等をキーワードに検索してみてください。 コチラでも載せてますがBS_AUTORADIOBUTTONとコード値がであることが分かると思います。 これらの情報を元にしてプログラムを組むと次のようになるでしょう。
 1
 2
 3
 4
 5
 6
 7
 8
 9
	objsize 100, 20
	repeat 3, 1
		button gosub "Radio Test" + cnt, *push
		sendmsg objinfo_hwnd(stat), $F4, $9 // 配置したボタンをラジオボタンスタイルに変更
	loop
	stop

*push
	return
実際に上記のスクリプトを動かしてみると、 ラジオボタンが3つ配置されて、1つを選択すると別の選択が解除される。 思ってた通りの動きになっていますね。 sendmsg命令のプログラムを組む時はこんな感じで、 全てを覚えておくことは不可能に近いので検索しながら組むことになることでしょう。 ちなみに、メッセージコードに指定するBM_SETSTYLEの先頭部分のBMとはButtonMessageの略で、 ボタンメッセージにはスタイルを変更するBM_SETSTYLE(=$F4)の他に、 現在のチェック状態を取得するBM_GETCHECK(=$F0)、 チェック状態を設定するBM_SETCHECK(=$F1)、 現在の状態を取得するBM_GETSTATE(=$F2)、 状態を設定するBM_SETSTATE(=$F3)、 ボタンクリックを擬似的に実現するBM_CLICK(=$F5)、 関連付けられたイメージハンドルを取得するBM_GETIMAGE(=$F6)、 イメージをボタンに関連付けるBM_SETIMAGE(=$F7) このようなものが用意されています。 同様に追加情報に指定するBS_AUTORADIOBUTTONの先頭部分のBSとはButtonStyleの略で、 自動制御型のラジオボタンスタイルに変更するBS_AUTORADIOBUTTON(=$9)の他に、 通常のボタンスタイルのBS_PUSHBUTTON(=$0)、 エンターキーでも押すことができるデフォルトボタンスタイルのBS_DEFPUSHBUTTON(=$1)、 チェックボックススタイルに変更するBS_CHECKBOX(=$2)、 自動制御型のチェックボックススタイルに変更するBS_AUTOCHECKBOX(=$3)、 ラジオボタンスタイルに変更するBS_RADIOBUTTON(=$4)、 3ステートチェックボックススタイルに変更するBS_3STATE(=$5)、 自動制御型の3ステートチェックボックススタイルに変更するBS_AUTO3STATE(=$6)、 グループボックススタイルに変更するBS_GROUPBOX(=$7)、 ボタンにアイコン貼付対応可能スタイルに変更するBS_ICON(=$40)、 ボタンにビットマップ貼付対応可能スタイルに変更するBS_BITMAP(=$80)、 テキストの横位置を左端表示スタイルに変更するBS_LEFT(=$100)、 テキストの横位置を右端表示スタイルに変更するBS_RIGHT(=$200)、 テキストの横位置を中央表示スタイルに変更するBS_CENTER(=$300)、 テキストの縦位置を上端表示スタイルに変更するBS_TOP(=$400)、 テキストの縦位置を下端表示スタイルに変更するBS_BOTTOM(=$800)、 テキストの縦位置を中央表示スタイルに変更するBS_VCENTER(=$C00)、 テキストを複数行表示可能スタイルに変更するBS_MULTILINE(=$2000)、 トグルボタンスタイルに変更するBS_PUSHLIKE(=$1000)、 立体感のないスタイルに変更するBS_FLAT(=$8000) このように、スタイル変更だけでも数多く用意されています。 ボタンだけでもこんなに色々とあるのに、 リスト系オブジェクトやエディット系オブジェクトにも別のメッセージが色々と用意されています。 気になる方は調べてみると、「こんなこともできるのか」と、その可能性に驚くかもしれません。 自分なりに色々調べてみると面白いかもしれませんね。