HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0408
可憐リストビューを50音順に表示したい8解決


可憐

リンク

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での資料は皆無でしょうね。



ht_ask

リンク

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



ht_ask

リンク

2015/4/9(Thu) 00:37:22|NO.68464

そういうことでしたらsortvalの前にstrfでゼロ埋めを行っておくという手がありますが、
なんにせよ、GUI上のソート処理に割り込むには科学太郎さんがおっしゃったように
ソート用の比較関数をコールバックさせる必要がありますね。
http://www.kumei.ne.jp/c_lang/sdk2/sdk_110.htm



リストビュー研究中

リンク

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

リストビュー研究中様

こんなに長いソースを作っていただいて大変お世話かけると同時に
とても嬉しいです
ありがとうございます
一応自分なりにカラムをクリックで変更できるまでに至りました!
ありがとうございました
完全に解決しました^^



ONION software Copyright 1997-2023(c) All rights reserved.