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


HSPTV!掲示板


未解決 解決 停止 削除要請

2016
0730
Cheesehamburg7273OSもどきでアイコン機能の実装について 第二弾4未解決


Cheesehamburg7273

リンク

2016/7/30(Sat) 08:14:28|NO.76427

前に「OSもどきのアイコン機能を実装」について質問させていただいているのですが、
http://hsp.tv/play/pforum.php?mode=all&num=76403

あれからいろいろと改造を施して、進化させたのですが意味不明なエラーが連発し、
頭がオワタ\(^o^)/しそうになったので質問させていただきます
以下のソースコードの208行目で「パラメータの値が異常です」と言われるので
ソースコードの修正をお願いします

#include"user32.as"
//パレットデータ 画像座標
// 0 ,50 スタートボタン(通常時)
// 50 ,50 スタートボタン(プッシュ中)
// 110,60 音楽ファイルアイコン
// 160,60 画像ファイルアイコン
// 210,60 ドキュメントアイコン
// 260,60 フォルダアイコン
// 310,60 終了操作アイコン
iconmax=5:dir_def=dir_cur
iconx=12,12,12,12,12
icony=5,60,60*2,60*3,60*4
iconname(0)=sysinfo(1)
iconname(1)="デバイス"
iconname(2)="アシスタント"
iconname(3)="ツール"
iconname(4)="終了操作"
ShortcutMenu="新規作成"
ShortcutMenuHot="開く","新規作成","削除","情報表示"
buffer 1:picload"Picture/Palette.png",0
buffer 2,ginfo(20),ginfo(21)
color 0,0,200:boxf
picload"Picture/Wallpaper/Harmony.png"
gzoom ginfo(20),ginfo(21),2,0,0,ginfo(12),ginfo(13),1
screen 0,ginfo(20),ginfo(21),0,0,0
GetWindowLong hwnd, -16
SetWindowLong hwnd, -16, stat | $10000 | $40000
width dispx,dispy
sendmsg hwnd, $112, $F030
notesel iconmax
noteload"Registry/IconMAX.registry",-1
iconmax=int(iconmax)
notesel iconname_load
noteload"Registry/IconNAME.registry",-1
repeat iconmax
noteget iconname(cnt),cnt
loop
notesel iconpath_load
noteload"Registry/IconPATH.registry",-1
repeat iconmax
noteget iconpath(cnt),cnt
loop
repeat iconmax
iconpath(cnt)=int(iconpath(cnt))
loop
notesel iconlink_load
noteload"Registry/IconLINK.registry",-1
repeat iconmax
noteget shortcuticon(cnt),cnt
loop
onclick gosub*desktop_move
scrx=ginfo(12):scry=ginfo(13)
repeat iconmax
iconname_length(cnt)=strlen(iconname(cnt))
if iconname_length(cnt)>8 {
iconname_cnt=cnt
iconname_two(cnt)="":iconname_one(cnt)=""
iconname_one(cnt)=strmid(iconname(cnt),0,8)
iconname_two(cnt)+strmid(iconname(cnt),0,16)
iconname_two_et(cnt)=strmid(iconname(cnt),0,8)
strrep iconname_two(cnt),""+iconname_two_et(cnt),""
iconname_strlen(cnt)=(strlen(iconname_two(cnt))*6)
iconname_path(cnt)="&SYSTEM"
iconname(cnt)=""+iconname_one(cnt)+"\n"+iconname_two(cnt)+"..."
}
loop
gosub*desktop_draw
repeat
if scrx!ginfo(12)|scry!ginfo(13) {
x=ginfo(12):y=ginfo(13)
buffer 2,ginfo(20),ginfo(21)
color 0,0,200:boxf
picload"Picture/Wallpaper/Harmony.png",0
gzoom x,y,2,0,0,ginfo(12),ginfo(13),1
gsel 0,0
gosub*desktop_draw
}
wait 20
loop
stop
*desktop_draw
redraw 0
gmode 0,ginfo(12),ginfo(13)
pos 0,0:gcopy 2,0,0,ginfo(12),ginfo(13)
gmode 3,ginfo(12),50,175
pos 0,ginfo(13)-50:gcopy 1,0,0,ginfo(12),50
gmode 0,ginfo(12),ginfo(13)
repeat iconmax
if iconx(cnt)!-1&icony(cnt)!-1 {
pos iconx(cnt),icony(cnt):gcopy 1,260,60,32,32
if cnt==4 :pos iconx(cnt),icony(cnt):gcopy 1,310,60,32,32
if cnt>4 {
if iconpath(cnt+1)==0 :pos iconx(cnt),icony(cnt):gcopy 1,110,60,32,32
if iconpath(cnt+1)==1 :pos iconx(cnt),icony(cnt):gcopy 1,160,60,32,32
if iconpath(cnt+1)==2 :pos iconx(cnt),icony(cnt):gcopy 1,210,60,32,32
}
color 255,255,255:font"MS UI GOTHIC",12
pos iconx(cnt)-5,icony(cnt)+34:mes iconname(cnt)
}
loop
redraw 1
return
*desktop_move
defdx=mousex:defdy=mousey
if wparam==1 {
newdraw=1
clrobj:gosub*desktop_draw
repeat iconmax
if mousex>iconx(cnt)&mousex<iconx(cnt)+32&mousey>icony(cnt)&mousey<icony(cnt)+32 {
iconID=cnt
repeat
defx=mousex:defy=mousey
iconx(iconID)=defx-16:icony(iconID)=defy-16
gosub*desktop_draw
await 1
getkey click,1
if click==0 :break
loop
}
loop
}
if wparam==2 {
clrobj:gosub*desktop_draw
repeat iconmax
if mousex>iconx(cnt)&mousex<iconx(cnt)+32&mousey>icony(cnt)&mousey<icony(cnt)+32 :MouseIconHot=1:iconno=cnt
loop
if MouseIconHot==0 {
gradf mousex,mousey,100,length(ShortcutMenu)*30,1,$FFFFFF,$000000
objsize 100,30:pos mousex,mousey
foreach ShortcutMenu
button gosub""+ShortcutMenu(cnt),*ShortcutRun
loop
}
if MouseIconHot==1 {
gradf mousex,mousey,100,length(ShortcutMenu)*30,1,$FFFFFF,$000000
objsize 100,30:pos mousex,mousey
foreach ShortcutMenuHot
button gosub""+ShortcutMenuHot(cnt),*ShortcutRunHot
loop
}
MouseIconHot=0
}
return
*ShortcutRun
if stat==0 :gosub*IconCreate
return
*ShortcutRunHot
if stat==0 :gosub*IconRun
if stat==1 :gosub*IconCreate
if stat==2 :gosub*IconDelete
if stat==3 :gosub*IconInfo
return
*IconRun
if iconno==4 :end
repeat setcnt
if iconno==cnt+5 :exec""+shortcuticon(cnt),16
loop
clrobj:gosub*desktop_draw
return
*IconDelete
iconx(iconno)=-1:icony(iconno)=-1
clrobj:gosub*desktop_draw
return
*IconCreate
dialog"",16,""
if stat==0 :return
selected=refstr
iconx(5+setcnt)=mousex:icony(5+setcnt)=mousey:iconmax+1
iconname(setcnt+5)=getpath(selected,8)
shortcuticon(setcnt)=refstr:setcnt+1
iconname_length(4+setcnt)=strlen(iconname(4+setcnt))
;iconpath(5+setcnt)=getpath(selected,2)
;strrep iconpath(5+setcnt),".",""
chdir dir_def
notesel audiopath
noteload"Config/FILETYPE_AUDIO.ini",-1
repeat notemax
noteget type,cnt
type=getpath(type,16)
if getpath(selected,2)=="."+type :iconpath(5+setcnt)=0
loop
notesel picturepath
noteload"Config/FILETYPE_PICTURE.ini",-1
repeat notemax
noteget type,cnt
type=getpath(type,16)
if getpath(selected,2)=="."+type :iconpath(5+setcnt)=1
loop
notesel textpath
noteload"Config/FILETYPE_TEXT.ini",-1
repeat notemax
noteget type,cnt
type=getpath(type,16)
if getpath(selected,2)=="."+type :iconpath(5+setcnt)=2
loop
if iconname_length(4+setcnt)>8 {
iconname_cnt=cnt
repeat iconmax
iconname_two(cnt)=str(iconname_two(cnt))
iconname_two_et(cnt)=str(iconname_two_et(cnt))
iconname_one(cnt)=str(iconname_one(cnt))
loop
iconname_two(cnt)=""
iconname_one(cnt)=""
iconname_one(cnt)=strmid(iconname(cnt),0,8)
iconname_two(cnt)+strmid(iconname(cnt),0,16)
iconname_two_et(cnt)=strmid(iconname(cnt),0,8)
strrep iconname_two(cnt),""+iconname_two_et(cnt),""
iconname_strlen(cnt)=(strlen(iconname_two(cnt))*6)
iconname_path(cnt)="&SYSTEM"
iconname(cnt)=""+iconname_one(cnt)+"\n"+iconname_two(cnt)+"..."
}
clrobj:gosub*desktop_draw
return
*IconInfo
repeat iconmax
if mousex>iconx(cnt)&mousex<iconx(cnt)+32&mousey>icony(cnt)&mousey<icony(cnt)+32 :iconno=cnt
loop
if iconno<6 {
if iconno==0 :exec dirinfo($10005),16,"properties"
if iconno==1 :exec""+dir_win+"\\explorer.exe /e, /root,/select,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
if iconno==2 :exec"Saltice Personal Assistant System SASAKI.exe"
if iconno==3 :dialog"Salticeで利用されるツールを実行できます",0,"プロパティ"
if iconno==4 :dialog"このアイコンはSalticeを安全に終了できます",0,"プロパティ"
}
repeat setcnt
if iconno==cnt+5 :exec""+shortcuticon(cnt),16,"properties"
loop
clrobj:gosub*desktop_draw
return
*Quit
repeat int(iconmax)
iconmax(cnt)=str(iconmax(cnt))
loop
notesel iconmax
notesave"Registry/IconMAX.registry"
notesel iconname_save
repeat int(iconmax)
iconname_save+""+iconname(cnt)+"\n"
loop
notesave"Registry/IconNAME.registry"
notesel iconpath_save
repeat int(iconmax)
iconpath_save+""+str(iconpath(cnt))+"\n"
loop
notesave"Registry/IconPATH.registry"
notesel iconlink
repeat int(iconmax)
iconlink+""+shortcuticon(cnt)+"\n"
loop
notesave"Registry/IconLINK.registry"
end



この記事に返信する


Cheesehamburg7273

リンク

2016/7/30(Sat) 08:15:09|NO.76428

すみませんpreで囲むの忘れていました



bellyoshi

リンク

2016/7/30(Sat) 08:56:09|NO.76431

画像がなかったので実行できないです。

207行目ぐらいに
assert 0
と書いてDebug Windowを表示させてみてはいかがでしょう。
変数の値がわかりますよ。

変数タブを開いて
配列変数のところにチェックを入れれば内容確認できます。

iconname_two
iconname_two_et
cnt
あたりを自分が思った値になっているか確認してみてください。



掘木

リンク

2016/7/30(Sat) 09:55:05|NO.76432

まあassertだのtitleだのlogmesだので変数の中身を見るしかないです。
そしてクロスリファレンスチェックとかの駆使しつつなんとか根元を見つけましょう。
対処療法ダメ、ゼッタイ

個人的に思うと以降にずらずらと。

動く、動かない以前にマジックナンバーが異様に多いのが気になります。
変数の説明もないので期待通りの物なのか何なのか把握困難でございまする。

コードを弄っている間は設計者は自分自身です。ただ、
「一週間後の自分は他人」なので数日あけて中身を見ると絶望出来ます(返答者談)
少なくとも一月後の自分が読めないものを書くとバージョンアップの際に髪の毛抜ける事になりますよう。



掘木

リンク

2016/7/31(Sun) 11:36:50|NO.76455

他人のコードのリファクタリングの練習を兼ねて調査してみました。
潜在的なエラーがぼこぼこ山のように出てきております。
きっと今回のエラーが治ってもたびたびエラーに悩まされることでしょう。
そのうえ、仕様不備かと思うものがたくさん出てきています。仕様ですと言い張るのか?

なんとかテストケースを生成しうるだけの情報をコードから獲得できたので実行できました。
で、今回のエラー箇所ですが、コードの転写の際に行数の情報は消失するのでどの行かわかるように投稿しましょうね。

strrep iconname_two(cnt),""+iconname_two_et(cnt),""
ここでiconname_two_et(cnt)は空文字です。
strrepは空文字を何かに置き換えようとした場合パラメータ異常のエラーになります。

これが空文字になる原因はHSPの妙な賢さにあります。
iconmaxは5っぽいので、iconname_two_etは要素数5くらいの文字列型配列になります。
で、iconname_two_et(cnt)は、cntが指しているrepeatブロックが*IconCreateの中ですらなく、
68行目〜79行目付近のrepeat〜loopになります。この値はかなり大きいと推測できます。
で、iconname_two_etは文字列型配列のため、参照時に要素が足りない場合「要素エラー」にならず、
自動的に拡張しやがります。その結果iconname_two_et(9999)は空文字("")だよって言ってくれる。なんてことを…。

この辺り部分は横幅の大きいテキストを複数行に分離、はみ出しの文字列を追加する処理と思われます。
で、よく見ると55行目あたりに全く同じコードが見えます。
コピーして作られたのでしょう。
「まずコピーして作って動かす」は構わないのです。コピーして動かないならコピー方法に問題があるのです。
現状コピーして動いてないんでしょうけど、それはそれで…
でも「コピーして作って動いた」をそのままにしてはいけません。
そのあとに同一処理をまとめる作業をしなくてはいけないのです。
(gosubによるサブルーチン化、deffunc、defcfuncによる命令/関数化)
場合によっては処理順序を再検討することも必要でしょう。(同じファイルから同じデータを読み込む等、複数あること自体が異常なもの)
(iconname_two、iconname_one、iconname_two_et、iconname_length辺りは現状のコードでは「配列変数」である必要がないとか突っ込みどころはいっぱいある)

あちこちに似たようなコード居てるんですよねえ…。サブルーチンなり新規命令なり作って纏めちゃいましょうぞ…。

個人的に気になるのは、*IconCreateでの配列添え字の扱いです。
4ずらしたり5ずらしたり統一感がありません。
そしてここでずらしたことによって別の個所でずらした分を戻して処理しなければいけません。
無駄とは言わないが、非常にバグを生み出しやすい要因になっております。
アイコンの登録番号と配列番号を合わせたほうがきっと見通しのいいものになる気がしますよ

そして[ ""+ ]ってのが異様に多い。
これは後ろに続く変数が数値だろうが文字列だろうがとりあえず文字列に変換してしまえっていうかなり頭ごなしな記述です。
正しく初期化、記述していれば、そもそも文字列の変数であることは確定なケースでも使ってませんか?
「何かの要因でいつの間にか数値型に変わったときにエラーにならない」問題があります。
「なんか知らんけどこうするとエラーにならないらしい」なんて解釈でつけるべきものじゃないです。
エラーになった時点で文字列でない何かを指定したのだから、いつの間にか数値型になってるか、初期化を忘れてるか…
コード上のエラーです。これでエラーを回避してはただの対処療法です。
"数値を意図的に文字列に変換する場合"に使うのは大いにかまわないけど、それならstr()を使うほうがいいと思う。



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