tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルフォームの重ね順番制御について
記事No11743
投稿日: 2016/10/11(Tue) 16:53
投稿者SUZUKI
いつもお世話になっております
vb6.0とvb2005の仕様の差で悩んでいます
少々説明しにくいのですがお助けお願いします

まずvb2005にてform1 form2 を表示させます(横並びに)
ここにエクセルでもワードでもよいのですが起動させます

ここからvb2005に戻りたくなってform1をクリックします
そうすると 上から form1 エクセル form2 という順番になります
当然という気はするのですが
しかし、vb6では 上から form1 form2 エクセル と
エクセルが一番下に行ってくれます

特にプログラムを組んでいないので
vb6は親切であったという感じです
検索の仕方もよくわからず
この解決策を教えていただきたいのですが


[ツリー表示へ]
タイトルRe: フォームの重ね順番制御について
記事No11744
投稿日: 2016/10/11(Tue) 21:28
投稿者魔界の仮面弁士
==== VB2005 ====

(1) プロジェクトに新しいクラス ファイルを
  "ThunderMain.vb" という名で追加します。

(2) そのファイルの内容を、以下のように差し替えます。

Public Class ThunderMain
    Inherits System.Windows.Forms.Form
End Class


(3) Form1 および Form2 の Load イベントに下記を記述します。

If Me.Owner Is Nothing Then Me.Owner = My.Forms.ThunderMain


これで、VB6 互換の動作になると思います。
もっと巧いやり方があるのかもしれませんが、とりあえず思いついた方法ということで。



ちなみに上記に書いた "ThunderMain" とは、VB6 が持つ「隠しフォーム」の名前です。
VB6 では下記のようにして、ThunderMain およびロード済みフォームのハンドルを得られます。
蛇足情報ですが、一応参考までに。

==== VB6 ====

'----- 出力先は ListBox でも Debug.Print でも良いけれど
List1.Clear
Dim f As Form
For Each f In Forms
    List1.AddItem TypeName(f) & vbTab & Hex(f.hWnd)
Next
With New CThunderMain
    List1.AddItem "ThunderMain" & vbTab & Hex(.hWnd)
End With

'----- 上記で使う CThunderMain.cls ファイル
Option Explicit
Private Declare Function FindWindowW Lib "user32.dll" (ByVal lpClassName As OLE_HANDLE, ByVal lpWindowName As OLE_HANDLE) As OLE_HANDLE
Private m_hWnd As OLE_HANDLE
Public Property Get hWnd() As OLE_HANDLE
    hWnd = m_hWnd
End Property
Friend Property Get IsDebug() As Boolean
    Dim debugMode As Boolean
    Debug.Assert OnDebug(debugMode)
    IsDebug = debugMode
End Property
Private Function OnDebug(ByRef debugMode As Boolean) As Boolean
    debugMode = True
    OnDebug = debugMode
End Function
Private Sub Class_Initialize()
    Dim sTitle As String
    sTitle = App.Title
    App.Title = Hex(ObjPtr(Me))
    If IsDebug Then
        m_hWnd = FindWindowW(StrPtr("ThunderMain"), StrPtr(App.Title))
    Else
        Dim sThunderMain As String
        'sThunderMain = "ThunderRTMain"     'VB4
        'sThunderMain = "ThunderRT5Main"    'VB5
        sThunderMain = "ThunderRT6Main"     'VB6
        m_hWnd = FindWindowW(StrPtr(sThunderMain), StrPtr(App.Title))
    End If
    App.Title = sTitle
End Sub

[ツリー表示へ]
タイトルRe^2: フォームの重ね順番制御について
記事No11745
投稿日: 2016/10/12(Wed) 08:47
投稿者SUZUKI
思ったような動きになりました
感動です
これから、じっくり鑑賞させていただきます
ありがとうございました

[ツリー表示へ]
タイトルRe^3: フォームの重ね順番制御について?
記事No11750
投稿日: 2016/10/25(Tue) 16:08
投稿者SUZUKI
魔界の仮面弁士さんからご提示いただいたサンプルを
観賞させてもらっています
自分にとっては、疑問だらけのコードで1行1行確認しています
このサンプルでどうしてもわからないというか
以前から疑問に思っている点があり一つ質問させて下さい

それは  Friend Property Get IsDebug() As Boolean という箇所です
自分の今までの概念ではFunction です
Propertyを使えれば使って行こうと思っているのですが
使う場面がよくわかっていません
なぜここで Friend Property を使うとよいのか
教えてもらえれば幸いです

[ツリー表示へ]
タイトルRe^4: フォームの重ね順番制御について?
記事No11751
投稿日: 2016/10/26(Wed) 19:45
投稿者魔界の仮面弁士
> 疑問だらけのコードで1行1行確認しています

数行だけのコードなので、コードそのものは難しくないと思いますが、
どうしてそれで回避できるのかは、ちょっとわかりにくいかも知れませんね。


> それは  Friend Property Get IsDebug() As Boolean という箇所です

えぇと、その部分は VB2005 向けのコードではなく、
VB6 用のものですが構いませんか?


今回作成した IsDebug プロパティというのは、
VB2005 でいうところの「Debugger.IsAttached」に相当するものです。

開発環境からのデバッグ実行時には True を返し、
コンパイルして EXE として実行すると False を返します。

この Boolean 値は、実行中に変化する事が無い値なので、
実際には毎回 OnDebug を呼び出すのではなく、一度調べた値を
使い回すようなプロパティ実装にした方が良かったかも知れません。


> 自分の今までの概念ではFunction です

ザックリ言えば、メソッド(Sub/Function)は「操作」。
そのオブジェクトの振る舞いを表します。
一方、プロパティ(Property)は「データ」や「状態」を
表すものです。この観点で使い分けています。

https://msdn.microsoft.com/ja-jp/library/ms229054.aspx


今回は、「デバッグモードか否か」という状態を返す実装と
位置づけたため、IsDebug プロパティとして実装しました。

VB.NET なら先述した Debugger.IsAttached プロパティ。
VB6 なら、ADODB.Connection の State プロパティとか、
UserControl の Ambient.UserMode プロパティとか、
あるいは App.StartMode プロパティなどをイメージしています。


とはいえ、無理にプロパティに拘る必要もないかと思います。

これを「デバッグモードかどうかを調べる『動作』である」
と考える場合は、メソッドとして実装しても良いと思いますし。



> 使う場面がよくわかっていません

自分自身、感覚で使い分けている部分が大きく、
あらためて質問されると、その使い分け方を
明確に説明できそうにありません…。(^^;


ちょいと脱線して、VB6の「CommonDialog」コントロールの実装。

VB2 の頃は、
 CommonDialog1.Action = 1
 CommonDialog1.Action = 3
 CommonDialog1.Action = 4
のように、Action プロパティをセットすることでダイアログを
表示させていました(技術的な理由もあったようですが)。

それが VB4 段階の実装では、プロパティ呼び出しは非推奨とされ、
 Call CommonDialog1.ShowOpen
 Call CommonDialog1.ShowColor
 Call CommonDialog1.ShowFont
のように、メソッド呼び出しで表示させるように変わっています。
これは、「動作」を指示するものであるのなら、メソッドの方が
望ましいという判断によるものだと思います。

これが .NET だと、ダイアログの種類ごとに別のクラスに
分離されたわけですが……Microsoft でさえこうした揺らぎが
あったわけですし、明確な使い分けルールの提示は難しそうです。


> なぜここで Friend Property を使うとよいのか

スコープを Friend にした理由に付いては、そもそも
Public にする必要が無いと考えてのことです。

何しろ、開発環境かどうかを「別のプロジェクト」から調べることは
ありえませんから。(別プロジェクトから呼ぶには DLL 化する必要があり、
その場合、IsDebug は常に False を返すことになりますので)

「自プロジェクト」からしか呼ばれないわけですから、スコープとして
選択肢に挙がるのは、Private または Friend のいずれかです。

その上で、今回は自クラス以外からも再利用できるようにと考え、
Friend を選択した次第です。

ただ、今にして思えば、Private の方が適切だったかもしれません。
(この点は、メソッドかプロパティかという問題とは別の話です)

そもそも「ThunderMain クラスがデバッグモードかどうか」を
調べている訳ではないので、ThunderMain の公開メンバーとして
実装されるのは不自然な気もしてきました。……非公開で十分だったかも。



でもって、なぜ Function ではなく Property Get にしたのかという点については、
先に述べた内容以上の理由は、特に持ち合わせていません。


メソッドとプロパティの使い分け方を、強いて例示するとすれば、
下記のようなイメージで考えています。

実装する段階で、プロパティにするかメソッドにするか悩む場合もありますが…。


------------
(1) 値の取得処理が軽量なケース、特に、内部のモジュール変数を
 単純にカプセル化したものはプロパティにしています。

いわゆる「バッキングフィールド」への間接的なアクセス手段を用意するケース。
一番多いのがこのパターンかも。

実際には「バッキングフィールドを公開するためにプロパティを作る」のではなく
「プロパティを実装する手段としてバッキングフィールドを用意する」ことが多いです。


------------
(2) 値の取得が比較的低速な場合は、メソッドを選択します。

今回の IsDebug は、実行中に値が変化するようなものでも無いですし、
さほど複雑な処理でもなく、十分に高速であるということで、
プロパティとして実装させました。

何を持って「低速」「高速」とするか線引きを聞かれると困りますが、
先の(1)のように、自身の内部データを取り出すだけなら、
プロパティでも良いのかな、と。


------------
(3) 引数を伴う処理はメソッドとして実装します。

プロパティに引数を付けるケースは非常に稀です。

たとえば ListBox.List のように、インデクサのような
振舞いにする場合はプロパティとして実装されますが、
それ以外のケースで引数を使う必要性は思い当たりません。
ADODB.Recordset の Collect プロパティもこの類ですね。

別パターンとしては、既存のプロパティを拡張するために、
省略可能な引数を付けるというケースがあります。
Excel はこれが意外と多くて困り者。(Range.Value プロパティなど)
------------

[ツリー表示へ]
タイトルRe^5: フォームの重ね順番制御について?
記事No11752
投稿日: 2016/10/27(Thu) 15:32
投稿者SUZUKI
詳細にわたるご説明でありがとうございます
今後、PROPERTYを積極的に使って見ようと思います
今回、formが隠れないようにするという単純な
問題でしたが奥が深いですね
継承、ハンドラ、実行モードとデバッグモード
OWNERとは 隠れフォーム と色々勉強になりました
まだまだ初級から脱していないと実感しました 

[ツリー表示へ]
タイトルRe^6: フォームの重ね順番制御について?
記事No11753
投稿日: 2016/10/28(Fri) 11:03
投稿者魔界の仮面弁士
> OWNERとは 隠れフォーム と色々勉強になりました

「Owner とは不可視フォームのこと」という認識だと間違いです。
あくまでも「不可視フォームを Owner に設定した」というだけ。


Owner はざっくり言えば、フォームの親子関係を示すものです。
たとえば、新規プロジェクトでこんなコードを書いてみます。

---
'.NET Framework 2.0 以降ではこう書ける
Dim f2 As New Form2()
Dim f3 As New Form3()
f2.Show(Me)
f3.Show()
---
'.NET Framework 1.x や .NET Compact Framework ではこう書く
Dim f2 As New Form2()
Dim f3 As New Form3()
f2.Owner = Me
f2.Show()
f3.Show()
---

後者(2002/2003 向け)では Owner プロパティが使われています。
前者(2005 以降向け)では、Show メソッドの owner 引数を使っています。
(Form.ShowDialog メソッドや MessageBox.Show にも owner 引数があります)

そしてこのコードでは、このような親子関係になります。

 Form1  … 親なし
 └Form2 … Form1が親
 Form3  … 親なし


この状態で、別アプリケーションとフォーカスを切り替えてみて下さい。
親子関係がどのように働くのか実感できるかと思います。


余裕があれば、Owner プロパティに加えて OwnedForms プロパティについても調べてみてください。

[ツリー表示へ]
タイトルRe^7: フォームの重ね順番制御について
記事No11754
投稿日: 2016/10/31(Mon) 16:57
投稿者SUZUKI
理解不足でした
FORMの親子関係おもしろいですね
親を動かすと子の裏に入る前には行かない
でしゃばらないで子に任せるという事ですね
ご丁寧な説明
ありがとうございました

[ツリー表示へ]