いつも参考にさせていただいてます。
過去ログを検索したのですが、少し違うケースでしたので質問させていただきます。
Form1にPictureBox1を貼り付けて、その中にPictureBox2を200個以上貼り付け
て、デザインモード上でPictureBox2(n)のVisibleをTrueに設定した場合です。
Form1のForm1_Load関数内でPictureBox2(n).Visibleを見るとFalseになってし
まっています。そこでForm1_Load関数内でPictureBox2(n).Visible = Trueに
設定して、その前後でVisibleを見てみると、やはりTrueが設定されずにFalse
のままになってしまうのですが、どうしてなのでしょうか?
過去ログからあらかじめPictureBoxを貼り付けておかなくても良い方法は載っ
ていましたが、貼り付けた場合は制御できないのでしょうか?
表現がわかりづらいかもしれませんが、どなたか教えてください。
よろしくお願いします。
仕様上の制限というものがあります。
コントロールを200個も貼り付けて作るようなアプリケーションは
設計上問題があるといわざるを得ないでしょう。
なるほど…。やはりそうですが。
あっきーさんありがとうございました。
それで解決なの?
根本の原因は?
あっきーさん、え?さん、レスありがとうございます。
補足です。
データの数の分だけ動的にピクチャーボックスを確保してやる必要があるため、
あらかじめ、予想される最大数を貼り付けて対処していたのですが、貼り付け
過ぎということが根本的な原因であり、設計上の問題だということなので、最初
から考え直してみます。ありがとうございました。板汚しすみませんでした。
まぁ解決だと言うなればそれでいいのですが
とりあえず1個2個の時は正常に動作するんですか?
確かに200とは数が多いですが・・・
根本を見ていない気もしますね
葉月αさんお返事ありがとうございます。
えっと結論から言えば、現時点ではPictureBox、TextBoxをそれぞれ254個ずつ
貼り付けていて問題なくできていたのですが、新しくPictureBoxが必要になり
まして、Picture2として5つ新たに追加したらNGになりました。
そのForm1のForm1_Loadが終了し、呼び元のForm2のUnload Me直前ではPicture2(n).VisibleがTrueになるのですが、そこ以前のPicture2(n).Visible=True
と設定している部分では設定されない状態でして、プログラムを終了まで走ら
せるとなぜかPicture2(0).VisibleだけがTrueになり、Picture2(1〜4).Visible
がFalseのままなので、なぜだろうと思って質問させていただいたのですが…。
前にどこかで貼り付け数が多いとダメになるとみたような気がしたので、やはり
それが原因かなと思った次第であります。
>貼り付け過ぎということが根本的な原因であり
これについては理解に苦しむのですが・・。
http://www.microsoft.com/japan/msdn/columns/askgui/askgui05222001.asp
には
>コントロール配列のインデックスは、どのバージョンでも 0 〜 32,767 に制限されています。
と記述されているので200個以上(以上っていうのも曖昧な気が・・)貼り付けることが根本になるか疑問だと思います。
ちなみにVB6の場合です。
え?さん、何度もありがとうございます。
確かに上記URLをみると、コントロール配列している限りは数百個程度では
問題なさそうですね…。私が以前みたのはコントロール名が254個以上ある
場合はNGという記述だったのかもしれません。
ちなみに今作っているソースではコントロール名自体が254もあるわけでは
ないのでその点については問題なさそうではありますが、いくら確かめても
Picture2(n).Visible = Trueのコードの時点では設定されない状態です。
Debug.Print Picture2(n).VisibleでVisibleにカーソルを合わせるとFalse
と表示されていますが、この部分を通してイミディエイトウィンドウに値を
表示してみるとTrueと表示されます。カーソルを当てた時とそこを通した時
の値が違うということ自体が何か変になってるとは思うのですが…。
>Debug.Print Picture2(n).VisibleでVisibleにカーソルを合わせるとFalse
>と表示されていますが
ステップ実行(黄色のライン)のことですか?
通常はPicture2(n).Visible = Trueでは「VisibleをTrueにしますよ〜」と
宣言してるだけだと思うので、このコードより下にいったら設定が反映される
と思うので、問題ないような気がしますが・・。
>そのForm1のForm1_Loadが終了し、呼び元のForm2のUnload Me直前では>Picture2(n).VisibleがTrueになるのですが、そこ以前のPicture2(n).Visible=True
>と設定している部分では設定されない状態でして、プログラムを終了まで走ら
>せるとなぜかPicture2(0).VisibleだけがTrueになり、Picture2(1〜4).Visible
>がFalseのままなので
この部分があまり想像できなかったのでよろしければ問題となっている
ソースを公開することはできないでしょうか?
ソースをそのまま貼り付けると、他のDB連携部分等もありわかりづらいので
簡略して書かせていただきます。
'呼び出し元Form2のボタンクリック時処理
Private Sub CommandButton_Click()
Dim i As Integer
Form1.Show '←ここでPictureBoxが多数貼り付けてあるFormをロード
For i = 0 To 4
Debug.Print Form1.Picture2(0).Visible '①
Next
Unload Me
End Sub
'呼び出される側のForm1のロード時処理
Private Sub Form1_Load()
Dim i As Integer
For i = Picture2.LBound To Picture2.UBound 'Picture2は5つです
Picture2(i).Visible = True
Next
End Sub
①の部分でステップ実行を止めて、Visibleにカーソルを当てると、ポップ
アップ表示される値がFalseです。その状態でF8を押して1行進めます。
1行進めた状態でVisibleにカーソルを当てるとFalseのままなのですが、
Debug.PrintによってイミディエイトウィンドウにはTrueが表示されます。
値が相違してるのもよくわからないのですが、この結果表示されるのは、
Picture2(0)だけが表示され、Picture2(1)〜Picture2(4)は表示されないの
です。意図する動作はPicture2を5つとも表示させるプログラムです。
> For i = 0 To 4
> Debug.Print Form1.Picture2(0).Visible '①
> Next
の部分でForm1.Picture2(i)ではなくForm1.Picture2(0)となっているのは
わざとでしょうか・・?
どの時点で変化しているのかを探るために、ウォッチウィンドウの、
『式の内容が変化したときに中断』機能を利用してみては如何でしょう?
あと、フォームの暗黙のインスタンスによる再ロードの可能性に備えて、
各フォームの Initialize/Load/Unload/Terminate イベントの際に
Debug.Print 等でログを残すようにしてみるとか。
> Form1.Show '←ここでPictureBoxが多数貼り付けてあるFormをロード
Form1 の Load イベントの処理を全て外した場合も、同様の現象になりますか?
> For i = Picture2.LBound To Picture2.UBound
> Picture2(i).Visible = True
> Next
こういう時は、
Dim P As PictureBox
For Each P In Picture2
P.Visible = True
Next
も便利ですよ。Index が連番で無い場合にも対応できますので。
え?さん
申し訳ありません。ご指摘の通り、Picture2(i)が正しいです。
iをIndexにして、0〜4の5つのPicture2.VisibleをTrueにしています。
Dentalさん
お返事ありがとうございます。
暗黙のインスタンスによる再ロードは前にも問題がでたことがあったので
確認したつもりではいましたが、もう一度確かめてみます。
>Form1 の Load イベントの処理を全て外した場合も、同様の現象になりますか?
これは未確認でした。試してみます。
> Dim P As PictureBox
> For Each P In Picture2
> P.Visible = True
> Next
は知らなかったです。調べてみます。ありがとうございます。
>Private Sub Form1_Load()
> Dim i As Integer
>
> For i = Picture2.LBound To Picture2.UBound 'Picture2は5つです
> Picture2(i).Visible = True
> Next
>End Sub
の部分でForm1_Load()ではなくForm_Load()ではないでしょうか?
Form1_Load()のままだとForm1.ShowしてもLoadイベントが発生しないので。
「Form1_Load()」という名前の関数を独自で宣言しているのが原因かと。。
え?さん、何回もすみません‥。それもミスです。
Form_Load()です。処理自体はLoad部分を通っているので、通ってない
ということはないと思うのですが‥。
一番最初に提示していただいたソース(修正箇所は修正)を実行したところ、
5つのPictureBoxは表示されました(初期値としてプロパティウインドウで
Visibleをfalseに設定)
Picture2.LBoundとPicture2.UBoundの値はどうなっていますか?
え?さん、返事が遅くなって申し訳ありません。
LBound⇒0
UBound⇒4
でした。
試しに新しくフォームを作って、PictureBoxを5つ貼り付け、
Private Sub Form_Load()
Dim i As Integer
With Picture1
For i = .LBound To .UBound
Debug.Print Picture1(i).Visible '①
Picture1(i).Visible = True
Debug.Print Picture1(i).Visible '②
Next
End With
Debug.Print Picture1(0).Visible '③
Debug.Print Picture1(1).Visible
Debug.Print Picture1(2).Visible
Debug.Print Picture1(3).Visible
Debug.Print Picture1(4).Visible
End Sub
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Debug.Print Picture1(0).Visible '④
Debug.Print Picture1(1).Visible
Debug.Print Picture1(2).Visible
Debug.Print Picture1(3).Visible
Debug.Print Picture1(4).Visible
End Sub
とやってみたのですが、①、②、③ではイミディエイトウィンドウ上では
VisibleはFalseになりました。フォーム表示後、フォームをクリックして
④を実行してみた結果、イミディエイトウィンドウ上ではVisibleはTrueと
なり、Picture1は表示されていました。もしかしてVBは元々こういう動作
なのでしょうか‥。だとしたら、私の勘違いです。Visible = Trueとした
時点でTrueになるものだと思っていたので。
> フォーム表示後、フォームをクリックして
Load イベントの処理中は、(通常は)まだフォームが表示されていないので、
その上にあるコントロールも非表示状態となる……という事です。
似たような話として、モーダルフォームの場合の動作にも注意してください。
Form2.Show vbModal, Form1
のようにした場合、Form2 が表示されている間は、オーナーフォームとなる
Form1 (および Form1 上のコントロール)の Enabled プロパティは、
すべて False を返すようになります。
> もしかしてVBは元々こういう動作なのでしょうか
VB2〜VB6 に関しては、そのような動作になります。
VB.NET だと、多少動作が変わりますけれどね。
魔界の仮面弁士さん、お返事ありがとうございます。
私の勘違い‥というか、勉強不足だったようです。
確かにForm_LoadではVisibleがFalseのままでも、Trueに設定しておけば、
Form_Activate時にはTrueになっていました。SetFocusはメモリロード後
しか設定できないという認識はあったのですが、Visibleも同じだったん
ですね‥。
あっきーさん、葉月αさん、え?さん、Dentalさん、魔界の仮面弁士さん、
ご迷惑をおかけしました。ありがとうございました。
ツイート | ![]() |