ツリービュー モジュール
絶賛準備中のコンテンツ
/*==================================================================================================
ツリービューモジュール(ControlObjectModule2.3号)
HSP3.31 2012.11.14 新規作成 (from 11.8結構かかったorz)
----------------------------------------------------------------------------------------------------
ツリービューをウィンドウに配置する
TreeView_Create 横幅, 縦幅, フラグ
フラグ + $1 親アイテムに[+][-]を付けない
+ $2 アイテムがチェックボックスを持つようにする
+ $4 アイテム同士を線でつなぐ
+ $8 マウスオーバーしているアイテムに下線を付ける
+ $10 ツリービューにフォーカスがないとき、選択アイテムのカーソルを消す
+ $20 アイテムが表示しきれていないとき、ツールチップを付ける
+ $40 行全体を選択可能とする($4線つなぎ指定時、無効)
+ $80 ルートアイテムに線や[+][-]を付けない
+$100 ツリービューの境界を表示しない
+$200 スクロール禁止(スクロールバーを表示しない)
stat HSPオブジェクトID
操作対象のツリービューを指定する
TreeView_Select HSPオブジェクトID
以降の操作命令は指定したツリービューに対しておこなわれる
TreeView_Create呼び出し時、作成したツリービューを操作先に変更する
ツリービューにアイテムを追加する
TreeView_InsertItem 項目名, 識別ID, 挿入位置指定, フラグ
項目名 ツリービューに表示されるアイテムの名前
識別ID アイテムを識別するためにユーザーがIDを指定できる 1以上のユニーク値が望ましい
挿入位置指定 追加位置を示すアイテムの識別ID(フラグで意味付けする)
フラグ 0〜7 挿入位置指定のアイテムとの関係
0:指定アイテムを親とする[一番下の位置]に追加する
1: [一番上の位置]
2: [ソートして ]
3:指定アイテムと同じグループの[一番下の位置 ]に追加する
4: [指定アイテムの直下]
5: [指定アイテムの直上]
6: [一番上の位置 ]
7: [ソートして ]
+ 8 アイテムに[+][-]を付ける
+16 アイテムのチェックボックスをチェックする
ツリービューの状態を取得する関数と、状態を変更する命令
TreeView_Info ( mode, 識別ID ) ;取得 識別IDとパラメタはmodeによっては
TreeView_State mode, 識別ID, パラメタ ;変更 無視される
┏━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓
┃ mode ┃ TreeView_Infoの返値 ┃ TreeView_Stateのパラメタ ┃
┣━━━╋━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━┫
┃ 0 ┃選択アイテムの識別ID ┃指定アイテムを選択状態にする ┃
┃ ┃-1:選択アイテム無し ┃ ┃
┠───╂─────────────────╂─────────────────┨
┃ 1 ┃ ┃全アイテム消去 ┃
┠───╂─────────────────╂─────────────────┨
┃ 2 ┃ ┃指定アイテムを消去 ┃
┠───╂─────────────────╂─────────────────┨
┃ 3 ┃ 0:子アイテムを展開していない ┃ 0:子アイテムを収納する ┃
┃ ┃ 1:子アイテムを展開している ┃ 1:子アイテムを展開する ┃
┠───╂─────────────────╂─────────────────┨
┃ 4 ┃-1:チェックボックスが無い ┃-1:チェックボックスを除去する ┃
┃ ┃ 0:チェックはついていない ┃ 0:チェックをはずす ┃
┃ ┃ 1:チェックされている ┃ 1:チェックする ┃
┠───╂─────────────────╂─────────────────┨
┃ 5 ┃ツリービューの持つアイテムの総数 ┃ ┃
┠───╂─────────────────╂─────────────────┨
┃ 6 ┃一度に表示できるアイテムの数 ┃指定アイテムを表示する ┃
┗━━━┻━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━┛
----------------------------------------------------------------------------------------------------
チェックボックス関係は一呼吸置かないと無視されるorz...Createの後にawait 0やdialogなどで処理時間を
挟むこと。
現在フォーカスを持っているツリービューを判別するにはobjsel -1を使う。
ガチで作るとマジでキレそうになるのでいろいろ(特にエラー処理)を省いている。使うときは留意する。
==================================================================================================*/
#ifndef TreeViewModuleIncluded
#define TreeViewModuleIncluded
#module TreeViewModule
#uselib "comctl32.dll"
#func InitCommonControlsEx "InitCommonControlsEx" var ;特定のコモンコントロールを初期化
#define ICC_TREEVIEW_CLASSES $00000002 ;ツリービュー、ツールチップ
#define WS_CHILD $40000000 ;子ウィンドウ
#define WS_VISIBLE $10000000 ;見えるウィンドウ
#define WS_BORDER $00800000 ;境界線を持つウィンドウ
#define TVS_HASBUTTONS $0001 ;親アイテムの横に[+]や[-]を表示
#define TVS_HASLINES $0002 ;アイテムを線でつなぐ
#define TVS_LINESATROOT $0004 ;ルートアイテムも[+][-][線]付け対象にする
#define TVS_EDITLABELS $0008 ;ユーザーがアイテムのテキストを編集できる
#define TVS_DISABLEDRAGDROP $0010 ;親ウィンドウに TVN_BEGINDRAG メッセージを送らないように
#define TVS_SHOWSELALWAYS $0020 ;アイテムの選択状態を表示(フォーカスを持っていないとき)
#define TVS_RTLREADING $0040 ;v4.70:右から左に表示(アラビア語やヘブライ語)
#define TVS_NOTOOLTIPS $0080 ;v4.70:ツールチップを付けない
#define TVS_CHECKBOXES $0100 ;v4.70:アイテムにチェックボックスを付ける
#define TVS_TRACKSELECT $0200 ;v4.70:マウスカーソル下のアイテムに下線を付ける
#define TVS_SINGLEEXPAND $0400 ;v4.71:選択アイテムのみ展開
#define TVS_INFOTIP $0800 ;v4.71:親ウィンドウに TVN_GETINFOTIP メッセージを送る
#define TVS_FULLROWSELECT $1000 ;v4.71:アイテムを行全体で選択できるように
#define TVS_NOSCROLL $2000 ;v4.71:ツリービューがスクロールしないようにしる
#define TVS_NONEVENHEIGHT $4000 ;v4.71:アイテムの高さを設定できるように(TVM_SETITEMHEIGHT)
#define TV_FIRST $1100 ;TreeView messages
; http://msdn.microsoft.com/en-us/library/ff486106(v=vs.85).aspx
#define TVM_INSERTITEM (TV_FIRST+ 0) ;[編集]アイテム挿入
#define TVM_DELETEITEM (TV_FIRST+ 1) ;[編集]アイテム削除
#define TVM_EXPAND (TV_FIRST+ 2) ;[操作]子アイテムの展開と収納(TVE_xxx)
#define TVM_GETITEMRECT (TV_FIRST+ 4)
#define TVM_GETCOUNT (TV_FIRST+ 5) ;[取得]アイテム数を取得する
#define TVM_GETINDENT (TV_FIRST+ 6) ;[取得]インデント(pixel)
#define TVM_SETINDENT (TV_FIRST+ 7)
#define TVM_GETIMAGELIST (TV_FIRST+ 8)
#define TVM_SETIMAGELIST (TV_FIRST+ 9)
#define TVM_GETNEXTITEM (TV_FIRST+10) ;[取得]関係を持つアイテムのハンドル(TVGN_xxx)
#define TVM_SELECTITEM (TV_FIRST+11) ;[操作]特定アイテムを選択したり表示したり
#define TVM_GETITEM (TV_FIRST+12) ;[取得]アイテム属性
#define TVM_SETITEM (TV_FIRST+13) ;[変更]アイテム属性
#define TVM_EDITLABEL (TV_FIRST+14)
#define TVM_GETEDITCONTROL (TV_FIRST+15)
#define TVM_GETVISIBLECOUNT (TV_FIRST+16) ;[取得]完全に表示できるアイテムの数
#define TVM_HITTEST (TV_FIRST+17) ;指定した点の下になにがあるか(TV_HITTESTINFO,TVHT_xxx)
#define TVM_CREATEDRAGIMAGE (TV_FIRST+18)
#define TVM_SORTCHILDREN (TV_FIRST+19)
#define TVM_ENSUREVISIBLE (TV_FIRST+20)
#define TVM_SORTCHILDRENCB (TV_FIRST+21)
#define TVM_ENDEDITLABELNOW (TV_FIRST+22)
#define TVM_GETISEARCHSTRING (TV_FIRST+23)
#define TVM_SETTOOLTIPS (TV_FIRST+24)
#define TVM_GETTOOLTIPS (TV_FIRST+25)
#define TVM_SETINSERTMARK (TV_FIRST+26)
#define TVM_SETITEMHEIGHT (TV_FIRST+27)
#define TVM_GETITEMHEIGHT (TV_FIRST+28)
#define TVM_SETBKCOLOR (TV_FIRST+29)
#define TVM_SETTEXTCOLOR (TV_FIRST+30)
#define TVM_GETBKCOLOR (TV_FIRST+31)
#define TVM_GETTEXTCOLOR (TV_FIRST+32)
#define TVM_SETSCROLLTIME (TV_FIRST+33)
#define TVM_GETSCROLLTIME (TV_FIRST+34)
#define TVM_SETINSERTMARKCOLOR (TV_FIRST+37)
#define TVM_GETINSERTMARKCOLOR (TV_FIRST+38)
#define TVM_GETITEMSTATE (TV_FIRST+39)
#define TVM_SETLINECOLOR (TV_FIRST+40)
#define TVM_GETLINECOLOR (TV_FIRST+41)
#define TVM_MAPACCIDTOHTREEITEM (TV_FIRST+42)
#define TVM_MAPHTREEITEMTOACCID (TV_FIRST+43)
#define TVM_SETEXTENDEDSTYLE (TV_FIRST+44) ;sendmsg h, TV_FIRST+44, $2, $2
#define TVM_GETEXTENDEDSTYLE (TV_FIRST+45)
#define TVM_SETAUTOSCROLLINFO (TV_FIRST+59)
#define TVM_GETSELECTEDCOUNT (TV_FIRST+70)
#define TVM_SHOWINFOTIP (TV_FIRST+71)
#define TVM_GETITEMPARTRECT (TV_FIRST+72)
;アイテム追加位置指定
#define TVI_ROOT $FFFF0000 ;ルートアイテムとして追加
#define TVI_FIRST $FFFF0001 ;リストの最初の位置に挿入
#define TVI_LAST $FFFF0002 ;リストの最後の位置に挿入
#define TVI_SORT $FFFF0003 ;アルファベット順に挿入
#define TVGN_ROOT $0000 ;最初のアイテム
#define TVGN_NEXT $0001 ;指定アイテムの妹アイテム
#define TVGN_PREVIOUS $0002 ;指定アイテムの一つ上の姉アイテム
#define TVGN_PARENT $0003 ;指定アイテムの親アイテム
#define TVGN_CHILD $0004 ;指定アイテムの子アイテム
#define TVGN_FIRSTVISIBLE $0005
#define TVGN_NEXTVISIBLE $0006
#define TVGN_PREVIOUSVISIBLE $0007
#define TVGN_DROPHILITE $0008
#define TVGN_CARET $0009 ;現在選択されているアイテム
#define TVGN_LASTVISIBLE $000A
#define TVGN_NEXTSELECTED $000B
#define TVIF_TEXT $0001 ;pszText,cchTextMax
#define TVIF_IMAGE $0002 ;iImage
#define TVIF_PARAM $0004 ;lParam
#define TVIF_STATE $0008 ;state,stateMask
#define TVIF_HANDLE $0010 ;hItem
#define TVIF_SELECTEDIMAGE $0020 ;iSelectedImage
#define TVIF_CHILDREN $0040 ;cChildren
#define TVIF_INTEGRAL $0080 ;iIntegral
#define TVIF_STATEEX $0100
#define TVIF_EXPANDEDIMAGE $0200
#define TVIF_DI_SETITEM $1000
#define TVE_COLLAPSE $0001 ;崩壊wさせる ⇒ 閉じる
#define TVE_EXPAND $0002 ;拡大wさせる ⇒ 展開する
#define TVE_TOGGLE $0003 ;閉じていれば開き、開いていれば閉じる
#define TVE_EXPANDPARTIAL $4000 ;v4.70:部分展開(TVE_EXPAND と一緒に)
#define TVE_COLLAPSERESET $8000 ;崩壊&除去 (TVE_COLLAPSEと一緒に)
#deffunc TreeView_Create int w, int h, int f ;横幅, 縦幅, flag
IsInit ++ ;初期化フラグ(未初期化変数対策で呼び出し回数をカウントアップする方式)
if IsInit == 1 { ;但しコモンコントロールの初期化は必要か不明。
ib = 8, ICC_TreeView_Classes
InitCommonControlsEx ib ;とりあえずモジュールの初回呼び出し時に初期化する
if stat == 0 : return -1 ;初期化に失敗するなんて。
dim TvItemPlus, 2 + 11 ;TVINSERTSTRUCT+TVITEMX構造体
TvItemPtr = varptr(TvItemPlus) ;↑構造体のポインター
}
ib = WS_Child | WS_Visible | WS_Border
ib = TVS_LinesAtRoot | TVS_ShowSelAlways | TVS_NoToolTips | TVS_HasButtons | ib
; TVS_LinesAtRoot ルート項目をサブ項目と同じ扱いにする(通常は±や線を付けられない)
; TVS_ShowSelAlways フォーカスが無くても選択項目がわかるように
if f & $1 : ib = ib ^ TVS_HasButtons ;こもちの[+][-]
if f & $2 : ib = ib | TVS_CheckBoxes ;チェックボックスを付ける
if f & $4 : ib = ib | TVS_HasLines ;線でつなぐ
if f & $8 : ib = ib | TVS_TrackSelect ;マウスオーバーでアイテムに下線を付ける
if f & $10 : ib = ib ^ TVS_ShowSelAlways ;フォーカスがないとき選択ハイライトを消す
if f & $20 : ib = ib ^ TVS_NoToolTips ;アイテムがはみ出しているときツールチップを付ける
if f & $40 : ib = ib | TVS_FullRowSelect ;行全体をハイライトする(線つなぎの時、無効)
if f & $80 : ib = ib ^ TVS_LinesAtRoot ;ルート項目に線や±を付けない
if f & $100 : ib = ib ^ WS_Border ;オブジェクトの境界線(枠線)を消す
if f & $200 : ib = ib | TVS_NoScroll ;スクロール禁止
winobj "SysTreeView32", "", 0, ib, w, h : ib(1) = stat
CurTreeHandle = objinfo(ib(1), 2)
CurTreeCount = 0
return stat
#deffunc TreeView_Select int t
CurTreeHandle = objinfo(t, 2) ;オブジェクトハンドル
gosub *TreeView_UpdateHandleList
return
*TreeView_UpdateHandleList
;アイテムデリート後にも呼ぶ必要があったのでサブルーチンとして分離(↑オブジェIDが都合悪い)
sendmsg CurTreeHandle, TVM_GetCount ;現在のアイテム数
CurTreeCount = stat
if CurTreeCount <= 0 : return ;アイテムなければここまで。
CurTreeItem(CurTreeCount - 1) = 0 ;配列数自動確保
sendmsg CurTreeHandle, TVM_GetNextItem, TVGN_Root, 0
CurTreeItem(0) = stat ;いっこ目のアイテムのハンドル
ib = 1 ;新しいハンドルを代入するindex
repeat CurTreeCount ;イモ蔓式リストアップ
sendmsg CurTreeHandle, TVM_GetNextItem, TVGN_Next, CurTreeItem(cnt) ;次のアイテムある?
if stat : CurTreeItem(ib) = stat : ib ++
sendmsg CurTreeHandle, TVM_GetNextItem, TVGN_Child, CurTreeItem(cnt) ;アイテムを含んでる?
if stat : CurTreeItem(ib) = stat : ib ++
loop
return
#defcfunc TreeView_SearchHandleFromId int i
TvItemPlus = TVIF_Param, 0, 0, 0, 0, 0, 0, 0, 0, 0
ib = 0
repeat CurTreeCount
TvItemPlus(1) = CurTreeItem(cnt) ;ハンドルリスト全てに総当たり
sendmsg CurTreeHandle, TVM_GetItem, 0, TvItemPtr ;設定したIDは?
if TvItemPlus(9) == i : ib = CurTreeItem(cnt) : break ;これだっ!!
loop
return ib
#deffunc TreeView_InsertItem str s, int i, int p, int f ;ツリービューにアイテムを追加する
; s=追加するアイテムの文字列 i=アイテムに割り当てる識別ID p=追加位置を示すアイテムのID
; f=追加位置iD(p)との関係とオプションフラグ 0〜7:追加位置との関係 8〜:オプションフラグ
; 0:pを親とする末娘 1:pを親とする長女 2:pを親とするソート
; 3:pを姉とする末っ子 4:pを姉とするすぐ下 5:pを妹とするすぐ上 6:pを妹とする長女
; 7:pを姉妹とするソート +8:強制こもち +16:チェックボックスにチェック
ib = TreeView_SearchHandleFromId(p), 0, 0 ;ib(0) = 挿入位置として渡されたアイテムのハンドル
;ib(1) = 親アイテムとなるハンドル ib(2) = 位置指定値
if 0 <= (f & 7) & (f & 7) <= 2 { ;渡されたアイテムIDを親とする場合
if (f & 7) == 0 : ib(1) = ib, TVI_Last
if (f & 7) == 1 : ib(1) = ib, TVI_First
if (f & 7) == 2 : ib(1) = ib, TVI_Sort
}
if 3 <= (f & 7) & (f & 7) <= 7 { ;渡されたアイテムIDを姉妹とする場合
sendmsg CurTreeHandle, TVM_GetNextItem, TVGN_Parent, ib ;親のハンドルは?
ib(1) = stat
if (f & 7) == 3 : ib(2) = TVI_Last
if (f & 7) == 4 : ib(2) = ib
if (f & 7) == 5 {
sendmsg CurTreeHandle, TVM_GetNextItem, TVGN_Previous, ib
if stat : ib(2) = stat : else : ib(2) = TVI_First ;一番上の上にくる場合がある
}
if (f & 7) == 6 : ib(2) = TVI_First
if (f & 7) == 7 : ib(2) = TVI_Sort
}
TvItemPlus = TVIF_Children, ib(1), 0, 0, 0, 0, 0, 0, 1, 0 ;親となるアイテムが子を持てるように
sendmsg CurTreeHandle, TVM_SetItem, 0, TvItemPtr ; フラグをセットする
sb = s ;文字列のポインタが欲しい
TvItemPlus = ib(1), ib(2), TVIF_TEXT | TVIF_PARAM, 0, 0, 0, varptr(sb), strlen(sb), 0, 0, 0, i
if f & 8 { ;こもちアイテム
TvItemPlus( 2) = TvItemPlus(2) | TVIF_CHILDREN
TvItemPlus(10) = 1
}
if f & 16 { ;チェックボックスにチェック
TvItemPlus( 2) = TvItemPlus(2) | TVIF_State ; ツリービュー造った後一呼吸おかないと
TvItemPlus( 4) = TvItemPlus(4) | $2000 ; このフラグは反映されないようだorz...
TvItemPlus( 5) = TvItemPlus(5) | $F000
}
sendmsg CurTreeHandle, TVM_InsertItem, 0, TvItemPtr ;アイテム追加
if stat == 0 : return ;失敗
CurTreeItem(CurTreeCount) = stat ;ハンドルリストに追記
CurTreeCount ++
return
#defcfunc TreeView_Info int t, int i
ib = 0 ;最終的に関数が返す値をここに代入する
if t == 0 { ;キャレットを持つアイテムを取得
sendmsg CurTreeHandle, TVM_GetNextItem, TVGN_Caret, 0 ;キャレットを持つアイテムのハンドル
if stat { ;キャレットなしもあり得る
TvItemPlus = TVIF_Param, stat, 0, 0, 0, 0, 0, 0, 0, 0
sendmsg CurTreeHandle, TVM_GetItem, 0, TvItemPtr ;そのアイテムのIDを取得
ib = TvItemPlus(9)
} else : ib = -1 ;アクティブオブジェクトではない。
}
if t == 3 { ;娘アイテムを展開しているか
ib(1) = TreeView_SearchHandleFromId(i) ;IDをハンドルに変換する
TvItemPlus = TVIF_State, ib(1), $0000, $00FF, 0, 0, 0, 0, 0, 0
sendmsg CurTreeHandle, TVM_GetItem, 0, TvItemPtr ;アイテムの状態を取得
if TvItemPtr(2) & $20 : ib = 1 : else : ib = 0 ;$20 = TVIS_EXPANDED
}
if t == 4 { ;アイテムのチェックボックスの状態を取得
ib(1) = TreeView_SearchHandleFromId(i) ;IDをハンドルに変換する
TvItemPlus = TVIF_State, ib(1), 0, $F000, 0, 0, 0, 0, 0, 0
sendmsg CurTreeHandle, TVM_GetItem, 0, TvItemPtr ;アイテムの状態を取得
if (TvItemPlus(2) & $3000) == 0 : ib = -1 ;チェックボックス自体を持っていない
if TvItemPlus(2) & $1000 : ib = 0 ;チェックはついていない
if TvItemPlus(2) & $2000 : ib = 1 ;チェックがついている
}
if t == 5 { ;今ツリービューが持っているアイテムの総数を取得
sendmsg CurTreeHandle, TVM_GetCount
ib = stat
}
if t == 6 { ;ツリービューの領域で表示できるアイテムの最低数
sendmsg CurTreeHandle, TVM_GetVisibleCount
ib = stat
}
;if t == {} ;マウスの下のアイテム
return ib
#deffunc TreeView_State int t, int i, int p
ib = TreeView_SearchHandleFromId(i) ;大抵の操作はアイテムハンドルが必要なので先に取得しておく。
if t == 0 { ;指定のアイテムを選択状態にする(キャレットを移動する)
sendmsg CurTreeHandle, TVM_SelectItem, TVGN_Caret, ib
}
if t == 1 { ;全アイテム消去
sendmsg CurTreeHandle, TVM_DeleteItem, 0, TVI_Root
gosub *TreeView_UpdateHandleList ;ハンドルリスト更新(というかアイテム数0にすれば)
}
if t == 2 { ;1アイテム消去
;if ib == 0 : ;そのアイテムは既に存在しない
sendmsg CurTreeHandle, TVM_DeleteItem, 0, ib
gosub *TreeView_UpdateHandleList ;ハンドルリスト更新
}
if t == 3 { ;娘アイテムの展開or収納(見えていないときでも裏で)
if p == 0 : sendmsg CurTreeHandle, TVM_Expand, TVE_Collapse, ib ;娘アイテムを収納
if p == 1 : sendmsg CurTreeHandle, TVM_Expand, TVE_Expand, ib ;娘アイテムを展開
}
if t == 4 { ;アイテムのチェックボックス操作
TvItemPlus = TVIF_State, ib, $0000, $F000, 0, 0, 0, 0, 0, 0
if p == -1 : TvItemPlus(2) = $0000 ;チェックボックス自体を消去
if p == 0 : TvItemPlus(2) = $1000 ;チェックボックス有(チェックは無し)
if p == 1 : TvItemPlus(2) = $2000 ;チェックボックス有(チェック済み)
sendmsg CurTreeHandle, TVM_SetItem, 0, TvItemPtr
}
if t == 6 { ;指定アイテムを表示(画面内に表す)
sendmsg CurTreeHandle, TVM_SelectItem, TVGN_FirstVisible, ib
}
; if t == 10 {;アイテムソート
; ib = TreeView_SearchHandleFromId(v)
; sendmsg CurTreeHandle, TVM_SortChildren, 1, ib
; }
return
; http://www.tvg.ne.jp/menyukko/ ; Copyright(C) 2012-2013 衣日和 All rights reserved.
#global
#endif