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


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0408
kanahironWM_SIZEでジャンプした先にgselがあるとランタイムエラーが出る12解決


kanahiron

リンク

2014/4/8(Tue) 23:11:44|NO.61472

まずは再現する最小のスクリプトを
#define WM_SIZE	0x00005	
oncmd gosub *windowsize, WM_SIZE screen 0 stop *windowsize gsel 0 return
実行した瞬間にランタイムエラーが出ます
gsel を別の命令に置き換えてもランタイムエラーは出ません

このスクリプトでは何がしたいのかわかりませんが、削る前は数百行あって結果的にこうなりました


この場合ランタイムエラーはなぜ起きるのでしょうか?
HSPの内部に詳しい方は教えていただけるとすっきりします

P.S.
400行のスクリプトで、screenをbgscrに変える処理を追加したのですがランタイムエラーになりました
なんでランタイムエラーが出たのかわからず少しずつ削っていって↑の最小スクリプトになるまで2時間かかりましたorz



この記事に返信する


fortunehill

リンク

2014/4/8(Tue) 23:33:39|NO.61475

/*ご参考(HSPの内部に詳しくないですが)*/

#define WM_SIZE 0x00005 buffer 0 screen 1 ;サイズ変更確認の為にSCREEM{1}を使用 oncmd gosub *windowsize, WM_SIZE ;初期 SCREEN{0}に対する割り込み命令 oncmd 0 ;割り込み命令の無効化 screen 1 ;SCREEN{0}の再構築命令 oncmd 1 ;hwndは同じなので割り込み命令を有効に出来る stop ;本来ならばoncmdをscreenの後に置くべき *windowsize gsel 1 title ii :ii++ return



暇人

リンク

2014/4/8(Tue) 23:38:30|NO.61476

これは仕様かバグか分からないが
screen等実行時に割り込みが発生する

ウィンドウ初期化と同時に発生した割り込み内で
そのIDに対してgselを行うとエラーがでる
複数ウィンドウを作ってて初期化した以外のIDをgselする場合はエラーは出ない

NO.61472のじゃどう言う状況でscreenを使用するのか分からないが
screenを使用した時点で操作先になってるのでgselする必要が無い

screen時に割り込みされないようにしたいなら

oncmd 0 screen 0 oncmd 1
みたいにする



kanahiron

リンク

2014/4/8(Tue) 23:41:45|NO.61477

fortunehillさんのスクリプトではランタイムエラーは出ないということでしょうか?
自分の環境では出ました…

もともとの処理は簡単にいえばボタンでジャンプし、screenとbgscrを切り替えるような処理でした
なのでボタンで飛んだ先でoncmd 0にしてしまえばエラーは出ないんですけどね

なんとなくHSPのバグというかそんな気がしたので聞いてみました



kanahiron

リンク

2014/4/8(Tue) 23:49:23|NO.61478

>>暇人さん

最小スクリプトでscreenにしましたが元は同じIDのbgscrでした
そこは変えないでよかったですね…

>screen時に割り込みされないようにしたいなら
はい、oncmd 0にしてしまえばエラーでなくなるのはわかっていました
そして書き忘れましたorz

>screenを使用した時点で操作先になってるのでgselする必要が無い
なのですが、
#define WM_SIZE	0x00005	
screen 2 screen 0 oncmd gosub *windowsize, WM_SIZE screen 0 stop *windowsize gsel 2 mes "aa" gsel 0 return
でもランタイムエラーが発生します…



fortunehill

リンク

2014/4/8(Tue) 23:54:09|NO.61479

/*NO.61477さん御免なさい

 title ii :ii++
 の部分は個人的マクロでした正しくは

 title str(ii) :ii++
です
 */



kanahiron

リンク

2014/4/8(Tue) 23:59:01|NO.61481

>NO.61479
あれ??
title ii :ii++
でエラーが出るとしても普通HSPのエラー3が出ますよね?

なんかよくわからない(ランタイム)エラーですね…



fortunehill

リンク

2014/4/9(Wed) 00:01:19|NO.61482

/*NO.61478 この場合もSCREEN{0}に対して割り込み命令が適用されているので
 下記の手段で回避できると思います*/

#define WM_SIZE 0x00005 screen 2 screen 0 oncmd gosub *windowsize, WM_SIZE oncmd 0 screen 0 oncmd 1 stop *windowsize gsel 2 mes "aa" gsel 0 return



暇人

リンク

2014/4/9(Wed) 00:38:47|NO.61486

>でもランタイムエラーが発生します…
だからウィンドウ初期化時の割り込みで初期化したウィンドウIDでgselしたらエラーが出ると・・・

割り込みを止めたく無いなら
ウィンドウ初期化で割り込みされたらgsel 0を飛ばして
return後にgsel出来る様にscreen 0の後にgsel 0



掘木

リンク

2014/4/9(Wed) 01:13:46|NO.61488

kanahironさんのソースを実行してみると、
HSPのバージョンが違うからか(こちら3.31)、こちらではランタイムエラーでなくエラー3が出ますね。

参考になるか分かりませんが3.31のSDKの中身を見てみました。(実際見ている場所があってるかは分かりませんが・・・。)

ウィンドウの再生成時(モデルケースに合わせてウィンドウID0として書いてみる)、
1.bmsrc[0]->hwndを保持する  (bmsrc配列はポインタ型です)
2.bmsrc[0]を削除、NULLを入れる
3.保持したhwndに対してサイズ変更、ウィンドウスタイル変更、拡張ウィンドウスタイル変更を行う
4.保持したhwndに対してSetWindowLongを行いGWL_USERDATAにwindowid(今は0)を入れる。
5.bmsrc[0] = new BMSRC;を行い新しいbmsrcを用意
6.bmsrc[0]の中身を入れ直す。
という順番になっている模様。(1〜3が再生成時のみ呼ばれる、新規生成時はCreateWindowでhwndを得ている)

この際3の部分でSetWindowPosを呼んでいる為、bmsrc[0]がNULLの状態でwindowID0にWM_SIZEが発生します。
この時ラベル割り込みが入り、gsel 0を呼ぶわけですから、
未初期化window扱いとなりHSPエラーが出ていると解釈できます。

ランタイムエラーとは一体・・・。



MillkeyStars

リンク

2014/4/9(Wed) 08:58:03|NO.61494

マスターウィンドウの BMSCR が作られる前に割り込みすればエラーが起きるのは当然だと思いますが。
これも対策があって、マスターウィンドウが作られた際に呼ばれるのは1回のみですから、その1回を処理せずにすればいいだけだと。

掘木さんも言っている通り、マスターウィンドウが正式に作成されると、そのマスターウィンドウはウィンドウID 0 へと変更されます。
この時点で、ウィンドウID 0 が有効化され、各種画面処理などを行うことができます。

ほとんどの人が言っていると思いますが、oncmd gosub は、screen 0 で明示的に初期化した後に行ってください。
(エディタ上から実行すると、ウィンドウが一瞬消える形になるので見た目は悪いですけどね。)

明示的に初期化しないサンプル。

#define WM_SIZE 0x00005 oncmd gosub *windowsize, WM_SIZE stop *windowsize if UE=0 : UE=1 : return gsel 0 return 0



kanahiron

リンク

2014/4/9(Wed) 16:37:32|NO.61499

>>NO.61486

>NO.61477
>なのでボタンで飛んだ先でoncmd 0にしてしまえばエラーは出ないんですけどね

と書いてあるとおり解決策は最初からわかっていました
この質問でもエラーの原因を聞いているだけで解決法を聞いてるつもりはありませんでした

>NO.61494
>ほとんどの人が言っていると思いますが、oncmd gosub は、screen 0 で明示的に初期化した後に行ってください。

元のスクリプトではちゃんとしています 最初に上げたのは最小再現スクリプトです
下手に削りすぎないほうが良かったですね

>NO.61488
解説ありがとうございます
内部の処理がわかりました

最後に処理の流れが分かる程度に書き直したスクリプトを貼っておきます
#include "user32.as"
#define WM_SIZE 0x00005 //ウィンドウサイズ変更 #define WS_MAXIMIZEBOX 0x10000 //最大化ボタン #define WS_THICKFRAME 0x40000 //サイズ変更可能 disw = ginfo(20) dish = ginfo(21) sx = 960 sy = 540 screen 1,200,50 buffer 2,disw,dish cls 4 screen 0,disw,dish title "サイズ変更可能" width sx,sy GetWindowLong hwnd, -16 SetWindowLong hwnd, -16, stat | WS_THICKFRAME | WS_MAXIMIZEBOX GetClassLong hwnd, -26 SetClassLong hwnd, -26, stat | $8 title "サイズ変更可能" oncmd gosub *windowsize, 0x0005 oncmd gosub *click, 0x0201 gosub *draw stop *click oncmd 0;← bgscr 0 oncmd 1;← gosub *draw return *draw gsel 1 ;〜〜〜 gsel 2 ;〜〜〜 gsel 0 ;←ここ color 255,255,255 boxf color pos 0,0 mes strf("%04d %04d",sx,sy) return *windowsize oncmd 0 sx = ginfo(12) sy = ginfo(13) gosub *draw oncmd 1 return

みなさまありがとうございました



暇人

リンク

2014/4/9(Wed) 20:15:35|NO.61500

screenとbgscrでは割り込み発生が異なるので補足

screenで作られたウィンドウは最初に、枠とタイトルを含んだサイズが指定サイズで作られ
その後枠タイトルを含まないサイズが指定サイズになるようにリサイズされる
作られた時とリサイズで二回割り込みが起きる

bgscrは枠タイトルが無いので割り込みは作られた時の一回

screen実行時の最初の割り込みでは
画面が使用されているかどうかのフラグが1以外(なのでgsel使用でエラーになっても不思議は無い)
サイズ修正される時の割り込みでは使用フラグは1になる(ここでgsel使用はエラーにならない)

#define WM_SIZE 0x00005 oncmd gosub *windowsize, WM_SIZE screen 0 repeat a mes "flag="+flag(cnt) mes "sx="+(lp(cnt)&$ffff) +" sy="+(lp(cnt)>>16)+"\n" loop stop *windowsize mref bm,67 flag(a)= bm(0) lp(a)=lParam a++ return
oncmdを設定してるウィンドウをscreen、bgscrする場合はoncmdを止めた方が無難かな・・・



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