hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
ウィンドウの親子関係 - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

小ワザ | SplitWindow

HSP2.61 HSP3.0

ウィンドウの親子関係

ウィンドウの呼び名

親ウィンドウとは

クライアント領域内に他のウィンドウを所有しているウィンドウを親ウィンドウと呼ぶ。
またその所有されているウィンドウを子ウィンドウと呼ぶ。

子ウィンドウとは

他のウィンドウに所有されているウィンドウを子ウィンドウと呼ぶ。

HSP標準オブジェクトである input / button / chkbox / listbox / combox / mesbox などは子ウィンドウである。(Windowsでは子コントロールと呼ぶことが多い。)

オーナーウィンドウとは

他のウィンドウを所有しているウィンドウをオーナーウィンドウと呼ぶ。

親ウィンドウに所有されている子ウィンドウは親ウィンドウのクライアント領域外には出られず、親ウィンドウの背後に回ることも出来ません。
またアクティブにもなれません。子ウィンドウをクリックしたときにアクティブになるのは親ウィンドウです。

一方のオーナーウィンドウに所有されている子ウィンドウ――という呼び方は一般的ではありません。
一般的にはオーナー付きウィンドウと呼び、子ウィンドウと区別をしています。
――オーナー付きウィンドウはオーナーウィンドウのクライアント領域に限らず画面を自由に移動できます。
アクティブにもなることができます。
ただし、所有関係からは脱することが出来ずにオーナーウィンドウの背後に回ることが出来ません。

2つのAPI関数

Win32 API関数にはウィンドウの親子関係を動的に変更するための関数が用意されています。
SetParent?()関数とSetWindowLong?()関数です。しかし両者は似ているようで若干動作が異なります。

SetWindowLong?()関数

ウィンドウスタイルを変更するときに良く使うのがSetWindowLong?()関数です。
SetWindowLong?()を使って親ウィンドウを変更することが出来ます。

  • hsp2.61
      1
      2
      3
      4
    
     
     
     
     
    
        #include "llmod.as"
        #define GWL_HWNDPARENT (-8)
        prm = hwndTarget, GWL_HWNDPARENT, hwndNewParent
        dllproc "SetWindowLongA", prm, 3, D_USER
  • hsp3.0
      1
      2
      3
    
     
     
     
    
        #include "user32.as"
        #define GWL_HWNDPARENT (-8)
        SetWindowLong hwndTarget, GWL_HWNDPARENT, hwndNewParent
    といった感じで使います。
    ということで早速サンプルです。fileSAMPLE1(失敗例)

呼び名で紹介した子ウィンドウの動作と違いますね。アクティブになりますし、クライアント外に移動できますし。
結論から言うとSetWindowParent?()はオーナーを変更するときに使います。つまりオーナー付きウィンドウを動的に設定するときに使います。(多分)

SetParent?()関数

親ウィンドウを変更する場合はSetParent?()関数を使います。つまり子ウィンドウを動的に設定するときに使います。

  • hsp2.61
      1
      2
      3
    
     
     
     
    
        #include "llmod.as"
        prm = hwndTarget, hwndNewParent
        dllproc "SetParent", prm, 2, D_USER
  • hsp3.0
      1
      2
    
     
     
    
        #include "user32.as"
        SetParent hwndTarget, hwndNewParent
    という感じで使います。
    では早速sample1をSetParent?に変更したものを示します。fileSAMPLE2(失敗例)

またまた子ウィンドウの動作と違いましたね。
クライアント領域外には出られませんがアクティブになります。(これはこれでMDIっぽいですが・・・本来の子ウィンドウではありません。)

子ウィンドウを定義する

子ウィンドウを作るときはウィンドウスタイルにWS_CHILD(0x40000000)を含めなければなりません。
失敗したのはHSPのscreenで作られるウィンドウにこのスタイルが含まれていないためです。
子ウィンドウ(コントロール)を配置する際にはWS_CHILDを含めてください。

ということでscreenで作ったウィンドウを子ウィンドウに出来ました。fileSAMPLE3

ウィンドウの作成順が逆なのはウィンドウスタイルや親ウィンドウを変更してもすぐさまそれが反映されるわけではないからです。
screen 2を作った時点ではscreen 2がアクティブになるため子ウィンドウにしてもアクティブになってしまうからです。(gsel 0で解決)

また子ウィンドウはWS_POPUP(0x80000000)とは併用できません。
これは子ウィンドウ(WS_CHILD)には自分自身を所有している親ウィンドウにメッセージを処理したことを伝えるという仕事も行っているからです。

というわけでWS_CHILDの有る無しで何が変わってくるのか、という動作をボタンを使って示します。fileSAMPLE4
ボタンが押されると親ウィンドウにWM_COMMANDが送られます。
ここで初めて指定したラベルにジャンプしてカウンタがインクリメントされますが、WS_CHILDを外すと子ウィンドウではなくなるので親がいません。
親は子からWM_COMMANDが送られてこないのでラベルにはジャンプしないため止まったままです。

いろいろな親子形態

  • グラフィックソフト GIMP
    ・ツール
    ・キャンバス
    ・レイヤー
    ・パレット
    GIMPにはツールウィンドウ(メインウィンドウ)、キャンバスウィンドウ、レイヤーウィンドウ、パレットウィンドウなどがあります。
    GIMPのウィンドウは全てが親です。ちょうどscreenで複数ウィンドウを作ったようなものです。
    クリックしたウィンドウが前面に出てきますし、最大化・最小化もウィンドウ毎に行えます。
    タスクバーにはウィンドウの数だけタスクバーにアイコン(?)が並びます
    親子関係のサンプルはこちらです。fileSAMPLE5
  • 音楽プレイヤー winamp
    ・メイン┬・プレイリスト
        ├・イコライザ
        └・ライブラリ
    winampには再生ボタンなどを配置したメインウィンドウにプレイリストウィンドウ、イコライザウィンドウ、ライブラリウィンドウなどがあります。
    メインウィンドウ以外のウィンドウはメインウィンドウの背後に回ることが出来ませんが、その他のウィンドウ同士では前面・背後と自由に入れ替わることが出来ますし、画面上どこにでも移動できます。
    また、他のアプリケーションにフォーカスがある時にwinampウィンドウをクリックするとクリックしたウィンドウ(メイン以外)が最前面になるのはもちろん、フォーカスを失ったアプリケーションが全てのwinampウィンドウの背後に回ります。
    これがメインウィンドウをオーナーとするオーナー付きウィンドウに当たります。
    タスクバーに表示されるアイコンはオーナーだけという点も注目してください。
    親子関係のサンプルはこちらです。fileSAMPLE6(親子関係にSetWindowLong?()を使っている点に注意してください。)

    SAMPLE6をWS_CHILDをセットしないでSetParent?()を使うとMDIちっくな外見になりますがMDIと動作が違うのは当たり前です。fileSAMPLE7

  • Borland 統合開発環境 Delphi
    [・オーナー]┬・トップ
           ├・ツリー
           ├・インスペクタ
           ├・フォーム
           └・エディット
    統合開発環境Delphiではメインとなるフォームウィンドウ、ソース編集を行うエディットウィンドウの他にオブジェクインスペクタ、オブジェクトツリーウィンドウなどがあり、最上部には各種ツールバーを備えたトップウィンドウから成っています。
    他のアプリケーションからフォーカスを得るとアプリケーション全体がフォーカスを失ったウィンドウの前面に出ます。
    トップウィンドウをオーナーとするオーナー付きウィンドウみたいですね。でも――
    注目するべきなのはトップウィンドウを含める全てのウィンドウが自由に前面・背後に入れ替えられる点です。
    オーナー付きウィンドウはオーナーの背後に回れませんがDelphiでは他のウィンドウがどのウィンドウの背後にも回れます。(ダイアログは除きますが)
    実はDelphiには目に見えないウィンドウがあり、それがオーナーとなっています。
    Delphiを実際に使って見れない人にはパッとこないので親子関係のサンプルを示します。fileSAMPLE8

    次の点に注目してください。

    • 4つのウィンドウはそれぞれが前面・背後に入れ替わることができる。
    • タスクバーにはウィンドウ一つ分のアイコンしか表示されない。(複数のウィンドウを使ってもタスクバーにはアプリケーションのタイトルだけを表示できます。)
    • オーナーウィンドウは目に見えない。(画面外に出してしまうというのも手ですが)
    • トップウィンドウを最小化しようとすると全て最小化される。

コメント

  • サンプルを示すのにAPI呼び出しが簡単なHSP3.0を使うことにしました。 -- kz3 2005-12-24 (土) 11:35:31
  • Delphiの親子関係のスクリのキャプションがwinampのままなのは気にしないでください。 -- kz3 2005-12-26 (月) 10:28:14

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2007-04-08 (日) 02:38:48 (2436d)