SSTab上にコントロールを動的に配置するには?

解決


mix  2006-04-26 18:32:57  No: 131107

初めて利用させて頂きます。よろしくお願いします。
ヘルプ・インターネットでの検索を行いましたが解決に至っておりません。

○環境
VB 6.0SP6
Windows XP SP2

○行いたい事
SStab上にコマンドボタン、テキストボックスを動的に配置する

○説明
formにSStabを貼り付けて、Tabの数、TabのCaptionを変更する所まではできました。
Tab数、CaptionともにDBからの値で可変です。

その後に、それぞれのTabにコマンドボタン、テキストボックスをそれぞれ貼り付けようとしているのですが、うまく動作しません。
このそれぞれのTabに貼り付けるコマンドボタン、テキストボックスの数も
DBからの値によって変わります。

ですので、コマンドボタン、テキストボックスも貼り付ける数が一定ではないので、動的に生成し、SStabに貼り付けようとしています。

以下コード(コマンドボタンのみ)
Do Until rs.EOF
   SSTab.Tab = i
   SSTab.Caption = rs("test").Value
   rs.MoveNext

   Set BtnDyn = Controls.Add("VB.CommandButton", "cmd" & i)
   With BtnDyn
    .Left = 100 * i
    .Top = 100
    .Width = 1000
    .Height = 400
    .Default = True
    .Visible = True
                
   End With
            
   lnghwnd = SetParent(BtnDyn.hwnd, SSTab.hwnd)
   BtnDyn.Visible = True
   BtnDyn.Move SSTab.Width \ 50, SSTab.Height \ 10, SSTab.Width \ 10, SSTab.Height \ 20
   BtnDyn.Caption = i
            
   'Set BtnDyn = Nothing
            
   i = i + 1
            
Loop

色々やってみたのですが、うまくいきません。
よろしくお願い致します。


ガッ  2006-04-26 19:21:59  No: 131108

なにがどううまくいかないの?


特攻隊長まるるう  2006-04-26 19:34:33  No: 131109

>ヘルプ・インターネットでの検索を行いましたが解決に至っておりません。
とりあえず、Container プロパティ。

…そのままではうまく動作しないと思うけど(^^;)


mix  2006-04-26 19:47:39  No: 131110

>ガッさん
言葉足らずでした。すみません。

最初に書いたコードでは
1.Tabを順次切り替えて
2.コマンドボタンを各Tabに貼り付ける
という事を行おうとしていたのですが、

コマンドボタンが一つしか表示されないのです。
これが私が先に述べた「うまくいきません」です。

>特攻隊長まるるうさん
Container プロパティですね。調べてみます。
うまく動作しないというのは、もう何か根本的にコードの書き方が間違っているのでしょうか?

お二方ともありがとうございます!


我龍院忠太  2006-04-26 19:49:24  No: 131111

少なくてもループの始めに、
If (SSTab.Tabs - 1) < i Then
     SSTab.Tabs = i + 1
End If
こんなのは要るんじゃないの。
それとエラーには関係ないけど、
BtnDyn.Move SSTab.Width \ 50, SSTab.Height \ 10, SSTab.Width \ 10, SSTab.Height \ 20
これは何してるの、上で既に位置を設定してるけど。


特攻隊長まるるう  2006-04-26 20:05:02  No: 131112

>こんなのは要るんじゃないの。
>それとエラーには関係ないけど、
まぁ、関係無いコードはたくさんあるよね。DB検索も質問と直接
関係無いし。
変数宣言してない変数や自分で作った関数(SetParent)が書いて
あって、説明が無い。ま、名前からある程度想像できるから特に
つっこまなかったけど、サンプルコードとしてはだめだめな感じ。

>コマンドボタンが一つしか表示されないのです。
それは単に同じ場所に重なって表示されているだけでは?
[VB6.0]
Private Sub Command1_Click()
    Dim Ctl As Control
    For Each Ctl In Me.Controls
        Debug.Print Ctl.Name
    Next
End Sub
とかでコントロール名を列挙してみれば?


mix  2006-04-26 20:05:39  No: 131113

>我龍院忠太さん
If (SSTab.Tabs - 1) < i Then
     SSTab.Tabs = i + 1
End If
に関しては、ループの前に別のロジックで、SSTab.Tabsの設定を実装しております。
コードが長くなると読みにくいかと思い、掲載しませんでした。すみません。

With BtnDyn
End With

BtnDyn.Move
に関してですが
こちらは、前者はボタンの大きさの指定、後者はボタンの位置の指定としていますが、間違っているのでしょうか。

プログラミングは初めてなので、勉強不足ですが
よろしくお願い致します。


特攻隊長まるるう  2006-04-26 20:28:32  No: 131114

>前者はボタンの大きさの指定、後者はボタンの位置の指定
…違うね。ヘルプを見ても分かるし、プロパティ名を和訳しても分かるけど
.Top…上(端の位置)
.Left…左(端の位置)
.Height…(ボタンの)高さ
.Width…(ボタンの)幅
で、全てを一度に指定できるのが Move メソッド(引数はボタンの
プロパティと同じもの)

大きさと位置で分けるなら、高さ(Height)と幅(Width)が決まれば
大きさは決まるし、位置はボタンの上(Top)と左(Left)の座標が
決まっただけで決まるよね?

>>特攻隊長まるるうさん
>Container プロパティですね。調べてみます。
>うまく動作しないというのは、もう何か根本的にコードの書き方が間違っているのでしょうか?
言葉足らずでした。すみません。意図的に言葉足らずにしてますので、
まずは調べて、結果を報告していただければ回答します。


mix  2006-04-26 20:36:53  No: 131115

>特攻隊長まるるうさん
お恥ずかしい限りです。。。
掲示板の使い方を含めて勉強します。

コントロール名を列挙して確認したところ
確かに存在は確認できたので、
表示位置を変数を用いて、以下のように変えてみました。

DynButton.Move i * 1000, i * 1000, SSTab.Width \ 10, SSTab.Height \ 20

実行してみると、それぞれコマンドボタンは表示されたのですが
各Tabに表示されているのではなく、
Formに張り付いているような表示のされ方をします。
#実際、Tabを切り替えると、表示されていたコマンドボタンは表示されなくなります。

私は
SSTab.Tab = i
でタブを切り替えて
SetParent(BtnDyn.hwnd, SSTab.hwnd)
でSStabに貼り付けると思っていたのですが、考え方が違うのでしょうか。

またSetParentですが
標準モジュールに
Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
を宣言しています。

言葉の使い方、伝え方でご迷惑をおかけしていますがよろしくお願い致します。


mix  2006-04-26 20:40:19  No: 131116

>特攻隊長まるるうさん

>大きさと位置で分けるなら、高さ(Height)と幅(Width)が決まれば
>大きさは決まるし、位置はボタンの上(Top)と左(Left)の座標が
>決まっただけで決まるよね?
確かに・・・。
ヘルプ等、再読します。

Containerプロパティについては
調べて、ご報告致します。

皆様、ご教授頂きありがとうございます。
大変勉強になります。


特攻隊長まるるう  2006-04-26 21:05:59  No: 131117

>またSetParentですが
>標準モジュールに
>Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
>を宣言しています。
おおぅ。APIにそんなのあるんだw。知識不足で申し訳ないです。

>実行してみると、それぞれコマンドボタンは表示されたのですが
>各Tabに表示されているのではなく、
>Formに張り付いているような表示のされ方をします。
>#実際、Tabを切り替えると、表示されていたコマンドボタンは表示されなくなります。
それは多分 Container プロパティを利用した時と同じ動作だと思います。
ここがボクの書いた『うまく動作しない』の部分です。

>私は
>SSTab.Tab = i
>でタブを切り替えて
>SetParent(BtnDyn.hwnd, SSTab.hwnd)
>でSStabに貼り付けると思っていたのですが、考え方が違うのでしょうか。
オイラもそうなって欲しいと思うよ。考え方の方向は普通だと思う。ただ、
実際にそうならないって事は、マイクロソフトがそんな風に作ってくれて
ないんでしょうねw。

次に考えるのは各タブを個別に『コンテナ(Container)もしくは親(Parent)』に指定できないか?
ってとこだけど、過去ログ検索『SSTab』をするとどうも SSTab ってコントロールの
見た目だけを自動で変えてんのか?…って感じだし、個別のタブを取得するような
命令も無さそう?

…じゃ、なんかコンテナになるコントロール(Frameとか)だけ最初に各タブに貼り付けて
おいてそれに設定してみる?とかいう代替案は浮かびます。

ま、オイラ SSTab はあんまり使わないから何か方法を知ってる人がいるかも
しれないのでもうちょっと(通常2・3日)くらい待ってみたら?。


mix  2006-04-26 22:28:48  No: 131118

>特攻隊長まるるうさん
ご教授、ありがとうございます。

早速Containerプロパティを調べました。
Frame,PictureBox,SSTabはコンテナコントロールというのですね。

で、そのコンテナコントロールは「親」コンテナになりうる事が可能であり、
「子」は、コマンドボタンなどのコントロールですね。

私のここまでのイメージだと
・子は親の領域内に配置する事ができる。
という事になってます。

画面上で、Frameを作って、その上にコマンドボタンをドラッグすると
コードでは表示されませんが、自動的にこの「親子」関係ができあがっているのですね。

なんとなくイメージつきました。

そして各Tabが親になるようにSStabに実装しましたが、特攻隊長まるるうさんのおっしゃられた
>それは多分 Container プロパティを利用した時と同じ動作だと思います。
>ここがボクの書いた『うまく動作しない』の部分です。
の言葉通り、うまく動作しませんでした・・・。
Tab個別では親になれないようだし、SStab自身を親にしても現状と同じ表示のされ方になりました。

>…じゃ、なんかコンテナになるコントロール(Frameとか)だけ最初に各タブに貼り付けて
>おいてそれに設定してみる?とかいう代替案は浮かびます。
やはりこの手法が主流なのでしょうか?
もし同じような事を実装されている方がいれば、ご教授下さい。

特攻隊長まるるうさん、ありがとうございます!
大変勉強になりました。


matsu  2006-04-27 01:45:00  No: 131119

参考までに。
フォームにSSTabとコマンドボタンを1個配置して実行してください。

Private Sub Command1_Click()
    Dim AddButon        As CommandButton
    Dim i               As Integer
    
    For i = 0 To 2
        SSTab1.Tab = i
        
        Set AddButon = Me.Controls.Add("VB.CommandButton", "cmd" & i)
        With AddButon
            Set .Container = SSTab1
            .Caption = i
            .Top = 500
            .Left = 300
            .Height = 480
            .Width = 1200
            .Visible = True
        End With
    Next i
End Sub


我龍院忠太  2006-04-27 02:17:22  No: 131120

問題はタブが上の方に増えていった時に、ボタンのTopが安定しないことと、
ボタンにWithEventsでイベントを追加しなければならないのだが、
これが結構面倒くさい、普通はボタンの配列を使うのだが....
それとこだわるようだけど、Forの次に
If (SSTab1.Tabs - 1) < i Then SSTab1.Tabs = i + 1
を入れといた方が良いと思われますが。
早めに、SSTabはあきらめて、TabStripを使った方が良いのでは。


特攻隊長まるるう  2006-04-27 03:58:48  No: 131121

>参考までに。
あれ?普通に乗るねぇ(汗)
…といろいろ調べたら、Load イベントでやると同じタブに
張り付くみたい。
(matsu さんのコードで確認。ありがとう御座いますm(__)m)


mix  2006-04-27 22:24:40  No: 131122

返信が遅れました。
あれから試行錯誤を繰り返し、なんとか自分の行いたい事を実現できました。
以下に整理してまとめます。

まず
1.matsuさんと特攻隊長まるるうさんのレスからForm_Loadイベントでは各タブに張り付かないので、SStab_GotFocusイベントにコマンドボタンの生成を行う。
#どうしてもForm_Load時にコマンドボタンを配置したかったので、苦肉の策です。
2.コマンドボタンを動的に増加させていくために、あらかじめコマンドボタンを一つ用意し、配列としてindex=0に設定。visibleはfalseにしておく。
3.我龍院忠太さんのレスからWithEventsでは、各タブのイベントを取得しにくいので、Loadを使用

以下コード
我龍院忠太さんご指摘の[If (SSTab1.Tabs - 1) < i Then SSTab1.Tabs = i + 1]は未実装

Private blnloadcheck As Boolean

Private Sub ADDButton()

    Dim i  As Integer

    If blnloadcheck = False Then
        
        blnloadcheck = True
        
        For i = 1 To 3
            SSTab.Tab = i
            Load cmdADD(i)
            
            With cmdADD(i)
                Set .Container = SSTab
                .Caption = i
                .Top = 800
                .Left = 300
                .Height = 480
                .Width = 1200
                .Visible = True
            End With
        Next i
    End If

End Sub

Private Sub Form_Load()

    Dim i As Integer    
    blnloadcheck = False
    
    SSTab.Tabs = 10
        
    (中略)←ここでrecordsetの取得を行っています
    i = 1

    If rs.BOF = False Then
        Do Until rs.EOF

            SSTab.Tab = i
            SSTab.Caption = rs("test").Value
            rs.MoveNext
            
            i = i + 1
            
        Loop
    End If
        
    cmdADD(0).Visible = False
    
End Sub

Private Sub SSTab_GotFocus()
    Call ADDButton
End Sub

'確認
Private Sub cmdADD_Click(Index As Integer)
    MsgBox Index
End Sub

この方法がスマートなのかどうかわかりませんが
最初に思い描いていた表示を行う事ができました!!

みなさま、ありがとうございました。
何かお気づきの点がありましたら、ご指摘下さい!


mix  2006-04-28 03:30:27  No: 131123

とりあえず解決という事で。ありがとうございました。


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




  


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