[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2005/01/06(Thu) 13:46
投稿者名:ダンボ
URL :
タイトル:
ボタンコレクションを引数として渡す
コマンドボタンのコレクションを引数で内部サブルーチンに渡したいと思っています。

具体的には、Loadして複製したcmd(1),cmd(2),...を渡します。
For i= 1 to n
Load cmd(i)
Next For
Call DecideOP( cmd )


Private Sub DecideOP( BTNS As Collection )
Dim N As Integer
N = BTNS.UBound - BTNS.LBound +1
End Sub

サブルーチン側の宣言と呼び出し側が合っていないとIDEに怒られています。(実行時エラー13:型が一致しません)
BTN As CommandButton と宣言しても、それはもちろん、実行時エラー13で怒られます。
BTN As CommandButtonのCollectionと宣言したいのですがね。

どのように書けば正しい文法になるでしょうか?

投稿時間:2005/01/06(Thu) 14:13
投稿者名:匿名くん
Eメール:
URL :
タイトル:
Re: ボタンコレクションを引数として渡す
cmd(i) は、オブジェクトのコレクションではなく、オブジェクト配列では。
ヘルプでオブジェクトのコレクションの作成をご覧になっては。

投稿時間:2005/01/06(Thu) 14:38
投稿者名:ダンボ
URL :
タイトル:
Re^2: ボタンコレクションを引数として渡す
匿名くん さん、どうもありがとうございます。素早い回答ですね。

> cmd(i) は、オブジェクトのコレクションではなく、オブジェクト配列では。
そうですね。「コントロール配列」と呼ぶのがもっとも適切なのかも。

多分、オブジェクト指向の用語・実装が固まっていなかった頃にVBで育ててしまったために
ちょっとコレクションとは違うところがあるのかも。添字が付いていることから「配列」ですね。

で、googleで「配列 VB」で引いたところ下記を発見。
「いきなりプロシジャにコントロール配列を渡す事はできません。一度Control型の変数に格納する必要があります。」
hhttp://www.geocities.co.jp/SiliconValley/4805/vbtips/vbtips058.htm

ええっ。そうなんですか?
半信半疑なので、皆様のご意見も伺いたく。

投稿時間:2005/01/06(Thu) 15:11
投稿者名:Say
Eメール:
URL :
タイトル:
Re^3: ボタンコレクションを引数として渡す
> 「いきなりプロシジャにコントロール配列を渡す事はできません。一度Control型の変数に格納する必要があります。」
Variantでわたせばいいのでは?

投稿時間:2005/01/06(Thu) 15:36
投稿者名:ダンボ
URL :
タイトル:
Re^4: ボタンコレクションを引数として渡す
Sayさん、ありがとうございます。 Sayさんも素早いですね。

> Variantでわたせばいいのでは?

ふむふむ。コンパイルは通るようになったのですが、コントロールとしては見られていないようです。

Private Sub DecideOP( BTNS As Variant )
Debug.Print TypeName(BTNS)    ○ "Object"
Debug.Print BTNS.UBound       ○ 正しい
Debug.Print BTNS.LBound       ○ 正しい
Debug.Print BTNS.Name         × オブジェクトはこのプロパティまたはメソッドをサポートしていません
Debug.Print BTNS.Top          × オブジェクトはこのプロパティまたはメソッドをサポートしていません
Debug.Print BTNS.Left         × オブジェクトはこのプロパティまたはメソッドをサポートしていません
End Sub

投稿時間:2005/01/06(Thu) 15:51
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^5: ボタンコレクションを引数として渡す
> ふむふむ。コンパイルは通るようになったのですが、コントロールとしては見られていないようです。
それはそうでしょう。(^^;
渡されたものは、「コントロール」ではなく、「コントロール配列」なのですから…。

  Debug.Print TypeName(Command1(0))   ' "CommandButton"
  Debug.Print TypeName(Command1)      ' "Object"
  Debug.Print Command1(0).Name        ' "Command1"
  Debug.Print Command1.Name           ' 当然、エラー

上記と同じ事が、提示されたコードにもいえるわけです。

>  Debug.Print TypeName(BTNS)    ○ "Object"
>  Debug.Print BTNS.Name         × オブジェクトはこのプロパティまたはメソッドをサポートしていません

投稿時間:2005/01/06(Thu) 15:42
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^3: ボタンコレクションを引数として渡す
> 匿名くん さん、どうもありがとうございます。素早い回答ですね。
>
> > cmd(i) は、オブジェクトのコレクションではなく、オブジェクト配列では。
> そうですね。「コントロール配列」と呼ぶのがもっとも適切なのかも。

VB6の「コントロール配列」は、一種のコレクションオブジェクトなので、
あながち間違っても居ないと思いますよ。

とはいえ、ボタンコレクションという表現は誤解をうみそうなので、
やはり、コントロール配列という表現を使った方が、意図を伝えやすいかと。


> ちょっとコレクションとは違うところがあるのかも。添字が付いていることから「配列」ですね。
混同させてしまいそうなのですが、実は「コントロール配列」は『配列ではありません』。
上記にも書いたように、VB固有のコレクションオブジェクトです。
(本当に「配列」だとしたら、UBoundプロパティではなく、UBound関数を使う必要がありますね)


> ええっ。そうなんですか?
それはおそらく、MSKBの記事を参考に書かれた物なのでしょうね。
hhttp://support.microsoft.com/default.aspx?scid=kb;ja;408439


確かに、「コントロール配列」を『Controlの配列』として渡したいのであれば、
そこに書かれたように、個別にControl型の変数に格納する必要があります。

しかし、『「コントロール配列」コレクション』のまま渡すのであれば、
汎用型の As Object を使うことで、プロシージャにも渡せます。

# 「コントロール配列」を表す固有の型は用意されていませんので、
# 汎用型のObjectやVariantなどを使う必要があります。


Option Explicit

Private Sub Command1_Click(Index As Integer)
    Call Sample(Command1)
End Sub

Private Sub Sample(ByVal Controls As Object)
    'Dim X As VB.Control
    Dim X As VB.CommandButton
    For Each X In Controls
        Debug.Print X.Caption
    Next
End Sub

投稿時間:2005/01/06(Thu) 17:11
投稿者名:ダンボ
URL :
タイトル:
(解決)ボタンコレクションを引数として渡す
皆さん、どうもありがとうございました。魔界の仮面弁士さん、いつもお世話になっております。

こんな風に直して、目的どおりの動作ができました。VB.CommandButtonがミソだったかな。

Call DecideOP( cmd() )


Private Sub DecideOP(BTNS As Object)
Dim BTN As VB.CommandButton
Dim N As Integer, XSum As Long, YSum As Long, X As Double, Y As Double

N = BTNS.Count - 1
XSum = 0: YSum = 0
For Each BTN In BTNS
    X = BTN.Left + BTN.Width / 2
    Y = BTN.Top + BTN.Height / 2
    XSum = XSum + X: YSum = YSum + Y
Next BTN
OPX = XSum / N: OPY = YSum / N