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


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0429
TNK透明な子ウィンドウがほしい16解決


TNK

リンク

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で表示される全ての要素を完全に個別管理したいと思っています。



この記事に返信する


TNK

リンク

2015/4/29(Wed) 07:48:43|NO.68872

書き忘れましたが、
SetParent hw(2), hw(1) ;子ウィンドウにする
この行をコメントアウトすると半透明なウィンドウは生成されます。



kanahiron

リンク

2015/4/29(Wed) 08:28:07|NO.68873

Windowsの仕様でレイヤードウィンドウは子ウィンドウになれません



MIZUSHIKI

リンク

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>

お試しください。



ht_ask

リンク

2015/4/30(Thu) 00:38:38|NO.68898

SetWindowLongPtrの第三引数は64bitなので32bit版のHSPからは使えないのだと思います。
Cのヘッダでは処理系が32bitのときSetWindowLongPtrはSetWindowLongに置換されるので、
あたかもSetWindowLongPtrを二種の環境で両用できるように振舞います。



TNK

リンク

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を使う意味はなさそうですね。
ありがとうございました。



kanamaru

リンク

2015/4/30(Thu) 08:17:16|NO.68900

新しいバージョンの3.5b1では64bit版ランタイムがありますよ。
といってもまだバグが残るベータ版ですが。
とりあえず一番上のソースを見る限りではバグの影響を受けないようなソースに
見えるので、3.5を使ってもいいかもしれません。



774

リンク

2015/4/30(Thu) 20:59:45|NO.68910

不躾ながら、子ウィンドウ単位で管理する必要性があるのでしょうか?
要素(物)単位で配列等を使って管理すれば済む話のように思えました。

特にボタンなどのオブジェクト(コントロール)は、それ自体が子ウィンドウのようなものなので二度手間のような気がします。



ht_ask

リンク

2015/4/30(Thu) 21:20:38|NO.68911

いまいち目的を理解していないので何とも言えないのですが私も同感です。
位置やサイズや種別(mesやbuttonなど)のデータベースを作って個別に操作という感じで。

たまたま似たようなことを以下のスレッドのサンプルコードで行っているので、ご参考までに。
http://hsp.tv/play/pforum.php?mode=all&num=68867



TNK

リンク

2015/4/30(Thu) 23:22:01|NO.68916

参考にさせて頂きました。大変綺麗で見やすかったです。

別に冒頭であげたような管理方法はどうしてもと言うわけでなく、
かえってその方法でめんどうになるようなら、使う理由はなくなります。

ただ、私の希望はプログラム全体の構造にも関わる物で、
例えば、オブジェクト自身(もしくはウィンドウハンドル)が最初からすでに自分の状態を知っている、
と言うのも望ましい理由の一つです。


>配列等を使って管理すれば済む話のように思えました
この助言でピンと来たのですが、例えばクロージャのような物は使えないでしょうか?
使えるとけっこう事情が変わってくるような気がしました。

いや、他にも思いつくような工夫の余地はいろいろあるので、別にクロージャでなければならない、と言う理由は全くありません。



ht_ask

リンク

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"



TNK

リンク

2015/5/1(Fri) 07:19:40|NO.68925

作るの早…ッ!

>こういう感じでしょうか?
まだ理解出来てないかもしれませんが、
そうゆう感じです。と言うかそれです。
HSPはそうなるのですね。
なんかモジュールを作らせてしまったようで本当に申し訳ありません。

ちなみにHSPでは、その管理方式でプログラムしていくのは良い方法ですか?
(私には良い方法に見えました)。

あと、(今回の件に関係なく)そうゆう管理方式は突発的に
id = 70098001 みたいな数値がどこかで発生すると困るのですが、
これは連想配列みたいな物をなんとか自分で作っておくのが良いのでしょうか?


HSPダウンロード当初は、
プログラムするためのモジュールから作らなければならないとは思っていなかったので、
質問の手順がおかしくなっている気がします。


>クロージャという概念を正しく理解できている自信がないので
おそらく理解されてると思うので全く説明の必要はないように思います。

ただしクロージャには、実装の手っ取り早さがあって、そうゆう意味の期待も込めてます。
例えば、透明な子ウィンドウなら、(例え透過pngを多用しようとも)
私は労力を使うこともなくhwndさえあればAPIが全部やってくれそうだ的な。
(そして次のプログラムを作っても事前準備なしで同一の方法が取れる)。



ht_ask

リンク

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から親の背景まで透過しているかのように見せかける小細工はできそうですが。



TNK

リンク

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だけになり完全に閉包される)。

こうゆう感じで事前準備がなく書けます。
私の場合プログラムスキルが低いのと、楽をしたい思いからいきなりそうゆうのが欲しくなります。
息をするようにモジュールを作る人にはクロージャは必要ないのかもしれません。
でもけっこう色々出来るので便利です。

主なクロージャの使い道。
ブラックボックス化された大量データの保存、管理。
また、それらの値を参照、使用する関数群。
関数を実行時の都合で定義して生成する。(関数生成時の引数で関数の挙動が定義でき、関数使用時にまた引数が送れるため)。
動的に似たような関数の大量生産。
簡易的なオブジェクト指向
など。



ht_ask

リンク

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



TNK

リンク

2015/5/3(Sun) 06:42:01|NO.68950

やり始めると終わらなくなりました。
きっと簡単には終わらない予感がします。



TNK

リンク

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



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