Last Update : 2009/04/xx
listbox命令で設置できるリストボックスオブジェクト。このページでは発展的なHSP3向けのサンプルスクリプトを掲載しています。基礎的な説明は、listbox命令の解説を参照。
リストボックスについての詳細な説明として、Delphi言語向けですがHalbow資料館さんの該当ページをチェック!
listbox命令の第3パラメータに項目として表示する文字列をあらかじめ指定しておきますが、設置後の文字列追加や削除を行うには、objprm命令を利用して項目全体を変更する方法が1つ。ここではsendmsg命令でいじってみます。
// リストボックス項目追加&削除サンプル (by Kpan) objsize 150 listbox a, 60, "ああ\nかか\nささ\nたた\nなな\nはは" ; リストボックスのウィンドウハンドル取得 hListbox = objinfo(stat, 2) button "追加", *add_item button "挿入", *ins_item button "削除", *del_item stop *add_item ; 最後部に項目を追加します。(LB_ADDSTRING) ; 第4パラ(lparam値)に追加する文字列を指定。 sendmsg hListbox, $180, , "★最後部に追加" stop *ins_item ; 現在選択中のインデックス番号を取得。(LB_GETCURSEL) ; statに選択状態のインデックス番号(0〜)が返ります。 sendmsg hListbox, $188 ; 特定位置に項目に挿入します。(LB_INSERTSTRING) ; 第3パラのwparam値に挿入するインデックス番号(0〜)を指定。 ; ここでは選択している項目の真下に挿入されます。 sendmsg hListbox, $181, stat + 1, "●特定項目に挿入" stop *del_item sendmsg hListbox, $188 ; 特定の項目を削除します。(LB_DELETESTRING) ; 第3パラのwparam値に削除するインデックス番号(0〜)を指定。 ; 全項目削除ならobjprm命令(第2パラ空欄) sendmsg hListbox, $182, stat stop
ちなみに、複数個の項目を一気に追加したい場合は、項目数分のsendmsg命令を繰り返すことになります。
上の項目追加の実践編といったところ? リストボックス内にファイル(フォルダも可)をドラッグ&ドロップして、ファイルのパスを項目として追加なサンプルソースです。
ファイルのドラッグ&ドロップ処理自体については、HSP付属のサンプル「sample\new\dragdrop.hsp」(HSP 3.2〜では「sample\misc\dragdrop.hsp」)や、ちょくとさんの該当ページを参照あれー。なお、このサンプルでは、ドラッグファイル数は1つしか想定してません。
// リストボックスにファイルをD&Dサンプルソース (by Kpan) #include "shell32.as" ; ファイルがドロップされた時 (WM_DROPFILES) oncmd gosub *dropfiles, $233 ; ファイルパス文字列用領域をあらかじめ確保 sdim filepath, 512 objsize 400 listbox a, , "" hListbox = objinfo(stat, 2) ; リストボックスにファイルドロップ受け入れ許可 DragAcceptFiles hListbox, 1 stop *dropfiles ; ドロップされたファイルパスを取得 ; (ここではfilepathという変数にファイルパスが返ってきます。 DragQueryFile wparam, 0, varptr(filepath), 512 ; ドロップされたファイル情報を開放 DragFinish wparam ; ファイルパスを項目として追加 (LB_ADDSTRING) sendmsg hListbox, $180, , filepath return
もし、リストボックスが複数ある場合は、ファイルがドラッグ&ドロップされた時のマウス座標位置を元に、真下にあるオブジェクトのハンドルを取得するWindowFromPoint関数を利用してテキトーに振り分けます。
// 複数個のリストボックスにファイルをD&Dサンプルソース (by Kpan) // (注) エディタの[HSP]メニュー→[HSP拡張マクロを使用する]を要有効。 #include "shell32.as" #include "user32.as" oncmd gosub *dropfiles, $233 sdim filepath, 512 objsize 400 listbox a, , "" hListbox.0 = objinfo(stat, 2) DragAcceptFiles hListbox.0, 1 listbox b, , "" hListbox.1 = objinfo(stat, 2) DragAcceptFiles hListbox.1, 1 stop *dropfiles DragQueryFile wparam, 0, varptr(filepath), 512 DragFinish wparam ; カーソル位置の真下にあるウィンドウ(オブジェクト)のハンドル取得 ; statにハンドルが返る WindowFromPoint ginfo(0), ginfo(1) if stat = hListbox.0 { sendmsg hListbox.0, $180, , filepath return } if stat = hListbox.1 { sendmsg hListbox.1, $180, , filepath return } return
リストボックスは、第1パラメータの変数を確認することで選択しているインデックス番号(0〜)を取得できます。これをリアルタイムで監視するには、HSP2の場合、スクリプト内でループさせてこの変数を動きをチェックする手段をとったでしょうが、HSP3からはoncmd命令のお世話になりましょう。
具体的には、リストボックスに変化があるとウィンドウメッセージ「WM_COMMAND」が通知されます。これを利用すれば、普通の選択(シングルクリック)とともに、ダブルクリック判定も可能です。ちなみに、コンボボックス(combox命令)も同じ感じです。
// リストボックス監視サンプル (by Kpan) // 普通の選択の場合 #define ctype HIWORD(%1) (%1 >> 16 & $FFFF) ; WM_COMMAND oncmd gosub *command, $111 objsize 100 listbox a, 60, "胡瓜\n林檎\n人参\n葡萄\n茄子\n南瓜\n玉葱" hListbox = objinfo(stat, 2) stop *command ; lparamにはオブジェクトのウィンドウハンドルが返る if lparam = hListbox { ; wparamの上位ワードに通知コードが返る ; 通知コード1の場合は選択状態変化 (LBN_SELCHANGE) if HIWORD(wparam) = 1 { ; 現在選択中のインデックス番号取得 (LB_GETCURSEL) ; (変数aは利用しません) sendmsg hListbox, $188 title "インデックス番号: "+stat return } return } return
// リストボックス監視サンプル (by Kpan) // マウスのダブルクリックの場合 #define ctype HIWORD(%1) (%1 >> 16 & $FFFF) ; WM_COMMAND oncmd gosub *command, $111 objsize 100 listbox a, 60, "亜米利加\n印度\n希臘\n独逸\n西班牙\n露西亜\n日本" hListbox = objinfo(stat, 2) stop *command if lparam = hListbox { ; 通知コード2の場合はマウスのダブルクリック (LBN_DBLCLK) if HIWORD(wparam) = 2 : dialog "インデックス番号: "+a return } return
sendmsg命令を利用して特定項目の文字列を取得するサンプルコードです。(HSPのnote系命令を使わない方法
// リストボックス項目文字列取得サンプル (by Kpan) ; 文字列が返る変数用の領域をあらかじめ確保 sdim listbox_text objsize 100 listbox a, 60, "蟷螂\n甲虫\n蟋蟀\n蜻蛉\n飛蝗\n蜘蛛" hListbox = objinfo(stat, 2) button "こんちゅう", *check stop *check ; 特定の項目の文字列を取得 (LB_GETTEXT) ; 第3パラのwparam値にインデックス番号(0〜)、 ; 第4パラのlparam値に取得した文字列を入れる変数ポインタを指定 sendmsg hListbox, $189, a, varptr(listbox_text) mes ""+listbox_text
リストボックスの項目を選択するには、マウスの場合に当然ながら左クリックですが、逆に右クリックによる選択を実現するサンプルスクリプトです。マウスの位置から選択インデックスを取得するLBItemFromPt関数を利用します。
左クリックで可能なものをわざわざ右クリックで行えるようにする必要性はないですが、たとえばポップアップメニューを表示するとか、項目を削除するとか、右クリック専用の特別な処理に応用できるかと思います。
// リストボックスの右クリック項目選択 (by Kpan) // !エディタの[HSP]→[HSP拡張マクロを使用する]を要有効 #include "comctl32.as" ; WM_CONTEXTMENUメッセージ ; (ウィンドウ上で右クリックした時、正確にはクリックボタンを離した時) oncmd gosub *contextmenu, $7B listbox a, , "HSP\nリストボックス\nアイテム\n右クリック\nサンプル" hListbox = objinfo(stat, 2) stop *contextmenu ; wparamにリストボックスのハンドル if wparam = hListbox { ; ポインタ位置からインデックス番号がstatに返る LBItemFromPt wparam, ginfo(0), ginfo(1), 0 title "インデックス番号: "+stat ; 項目選択 objprm 0, stat return } return
リストボックスで選択した項目を上下に移動するサンプルです。(HSPのnote系命令+objprm命令を利用しない方法
1発のsendmsg命令で入れ替えてくれる処理は存在しません。上のトピックスで登場した、(1)選択項目のインデックス番号取得、(2)その項目の文字列取得、(3)その項目削除、(4)取得した文字列を元に新たに項目挿入、(5)項目を選択状態に変更、というような作業を1つ1つ地味〜に行っていきます。ちなみに、(5)の項目選択は、sendmsg命令を使わないでobjprm命令で済ますことも可能。
// リストボックス項目文字列入れ替えサンプル (by Kpan) ; 項目文字列取得用に確保 sdim listbox_text pos 50, 50 listbox a, 60, "1. あー\n2. いー\n3. うー\n4. えー\n5. おー" hListbox = objinfo(stat, 2) pos 120, 65 button "上へ", *listup button "下へ", *listdown stop ; 上方向に入れ替え *listup ; 選択項目のインデックス番号取得 (LB_GETCURSEL) sendmsg hListbox, $188 if stat = 0 : stop ; 選択項目が先頭だった場合 index = stat ; 選択項目の文字列取得 (LB_GETTEXT) sendmsg hListbox, $189, index, varptr(listbox_text) ; 選択項目の削除 (LB_DELETESTRING) sendmsg hListbox, $182, index ; 選択項目の1つ上に取得した文字列を挿入 (LB_INSERTSTRING) sendmsg hListbox, $181, index - 1, listbox_text ; 項目の選択 (LB_SETCURSEL) ; 第3パラのwparam値にインデックス番号を指定 sendmsg hListbox, $186, index - 1 // objprm 0, index - 1 stop ; 下方向に入れ替え *listdown sendmsg hListbox, $188 if stat = 4 : stop ; 選択項目が最後部だった場合 index = stat sendmsg hListbox, $189, index, varptr(listbox_text) sendmsg hListbox, $182, index ; 選択項目の1つ下に取得した文字列を sendmsg hListbox, $181, index + 1, listbox_text sendmsg hListbox, $186, index + 1 // objprm 0, index + 1 stop
リストボックス内にある項目文字列の表示色を変更します。HSP3から登場したoncmd命令で、それなりに手軽に実装できます。なお、背景部分の色を変更する処理は用意していないので、デフォルト環境では白色になります。
// リストボックス文字色変更サンプルソース (by Kpan) #include "gdi32.as" #include "user32.as" ; RGBマクロ #define ctype RGB(%1,%2,%3) (%1 | %2 << 8 | %3 << 16) objsize 100 listbox a, , "赤\nレッド\nあか" hListbox.0 = objinfo(stat, 2) listbox b, , "青\nブルー\nあお" hListbox.1 = objinfo(stat, 2) ; ウィンドウ背景色のブラシを取得 (リストボックス自体の背景色用) GetSysColorBrush 5 hBrush = stat ; ウィンドウメッセージ (WM_CTLCOLORLISTBOX) oncmd gosub *ctlcolorlistbox, $134 stop *ctlcolorlistbox ; lparamにオブジェクトのウィンドウハンドルが返る if lparam = hListbox.0 { ; テキスト色 SetTextColor wparam, RGB($FF, $00, $00) ; テキスト部分背景色 (透過) SetBkMode wparam, 1 ; リストボックス自体の背景色ブラシを返す return hBrush } if lparam = hListbox.1 { SetTextColor wparam, RGB($00, $00, $FF) SetBkMode wparam, 1 return hBrush } return
ちなみに、項目別に異なる文字色を指定したい場合は「オーナードロー」という処理が必要です。リストボックスの項目描画をすべて自前で行わないといけないので、かなりメンドーなことになります。(参照、HSP開発wiki)
listbox命令で設置できるリストボックスは、複数の選択肢の中から1項目しか選択できません。複数個の項目を選択できるリストボックスを作成してみます。
で、作成するのに標準のlistbox命令は使えません。HSPのwinobj命令(今回のサンプル)や、Win32APIのCreateWindowEx関数を利用して、コントロールそのものを最初から作成する必要があります。
そして、項目の追加や、どの項目が選択されているか、項目の選択状態変更などの各制御にsendmsg命令を利用します。(上の項目追加や削除の説明を参照〜
// 複数選択可能なリストボックス表示サンプル (by Kpan) #include "gdi32.as" ; リストボックスオブジェクトを設置 ; 第2パラメータの $8 がポイント。これにより複数選択可能なリスト ; ボックスになります。あるいは $800 を指定した場合、Shiftキーや ; Ctrlキーを押しながらの複数選択可能リストボックスになります。 winobj "listbox", "", $200, $50200001 | $8, 100, 200 ; winobj "listbox", "", $200, $50200001 | $800, 100, 200 hListbox = objinfo(stat, 2) ; オブジェクト内の文字列用フォントを指定。 ; ここではsysfont命令の「デフォルトGUIフォント」相当が反映されます。 GetStockObject 17 sendmsg hListbox, $30, stat ; 項目の追加 (LB_ADDSTRING) ; 追加する項目数分、sendmsg命令を繰り返します。 repeat 10 sendmsg hListbox, $180, , "こうもく "+cnt+"" loop ; 特定項目の選択状態を変更する場合 (LB_SETSEL) ; (複数選択リストボックスのみ) ; 第3パラのwparam値に選択する(=1) or 選択はずす(=0) ; 第3パラのlparam値にインデックス番号(0〜)を指定 sendmsg hListbox, $185, 1, 3 sendmsg hListbox, $185, 1, 7 button "チェーック!", *check stop ; 選択されているインデックス番号の取得 ; インデックス番号を一挙に取得する処理は存在しないので、 ; 選択されているかを項目1つ1つ調べていきます。 *check ; 選択項目数の取得 (LB_GETSELCOUNT) ; statに選択状態の項目数が返ります。 sendmsg hListbox, $190 mes "選択項目数: "+stat+"コ" ; 項目数の取得 (LB_GETCOUNT) ; statにリストボックス内の項目数が返ります。 sendmsg hListbox, $18B repeat stat ; 特定項目が選択されているかどうかの確認 (LB_GETSEL) ; 第3パラのwparam値にインデックス番号(0〜)を指定 ; 選択項目の場合はstatに1が返ります。 sendmsg hListbox, $187, cnt if stat : mes " 選択項目: "+cnt loop stop
リストボックスコントロールには、項目文字列をソートする機能が用意されています。HSPのlistbox命令は、その機能が働くようにはなっていません。winobj命令でソート機能付きリストボックスを表示してみます。項目の追加や削除に標準のobjprm命令は使えないので、sendmsg命令を利用します。(英文字の半角/全角は区別せずソート?
// ソート機能付きリストボックス表示サンプル (by Kpan) #include "gdi32.as" ; ソート機能付きリストボックス ($2=LBS_SORT) winobj "listbox", "", $200, $50200001 | $2, 150, 100 hListbox = objinfo(stat, 2) ; sysfont命令「デフォルトGUIフォント」相当適用 GetStockObject 17 sendmsg hListbox, $30, stat sdim a pos 170, 40 input a, 100 button "追加", *add stop *add if a = "" : stop ; 項目追加 (LB_ADDSTRING) sendmsg hListbox, $180, , a ; 入力ボックスを空に objprm 1, ""
HSPのリストボックスは、第2パラの拡張Yサイズで指定された高さを超える項目数になると自動的に縦方向の垂直スクロールバーが表示されます。逆に横方向の水平スクロールバーは文字列の長さ(横幅)に関係なく表示されません。
これは全項目表示されるよう垂直スクロールバーは自動的に表示してくれるのに対して、水平スクロールバーにはそのような処理がないためです。自前で文字列の長さを調べて(GetTextExtentPoint32関数)、文字列の長さに合った水平スクロールバーを表示し、長さを調節してやらないといけません。このようなリストボックスを用意するにはlistbox命令は無理なので、winobj命令でコントロールそのものを最初から作成する必要があります。
そして、項目の追加やどの項目が選択されているかなどのさまざまな制御はHSPのsendmsg命令を利用します。
// リストボックスに水平スクロールバー表示サンプル (by Kpan) // (注) エディタの[HSP]メニュー→[HSP拡張マクロを使用する]を要有効。 #include "gdi32.as" ; リストボックスを設置。ウィンドウスタイルにスクロールバー表示指定。 ; 水平(WS_HSCROLL=$100000)、垂直(WS_VSCROLL=$200000) winobj "listbox", "", $200, $50000001 | $100000 | $200000, 100, 50 hListbox = objinfo(stat, 2) ; フォント設定 ; sysfont命令の「デフォルトGUIフォント」相当が適用されます。 GetStockObject 17 hFont = stat sendmsg hListbox, $30, hFont ; 追加する項目文字列をテキトーに ; 普通は後ろ部分が見れない「い」の長さに合った水平バーを表示 item = "あああああ", "いいいいいいいいいいいいいいいイ", "うう" ; SIZE構造体 dim SIZE, 2 ; 3ループさせて各項目追加 repeat 3 sendmsg hListbox, $180, , item(cnt) ; 文字列の横幅(ピクセル単位)を取得 SelectObject hdc, hFont GetTextExtentPoint32 hdc, item(cnt), strlen(item(cnt)), varptr(SIZE) ; 最も横幅のある文字列だったら、水平スクロールバーのサイズを調整。 if SIZE > maxSIZE { ; 水平スクロール可能範囲の指定 (LB_SETHORIZONTALEXTENT) ; 第3パラ(wparam値)にピクセル単位で幅を指定します。 ; 文字列の横幅+余裕を持たせてプラス3 sendmsg hListbox, $194, SIZE + 3 maxSIZE = SIZE } loop
リストボックスには、ドラッグリストボックスという拡張機能が用意されています。これは、項目文字列をマウスでドラッグ&ドロップすることで項目の入れ替えというのができるものです。サンプルスクリプトを公開しています。
ものすごいテキトーな処理の流れを書くと、普通のリストボックスをMakeDragList関数でドラッグリストボックス化、ドラッグ時の通知メッセージ(RegisterWindowMessage関数で「DRAGLISTMSGSTRING」)のDRAGLISTINFO構造体を見て色々と処理をしていきます。LBItemFromPt関数からマウスポインタのある項目インデックスを取得し、DrawInsert関数でコントロール脇に目印を付け、実際の項目の入れ替えはsendmsg命令を利用します。
<< オブジェクト 3 | HSP3 オブジェクト | オブジェクト 5 >>
Copyright © 2005-2012 Kpan. All rights reserved.