|
 |
|
2012/9/22(Sat) 15:23:43|NO.49485
デザインを工夫したくて擬似スクロールバーを作りたいのですが
自分のスクリプトに無駄を感じてしまうので皆さんに改善していただきたいです。
x=6 //アイコンの横の数
ix=96 //アイコンの横幅
scx=15 //スクロールバーの幅
winx=640-scx //スクロールバーを除くウィンドウの横幅
winy=480 //ウィンドウの縦幅
spax=(winx-6*ix)/(x+1) //アイコンの横間隔
spay=15 //アイコンの縦間隔
pcs=300 //アイコンの数
num=pcs/x //縦列の数
//スクロールバーの↑↓ボタンの縦幅
scbut=(winy-2*scx)*((winy-2*scx)*100)/(num*(ix+spay))/100
//スクロールバーの↑↓ボタンのy座標(↑ボタン抜き)
scpos=0
//アイコンだけをずらーっと並べるバッファ
buffer 1,640,(ix+spay)*pcs
repeat pcs/x //ずらーっと描画
pos 0,ix+spay
gcopy 1,0,0,winx,(ix+spay)*lin
repeat x
i=cnt+1
color:boxf winx-(spax+ix)*i,spay,winx-(spax+ix)*i+ix,spay+ix
pos winx-(spax+ix)*i,spay+3
color 255,255,255:mes 6*lin+i
loop
lin+=1
await 0
loop
//メインウィンドウ
screen 0,640,480
onclick gosub *onc
color:boxf winx,0,winx+scx,winy
gosub *draw
color 255,255,255
gosub *onup:gosub *ondown:gosub *onbutton
//ホイールの動きを監視するメインループ(?)
repeat
mw=mousew
if mw!0{
scpos+=mw/-20 //ここは適当にしたので動くかどうか
gosub *draw
title "wheel "+scpos
}
wait 1
loop
stop
*onc
mx=mousex:my=mousey
if mx>(640-scx){ //マウスがスクロールバー内に入っていたら
//マウスが↑ボタンを押したとき
if my<scx{
color 0,255,255:gosub *onup
repeat
getkey key,1
if key=0:break
scpos-=2
gosub *draw
title "↑ "+scpos
wait 1
loop
color 255,255,255:gosub *onup
}
//マウスが↓ボタンを押したとき
if my>(winy-scx){
color 0,255,255:gosub *ondown
repeat
getkey key,1
if key=0:break
scpos+=2
gosub *draw
title "↓ "+scpos
wait 1
loop
color 255,255,255:gosub *ondown
}
//マウスが↑↓ボタンを押したとき
if my>(scx+scpos) and my<(scx+scpos+scbut){
my=my-scx-scpos
repeat
getkey key,1
if key=0:break
scpos=mousey-my-scx
gosub *draw
title "↑↓ "+scpos
wait 1
loop
color 255,255,255:gosub *onbutton
}
}else{
//マウスがアイコンを押したとき
if mx\(ix+spax)-spax>0 and (my+y)\(ix+spay)-spay>0{
//マウスの座標とscposからアイコンの番号を取得
title "hit "+(pcs-((my+y)/(ix+spay)*x)-mx/(ix+spax))
}else:title "out"
}
return
*draw //画面の描画とスクロールバーの↑↓ボタンの描画
//---ここでscposの超えすぎを防ぐ
if scpos<0:scpos=0
if scpos>(winy-scx*2-scbut):scpos=(winy-scx*2-scbut)
y=scpos*(num*(ix+spay)-480+scx)/(winy-2*scx-scbut)
redraw 0
color:boxf winx,scx,winx+scx,winy-scx
color 0,255,255:gosub *onbutton
pos 0,0:gcopy 1,0,y,640-scx,480+y
redraw 1
return
*onup //↑ボタンの再描画
boxf winx+1,1,winx+scx-2,scx-2
return
*ondown //↓ボタンの再描画
boxf winx+1,winy-scx+1,winx+scx-2,winy-2
return
*onbutton //↑↓ボタンの再描画
boxf winx+1,scx+scpos+1,winx+scx-2,scx+scpos+scbut-2
return
ためしに組んだスクリプトです
複数のボタンを扱うのにif文で個別に処理さしているので
その分無駄が多い気がします。
まだ初心者なのでどのように改善すれば良いが分かりません。
分かりにくいスクリプトだと思いますが、よろしくお願いします。

| |
|
2012/9/22(Sat) 15:56:49|NO.49486
ざっと見た感じでは無理に最適化させない方が
構造が理解しやすく応用させやすい様に私は感じます。
実際にプログラムに組み込む時の事を考えて
変数名を分かりやすくしたりモジュール化する程度でも
十分使えるものだと思います。
|
|
2012/9/22(Sat) 16:04:05|NO.49487
よく作りこまれていてびっくり。
擬似コントロールを自作しようとすると、大抵想定外の操作に対応できなくてバグを起こすんですけど、そんなこともなく。
さて、
マウスが押されてから離れるまでの間、常にマウスのボタンの状態を監視しているため、
その他の処理が中断してしまいます。
HSPではマウスが押された時の処理をonclick命令で指定できますね。
これは、Windows側から「マウスが押されたぞ!」っていうお知らせ(ウィンドウメッセージ)が届いて、
それを受け取って処理をするというものなんですが、別にクリックに限らずWindowsからは大量にメッセージが届きます。
おそらく今回使えそうなメッセージは
WM_LBUTTONDOWN…マウスの左ボタンが下がった
WM_LBUTTONUP…マウスの左ボタンが上った
WM_MOUSEWHEEL…マウスのホイールが回転した
の3つだと思われます。
このメッセージがWindowsから届いた時だけ、処理をするように改良すると早くなると思われます。
詳しくは HSPヘルプから「oncmd」という命令を調べてみてください。
なお、メッセージは実際には上記の名前ではなく、数字で届きます。各メッセージがどのような値で届くのかは
「WM_LBUTTONDOWN msdn」などで検索するとすぐに見つかると思われます。
少し難しい話ですが、コントロールを作るときは
・各種イベント(マウスのボタンが下がった・上がった、ドラッグされた、etc...)の処理
が最大のポイントになってきます。
HSPではなく、他言語での開発の場合は「クリックされたらこの処理を呼び出してくれ!」と
予め、各種イベントが発生した際の処理を登録しておくことができます(コールバックといいます)
しかし残念ながら、HSPでは言語仕様上、部分的にしかこのコールバック処理を実装できません
(onkey, oncmd, onclickや、button命令のジャンプ先ラベル指定など)
基本的には、ウィンドウのみがメッセージを受け取れて、その他のコントロールは受け取れません。
たとえば、「テキストボックスのテキストの内容が変化したときに処理をする」などといった処理は
通常、無限ループで監視をするしか手がありません。
ですので、HSPで独自のコントロールを作ろうとした場合
今回のようにウィンドウに直接描く方法以外にも
①既存のコントロールをオーナードローすることで対処する
②もし、ゼロからつくるならbgscr命令で縁無しウィンドウを作り、子ウィンドウ化してコントロールとして使用する。
などの方法が考えられます。
①の場合は、本来Windows側に任せている、コントロールの描画を自分で行うというものです。
この方法の場合、デザインは変更できますが、機能は追加できません。
今回の例ですと、これだけでも要件を満たせそうな気はします。
②の方法は、HSPの「ウィンドウのみがウィンドウメッセージを受け取れる」という言語制約をむりやり突破したものです。
まだ詳しくないうちは特に知らなくてもいいでしょう。

| |
|
2012/9/22(Sat) 16:55:03|NO.49488
>>ありさん
自分の英単語力が無さ過ぎて
変数に適してる単語が出てこなくて適当につけちゃいました
たしかにこのままじゃ応用がしにくいですね・・・
ためしに別のプログラムに組み込んでみましたが大変でした;
モジュールについては勉強不足で
自分で作ったことは無いですが一度挑戦してみます
>>てんさん
いろいろ教えていただき、ありがとうございます。
ループで監視する必要の無いonclickやoncmd命令は便利だなと思っていたのですが
そんな便利なウィンドウメッセージが用意されていたんですね
Windowsでデスクトップ開発をする場合は知っておいたほうがよさそうですね
>①の場合は、本来Windows側に任せている、コントロールの描画を自分で行うというものです。
描画だけ自分で行うってことは、①の方法だとスクロールバーの幅が
個人の設定でそれぞれ違っていた場合デザインを統一しにくかったりしますか?
気になっていたのですが、ウェブブラウザのChromeのなどウィンドウは独自のデザインなのに
本物のウィンドウとまったく同じ様な動きをします。
これもその方法で実装されているのでしょうか。
②の方法は枠の無いウィンドウを個別に上に被せるって感じでしょうか
ってことは移動するたびに一緒に移動って感じでしょうか
理解力が無くてすみません;
|
|
2012/9/22(Sat) 18:05:23|NO.49489
ごめんなさいorz
オーナードローはどうやらスクロールバーには実装されていないようです。
ボタンとかならあるんですけどね。
>気になっていたのですが、ウェブブラウザのChromeのなどウィンドウは独自のデザインなのに
>本物のウィンドウとまったく同じ様な動きをします。
>これもその方法で実装されているのでしょうか。
おそらく。
独自のクラスを作っているのではないかと思われます。
>②の方法は枠の無いウィンドウを個別に上に被せるって感じでしょうか
そのとおりです。ただ、かぶせるのではなく、子ウィンドウ化します。
要は、ボタンとかその他のコントロール同様、縁無しウィンドウを縁有りウィンドウの中にしまってしまうのです。
>ってことは移動するたびに一緒に移動って感じでしょうか
ウィンドウの中にしまってしまうので、ウィンドウを動かせばちゃんとついてきてくれますよ。
この方法だと、本来、onclick後にスクロールバーをクリックしたのか、それ以外なのか判定していた作業が不要になります。
|
|
2012/9/23(Sun) 01:15:23|NO.49495
>>てんさん
>ごめんなさいorz
>オーナードローはどうやらスクロールバーには実装されていないようです。
オブジェクトなどを配置した画面をスクロールする予定ではないので
標準のスクロールバーがベースでなくても大丈夫です^^
>要は、ボタンとかその他のコントロール同様、縁無しウィンドウを縁有りウィンドウの中にしまってしまうのです。
そんなことが出来るのですね
実現するにはどのようなソースになるのでしょうか。
てんさんに教えて頂いたWM_MOUSEWHEELで常にホイールを監視する必要がなくなりました
WM_LBUTTONUPも使えそうだったのですが
ウィンドウ外でマウスが離れた場合対処できなかったので、そのままにしました
あとラベル型配列変数などを使いソースを少し短縮できました
(効率の良さは分かりませんが・・・
scSize=15 //スクロールバーの幅
Viewx=640-scSize //表示する横幅
Viewy=480 //表示する縦幅
iconSide=10 //アイコンの横の数
iconSize=48 //アイコンの大きさ
iconNum=300 //アイコンの数(iconSideの倍数限定)
Row=iconNum/iconSide //列の数
Spacey=15 //アイコンの縦間隔
Spacex=(Viewx-iconSide*iconSize)/(iconSide+1) //アイコンの横間隔
//スクロールバーの↑↓ボタンの縦幅
scTabSize=(Viewy-2*scSize)*((Viewy-2*scSize)*100)/(Row*(iconSize+Spacey))/100
//スクロールバーの↑↓ボタンの位置
scPos=120
//ホイールの増減量
wheel_Plus=5
;配列ラベルの割り当て
ldim redraw_, 3
redraw_(0)=*onup : redraw_(1)=*ondown : redraw_(2)=*onbutton
//アイコンだけをずらーっと並べるバッファ
buffer 1,Viewx,(iconSize+Spacey)*iconNum
repeat iconNum/iconSide //ずらーっと描画
pos 0,iconSize+Spacey
gcopy 1,0,0,Viewx,(iconSize+Spacey)*lin
repeat iconSide
i=cnt+1
color:boxf Viewx-(Spacex+iconSize)*i,Spacey,Viewx-(Spacex+iconSize)*i+iconSize,Spacey+iconSize
pos Viewx-(Spacex+iconSize)*i,Spacey+3
color 255,255,255:mes iconSide*lin+i
loop
lin+=1
await 0
loop
//メインウィンドウ
screen 0,640,480
color:boxf
dim on_Color,3 //↑↓ボタンの色
on_Color = 255,255,255
gosub *draw:gosub *onup:gosub *ondown:gosub *onbutton
oncmd gosub *onc, 0x0201
oncmd gosub *wheel, 0x020A
stop
*onc
xPos = lParam & 0xFFFF // カーソルx座標
yPos = (lParam >> 16) & 0xFFFF // カーソルy座標
if xPos>Viewx{ //マウスがスクロールバー内に入っていたら
mode=2
//マウスが↑ボタンを押したとき
if yPos<scSize:scplus=-2:mode=0
//マウスが↓ボタンを押したとき
if yPos>(Viewy-scSize):scplus=2:mode=1
//マウスが↑↓ボタンを押したとき
if yPos>(scSize+scPos) and yPos<(scSize+scPos+scTabSize):Clicky=yPos-scSize-scPos:on_Color = 0,255,255
gosub *click_loop
on_Color = 255,255,255
}else{
//マウスがアイコンを押したとき
if xPos\(iconSize+Spacex)-Spacex>0 and (yPos+drawy)\(iconSize+Spacey)-Spacey>0{
//マウスと表示している画面の座標からアイコンの番号を取得
title "hit "+(iconNum-((yPos+drawy)/(iconSize+Spacey)*iconSide)-xPos/(iconSize+Spacex))
}else:title "out"
}
return
*click_loop
color 0,255,255:gosub redraw_(mode)
repeat
getkey key,1:if key=0:break
if mode==2{scPos=mousey-Clicky-scSize
}else:scPos+=scplus
gosub *draw:title "mode="+mode+" scPos="+scPos
wait 1
loop
color 255,255,255:gosub redraw_(mode)
return
*draw //画面の描画とスクロールバーの↑↓ボタンの描画
//---ここでscPosの超えすぎを防ぐ
if scPos<0:scPos=0
if scPos>(Viewy-scSize*2-scTabSize):scPos=(Viewy-scSize*2-scTabSize)
//表示するバッファのy座標
drawy=scPos*(Row*(iconSize+Spacey)-Viewy+scSize)/(Viewy-2*scSize-scTabSize)
redraw 0
color:boxf Viewx,scSize,Viewx+scSize,Viewy-scSize
color on_Color.0,on_Color.1,on_Color.2:gosub *onbutton
pos 0,0:gcopy 1,0,drawy,Viewx,Viewy+drawy
redraw 1
return
*onup //↑ボタンの再描画
boxf Viewx+1,1,Viewx+scSize-2,scSize-2
return
*ondown //↓ボタンの再描画
boxf Viewx+1,Viewy-scSize+1,Viewx+scSize-2,Viewy-2
return
*onbutton //↑↓ボタンの再描画
boxf Viewx+1,scSize+scPos+1,Viewx+scSize-2,scSize+scPos+scTabSize-2
return
*wheel //ホイールが回転したとき
scPos+=wParam/(-7864320)*wheel_Plus
gosub *draw
return
それと変数名を分かりやすい名前に書き換えました
こういうときに「文字の置換」って便利な機能ですね;
あとはmouseyだとウィンドウからでると止まってしまうので
そこの修正と↑↓キーの対応とかですかね・・・
それが出来たら別のプログラムに組み込む予定でつ

| |
|
2012/9/24(Mon) 18:22:16|NO.49525
テストage
|
|