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


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0703
とあるプログラマモジュール型変数の識別について3解決


とあるプログラマ

リンク

2020/7/3(Fri) 23:32:58|NO.90901

モジュール型変数のメソッド内で作成したウィンドウからoncmdでジャンプをした際にジャンプ先ラベル内からジャンプ元のモジュール型変数を知ることは可能でしょうか。


例えば以下のような方法はパッと思いつくような方法ですが、残念ながらエラーになります。

#module test id #modinit id = ginfo_newid screen id title "module screen" // 左クリックしたら*lbuttonへ oncmd gosub *lbutton, 0x00000201 //WM_LBUTTONDOWN return #modfunc showid dialog id return stat *lbutton showid thismod //ここでエラー return 0 #global newmod var, test stop

具体的にはモジュール型変数でコントロールを作成し、コントロールへの操作によってコントロールの再描画を行うことを想定しています。


通常のボタンやコンボボックスといったコントロールも、ウィンドウプロシージャからは送信元のウィンドウハンドルまでしか分からないはずですが、この辺のメッセージ処理はどうやって個別に処理しているんでしょうか。



この記事に返信する


ベイン

リンク

2020/7/4(Sat) 15:35:29|NO.90902

oncmd の段階で thismod の値 (インスタンス) が何であったかを
何らかの方法で覚えておき、ラベルが呼ばれた後に判別する必要があります。

この例ではウィンドウ ID ごとにインスタンスが異なるので、
ウィンドウ ID をインデックスとする配列変数を用意して、
それに thismod を代入しておく方法があります。

(ただしインスタンスを = で代入して作った値はただの参照であり、
元のインスタンスが delmod などで破棄されると無効になるので注意。)


#module m_mywin window_id_ // モジュールの初期化 #deffunc init@m_mywin // struct 型の無効な値を用意しておく。 dimtype s_nullmod, vartype("struct") // ウィンドウ ID w に対応するインスタンスを // s_instance_refs(w) に入れておく。 dimtype s_instance_refs, vartype("struct") // ウィンドウ ID w に対応するインスタンスが生きているとき // s_instance_alive(w) = 1 とする。 dim s_instance_alive return // インスタンスが生成されたとき #modinit window_id_ = ginfo_newid // ウィンドウ ID とインスタンスの対応を記録する。 s_instance_alive(window_id_) = 1 // = thismod は NG // s_instance_refs(window_id_) = thismod dup s_self, thismod s_instance_refs(window_id_) = s_self dim s_self screen window_id_ title "module screen" // WM_LBUTTONDOWN oncmd gosub *l_l_button_down, 0x201 return // インスタンスが破棄されたとき #modterm // インスタンスが破棄されたことを記録する。 s_instance_alive(window_id_) = 0 s_instance_refs(window_id_) = s_nullmod // (サンプル用) 破棄されたことを分かりやすくするため。 gsel window_id_ boxf return #modfunc showid dialog window_id_ return stat // 左クリックされたとき *l_l_button_down s_window_id = ginfo_act // このウィンドウ ID に対応するインスタンスが生きているか確認する。 if s_window_id < 0 || s_window_id >= length(s_instance_alive) { return } if s_instance_alive(s_window_id) == 0 { return } // assert varuse(s_instance_refs(s_window_id)) == 1 // クリック時の処理: showid s_instance_refs(s_window_id) return stat #global init@m_mywin // ここまでモジュール // ----------------- // ここからアプリ repeat 3 newmod w, m_mywin loop delmod w(1)

ウィンドウ ID が使えないときは適当に ID を割り振ります。
oncmd でラベルが呼ばれたとき、その割り振った ID をどう探すかは場合によります。

> 通常のボタンやコンボボックスといったコントロールも、
> ウィンドウプロシージャからは送信元のウィンドウハンドルまでしか分からないはずですが、
> この辺のメッセージ処理はどうやって個別に処理しているんでしょうか。

ボタンを作る際に識別子を設定しておくと WM_COMMAND でその識別子ももらえるので、
それで判別するみたいです。

参考: C++ + Win32API でボタンを使う方法の説明記事
[ボタン](http://wisdom.sakura.ne.jp/system/winapi/win32/win51.html)



とあるプログラマ

リンク

2020/7/6(Mon) 14:29:33|NO.90920

なるほど、メンバ変数でないモジュール配列変数にID別で参照先を確保しておいて呼び出し時に自身のIDを使いメソッド呼び出しというわけですか… この方法は盲点でした。
(というかthismodが#mod(c)func以外の関数でも普通の変数と同様に扱えることを初めて知った…)

ただどこかの記事で(恐らくQiitaだったような)モジュール型変数に対してのdupは不安定といったような記事を見かけたことがあるので、dupより=によるクローンのほうが良いのかもしれません。
(対象の記事とdup/=による差がイマイチ分かっていないので不確定で申し訳ないです)

しかし解決への糸口が見つかり感謝しています。ありがとうございます。



とあるプログラマ

リンク

2020/7/6(Mon) 23:21:44|NO.90923

いろいろ調べていたところSet/GetPropという関数を発見したので、それによりさらに簡略化できたためベインさんのコードを基にしたものを載せておきます。


#module m_mywin window_id_ // インスタンスが生成されたとき #modinit window_id_ = ginfo_newid screen window_id_ title "module screen" oncmd gosub *l_l_button_down, 0x201 // WM_LBUTTONDOWN SetProp hwnd, "hThismod", varptr(thismod) // ウィンドウプロパティにthismod(自身)のポインタを設定 SetProp hwnd, "Sizeof", varsize(thismod) // dupptr用にサイズも格納(モジュール型変数自体はポインタを格納しているだけで配列要素によってサイズは変わらないのでいらないかも?) return // インスタンスが破棄されたとき #modterm // (サンプル用) 破棄されたことを分かりやすくするため。 gsel window_id_ boxf // プロパティを破棄 (ウィンドウ破棄前にプロパティの削除をするべきらしいのでSetPropで0を代入することはしない) RemoveProp hwnd, "hThismod" RemoveProp hwnd, "Sizeof" return #modfunc showid dialog window_id_ return stat // 左クリックされたとき *l_l_button_down gsel ginfo_act // システム変数 hwnd を使うため選択 // プロパティ取得 ptr = GetProp(hwnd, "hThismod") size = GetProp(hwnd, "Sizeof") if (ptr == 0 || size == 0) : return // プロパティに設定したアドレスからdupptr dupptr thismod_, ptr, size, 5 // struct showid thismod_ return stat #global // ここまでモジュール // ----------------- // ここからアプリ repeat 3 newmod w, m_mywin loop delmod w(1)



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