ユーザーコントロールのParentプロパティについて

解決


るーちゃん  2006-07-14 03:10:46  No: 132342

みなさま、こんにちは。
親コントロールの取得の仕方で悩んでます。
分かりづらい文面で申し訳ありません。

開発環境は
VB6.0SP6
WindowsXP
です。

VB6で作成できるユーザーコントロールを
作ってみました。一応コンテナなので、この
ユーザーコントロールに任意のコントロールを
貼ったりしています。

ここで、ユーザーコントロール.Parent として
得られるのはすぐ上の親だろうと考えていました。
ところが、ユーザーコントロールの上に、更に
同ユーザーコントロールを置いた場合(前者をuctl1
後者をuctl2とします)、uctl2.parent としても
フォームを指しているようです。この状況のときは
uctl1を指すのかと思っていましたがフォームを
指しています。

何がしたいのかというと、
自身を配置している親上で、自身の位置(topとleft)を調べて、
自身を丸々ピクチャーボックスで隠すことをしたいのです。
uctl1の場合は、Form1上の座標から、
uctl2の場合は、uctl1上の座標から、
という感じ。

自身の親を参照するロジックは次の通りです。
uctlBaseBoxというのが、自作のユーザーコントロール名です。
----------------
private mHwnd as Long

Dim c1 As Control

'hWnd
Public Property Get pHwnd() As Long
    pHwnd = mHwnd
End Property

Private Sub UserControl_Initialize()
    mHwnd = UserControl.hwnd
End Sub

Private Sub xxx()
'親にぶら下がっている自分の位置を取得
For Each c1 In UserControl.Parent.Controls
   If (TypeOf c1 Is uctlBaseBox) Then
       If c1.pHwnd = mHwnd Then
           Exit For
       End If
   End If
Next c1

Set mMask = c1.Parent.Controls.Add("VB.PictureBox", "mMask" & mHwnd)
mMask.Top = c1.Top
mMask.Left = c1.Left
mMask.width = c1.width
mMask.height = c1.height
mMask.AutoRedraw = True
mMask.Appearance = 0
mMask.BorderStyle = 0
mMask.BackColor = mLockColor
mMask.ZOrder '自身の上にピクチャボックスを被せる
mMask.tabStop = False
mMask.CausesValidation = False
mMask.DrawWidth = 3
mMask.DrawStyle = vbSolid
mMask.DrawMode = vbCopyPen
mMask.Line (0, 0)-(mMask.width, mMask.height), RGB(255, 0, 0)
mMask.Line (mMask.width, 0)-(0, mMask.height), RGB(255, 0, 0)
mMask.visible = True

End Sub
----------------

#ここで、c1.name をuctl1とuctl2の両者で
 出力すると、どちらも Form1 が出てきます。


魔界の仮面弁士  2006-07-14 05:36:04  No: 132343

Parent → Container なのでは。


るーちゃん  2006-07-14 23:52:45  No: 132344

魔界の仮面弁士さん
ご返答ありがとうございます。

Containerを使う方法ですが、
これを使うと親がフォームの場合と
コンテナの場合とでコーディングの
方法が変わってしまいます。
(フォームでコンテナを参照するとエラーになる)

c1.parent.controls.add ←フォームのとき
c1.Container.Parent.Controls.Add ←コンテナのとき

・・・・実は、このように切り分けるのを
避けた結果、提示したソースのような格好に
なってます。
VBでのparentの扱い方は、親がコンテナを
持ってるかそうでないかで切り分けるべき?


特攻隊長まるるう  2006-07-15 03:23:31  No: 132345

>c1.parent.controls.add ←フォームのとき
>c1.Container.Parent.Controls.Add ←コンテナのとき
そこは Parent 使えば良いんじゃないですか???

>ところが、ユーザーコントロールの上に、更に
>同ユーザーコントロールを置いた場合(前者をuctl1
>後者をuctl2とします)、uctl2.parent としても
>フォームを指しているようです。
Container は Container が必要な場所のみ使ってみてください。


るーちゃん  2006-07-18 20:33:36  No: 132346

こんにちは。

コンテナがある場合とそうでない場合とで
切り分けることにしました。

ご指導、ありがとうございました。


特攻隊長まるるう  2006-07-18 20:58:56  No: 132347

>コンテナがある場合とそうでない場合とで
>切り分けることにしました。
ユーザーコントロールを扱っている限りでは必要な処理には
思えませんが...解決したならそれが一番でしょう。

>c1.parent.controls.add ←フォームのとき
>c1.Container.Parent.Controls.Add ←コンテナのとき
このコードを見た時、無駄の多いコードを書いていると予想できました。
時間があるときに Container と Parent に関してどのコントロールを
指しているか?どういった構造でコントロールが管理されているか?
整理してみるといいと思います。

解決としたコードを公開すれば、改善点があればコメントが付く
と思います。


魔界の仮面弁士  2006-07-18 22:16:31  No: 132348

# どこかで話が食い違っているような気がする…。

>(フォームでコンテナを参照するとエラーになる)
つまり、
  Set 子コントロール.Container = フォーム
はできたけれど、
  Set フォーム.Container = 何某
ができない…という意味でしょうか? だとしたらそれは当然かと。

フォーム自体はコンテナの親要素になりえますが、
フォームをコンテナの子要素にする事はできませんよね。

>ところが、ユーザーコントロールの上に、更に
>同ユーザーコントロールを置いた場合(前者をuctl1
>後者をuctl2とします)、uctl2.parent としても
>フォームを指しているようです。

その点は、ユーザーコントロールやコンテナなどは関係無い話かと。

ブラウザ上で使う場合などを考慮せず、VB6 上での動作のみに限定するなら、
UserControl であろうと標準コントロールであろうと、指し示すものは
Parent は常に「フォーム」、Container は常に「親コンテナ」でしょうし。

http://www.vb-user.net/junk/replySamples/2006.07.18.12.50/Container.gif


るーちゃん  2006-07-19 01:42:19  No: 132349

こんにちは。
たびたび、失礼します。

結局、切り分けしようとした判断自体、私が勘違いしていた
ようです。
下記ロジックで、無事ピクチャボックスを被せることができました。

魔界の仮面弁士殿ご指摘の、
Set フォーム.Container = なんとか
が抜けていた格好です。

Parentで指す親は、自身のひとつ上の階層(?)のオブジェクトを
さしていると思ってたことと、xxx.Parent.Controls.Addを
使うと、xxxを親とするコントロールを動的配置できることと
思ってたために、変な勘違いをしてました。
(うーん。なんか違う言語の仕様(VC++とMFCだっけ)を変に持ち出して
きたようです)

後からのご指摘、ありがとうございます。

Dim c1 As Object

'親にぶら下がっている自分の位置を取得
For Each c1 In UserControl.Parent.Controls
  If (TypeOf c1 Is uctlBaseBox) Then
    If c1.pHwnd = mHwnd Then
      Exit For
    End If
  End If
Next c1
                    
Set mMask = c1.Parent.Controls.Add("VB.PictureBox", "mMask" & mHwnd)
Set mMask.Container = c1.Container
mMask.Top = c1.Top
mMask.Left = c1.Left
mMask.width = c1.width
mMask.height = c1.height
mMask.AutoRedraw = True
mMask.Appearance = 0
mMask.BorderStyle = 0
mMask.BackColor = mLockColor
mMask.ZOrder
mMask.tabStop = False
mMask.CausesValidation = False
mMask.Cls
mMask.DrawWidth = 3
mMask.DrawStyle = vbSolid
mMask.DrawMode = vbCopyPen
mMask.Line (0, 0)-(mMask.width, mMask.height), vbRed
mMask.Line (mMask.width, 0)-(0, mMask.height), vbRed


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加