初めて利用させて頂きます。よろしくお願いします。
ヘルプ・インターネットでの検索を行いましたが解決に至っておりません。
○環境
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
色々やってみたのですが、うまくいきません。
よろしくお願い致します。
なにがどううまくいかないの?
>ヘルプ・インターネットでの検索を行いましたが解決に至っておりません。
とりあえず、Container プロパティ。
…そのままではうまく動作しないと思うけど(^^;)
>ガッさん
言葉足らずでした。すみません。
最初に書いたコードでは
1.Tabを順次切り替えて
2.コマンドボタンを各Tabに貼り付ける
という事を行おうとしていたのですが、
コマンドボタンが一つしか表示されないのです。
これが私が先に述べた「うまくいきません」です。
>特攻隊長まるるうさん
Container プロパティですね。調べてみます。
うまく動作しないというのは、もう何か根本的にコードの書き方が間違っているのでしょうか?
お二方ともありがとうございます!
少なくてもループの始めに、
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
これは何してるの、上で既に位置を設定してるけど。
>こんなのは要るんじゃないの。
>それとエラーには関係ないけど、
まぁ、関係無いコードはたくさんあるよね。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
とかでコントロール名を列挙してみれば?
>我龍院忠太さん
If (SSTab.Tabs - 1) < i Then
SSTab.Tabs = i + 1
End If
に関しては、ループの前に別のロジックで、SSTab.Tabsの設定を実装しております。
コードが長くなると読みにくいかと思い、掲載しませんでした。すみません。
With BtnDyn
End With
と
BtnDyn.Move
に関してですが
こちらは、前者はボタンの大きさの指定、後者はボタンの位置の指定としていますが、間違っているのでしょうか。
プログラミングは初めてなので、勉強不足ですが
よろしくお願い致します。
>前者はボタンの大きさの指定、後者はボタンの位置の指定
…違うね。ヘルプを見ても分かるし、プロパティ名を和訳しても分かるけど
.Top…上(端の位置)
.Left…左(端の位置)
.Height…(ボタンの)高さ
.Width…(ボタンの)幅
で、全てを一度に指定できるのが Move メソッド(引数はボタンの
プロパティと同じもの)
大きさと位置で分けるなら、高さ(Height)と幅(Width)が決まれば
大きさは決まるし、位置はボタンの上(Top)と左(Left)の座標が
決まっただけで決まるよね?
>>特攻隊長まるるうさん
>Container プロパティですね。調べてみます。
>うまく動作しないというのは、もう何か根本的にコードの書き方が間違っているのでしょうか?
言葉足らずでした。すみません。意図的に言葉足らずにしてますので、
まずは調べて、結果を報告していただければ回答します。
>特攻隊長まるるうさん
お恥ずかしい限りです。。。
掲示板の使い方を含めて勉強します。
コントロール名を列挙して確認したところ
確かに存在は確認できたので、
表示位置を変数を用いて、以下のように変えてみました。
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
を宣言しています。
言葉の使い方、伝え方でご迷惑をおかけしていますがよろしくお願い致します。
>特攻隊長まるるうさん
>大きさと位置で分けるなら、高さ(Height)と幅(Width)が決まれば
>大きさは決まるし、位置はボタンの上(Top)と左(Left)の座標が
>決まっただけで決まるよね?
確かに・・・。
ヘルプ等、再読します。
Containerプロパティについては
調べて、ご報告致します。
皆様、ご教授頂きありがとうございます。
大変勉強になります。
>また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日)くらい待ってみたら?。
>特攻隊長まるるうさん
ご教授、ありがとうございます。
早速Containerプロパティを調べました。
Frame,PictureBox,SSTabはコンテナコントロールというのですね。
で、そのコンテナコントロールは「親」コンテナになりうる事が可能であり、
「子」は、コマンドボタンなどのコントロールですね。
私のここまでのイメージだと
・子は親の領域内に配置する事ができる。
という事になってます。
画面上で、Frameを作って、その上にコマンドボタンをドラッグすると
コードでは表示されませんが、自動的にこの「親子」関係ができあがっているのですね。
なんとなくイメージつきました。
そして各Tabが親になるようにSStabに実装しましたが、特攻隊長まるるうさんのおっしゃられた
>それは多分 Container プロパティを利用した時と同じ動作だと思います。
>ここがボクの書いた『うまく動作しない』の部分です。
の言葉通り、うまく動作しませんでした・・・。
Tab個別では親になれないようだし、SStab自身を親にしても現状と同じ表示のされ方になりました。
>…じゃ、なんかコンテナになるコントロール(Frameとか)だけ最初に各タブに貼り付けて
>おいてそれに設定してみる?とかいう代替案は浮かびます。
やはりこの手法が主流なのでしょうか?
もし同じような事を実装されている方がいれば、ご教授下さい。
特攻隊長まるるうさん、ありがとうございます!
大変勉強になりました。
参考までに。
フォームに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
問題はタブが上の方に増えていった時に、ボタンのTopが安定しないことと、
ボタンにWithEventsでイベントを追加しなければならないのだが、
これが結構面倒くさい、普通はボタンの配列を使うのだが....
それとこだわるようだけど、Forの次に
If (SSTab1.Tabs - 1) < i Then SSTab1.Tabs = i + 1
を入れといた方が良いと思われますが。
早めに、SSTabはあきらめて、TabStripを使った方が良いのでは。
>参考までに。
あれ?普通に乗るねぇ(汗)
…といろいろ調べたら、Load イベントでやると同じタブに
張り付くみたい。
(matsu さんのコードで確認。ありがとう御座いますm(__)m)
返信が遅れました。
あれから試行錯誤を繰り返し、なんとか自分の行いたい事を実現できました。
以下に整理してまとめます。
まず
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
この方法がスマートなのかどうかわかりませんが
最初に思い描いていた表示を行う事ができました!!
みなさま、ありがとうございました。
何かお気づきの点がありましたら、ご指摘下さい!
とりあえず解決という事で。ありがとうございました。
ツイート | ![]() |