|
|
|
2015/4/8(Wed) 21:07:34|NO.68455
リストビューの文字列を50音順にしたいのですが
どうすればいいのかわかりません。
色々調べてみたものの答えにつながるようなものがありませんので教えて頂きたいです。
【文字】【数字】を押せば50音順になるようなものを作りたいです。
以下がリストビューのソースになります。
よろしくお願いします。
;【HSP3.x 移植版】
;『HSPの裏技』リストビューを作成してみる ACT-2
; http://chokuto.ifdef.jp/urawaza/listview2.html
#module ;============= リストビュー操作モジュール ===============
#uselib "comctl32.dll"
#func InitCommonControlsEx "InitCommonControlsEx" int
; 各種定数定義
#define ICC_LISTVIEW_CLASSES 4
#define WS_CHILD 0x40000000
#define WS_VISIBLE 0x10000000
#define LVS_REPORT 0x0001
#define LVM_SETITEM 0x1006
#define LVM_INSERTITEM 0x1007
#define LVM_DELETEITEM 0x1008
#define LVM_INSERTCOLUMN 0x101B
#define LVM_GETNEXTITEM 0x100C
#define LVM_GETITEMTEXT 0x102D
#define LVCF_FMT 0x0001
#define LVCF_WIDTH 0x0002
#define LVCF_TEXT 0x0004
#define LVCF_SUBITEM 0x0008
#define LVIF_TEXT 0x0001
#define LVNI_SELECTED 0x0002
; (外部から参照できるように global 指定)
#define global LVCFMT_LEFT 0x0000
#define global LVCFMT_RIGHT 0x0001
#define global LVCFMT_CENTER 0x0002
; リストビュー作成
#deffunc CreateListView int sx, int sy
; コモンコントロールライブラリの初期化
initinfo = 8, ICC_LISTVIEW_CLASSES
InitCommonControlsEx varptr(initinfo)
; リストビューの作成
styleFlags = WS_CHILD | WS_VISIBLE | LVS_REPORT
winobj "SysListView32", "", 0, styleFlags, sx, sy
return
; リストビューに列を追加
#deffunc InsertListViewColumn int objID, int index, str text, int align, int pixels
textbuf = text
; LVCOLUMN 構造体をセット
dim lvcolumn, 8
lvcolumn(0) = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM
lvcolumn(1) = align
lvcolumn(2) = pixels
lvcolumn(3) = varptr(textbuf)
; LVM_INSERTCOLUMN メッセージ送信
sendmsg objinfo_hwnd(objID), LVM_INSERTCOLUMN, index, varptr(lvcolumn)
return
; リストビューに項目追加
#deffunc InsertListViewItem int objID, int index, str text
textbuf = text
; LVITEM 構造体をセット
dim lvitem, 13
lvitem(0) = LVIF_TEXT
lvitem(1) = index
lvitem(5) = varptr(textbuf)
; LVM_INSERTITEM メッセージ送信
sendmsg objinfo_hwnd(objID), LVM_INSERTITEM, 0, varptr(lvitem)
return
; リストビューの項目またはサブ項目テキスト設定
#deffunc SetListViewItemText int objID, int index, int subitem, str text
textbuf = text
; LVITEM 構造体をセット
dim lvitem, 13
lvitem(0) = LVIF_TEXT
lvitem(1) = index
lvitem(2) = subitem
lvitem(5) = varptr(textbuf)
; LVM_SETITEM メッセージ送信
sendmsg objinfo_hwnd(objID), LVM_SETITEM, 0, varptr(lvitem)
return
; リストビューの項目またはサブ項目テキスト取得
#defcfunc GetListViewItemText int objID, int index, int subitem
; LVITEM 構造体をセット
dim lvitem, 13
lvitem(2) = subitem
textbufsize = 256
; 取得できるまでバッファサイズを拡張
repeat
sdim textbuf, textbufsize
lvitem(5) = varptr(textbuf)
lvitem(6) = textbufsize
; LVM_GETITEMTEXT メッセージ送信
sendmsg objinfo_hwnd(objID), LVM_GETITEMTEXT, index, varptr(lvitem)
if stat < textbufsize - 1 : break
textbufsize *= 2
loop
return textbuf
; リストビューの項目削除
#deffunc DeleteListViewItem int objID, int index
; LVM_DELETEITEM メッセージ送信
sendmsg objinfo_hwnd(objID), LVM_DELETEITEM, index, 0
return
; リストビューの選択項目のインデックス取得
#defcfunc GetSelectedListViewItem int objID, int startIndex
; LVM_GETNEXTITEM メッセージ送信
sendmsg objinfo_hwnd(objID), LVM_GETNEXTITEM, startIndex, LVNI_SELECTED
return stat
#global ;================= モジュール終わり =====================
objsize ginfo_winx / 2, 25
pos 0, 0
button gosub "選択項目の情報表示", *OnShowInfoButtonClicked
pos ginfo_winx / 2, 0
button gosub "選択項目削除", *OnDeleteButtonClicked
pos 0, 25
CreateListView ginfo_winx, ginfo_winy
listviewID = stat
InsertListViewColumn listviewID, 0, "文字", LVCFMT_LEFT, 100
InsertListViewColumn listviewID, 1, "数字", LVCFMT_LEFT, 200
InsertListViewItem listviewID, 0, "さしすせそ"
SetListViewItemText listviewID, 0, 1, "121"
InsertListViewItem listviewID, 1, "あいうえお"
SetListViewItemText listviewID, 1, 1, "5"
InsertListViewItem listviewID, 2, "ああうえお"
SetListViewItemText listviewID, 2, 1, "32"
InsertListViewItem listviewID, 3, "かきくけこ"
SetListViewItemText listviewID, 3, 1, "4231"
InsertListViewItem listviewID, 4, "はひふへほ"
SetListViewItemText listviewID, 4, 1, "87"
InsertListViewItem listviewID, 5, "なにぬねの"
SetListViewItemText listviewID, 5, 1, "0"
stop
*OnShowInfoButtonClicked
; 選択されている項目の情報を表示
; (複数項目が選択されている場合があるので繰り返す)
index = -1
repeat
index = GetSelectedListViewItem(listviewID, index)
if index == -1 : break
name = GetListViewItemText(listviewID, index, 0)
reading = GetListViewItemText(listviewID, index, 1)
message = "Index: " + index + "\nName: " + name + "\nReading: " + reading
dialog message, 0, "情報表示"
loop
return
*OnDeleteButtonClicked
; 選択されている項目をリストビューから削除
; (複数項目が選択されている場合があるので繰り返す)
index = -1
repeat
index = GetSelectedListViewItem(listviewID, index)
if index == -1 : break
DeleteListViewItem listviewID, index
index-- ; アイテム削除によるインデックスのずれを補正
loop
return
| |
|
2015/4/8(Wed) 22:56:09|NO.68459
> リストビューの文字列を50音順にしたいのですが
> どうすればいいのかわかりません。
C/C++言語ならばコールバック関数を利用できるため可能です。
しかし、HSPは基本的にコールバック関数を使えません。
よって、普通に考えると不可能という回答ですが、
この掲示板では凄腕の方がおり、過去ログで
コールバック関数を使えるモジュールを公開してました。(過去ログ探してね)
> 色々調べてみたものの答えにつながるようなものがありませんので教えて頂きたいです。
HSPでの資料は皆無でしょうね。
|
|
2015/4/8(Wed) 23:03:56|NO.68460
リストビューってカラム名をクリックすれば自動でソートできるようになってませんでしたか?
手動でやるならsortvalとsortgetでアイテム名を変更するだけでいいと思います。
|
|
2015/4/9(Thu) 00:16:28|NO.68463
数字は数字の小さい順・・・大きい順・・・
sortvalとsortgetでやると
1と10と5だと
1,5,10にしたいのが1,10,5になってしまいますよねー
やはりHSPでは難しいのでしょうか・・・T_T
|
|
2015/4/9(Thu) 04:07:17|NO.68470
ソートに関しては以下のページが参考になります
http://rpen.blogspot.jp/2008/02/blog-post.html
LVM_SORTITEMSEXのlparamにコールバック関数のポインタを指定しなければならないため、標準命令のみでは不可能です
呼び出されたコールバック関数の第一引数と第二引数にはアイテムのインデックスがあり、第一アイテムを前に置きたければ負の値、第二アイテムを前に置きたければ正の値、同列であれば0を戻り値にします
奇妙の言い回しになっていますが、これは「大小の比較」を絶対に関数内でする必要は無いことからです
第三引数にはLVM_SORTITEMSEXのwparamの値が入ります。ただしグローバル変数が基本のHSPなので必要はありません
カラムのクリックについてはWM_NOTIFYのメッセージを処理します
#global ;================= モジュール終わり =====================
の次の行に
oncmd gosub *OnNotify, /*WM_NOTIFY*/0x4E
文末に
*OnNotify
dupptr NMHDR, lparam, 3*4
if(NMHDR(0) == objinfo_hwnd(listviewID) & (NMHDR(2) == /*LVN_COLUMNCLICK*/0xFFFFFF94)) {
dupptr NMLISTVIEW, lparam, 10*4
//NMLISTVIEW(4)にクリックされたカラムのインデックスの値があります
title strf("%s番目のカラムをクリック", NMLISTVIEW(4))
}
return
を追加してください
|
|
2015/4/10(Fri) 00:34:46|NO.68485
リストビュー研究中様
ありがとうございます。
まだカラムクリックでの順番変更等はできておりませんが
ボタン形式ではできました。
ありがとうございました
かなり大変な事をしようとしてるんだな。。と感じましたT_T
|
|
2015/4/11(Sat) 19:10:03|NO.68501
解決していますが
こんなモジュールを作成してみました
#module
//各種定数
#define WM_NOTIFY 0x0000004E
#deffunc AutoSort int ObjID
hListview = objinfo_hwnd(ObjID)
oncmd gosub *OnNotify, WM_NOTIFY
return
//WM_NOTIFYが届いたときのサブルーチン
*OnNotify
NotifyProc lparam, hListview//lparamとリストビューのハンドルを引数に命令を呼び出す
return
#global
#module
//各種定数
#define LVN_COLUMNCLICK 0xFFFFFF94
#define LVM_GETCOLUMN 0x00001019
#define LVCF_FMT 0x00000001
#define LVM_GETHEADER 0x0000101F
#define HDM_GETITEMCOUNT 0x00001200
#define LVM_SETCOLUMN 0x0000101A
#define LVM_SORTITEMSEX 0x00001051
#define LVM_GETITEMTEXT 0x0000102D
#define HDF_SORTUP 0x00000400
#define HDF_SORTDOWN 0x00000200
//WM_NOTIFYの通知メッセージを処理する命令
#deffunc NotifyProc int _lparam, int hListview, local NMHDR, local NMLISTVIEW
//NMHDR 構造体の割り当て
dupptr NMHDR, _lparam, 3*4
//通知メッセージがリストビューからでなければ戻る
if(NMHDR(0) != hListview) : return 0
//通知メッセージにより処理を分岐
switch NMHDR(2)
case LVN_COLUMNCLICK
dupptr NMLISTVIEW, _lparam, 10*4
//NMLISTVIEW(4)にクリックされたカラムのインデックスの値があるので、そのカラムを指定してソート命令を呼び出す。カラムの昇順降順マークでソートの方向を判断している
SortItem hListview, NMLISTVIEW(4), (GetSortMark(hListview, NMLISTVIEW(4)) == HDF_SORTDOWN)
swbreak
swend
return 0
//カラムの昇順降順マークを取得する関数
#defcfunc GetSortMark int hListview, int Index, local LVCOLUMN
dim LVCOLUMN, 11
LVCOLUMN(0) = LVCF_FMT //この定数を設定するとカラムの状態を取得できる
sendmsg hListview, LVM_GETCOLUMN, Index, varptr(LVCOLUMN) //カラムの状態を取得
return LVCOLUMN(1) & (HDF_SORTUP | HDF_SORTDOWN) //カラムの状態から昇順降順マークの部分だけ抜き出す
//カラムの昇順降順マークを設定する命令
#deffunc SetSortMark int hListview, int Index, local LVCOLUMN, local BeforeMark
dim LVCOLUMN, 11
LVCOLUMN(0) = LVCF_FMT //この定数を設定するとカラムの状態を取得できる
//カラム数だけ繰り返しの処理をしたいが、リストビューから直接取得できない。ヘッダから取得する
sendmsg hListview, LVM_GETHEADER //ヘッダのハンドルを取得
sendmsg stat, HDM_GETITEMCOUNT //ヘッダのアイテム数 = リストビューのカラム数を取得
//カラムの昇順降順マークを削除しつつ、指定のカラムにマークを付ける
repeat stat //カラム数だけ繰り返す
sendmsg hListview, LVM_GETCOLUMN, cnt, varptr(LVCOLUMN) //カラムの状態を取得
BeforeMark = LVCOLUMN(1) & (HDF_SORTDOWN | HDF_SORTUP) //現在の昇順降順マークを取得
LVCOLUMN(1) = LVCOLUMN(1) & (BeforeMark ^ 0xFFFFFFFF) //昇順降順マークを消す
if(cnt == Index) { //指定されたカラムのインデックスならば
if(BeforeMark) { //以前に昇順降順マークがあれば
LVCOLUMN(1) = LVCOLUMN(1) | ((HDF_SORTDOWN | HDF_SORTUP) ^ BeforeMark) //それを反転させた方向のマークを追加
} else { //昇順降順マークが無ければ
LVCOLUMN(1) = LVCOLUMN(1) | HDF_SORTDOWN //降順マークを自動で追加
}
}
sendmsg hListview, LVM_SETCOLUMN, cnt, varptr(LVCOLUMN) //カラムの状態を上書き
loop
return
//クリックされたカラムをソートする命令
#deffunc SortItem int hListview, int SortColumn, int SortMode, local prm, local TextBuf
//比較用のコールバック関数を作成していなければ作成
if(pCompareItemFunc == 0) : newclbk3 pCompareItemFunc, 3, *CompareItemFunc
//コールバック関数を呼び出してアイテムを並べ替え。wparamにはコールバック関数の第三引数を指定できるがHSPでは不要
sendmsg hListview, LVM_SORTITEMSEX, 0, pCompareItemFunc
//カラムに昇順降順マークを付ける
SetSortMark hListview, SortColumn
return
//アイテム比較用コールバック関数
*CompareItemFunc
//関数の引数を取得
clbkargprotect prm
//アイテムの文字列が格納される変数
sdim TextBuf, 64, 2
//比較する二つのアイテムの文字列を取得
TextBuf(0) = GetItemText(hListview, prm(0), SortColumn)
TextBuf(1) = GetItemText(hListview, prm(1), SortColumn)
//二つのアイテム共に先頭文字が半角数字ならば整数型に変換して比較。文字列で比較すると"1"と"2"と"11"では並びが"1,11,2"となってしまう
if( (48 <= peek(TextBuf(0),0) & (peek(TextBuf(0),0) <= 57)) & (48 <= peek(TextBuf(1),0) & (peek(TextBuf(1),0) <= 57)) ) {
return int(TextBuf(SortMode & 1)) - int(TextBuf((SortMode & 1) ^ 1))
}
return TextBuf(SortMode & 1) ! TextBuf((SortMode & 1) ^ 1)
//アイテムの文字列を取得する関数
#defcfunc GetItemText int hListview, int Index, int iSubItem, local LVITEM, local cchTextMax, local pszText
//LVITEM 構造体をセット
dim LVITEM, 13
LVITEM(2) = iSubItem
cchTextMax = 32
//取得できるまでバッファサイズを拡張
do
cchTextMax *= 2
sdim pszText, cchTextMax
LVITEM(5) = varptr(pszText)
LVITEM(6) = cchTextMax
//文字列取得
sendmsg hListview, LVM_GETITEMTEXT, Index, varptr(LVITEM)
until (stat < cchTextMax-1)
return pszText
#global
使用方法ですが
こちらのコールバック関数モジュールを必ずこのモジュールの前に記述してください
http://hsp.tv/play/pforum.php?mode=all&num=62130
そしてリストビューの作成後に
AutoSort リストビューのオブジェクトID
と記述するだけで、カラムをクリックするとソートされるようになります
手抜きの部分も幾つかありますが、ソースを読んで処理を理解して、改良していってみてください
| |
|
2015/4/12(Sun) 21:43:32|NO.68523
リストビュー研究中様
こんなに長いソースを作っていただいて大変お世話かけると同時に
とても嬉しいです
ありがとうございます
一応自分なりにカラムをクリックで変更できるまでに至りました!
ありがとうございました
完全に解決しました^^
|
|