|
|
|
2015/4/29(Wed) 07:47:06|NO.68871
最近HSPを始めたばかりです。まだよく分かってません。
ついでにGUIもあまり経験がありません。
(ちょっとCでWin32APIでウィンドウ作って発狂してやめたことがあります)
#packopt hide 1
screen 0,1,1,2 ;; 0は見えなくしておく
#uselib "user32.dll"
#func SetParent "SetParent" int,int
#func SetWindowLongA "SetWindowLongA" int , int , int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int , int , int , int
dim hw, 999
screen 1, 800, 600, 0, 800, 300
hw(1) = hwnd
;; picload "./back1.png", 1 ;見やすいように適当に背景画像を突っ込む
screen 2, 400, 200, 0, 200, 200
hw(2) = hwnd
SetParent hw(2), hw(1) ;子ウィンドウにする
SetWindowLongA hw(2), -20, 0x00080000
SetLayeredWindowAttributes hw(2), 0, 128, 2 ;透明にする
mes "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
stop
なにがやりたいかと言うと、上の記述とは違うと思うのですが、
「背景だけ」が透明のウィンドウを作り、そこに様々な物を一つだけ配置し、
それぞれの要素を個別にウィンドウ単位で管理したい、と言うことをやりたいです。
実際にはhw(2)以降のウィンドウは、bgscrを使いたいと思っています。
ただ、上記の方法では作り終わったウィンドウが透明になりますので、
実は私のやりたいことと違います。
さらに、子ウィンドウと透明なウィンドウが両立してくれません。
https://msdn.microsoft.com/ja-jp/library/cc410656.aspx
まずしばらくここを眺めましたが、背景が透明に初期化されたウインドウと言うのはよくわかりませんでした
違うかもしれませんが
https://msdn.microsoft.com/en-us/library/ff700543(v=vs.85).aspx
ここを眺めるとwindows8未満は子ウィンドウに対応していないような雰囲気があります。
また、SetWindowLongAは古いのでSetWindowLongPtrを使え、
みたいなことが書いてあったのでやってみると、DLLからエラーが返りました。(私の記述間違い?)
別に以上のような方法を狙い撃ちで取りたいわけではなくて、
HSPで表示される全ての要素を完全に個別管理したいと思っています。
| |
|
2015/4/29(Wed) 07:48:43|NO.68872
書き忘れましたが、
SetParent hw(2), hw(1) ;子ウィンドウにする
この行をコメントアウトすると半透明なウィンドウは生成されます。
|
|
2015/4/29(Wed) 08:28:07|NO.68873
Windowsの仕様でレイヤードウィンドウは子ウィンドウになれません
|
|
2015/4/29(Wed) 23:56:31|NO.68897
>Windowsの仕様でレイヤードウィンドウは子ウィンドウになれません
調べてみるとどうやら従来はそのようでしたが、
Windows 8 からは半透明子ウィンドウを作成できるようになったようです。
http://mtamaki.cocolog-nifty.com/blog/2004/06/post_e826.html
http://blog.fenrir-inc.com/jp/2012/10/window8_layered_window_.html
で、上記のページを見るとマニフェストを書き換えれば良いらしいのですが、
HSPではどうしたら良いのかというと、下記ページに方法が載っていました。
(Resource Hacker を使う必要があるみたいです。別途ご用意ください。)
http://d.hatena.ne.jp/tsukaban/20130623/p1
書き換える内容は、
http://www.gesource.jp/weblog/?p=5648
上記ページから
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
を書き加えたら良さそうです。
具体的な手順としては、
1. TNKさんの書いたスクリプトを「実行ファイル自動作成」して実行ファイルを作る。
2. Resource Hackerで実行ファイルを開き、マニフェスト[24->1->1033(?)]に上記内容を書き加えて保存。
3. 保存したexeファイルを実行してみると子ウィンドウが半透明に!!
私が試したときのマニフェストはこんな感じです。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="OnionSoftware.hsp3.exe"
type="win32"
/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
</application>
</compatibility>
<description>XPStyle</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
お試しください。
| |
|
2015/4/30(Thu) 00:38:38|NO.68898
SetWindowLongPtrの第三引数は64bitなので32bit版のHSPからは使えないのだと思います。
Cのヘッダでは処理系が32bitのときSetWindowLongPtrはSetWindowLongに置換されるので、
あたかもSetWindowLongPtrを二種の環境で両用できるように振舞います。
|
|
2015/4/30(Thu) 01:02:36|NO.68899
色々調べてくださってありがとうございます。
大変勉強になります。本当にありがとうございます。
HSPもこうゆうプログラミングも不慣れなので、冒頭の記述を調べて書くだけでも数時間かかってました。
冒頭に書いた
>windows8未満は子ウィンドウに対応していないような雰囲気があります
は、事実と言うことなのですね。
(しかも、リンク先を読むとかなり不親切なドキュメントが発生してるような)
後日、windows8で動かしてみたいと思います。
(プログラム開発環境用は7とXPしかない)。
ただ、プログラミングを楽をするためにwindows8専用には出来ないですねぇ。
また、本当の質問の趣旨は
>全ての要素を完全に個別管理したいと思っています。
と言うことで、もっと楽に方法あるよ、と言うのをご存知の方がいれば随時募集しております。
(この方法はたまたま思いついた、出来れば楽だろうな、と言うだけの物です)。
ちなみに(最初にも書きましたが)7やXPで子ウィンドウを作れてもまだ問題があって、
最初から透明ではなく、完成したウィンドウを処理して透過する、と言う点に問題があります。
この場合、一番顕著に問題が発生するのは、アルファを扱うPNGを使う場合でしょうか。
(また逆にArtlet2Dはその辺は処理してくれますが、
あれはウィンドウではないため、ボタンなどが設置できず、なにより直接上書きで貼り付けてしまいます)。
>SetWindowLongPtrの第三引数は64bitなので32bit版のHSPからは使えないのだと思います。
なるほど、
私はあたかもドキュメントを読んだふりして何も読んでないと言うことですね。
APIについてもHSPについても。
しかもHSPでPtrを使う意味はなさそうですね。
ありがとうございました。
|
|
2015/4/30(Thu) 08:17:16|NO.68900
新しいバージョンの3.5b1では64bit版ランタイムがありますよ。
といってもまだバグが残るベータ版ですが。
とりあえず一番上のソースを見る限りではバグの影響を受けないようなソースに
見えるので、3.5を使ってもいいかもしれません。
|
|
2015/4/30(Thu) 20:59:45|NO.68910
不躾ながら、子ウィンドウ単位で管理する必要性があるのでしょうか?
要素(物)単位で配列等を使って管理すれば済む話のように思えました。
特にボタンなどのオブジェクト(コントロール)は、それ自体が子ウィンドウのようなものなので二度手間のような気がします。
|
|
2015/4/30(Thu) 23:22:01|NO.68916
参考にさせて頂きました。大変綺麗で見やすかったです。
別に冒頭であげたような管理方法はどうしてもと言うわけでなく、
かえってその方法でめんどうになるようなら、使う理由はなくなります。
ただ、私の希望はプログラム全体の構造にも関わる物で、
例えば、オブジェクト自身(もしくはウィンドウハンドル)が最初からすでに自分の状態を知っている、
と言うのも望ましい理由の一つです。
>配列等を使って管理すれば済む話のように思えました
この助言でピンと来たのですが、例えばクロージャのような物は使えないでしょうか?
使えるとけっこう事情が変わってくるような気がしました。
いや、他にも思いつくような工夫の余地はいろいろあるので、別にクロージャでなければならない、と言う理由は全くありません。
|
|
2015/5/1(Fri) 02:48:19|NO.68924
同一のモジュール空間内では関数同士で変数が共有できますが、それとは別物でしょうか。
HSPのスコープはグローバル空間とモジュール空間の二つあり、
静的ですが、入れ子にはできないのでスコープチェーンのようなものはありません。
お恥ずかしながら、私自身がクロージャという概念を正しく理解できている自信がないので、
とりあえずHSPのスコープ周辺で知っている知識を並べ書きました。
それはともかく、個別に管理して状態を知るというのはこういう感じでしょうか?
やっつけ仕事で試作してみました。
/* Widgetとでも名づけてGUIを色々管理してみる */
#include "user32.as"
#include "obj.as"
#undef objsize
#define objsize(%1, %2) ginfo_objx = %1 : ginfo_objy = %2 : objsize@hsp %1, %2
ginfo_objx = 50 : ginfo_objy = 20
#module widget
#define WG_MAX 256 ; 設置最大数
#enum WG_TYPE_MES = 0
#enum WG_TYPE_LINE
#enum WG_TYPE_GCOPY
#enum WG_TYPE_INPUT = 101 ; 100以上はオブジェクトとする
#enum WG_TYPE_CHKBOX
#enum WG_TYPE_BUTTON
#define ctype is_obj(%1) (%1 >= 100)
#deffunc wg_init
; Widget Struct 的なものを定義
dim wgs_using, WG_MAX ; 使用フラグ
dim wgs_parent, WG_MAX ; 配置先のウィンドウID
dim wgs_type, WG_MAX ; GUIの種類(100以上ならばオブジェクト)
dim wgs_visible, WG_MAX ; 表示 or 非表示
dim wgs_x, WG_MAX ; 座標
dim wgs_y, WG_MAX
dim wgs_w, WG_MAX ; 大きさ
dim wgs_h, WG_MAX
; ここからは要素の個別データ(二次元配列にして共用体っぽく使う手もある)
dim wgs_objid, WG_MAX ; ウィンドウハンドルなど(あれば)
dim wgs_r, WG_MAX ; 色情報(あれば)
dim wgs_g, WG_MAX
dim wgs_b, WG_MAX
sdim wgs_text, 64, WG_MAX ; mesの内容やbuttonのキャプションなど
; その他、フォント名や文字サイズや色々
return
#deffunc wg_term onexit
; 終了処理
return
#defcfunc wg_get_newid
newid = -1
repeat WG_MAX
if wgs_using(cnt) = 0 {
newid = cnt
break
}
loop
if newid = -1 : dialog "これ以上ウィジェットを配置できません"
return newid
#deffunc wg_destroy int _id
wgs_using(_id) = 0
if is_obj(wgs_type(_id)) : clrobj _id ; オブジェクトなら実体も削除
return
#deffunc wg_update
save_id = ginfo_sel
save_x = ginfo_cx : save_y = ginfo_cy
save_r = ginfo_r : save_g = ginfo_g : save_b = ginfo_b
redraw 0
color 255, 255, 255 : boxf
repeat WG_MAX
if wgs_using(cnt) = 0 | wgs_visible(cnt) = 0 : continue
gsel wgs_parent(cnt)
pos wgs_x(cnt), wgs_y(cnt)
type = wgs_type(cnt)
; 共通の処理
if is_obj(type) {
v = wgs_w(cnt), wgs_h(cnt), wgs_x(cnt), wgs_y(cnt)
resizeobj wgs_objid(cnt), v, 0
continue
} else {
color wgs_r(cnt), wgs_g(cnt), wgs_b(cnt)
}
; 固有の処理
switch type
case WG_TYPE_MES
mes wgs_text(cnt)
swbreak
case WG_TYPE_LINE
swbreak
swend
loop
redraw 1
gsel save_id
pos save_x, save_y
return
; Widget作成時の共通の初期化処理
#defcfunc wg_create int _type, int _w, int _h, str _text
id = wg_get_newid()
wgs_using(id) = 1
wgs_parent(id) = ginfo_sel
wgs_type(id) = _type
wgs_visible(id) = 1
wgs_x(id) = ginfo_cx
wgs_y(id) = ginfo_cy
wgs_w(id) = _w
wgs_h(id) = _h
wgs_r(id) = ginfo_r
wgs_g(id) = ginfo_g
wgs_b(id) = ginfo_b
wgs_text(id) = _text
if is_obj(_type) = 0 : wg_update
return id
#deffunc wg_mes str _text
id = wg_create(WG_TYPE_MES, 0, 0, _text)
pos wgs_x(id), wgs_y(id) + 20
return id
#deffunc wg_input str _text
id = wg_create(WG_TYPE_INPUT, ginfo_objx@, ginfo_objy@, _text)
dummy = ""
input dummy, wgs_w(id), wgs_h(id)
wgs_objid(id) = stat
objprm wgs_objid(id), wgs_text(id)
return id
#deffunc wg_show int _id, int _flag
wgs_visible(_id) = _flag
if is_obj(_type) {
if _flag {
ShowWindow objinfo_hwnd(wgs_objid(_id)), 5
} else {
ShowWindow objinfo_hwnd(wgs_objid(_id)), 0
}
} else {
wg_update
}
return
#deffunc wg_get_pos int _id, var _x, var _y
_x = wgs_x(_id)
_y = wgs_y(_id)
return
#deffunc wg_set_pos int _id, int _x, int _y
wgs_x(_id) = _x
wgs_y(_id) = _y
wg_update
return
#defcfunc wg_get_text int _id
return wgs_text(_id)
#deffunc wg_set_text int _id, str _text
wgs_text(_id) = _text
if is_obj(wgs_type(_id)) {
objprm wgs_objid(_id), _text
} else {
wg_update
}
return
#global
wg_init
; サンプルなのでmesとinputだけ実装
screen 0
pos 100, 100
color 255, 0, 100
wg_mes "メッセージA" : id_msga = stat
color 0, 0, 0
wg_mes "メッセージB" : id_msgb = stat
objsize 50, 20 : wg_input "hello" : id_inpt = stat
await 1000 ; 1秒後にinputの位置を変更
wg_get_pos id_inpt, x, y
wg_set_pos id_inpt, x + 50, y + 50
await 1000
wg_show id_msga, 0 ; 2秒後にメッセージAを非表示
await 1000
wg_set_text id_msgb, "see" ; 3秒後にメッセージBとinputのテキストを変更
wg_set_text id_inpt, "you"
| |
|
2015/5/1(Fri) 07:19:40|NO.68925
作るの早…ッ!
>こういう感じでしょうか?
まだ理解出来てないかもしれませんが、
そうゆう感じです。と言うかそれです。
HSPはそうなるのですね。
なんかモジュールを作らせてしまったようで本当に申し訳ありません。
ちなみにHSPでは、その管理方式でプログラムしていくのは良い方法ですか?
(私には良い方法に見えました)。
あと、(今回の件に関係なく)そうゆう管理方式は突発的に
id = 70098001 みたいな数値がどこかで発生すると困るのですが、
これは連想配列みたいな物をなんとか自分で作っておくのが良いのでしょうか?
HSPダウンロード当初は、
プログラムするためのモジュールから作らなければならないとは思っていなかったので、
質問の手順がおかしくなっている気がします。
>クロージャという概念を正しく理解できている自信がないので
おそらく理解されてると思うので全く説明の必要はないように思います。
ただしクロージャには、実装の手っ取り早さがあって、そうゆう意味の期待も込めてます。
例えば、透明な子ウィンドウなら、(例え透過pngを多用しようとも)
私は労力を使うこともなくhwndさえあればAPIが全部やってくれそうだ的な。
(そして次のプログラムを作っても事前準備なしで同一の方法が取れる)。
|
|
2015/5/1(Fri) 11:12:45|NO.68927
> なんかモジュールを作らせてしまったようで本当に申し訳ありません。
やったことがない試みだったので興味が乗っただけですよ。
> ちなみにHSPでは、その管理方式でプログラムしていくのは良い方法ですか?
> (私には良い方法に見えました)
上記の通り、オブジェクトと非オブジェクトを一緒くたに扱う部品化は
初めての試みなので、どうなのかは分かりませんが悪くはないと思います。
ドラッグで移動できれば開発時にはフォームデザイナとしても使えそうですし。
しかし、個人的にHSPであまり画面の忙しいダイナミックなGUI捌きは行わないので、
わざわざそういうモジュールを用意する必要に迫られないというのが実情です。
> あと、(今回の件に関係なく)そうゆう管理方式は突発的に
> id = 70098001 みたいな数値がどこかで発生すると困るのですが、
> これは連想配列みたいな物をなんとか自分で作っておくのが良いのでしょうか?
このソースくらいの走査数(最大256)ならIDの断片化は問題になりませんが、
もっと拡張したり、IDを任意に決定できる仕様にしたいということでしょうか。
その場合には仰るようにIDをリスト構造や連想配列で管理したいところですが、
HSPには配列とモジュール変数(newmodで実体化するやつ)しかないので、
そういう仕様は極力防ぐというメタな解決方法がせめてもの回答です。
実行ファイル以外にDLLなどのバイナリを同梱することに抵抗がないのなら、
探せばリスト構造などの良さそうなコンテナのプラグインもありますが。
> HSPダウンロード当初は、
> プログラムするためのモジュールから作らなければならないとは思っていなかったので、
> 質問の手順がおかしくなっている気がします。
そうですね。初心者としてはかなり飛ばされていると思います。
それだけに疑問なのですが、TNKさんはどうしてHSPを学び始めたんですか?
> おそらく理解されてると思うので全く説明の必要はないように思います。
そうですか。
一応、認識を書いておくと、「一つ外のスコープの変数が読める関数」程度です。
> 透過pngについて
アルファチャンネル付きのPNG画像を子ウィンドウに貼り付けたとき、
子ウィンドウの背景が透明(≠半透明)ならば、
そのPNG画像からは親ウィンドウの背景が透けて見える……なんてことはない
というのが私の予想ですが、実際にはどうなるのか気になるところです。
親ウィンドウの背景を子ウィンドウに転写してその上にPNGを乗せることで、
あたかも子のPNGから親の背景まで透過しているかのように見せかける小細工はできそうですが。
| |
|
2015/5/1(Fri) 23:54:49|NO.68935
ハッシュテーブルを検索して見ましたが、どうも思ったほど柔軟でも万能でもないようです。
もうめんどうくさくなったら、ファイル名→データ をやってしまいそうな気がしないでもないです。
>TNKさんはどうしてHSPを学び始めたんですか?
どこかで最も手軽にGUIを表示できると見て…。完全にそれだけですね。
>親ウィンドウの背景が透けて見える……なんてことはない
どうなんでしょうか。
そもそも仕上がったウィンドウを透明にレイヤー化は出来るみたいですが、
ウィンドウデフォルトカラーを透明に初期化するってのはないみたいですし。
夢みててもしょうがないんで切り替えました。
>親ウィンドウの背景を子ウィンドウに転写して
それは一瞬思いつきましたが、無駄なのでやらないほうが良いことと思いました。
無条件に子ウィンドウを動かしてもなんでもないよ、ってのが元々ポイントの一つだったわけで。
それならArtlet2D を普通に使うほうが良いと言うか。
一度ht_askさんの方式で何か作ってみようと思います。
気になるのは 関数名の大量汚染、新規に何か作るたびいちいちモジュール側の徹底対応と記憶、ID管理の3点でしょうか。
これらがどの程度(私にとって)めんどうなことを起こすのかがポイントです。
モジュールは一度完璧にしてしまえば、それ以後は比較的楽になる気もしますが…。
>クロージャという概念を正しく理解できている自信がないので
>認識を書いておくと、「一つ外のスコープの変数が読める関数」程度です。
いつでも動的に空間と変数、関数の三点セットを作れるですね。
まぁ全部書くと長くなるんですが、私が今ここで希望してるのは手軽かつシンプル(そして問題が発生しない)と言う点でしょうか。
一応、本当のクロージャを書いてみますが、明らかに無理そうな機能は希望してません。
(以下はなんの言語でもありません。記述を簡略化するためスクリプト風に書きます)。
//▼クロージャ定義
function new{
// 初期値設定 (局所化変数)
static dataA = 引数1; //これは new に対しての引数。
static dataB = 引数2; //※staticは動的な宣言ごとに各個新規発生とする。(アドレスも実体も別)。
static function get_data{
return(dataA, dataB);
}
static function set_data{
dataA = 引数1; //これは set_data に対しての引数
dataB = 引数2;
}
// さらに普通は、ここに dataAとdataBを使って何か本格的な処理をする static function :execute{} を記述する。
return( &get_data, &set_data ); //言語によって方式は違うが、ここでは閉包関数のアドレス群を返すことで処理が成立するものとする。
}
//▼クロージャ使用
box_A = new(10, 20); // box_Aが定義され、ブラックボックス的な空間が生成される
box_B = new(50, 60); // box_Bも作る。
print *box_A[get_data]; // box_Aが持つget_dataを起動。10と20が出力。
*box_A[set_data] = (100, 200); // box_Aのdataを書き換える。(関数を左辺値のように使える言語もある。気にすることなかれ)。
print *box_A[get_data]; // 100と200が出力
print *box_B[get_data]; // 50と60が出力。box_Aとbox_Bが内部に持つ変数と関数は無関係で干渉しない。
// クロージャは実行中の都合により、いつでもいくつでも個別の新規空間が生成できること。
// その空間には、いかなる手段を用いても他からのアクセスが許されないこと。(ただしnewがdataのポインタをreturnした場合はやむを得ない)。
// その空間を処理する関数(この場合だとset_dataとか)があり、newはbox_Aだけに対し、それを与えること。
// box_Aに与えられた関数の名前もbox_Aだけの所有であり、関係ない場所を汚染しないこと。
// (上記の場合、set_dataを用意せずにexecuteを用意すれば、実質dataの操作権はexecuteだけになり完全に閉包される)。
こうゆう感じで事前準備がなく書けます。
私の場合プログラムスキルが低いのと、楽をしたい思いからいきなりそうゆうのが欲しくなります。
息をするようにモジュールを作る人にはクロージャは必要ないのかもしれません。
でもけっこう色々出来るので便利です。
主なクロージャの使い道。
ブラックボックス化された大量データの保存、管理。
また、それらの値を参照、使用する関数群。
関数を実行時の都合で定義して生成する。(関数生成時の引数で関数の挙動が定義でき、関数使用時にまた引数が送れるため)。
動的に似たような関数の大量生産。
簡易的なオブジェクト指向
など。
| |
|
2015/5/2(Sat) 01:38:14|NO.68939
詳しく説明してくださってありがとうございます。
クラスのない言語がクラスの機能を欲しいときの機構という感じですね。
HSPのモジュール変数でそれっぽいのを再現するとこうです。
#module new dataA, dataB
#modinit int 引数1, int 引数2
dataA = 引数1
dataB = 引数2
return
#modfunc get_data var a, var b
a = dataA
b = dataB
return
#modfunc set_data int a, int b
dataA = a
dataB = b
return
#global
newmod box_A, new, 10, 20
newmod box_B, new, 50, 60
get_data box_A, a, b
print "" + a + ", " + b
set_data box_A, 100, 200
get_data box_A, a, b
print "" + a + ", " + b
get_data box_B, a, b
print "" + a + ", " + b
|
|
2015/5/3(Sun) 06:42:01|NO.68950
やり始めると終わらなくなりました。
きっと簡単には終わらない予感がします。
|
|
2015/5/4(Mon) 05:05:47|NO.68970
ちょっと昨日から他のこと始めて気持ちが離れてるけど。
骨組みだけで作って保留中。作り変えるなら今のうち…
#module Atlas\
name, widget_type, widget_id, obj_estable, window_id, visibility,\
colors, text, font_name, font_size, font_style, drawing,\
label, flag, style
; モジュール内グローバル変数一覧 delete_check, b_push これ以外にあったらミス
;
; 1:mes, 101:input, 102:chkbox, 103:botton. 104:conbox, 105:listbox, 106:mesbox
; 100以上でHSPオブジェクトだが区別しなくても問題は出ない(ように出来てるはず)。
; メモ → 104〜106は表示未テスト
#modinit int wtp, int wid
name = "" ; 名前を付けると便利かもしれない。いらないかもしれない。現在モジュール使用側の任意的な識別子以上の意味は持たない。
widget_type = wtp ; ウィジェットの種類。
widget_id = -1 ; HPSオブジェクト場合は設置した瞬間IDを取る。(初期値はあり得ない値にしておく)
window_id = wid ; 表示先ウィンドウID
visibility = 1 ; 1=表示, 0=非表示
colors(0) = 0 ; R 色
colors(1) = 0 ; G
colors(2) = 0 ; B
colors(3) = 255 ; α 不透明度
text = "" ; 表示文字
font_name = "MS ゴシック" ;フォント名
font_size = 14 ; size
font_style = 1 ; style HSPの仕様と同じ
drawing(0) = 0 ; x 座標(図面)
drawing(1) = 0 ; y
drawing(2) = 0 ; w
drawing(3) = 0 ; h
label = *jump ; ボタン用ラベル
flag = 0 ; チェックボックスとか
style = 0 ; メッセージボックスとか
b_push(0) = 0 ; ボタンが押されたのかチェック用 (押したflag) モジュール型ではない。
b_push(1) = 0 ; ボタンが押されたのかチェック用 (id管理)
return
//
// パック関係
// pack_widget 以外は内部関数
#deffunc pack_widget array all, local cp, local wid, local clr
redraw 0
clrobj 0, -1
cp(0) = ginfo_cx : cp(1) = ginfo_cy ;元に戻す物記憶
wid = ginfo_sel
clr(0) = ginfo_r : clr(1) = ginfo_g : clr = ginfo_b
dim delete_check, 1024
foreach all
pack_single all(cnt)
loop
pos cp(0), cp(1) ;なるべく元に戻す。戻しかたが分からないやつはもう知らん
color clr(0), clr(0), clr(0)
gsel wid
redraw 1
return
#modfunc pack_single
if visibility == 0 : return ;お帰り下さい
if widget_type == 0 : return
gsel window_id
if delete_check(window_id) != 1 { ;初回操作は画面削除
color 255, 255, 255 : boxf
delete_check(window_id) = 1
}
color colors(0), colors(1), colors(2) ;変更
font font_name, font_size, font_style
pos drawing(0), drawing(1)
if widget_type > 100 { ;HSPオブジェクトにのみ関係ある変更
objsize drawing(2), drawing(3)
objmode 2
}
if widget_type == 1 : pack_mes thismod
if widget_type == 101 : pack_input thismod
if widget_type == 102 : pack_chkbox thismod
if widget_type == 103 : pack_button thismod
if widget_type == 104 : pack_combox thismod
if widget_type == 105 : pack_listbox thismod
if widget_type == 106 : pack_mesbox thismod
return
#modfunc pack_mes
mes text
return
#modfunc pack_input
input text
widget_id = stat
return
#modfunc pack_chkbox
chkbox text, flag
widget_id = stat
return
#modfunc pack_button
button gosub text, label
if 0 { *jump : b_push(0) = 1 : b_push(1) = stat : return }
widget_id = stat
return
#modfunc pack_combox
combox flag, 100, text ; 100は適当
widget_id = stat
return
#modfunc pack_listbox
listbox flag, 100, text ; 100は適当
widget_id = stat
return
#modfunc pack_mesbox
mesbox text, drawing(2), drawing(3), style, -1 ; -1は変数の容量に応じる。
widget_id = stat
return
//
// setとget
//
#modfunc set_name str set ;set名前
name = set
return
#modcfunc get_name ;get名前
return name
#modcfunc get_widget_type ;getウィジェットタイプ //setは意義がわからないので未実装。
return widget_type
#modfunc set_window int set ;setウィンドウID
window_id = set
return
#modcfunc get_window ;getウィンドウID
return window_id
#modfunc set_visibility int set ;set可視化
visibility = set
if set == 0 : widget_id = -1 ; 過去の遺物は混乱を起こすかもしれない
return
#modcfunc get_visibility ;get可視化
return visibility
#modfunc set_txt str set ;set文字
text = set
return
#modcfunc get_txt ;get文字
return text
#modfunc set_color int set0, int set1, int set2, int set3 ;set色 arrarにしてループで代入したら呼び出しが変数じゃないとエラーだった。
colors(0) = set0
colors(1) = set1
colors(2) = set2
if set3 : colors(3) = set3
return
#modfunc get_color array _get ;get色
repeat 4
_get(cnt) = colors(cnt)
loop
return
#modfunc set_font str set1, int set2, int set3 ;setフォント
font_name = set1
font_size = set2
font_style = set3
return
#modfunc get_font str _get1, int _get2, int _get3 ;getフォント
_get1 = font_name
_get2 = font_size
_get3 = font_style
return
#modfunc set_drawing int set0, int set1, int set2, int set3 ;set座標と長さ
drawing(0) = set0
drawing(1) = set1
if(set2) : drawing(2) = set2
if(set3) : drawing(3) = set3
return
#modfunc get_drawing array _get ;get座標と長さ。
repeat 4
_get(cnt) = drawing(cnt)
loop
return
#modfunc set_label var set ;setラベル //必要性が分からないのでgetは作らない
label = set
return
#modcfunc get_widget_id ;getウィジェットID
return widget_id
#modcfunc get_push ;getボタン判定
if b_push(0) and b_push(1) == widget_id {
b_push(0) = 0 : b_push(1) = 0
return 1
}else{
return 0
}
return
#modfunc set_flag int set ;setフラグ(もしくは現在の選択内容)
flag = set
return
#modcfunc get_flag ;getフラグ
return flag
#modfunc set_style int set ;setスタイル
style = set
return
#modcfunc get_style ;getスタイル
return style
#global
; もしかしてオブジェクトの管理方法(番号制)がめんどうかも。
label = *jump
newmod widget, Atlas, 103, 0 ; widget(0): 103はボタン
set_txt widget, "ボタン名" ; 何も設定しなくても動くけど、何も設定してないのでいいことなし。
set_label widget, label ; ボタンにラベルは設定しない方法もある。
set_drawing widget, 150, 30, 160, 40 ; x y w h
set_font widget, "MS ゴシック", 20, 3
newmod widget, Atlas, 1, 0 ; widget(1): 1はmes
set_txt widget(1), "テスト用表示文字列"
set_drawing widget(1), 10, 10
set_color widget, 128, 0, 64 ; r g b
newmod widget, Atlas, 103, 0 ; widget(2):
set_txt widget(2), "ボタン2"
set_label widget(2), label
set_drawing widget(2), 360, 210, 120, 28
set_font widget(2), "MS ゴシック", 12, 1
pack_widget widget ; pack_widgetで全部描画。(それ以前の表示物は消えます)。
wait 100000 ;waitと言うか、ボタンが押されたら(イベントハンドラが起動したら)解除される
set_drawing widget(0), 240, 100, 210, 28 ;ボタンを移動してみる
newmod widget, Atlas, 103, 0 ; widget(3):
set_txt widget(3), "ラベル設定のないボタン1"
set_drawing widget(3), 360, 410, 180, 28
set_font widget(3), "MS ゴシック", 12, 1
newmod widget, Atlas, 103, 0 ; widget(4):
set_txt widget(4), "ラベル設定のないボタン2"
set_drawing widget(4), 360, 440, 180, 28
set_font widget(4), "MS ゴシック", 12, 1
newmod widget, Atlas, 101, 0 ; widget(5): 101 input
set_txt widget(5), "input"
set_drawing widget(5), 30, 450, 180, 20
newmod widget, Atlas, 102, 0 ; widget(6): 102 checkbox
set_txt widget(6), "chk\nbox"
set_drawing widget(6), 30, 420, 180, 20
pack_widget widget
; ラベル名を設定していないボタンが押された場合、該当の get_push が1を返す。(設定した場合はダメ)。
; get_pushは読み出すと勝手に0に戻る。入力待ちができる。
repeat
wait 1
foreach widget
if get_visibility (widget(cnt)) == 0 : continue ; もっといろいろな監視や処理をしたい場合は不要。
if get_widget_type(widget(cnt)) != 103 : continue ;
if get_push(widget(cnt)) {
mes_txt = "オブジェクト widget(" + cnt + ")が押されました。\n"
mes_txt += "このボタンを扱う際、statは不要。\n"
mes_txt += "\n\n\n左下input内容:"
mes_txt += "" + get_txt(widget(5)) + "\n"
set_txt widget(1), mes_txt
pack_widget widget
}
loop
loop
if 0 { ;ラベルを設定したボタン
*jump
mes_txt = "押されたボタン stat:" + stat + " に get_widget_id(widget(*)) が対応\n"
mes_txt += "ただしget_widget_idはpack後に成立します。\n"
set_txt widget(1), mes_txt
pack_widget widget
return
}
stop
| |
|