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


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0823
hamWM_TIMERを使うとバグる?4解決


ham

リンク

2018/8/23(Thu) 11:13:47|NO.85167

画像のビューアーを作っています。
ウィンドウのサイズを変更したりするときにドラッグ中も画像のリサイズをしたいと思いまして
WM_TIMERを使ってみたのですが、ウィンドウをドラッグ中にタイマーによる割り込みが入ると
何かがバグって正常に操作を受け付けなくなってしまいます...
しばらくするとランタイムエラーが英語で出てきます。
https://i.imgur.com/VmAx2Um.png

どなたか原因わかりますでしょうか?
HSPは3.51でOSはWindows10 Proです。

以下スクリプトです。

#include "user32.as" #define WM_TIMER 0x0113 #define timer_id 1 ; タイマーID (0 以外の値) oncmd gosub *OnTimer, WM_TIMER onexit *exit screen 0, ginfo(20), ginfo(21):gosub*bg ; 自ウィンドウのスタイルを変更 ; $10000 = 最大化ボタン有効 ; $40000 = ウィンドウサイズ可変有効 GetWindowLong hwnd, -16 SetWindowLong hwnd, -16, stat | $10000 | $40000 ; 実際に表示するサイズを指定 width 1290, 730 dialog "",16,"":file=refstr:if refstr="":end ex=getpath(refstr,2):font"",10 if start=0:buffer 1,10,10:start=1:else:gsel 1 if ex=".bmp"|ex=".jpg"|ex=".gif"|ex=".ico"|ex=".png":pos 0,0:picload refstr:color 34,34,34:boxf:pos 0,0:picload refstr,1 ix=ginfo(12):iy=ginfo(13) ;画像の大きさ代入 *redrawimage gsel 0 wx=ginfo(12):wy=ginfo(13):zy=ginfo(12):zx=ginfo(13) ;ウィンドウの大きさ代入 redraw 0 gosub*bg if ix>wx|iy>wy{ //画面内に収まらない zx = double(wx) / ix //横幅の倍率 zy = double(wy) / iy //縦幅の倍率 if zx>zy { ;縦が長い pos (wx-zy*ix)/2,0 ;画像を表示する座標を決定 gzoom zy*ix, wy, 1, 0, 0, ix, iy, 1 ;ウィンドウの大きさに合わせて描画 } else { ;横が長い pos 0,(wy-zx*iy)/2 ;画像を表示する座標を決定 gzoom wx, zx*iy, 1, 0, 0, ix, iy, 1 ;ウィンドウの大きさに合わせて描画 } }else{ //画面内に収まる gmode 0,ix,iy pos (wx-ix)/2,(wy-iy)/2 gcopy 1 } redraw 1 SetTimer hwnd, timer_id, 200, 0 stop //背景 *bg color 34,34,34:boxf return *OnTimer if wparam == timer_id:title""+ginfo(12)+" x "+ginfo(13): gosub *redrawimage return 0



この記事に返信する


ham

リンク

2018/8/23(Thu) 11:21:35|NO.85168


*exit KillTimer hwnd, timer_id end
すみません一部抜けてました。



inovia

リンク

2018/8/23(Thu) 11:36:49|NO.85169

> ウィンドウのサイズを変更したりするときにドラッグ中も画像のリサイズをしたい

この用途なら、タイマーではなく WM_SIZE を使ったほうが良いかと思われます。
タイマーだと定期的に再描画してしまいますが、
WM_SIZE であればリサイズ時のみの再描画になるので。


#include "user32.as" #define WM_SIZE 0x0005 screen 0, ginfo(20), ginfo(21):gosub*bg ; 自ウィンドウのスタイルを変更 ; $10000 = 最大化ボタン有効 ; $40000 = ウィンドウサイズ可変有効 GetWindowLong hwnd, -16 SetWindowLong hwnd, -16, stat | $10000 | $40000 ; 実際に表示するサイズを指定 width 1290, 730 dialog "",16,"":file=refstr:if refstr="":end ex=getpath(refstr,2):font"",10 if start=0:buffer 1,10,10:start=1:else:gsel 1 if ex=".bmp"|ex=".jpg"|ex=".gif"|ex=".ico"|ex=".png":pos 0,0:picload refstr:color 34,34,34:boxf:pos 0,0:picload refstr,1 ix=ginfo(12):iy=ginfo(13) ;画像の大きさ代入 gsel 0 : oncmd gosub *resize, WM_SIZE gosub *redrawimage stop *redrawimage gsel 0 wx=ginfo(12):wy=ginfo(13):zy=ginfo(12):zx=ginfo(13) ;ウィンドウの大きさ代入 redraw 0 gosub*bg if ix>wx|iy>wy{ //画面内に収まらない zx = double(wx) / ix //横幅の倍率 zy = double(wy) / iy //縦幅の倍率 if zx>zy { ;縦が長い pos (wx-zy*ix)/2,0 ;画像を表示する座標を決定 gzoom zy*ix, wy, 1, 0, 0, ix, iy, 1 ;ウィンドウの大きさに合わせて描画 } else { ;横が長い pos 0,(wy-zx*iy)/2 ;画像を表示する座標を決定 gzoom wx, zx*iy, 1, 0, 0, ix, iy, 1 ;ウィンドウの大きさに合わせて描画 } }else{ //画面内に収まる gmode 0,ix,iy pos (wx-ix)/2,(wy-iy)/2 gcopy 1 } redraw 1 return //背景 *bg color 34,34,34:boxf return *resize title""+ginfo(12)+" x "+ginfo(13): gosub *redrawimage return



inovia

リンク

2018/8/23(Thu) 11:43:06|NO.85170

一応、タイマー版も動くように直しました。
gosub *redrawimage で飛んでいるにもかからわず、中で stop してしまっており、
サブルーチンネストを上限まで使い切ってエラーになっている感じでしょうか。


#include "user32.as" #define WM_TIMER 0x0113 #define timer_id 1 ; タイマーID (0 以外の値) oncmd gosub *OnTimer, WM_TIMER onexit *exit screen 0, ginfo(20), ginfo(21):gosub*bg ; 自ウィンドウのスタイルを変更 ; $10000 = 最大化ボタン有効 ; $40000 = ウィンドウサイズ可変有効 GetWindowLong hwnd, -16 SetWindowLong hwnd, -16, stat | $10000 | $40000 ; 実際に表示するサイズを指定 width 1290, 730 dialog "",16,"":file=refstr:if refstr="":end ex=getpath(refstr,2):font"",10 if start=0:buffer 1,10,10:start=1:else:gsel 1 if ex=".bmp"|ex=".jpg"|ex=".gif"|ex=".ico"|ex=".png":pos 0,0:picload refstr:color 34,34,34:boxf:pos 0,0:picload refstr,1 ix=ginfo(12):iy=ginfo(13) ;画像の大きさ代入 gosub *redrawimage SetTimer hwnd, timer_id, 200, 0 stop *redrawimage gsel 0 wx=ginfo(12):wy=ginfo(13):zy=ginfo(12):zx=ginfo(13) ;ウィンドウの大きさ代入 redraw 0 gosub*bg if ix>wx|iy>wy{ //画面内に収まらない zx = double(wx) / ix //横幅の倍率 zy = double(wy) / iy //縦幅の倍率 if zx>zy { ;縦が長い pos (wx-zy*ix)/2,0 ;画像を表示する座標を決定 gzoom zy*ix, wy, 1, 0, 0, ix, iy, 1 ;ウィンドウの大きさに合わせて描画 } else { ;横が長い pos 0,(wy-zx*iy)/2 ;画像を表示する座標を決定 gzoom wx, zx*iy, 1, 0, 0, ix, iy, 1 ;ウィンドウの大きさに合わせて描画 } }else{ //画面内に収まる gmode 0,ix,iy pos (wx-ix)/2,(wy-iy)/2 gcopy 1 } redraw 1 return //背景 *bg color 34,34,34:boxf return *OnTimer if wparam == timer_id:title""+ginfo(12)+" x "+ginfo(13): gosub *redrawimage return 0 *exit KillTimer hwnd, timer_id end



ham

リンク

2018/8/23(Thu) 12:06:00|NO.85171

おお!ありがとうございます!
WM_SIZE、こんな便利なものがあったとは。

>gosub *redrawimage で飛んでいるにもかからわず、中で stop してしまっており、
returnせずにstopしてましたね...完全に自分のミスでした;;

ご回答いただきありがとうございました。大変助かりました。



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