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


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
0208
sinリストビューのソート(LVM_SORTITEMS)メッセージ2解決


sin

リンク

2008/2/8(Fri) 01:41:28|NO.13457


winobj "SysListView32","ListView",0,0x10000000|0x40000000|0x0001,x,y,0,0
で作成した詳細表示のリストビュー(ハンドルはhlist)にsendmsgで
LVM_SORTITEMS(0x1030)メッセージを送信してアイテムのソートを試みたのですが、


sendmsg hlist,0x1030,0,0
では一番左の列を基準に昇順ソートとなりました。

ここから降順ソートなどを行うため、wParamやlParamの値を弄ってみたのですが、
wParamの値を変化させても結果に特に変化がなく、lParamは0以外ではシステムエラーと
なってしまいました。

資料を調べたところ、HSPの資料ではないものの、
http://www.kumei.ne.jp/c_lang/sdk2/sdk_110.htm
にリストビューのソートについて書かれており、
また、別の資料
http://www.interq.or.jp/chubu/r6/masm32/tute/tute031_Jp.html
より
wParam = lParamSort
lParam = pCompareFunction
ということも書かれてありました。

資料を読み進めていくとどうやらpCompareFunctionというのは比較関数のポインタ
らしいのですが、#defcfuncにより比較関数を作ってlibptrをつくってlParamにいれても
やはりシステムエラーのままです。

ソース上にstopなどを入れてエラー場所を調べてみたところ、どうやらlParamの値に
問題があるようです。(比較関数以前の問題らしい)

その後もネットで色々と調べてみたのですが、いまだに解決できていません。
どうすれば降順などを行えるようになるのでしょうか?
以下、実現しようとしていたソート機能
①昇順・降順のソート
②任意サブアイテムでソート



この記事に返信する


eller

リンク

2008/2/8(Fri) 10:22:59|NO.13461

sinさん、こんにちは。おもしろそうな題材だったので調べてみました。

関数のアドレスを渡す方法ですが(私自身詳しくはないので自信はありません)、ヘルプによればlibptr()で得られる値は「STRUCTDAT構造体のアドレス」であって、関数自体のアドレスではないそうです。
もちろんユーザー定義命令にvarptr()は利用できないので、ちょくとさんのhscallbk.dllを利用するのが一番簡単ではないかと思います。
http://yokohama.cool.ne.jp/chokuto/download/index.html#hscallbk
DLLの利用方法は付属テキストをご覧ください。

問題の降順ソートですが、LVM_SORTITEMSよりもLVM_SORTITEMSEXを利用した方が目的のプログラムを実現しやすいようです。
LVM_GETITEMTEXTAメッセージを利用して任意のアイテム・サブアイテムのテキストを取得し、その2つを比較する関数(上記DLLを利用する場合はサブルーチン)を用意するだけで実現できました。

急ぎで作った物でモジュール化などされていませんが、一応動作するスクリプトを載せておきます。
DLLの利用法や各メッセージの利用例として役立ててください。

// 参考資料: // リストビューを作成してみる // http://yokohama.cool.ne.jp/chokuto/urawaza/listview1.html // Windows32 API Constance 検索 // http://hspnext.com/tool/hsptool04.htm // MSDN - LVM_SORTITEMSEX // http://msdn2.microsoft.com/ja-jp/library/bb761055(en-us).aspx #include "hscallbk.as" #uselib "" #func sort_items "" int, int, int #define LVM_SETITEM $00001006 #define LVM_INSERTITEM $00001007 #define LVM_INSERTCOLUMN $0000101B #define LVM_SORTITEMSEX $00001051 #define LVM_GETITEMTEXTA $0000102D #define LVS_REPORT $00000001 #define WS_EX_NOPARENTNOTIFY $00000004 #define WS_VISIBLE $10000000 #define WS_CHILD $40000000 // 疑似的な「ファイル」の数 #define NUM_FILES 10 randomize gosub *createGuiObjects setcallbk proc, sort_items, *sort stop // サブアイテム(ファイルサイズ)でソート // 第2引数が0なら昇順、1なら降順 *sort lvitem.2 = 1 // サブアイテムを対象とする sortmode = callbkarg(2) & 1 repeat 2 lvitem.5 = varptr(item_name(cnt)) sendmsg objinfo_hwnd(id_list), LVM_GETITEMTEXTA, callbkarg(cnt^sortmode), varptr(lvitem) loop return int(item_name(0)) - int(item_name(1)) // ボタンクリックによって呼び出されるサブルーチン *sort_asc sendmsg objinfo_hwnd(id_list), LVM_SORTITEMSEX, 0, varptr(proc) return *sort_desc sendmsg objinfo_hwnd(id_list), LVM_SORTITEMSEX, 1, varptr(proc) return // ボタンとリストビューの作成 *createGuiObjects // ボタンを作成 objsize ginfo_winx / 2, 32 button gosub "ファイルサイズで昇順にソート", *sort_asc pos ginfo_winx / 2, 0 : button gosub "ファイルサイズで降順にソート", *sort_desc // リストビューコントロール作成 w = ginfo_winx : h = ginfo_winy - 32 style = WS_VISIBLE | WS_CHILD | LVS_REPORT pos 0, 32 winobj "SysListView32", "ListView", WS_EX_NOPARENTNOTIFY, style, w, h, 0, 0 id_list = stat // カラムを追加 dim lvcolumn, 8 lvcolumn.0 = 0x000F lvcolumn.2 = 100 column_name = "ファイル名", "ファイルサイズ" repeat 2 lvcolumn(3) = varptr(column_name(cnt)) sendmsg objinfo_hwnd(id_list), LVM_INSERTCOLUMN, cnt, varptr(lvcolumn) if stat == -1 { dialog "カラムの追加に失敗", 1 end } loop // アイテムの追加 dim lvitem, 13 sdim item_name, 64, 2 lvitem.0 = 0x0001 lvitem.6 = 64 repeat NUM_FILES item_name = "ファイル" + cnt lvitem.1 = cnt lvitem.5 = varptr(item_name) sendmsg objinfo_hwnd(id_list), LVM_INSERTITEM, 0, varptr(lvitem) if stat == -1 { dialog "アイテムの追加に失敗", 1 end } loop // サブアイテムの追加 repeat NUM_FILES item_name = "" + rnd(1000) + " KB" lvitem.1 = cnt lvitem.2 = 1 lvitem.5 = varptr(item_name) sendmsg objinfo_hwnd(id_list), LVM_SETITEM, 0, varptr(lvitem) if stat == -1 { dialog "サブアイテムの追加に失敗", 1 end } loop return



sin

リンク

2008/2/8(Fri) 23:50:48|NO.13467

ellerさん、回答ありがとうございます。

これまでにもコールバック関数については、以前の資料内でも出てきたため、一度は手を出しては
いたのですが、理解が薄かったため直接エラー解消とはなっていませんでした。
どうやら、元々モジュール化していたものにソート機能を付加する際、setcallbkの宣言場所が悪く
これが実行される前にsendmsgを行っていたのがエラー原因だったようです・・・

ellerさんのサンプルを参考に改めて自分のプログラムを改良した結果、何とかソートを行える
ようになりました。
本当にありがとうございました。



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