ラジオボタン破棄後の再表示

[戻る]
MI 2007/07/11(水) 12:46:06
OS:WindowsXP Professional SP2
使用ツール:Visual Stadio 2005(MFC)

ダイアログベースでエディットボックス(IDC_EDIT1)に
数値を入力してボタンをクリックすると、以下のソース
でラジオボタンをその数値分生成して表示するように
したいのですが。

たとえば、エディットボックスに"5"と入れてクリックした後に
"2"と入れると差分の3つが再描画されて消えずに残ってしまいます。
どのうしたらよいのか教えてください。

<ソース>
void Ctest7Dlg::OnBnClickedButton1()
{
    unsigned int i;
    int x = 10;
    int y = 10;
    int iWidth = 30;
    int iHeight = 30;

    //スタティックボックス内のラジオボタンすべてを破棄する。
    while(GetDlgItem(IDC_STATIC)->GetTopWindow() != NULL)
    {
        GetDlgItem(IDC_STATIC)->GetTopWindow()->DestroyWindow();
    }

    //エディットボックスの数値分ラジオボタンを生成
    for(i = 0; i < GetDlgItemInt(IDC_EDIT1); i++)
    {
    chChildWindow = new CWnd;
    //ラジオボタン作成
    chChildWindow->Create(
        _T("BUTTON"), 
        _T("OK"), 
        BS_AUTORADIOBUTTON | WS_CHILD, // | WS_VISIBLE,
        CRect(x, y, iWidth, iHeight),
        this, //GetDlgItem(IDC_STATIC),
        i+1);
    chChildWindow->ShowWindow(SW_SHOW);
    chChildWindow++;
    x += 30;
    iWidth += 30;
    }

    this->UpdateWindow();
}

とおりすがり 2007/07/11(水) 17:06:27
作ったウインドウを消してないからね。
メモリも消してないし

とおりすがり 2007/07/11(水) 17:11:12
あ、ウィンドウの方は消してるのかな。
だったら作成されたウィンドウハンドルと、消してるウィンドウハンドルが
あってるかどうか確認してみては如何でしょうか

しろう 2007/07/11(水) 18:19:16
GetDlgItem(IDC_STATIC)->GetTopWindow()->DestroyWindow();
この戻り値は?

chChildWindow++;
これは何?

2007/07/11(水) 23:45:23
・破棄するときはCtest7Dlgの子ウィンドウであるGetDlgItem(IDC_STATIC)の
子ウィンドウを破棄しているが、Ctest7Dlgの子ウィンドウとして作っているように見
える。
・作成するコントロールのIDが1から始まっているが、元々あるコントロールと競合
している可能性がある。
・GetDlgItem(IDC_STATIC)そのものが失敗している可能性があ
る。IDC_STATICのIDをもつコントロールは唯一ですか。
・「chChildWindow = new CWnd;」で確保したメモリを開放していない。
・ループ先頭でポインタの値を更新しているため「chChildWindow++;」が意味を
成していない。そもそも配列として確保していない。
・「for(i = 0; i < GetDlgItemInt(IDC_EDIT1); i++)」好みにもよるが、1ループご
とに値を取得するのは無駄で、最悪の場合ループ中に値が変わる。

メモリリークの問題の解決手法
1、確保したCWndを保存しておき、破棄する際にこれを削除する。保存先は
Ctest7Dlgのメンバなど。
 破棄失敗の問題はほぼ確実に回避できます。
1-1、リンクリストを自分で作り、そのメンバとしてCWndを持たせ、それを保存す
る。
1-2、std::vectorやstd::listを使い、そこに追加していく。
1-3、必要なサイズのCWndの配列を確保し、その先頭ポインタを保存する。
2、確保したCWndをDetachする事で使いまわす。
…そもそも自動変数だと作った端から消えるからこうしたのだと思いますが、デスト
ラクタでのウィンドウの破棄を防ぐ方法もあります。
その場合自動変数に一つCWnd確保すれば済むと思います。
3、CWndを使わない。Win32APIで直接作る。この方法で破棄するのならば
CWnd使う意味も無いので。
4、消さないで、Hide+Disableにする事で見た目に消しておく。
ウィンドウサイズは有限だと思うので、この方が高速化を測れる可能性がありま
す。
ラジオボタンとの事で、グループ分けの手間も考えるとこの方法も十分検討価値
があります。

親ウィンドウがどれだとか、コントロールのIDは良く考えてみてください。

MI 2007/07/20(金) 09:59:03
[[解決]]
麩さんへ

どうもありがとうございます。
基本的なことが全然分かっていないみたいですね。
もうすこし勉強してみます。

古いスレッドには追加発言できません。