おはようございます。再びお世話になります。
.NET2005 VC++/CLI
フォームには「コントロール作成ボタン」と「コントロール削除ボタン」があります。
「コントロール作成ボタン」押下時に
//コントロールの生成
No = m_Button->Length;
Array::Resize( m_Button, m_Button->Length + 1 );
m_Button[No] = gcnew Button();
Controls->Add(m_Button[No]);
上記のようにフォーム上に動的にボタンコントロールを作成するプログラムを作成して
います。
今回やりたいのは「コントロール削除ボタン」を押下した際に上記で作成した動的ボタ
ンを削除させたいのです。
本などで調べデストラクタやファイナライザを使用することまでは理解できましたが実
装方法がわかりません(><)
お手数ですがアドバイスお願いします。
# どういうことをするプログラムなのか興味がありますが、、、
# (コントロール作成ボタンとか、、、フォームデザイナ見たいなものですかねぇ?)
Formのコントロールから対象のものを消すのだから
> Controls->Add(m_Button[No]);
と反対の処理になりそうです。
Control.ControlCollection クラス
http://msdn2.microsoft.com/ja-
jp/library/system.windows.forms.control.controlcollection(VS.80).aspx
の
>Add、Remove、RemoveAt の各メソッドを使用すると、コレクションから
>個別のコントロールを追加および削除できます。
とありますのでそこらへんを調べてみてください。
>m_Button
のほうは、どのように削除するかわからないので回答できません。
(ボタンのコントロール名をキーにして削除する?
→だったら配列よりも名前をキーに配置できるコレクションを使うべき)
Blueさん
アドバイスありがとうございます。
>Add、Remove、RemoveAt の各メソッドを使用すると、コレクションから
>個別のコントロールを追加および削除できます。
Removeメソッドでフォーム上からコントロールを削除することが出来たのですがメモリ
上には残ってしまっていると思います。Removeはメモリの開放までは行ってくれないの
でしょうか?
であればRemoveの後に何かメモリを開放させる処理を追加しなければいけないのでしょ
うか?
>m_Button
これは配列です。m_Button[変数]でボタン名が異なるボタンを作成しています。
>メモリを開放させる処理
メモリはおそらくGCが面倒見てくれるので意識しないでよさそうです。
しかしながら、RemoveしたときはDisposeをよばないとだめでしょう。
類似スレ:作成したコントロール配列をすべて解放する方法
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=1262482&SiteID=7
ただ、C++/CLIの場合明にDisposeを呼べないので、
代わりににdeleteしてあげればいいです。
~~~~~~
>これは配列です。
それはわかっています。
消すときに、ボタン名をキーにして消しているのであれば、
消したところはnullptrを入れるのか、配列のサイズを-1して詰めるのかというのが
問題だと思っています。
しかも、ボタン名をキーにするとインデックスでアクセスでない
(配列のサイズを-1して詰めるということをしたらインデックス≠ボタン名という関係に
なる。そうなると削除ボタンを検索するときシーケンシャルリサーチしかできなさそう)
ので、そういうリストを使うよりも、Dictionaryジェネリック・クラスを使うべきか
と。
Blueさん
>>消すときに、ボタン名をキーにして消しているのであれば、
>>消したところはnullptrを入れるのか、配列のサイズを-1して詰めるのかというのが
>>問題だと思っています。
削除処理は以下のようにしています。
pictureBox3->Controls->Remove(m_Button[RetTag]);
delete m_Button[RetTag];
コントロール作成時に
No = m_Button->Length;
Array::Resize( m_Button, m_Button->Length + 1 );
m_Button[No] = gcnew Button();
m_Button[No]->Tag = No;
として
Button^ lb = (dynamic_cast<Button^>(sender));
RetTag = int::Parse(lb->Tag->ToString());
コントロールにタグを持たせて識別しています。
>コントロールにタグを持たせて識別
それでも、結局は Tag が 10 のボタンを消せ!となったとき
配列の頭から検索するしかないわけですよね?
それだったら、キーと値を格納できるリスト「Dictionaryジェネリック・クラス」
をつかうべきだと思うのですが。
それと
>pictureBox3->Controls->Remove(m_Button[RetTag]);
>delete m_Button[RetTag];
は配列に対しては何もいじらないのでしょうか?
消したってのを明確にするためにも nullptr を入れておくほうが無難でしょう。
(削除対象を探すときにdeleteしたのにもかかわらず参照することになりそう)
>No = m_Button->Length;
>Array::Resize( m_Button, m_Button->Length + 1 );
>m_Button[No] = gcnew Button();
>m_Button[No]->Tag = No;
これだと、削除してから追加するとダブる番号が出ませんか?
ボタン1 Tag 0
ボタン2 Tag 1
ボタン3 Tag 2
の状態から Tag 1 のボタンを削除する
ボタン1 Tag 0
ボタン3 Tag 2
そしてボタンを追加する
ボタン1 Tag 0
ボタン3 Tag 2
ボタン4 Tag 2
> これだと、削除してから追加するとダブる番号が出ませんか?
あー勘違いです。
>ボタン1 Tag 0
>ボタン3 Tag 2
は
ボタン1 Tag 0
ボタン2 Tag 1 →のこっているけどdelete済み(参照できない)
ボタン3 Tag 2
だったので
ボタン1 Tag 0
ボタン2 Tag 1
ボタン3 Tag 2
ボタン4 Tag 3
となるので大丈夫でしたね。
Blueさん
ご指摘ありがとうございます。
>>それだったら、キーと値を格納できるリスト「Dictionaryジェネリック・クラス」
>>をつかうべきだと思うのですが。
こちらの方法も検討してみます。
>>pictureBox3->Controls->Remove(m_Button[RetTag]);
>>delete m_Button[RetTag];
>>は配列に対しては何もいじらないのでしょうか?
>>消したってのを明確にするためにも nullptr を入れておくほうが無難でしょう。
>>(削除対象を探すときにdeleteしたのにもかかわらず参照することになりそう)
確かに削除したコントロールを明確にするためにもnullptrしたほうが良いですね!
アドバイスありがとうございます。
よく考えてみると、配列の要素を消さないのであれば、
インデックスの値と Tag の値が一緒なので、そのままのインデックスで取得できるので
は?(Tagの値は無意味)
Blueさん
>>よく考えてみると、配列の要素を消さないのであれば、
>>インデックスの値と Tag の値が一緒なので、そのままのインデックスで取得できるの
>>では?(Tagの値は無意味)
ご指摘ありがとうございます。確かに上記の指摘のように無駄なことをやっているよう
に見えてきました(- -);もう少し見直してみます。
一応、本件は解決したので済とします。
Blueさん
>>よく考えてみると、配列の要素を消さないのであれば、
>>インデックスの値と Tag の値が一緒なので、そのままのインデックスで取得できるの
>>では?(Tagの値は無意味)
ご指摘ありがとうございます。確かに上記の指摘のように無駄なことをやっているよう
に見えてきました(- -);もう少し見直してみます。
一応、本件は解決したので済とします。