我在一个MFC的对话框程序里动态创建4个Radio单选按钮,是用指针和new生成。但在类的另一个成员函数里再使用指针去控制4个Radio按钮的时候,却激发了断言。代码如下://**************************************************
//头文件的定义部分如下:
class CCreateButton : public CWnd
{
public:
//……
CButton *m_BnRadio1;
CButton *m_BnRadio2;
CButton *m_BnRadio3;
CButton *m_BnRadio4;
         //单击Radio的响应函数
         afx_msg void OnBnRadioClked(UINT m_BnRaID);
         //……
}
//*******************************************************
//*******************************************************
//.cpp文件定义如下:
//定义控件ID
#define IDB_RABUTTON1 310
#define IDB_RABUTTON2 311
#define IDB_RABUTTON3 312
#define IDB_RABUTTON4 313BEGIN_MESSAGE_MAP(CCreateButton,CWnd)
//……
ON_CONTROL_RANGE(BN_CLICKED,IDB_RABUTTON1,IDB_RABUTTON4,&CCreateButton::OnBnRadioClked)
//……
END_MESSAGE_MAP()CCreateButton::CCreateButton(CWnd *pParent /* = NULL */)
{
//……
         //初始化指针为空
m_BnRadio1 = NULL;
m_BnRadio2 = NULL;
m_BnRadio3 = NULL;
m_BnRadio4 = NULL;
}
void CCreateButton::CreateButton1()
{
         //……         //新建4个单选控件
m_BnRadio1 = new CButton;
m_BnRadio1->Create(_T("图1"),WS_GROUP | WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
CRect(0,370,80,395),m_WndCreate,IDB_RABUTTON1);
m_BnRadio2 = new CButton;
m_BnRadio2->Create(_T("图2"),WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
CRect(100,370,180,395),m_WndCreate,IDB_RABUTTON2);
m_BnRadio3 = new CButton;
m_BnRadio3->Create(_T("图3"),WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
CRect(200,370,280,395),m_WndCreate,IDB_RABUTTON3);
m_BnRadio4 = new CButton;
m_BnRadio4->Create(_T("图4"),WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
CRect(300,370,380,395),m_WndCreate,IDB_RABUTTON4);
         //预置第一Radio为选中
m_BnRadio1->SetCheck(true);
m_BnRadio2->SetCheck(false);
m_BnRadio3->SetCheck(false);
m_BnRadio4->SetCheck(false);
//顺利执行,没有发生断言         //……
}
void CCreateButton::OnBnRadioClked(UINT m_BnRaID)    //响应4个Radio控件的单击事件
{
switch(m_BnRaID)
{
case IDB_RABUTTON1:
{
/*m_BnRadio1->SetCheck(true);
m_BnRadio2->SetCheck(false);
m_BnRadio3->SetCheck(false);
m_BnRadio4->SetCheck(false);*/
//触发断言如下:***************************************
//_AFXWIN_INLINE void CButton::SetCheck(int nCheck)
//{ ASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, BM_SETCHECK, nCheck, 0); }
//**********************************************************
                            //下面的可以执行
((CButton*)GetDlgItem(IDB_RABUTTON1))->SetCheck(true);
((CButton*)GetDlgItem(IDB_RABUTTON2))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON3))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON4))->SetCheck(false);

//……
break;
}
case IDB_RABUTTON2:
{
/*m_BnRadio1->SetCheck(false);
m_BnRadio2->SetCheck(true);
m_BnRadio3->SetCheck(false);
m_BnRadio4->SetCheck(false);*/
//激发断言,同上
               
                           //下面的可以执行 ((CButton*)GetDlgItem(IDB_RABUTTON1))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON2))->SetCheck(true);
((CButton*)GetDlgItem(IDB_RABUTTON3))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON4))->SetCheck(false);

//……
break;
}
case IDB_RABUTTON3:
{
/*m_BnRadio1->SetCheck(false);
m_BnRadio2->SetCheck(false);
m_BnRadio3->SetCheck(true);
m_BnRadio4->SetCheck(false);*/
//激发断言,同1                           //下面的可以执行 ((CButton*)GetDlgItem(IDB_RABUTTON1))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON2))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON3))->SetCheck(true);
((CButton*)GetDlgItem(IDB_RABUTTON4))->SetCheck(false);

//……
break;
}
case IDB_RABUTTON4:
{
/*m_BnRadio1->SetCheck(false);
m_BnRadio2->SetCheck(false);
m_BnRadio3->SetCheck(false);
m_BnRadio4->SetCheck(true);*/
//激发断言,同1                            //下面的可以执行 ((CButton*)GetDlgItem(IDB_RABUTTON1))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON2))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON3))->SetCheck(false);
((CButton*)GetDlgItem(IDB_RABUTTON4))->SetCheck(true);

//……
break;
}
}
}
void CCreateButton::OnClose()
{
//……
         //释放内存
if(m_BnRadio1)
delete m_BnRadio1;
if(m_BnRadio2)
delete m_BnRadio2;
if(m_BnRadio3)
delete m_BnRadio3;
if(m_BnRadio4)
delete m_BnRadio4;}//*******************************************************
我在其他地方没有对4个指针进行过任何操作。为什么在创建按钮的成员函数里可以使用指针对控件进行控制,而在类的另一个成员函数里就不能使用这4个指针对控件进行控制了呢?这4个指针是类的成员变量,应该还是指向相应的控件吧?但是,我用断点跟踪,发现在创建控件的函数里,指针是指向相应地址的。但在另一个成员函数里(即响应4个Radio单击事件的函数)4个指针却是空地址。我在其他地方没有对指针进行过任何操作。这是什么原因呢?希望各位指教……

解决方案 »

  1.   

    你创建的是CBUTTON指针 ,不能访问m_hwndCButton *m_BnRadio1;
        CButton *m_BnRadio2;
        CButton *m_BnRadio3;
        CButton *m_BnRadio4;
    改成CWnd
      

  2.   

    你在CCreateButton的构造函数中将指针赋为NULL,在CCreateButton::CreateButton1()
    中将创建按钮(这个函数是什么时候调用的,我看不懂),当你调用CCreateButton::OnBnRadioClked时,应该指针值还是NULL,也就是说窗口没有创建,根据MSDN,IsWindow的返回值:“If the window handle does not identify an existing window, the return value is zero. ”
    所以会触发断言。
      

  3.   

    我是在创建Radio按钮之后才能调用CCreateButton::OnBnRadioClked。因为CCreateButton::OnBnRadioClked是相应4个Radio单击事件的。没有创建的话,如何单击呢???
      

  4.   

     ASSERT(::IsWindow(m_hWnd)); 这个断言判断m_hWnd是否是一个已存在窗口的句柄。但你在这个窗口中所使用的m_hWnd是CCreateButton的成员变量,而CCreateButton始终没有创建窗口,你应该调用CButton的m_hwnd。还有CCreateButton::CreateButton1()这个函数是什么时候调用的?
      

  5.   

    没有!所有用到这些指针的代码我都贴出来了。我再新建一个工程试试。
    如果大家有时间的话,也可以试一试。我用的是Win 7系统,vs2008
      

  6.   

    我知道,我也用断点跟踪了,在CCreateButton::OnBnRadioClked成员函数里,4个指针都是空的。而在创建Radio按钮的成员函数里是有地址的。
      

  7.   

    我新建一个工程后,发现问题依然存在,尝试了多种方法,依然找不到问题的解决办法。现将我新建工程的源代码附上。希望各位高手、大侠和热心人士可以帮忙解决。谢谢!
    源代码:http://download.csdn.net/source/2757357
    内有说明。有什么问题随时可以和我联系。小弟万分感谢!
      

  8.   

    你看看自己的代码:
    void CClassPointDlg::OnBnClickedButton1()
    {
    // TODO: 在此添加控件通知处理程序代码 //新建子窗口和4个Radio单选控件
    /*m_WndCreate = new CCreateButton;
    m_WndCreate->CreateButton1();*/
    CCreateButton m_WndCreate;
    m_WndCreate.CreateButton1();
    }
    CreateButton1的时候当然没有问题,m_WndCreate对象还存在。
    出了这个函数后,m_WndCreate对象是局部变量,就被回收了啊。
      

  9.   

    我用注释掉的代码也不行啊,就是用指针new一个对象,一直在内存里的吧
      

  10.   

    //新建子窗口和4个Radio单选控件
    /*m_WndCreate = new CCreateButton;
    m_WndCreate->CreateButton1();*/
    //CCreateButton的析构函数不调用,直到释放内存才调用
    //说明一直在内存中存在
    CCreateButton m_WndCreate;
    m_WndCreate.CreateButton1();
    //调用完成后调用析构函数,关闭程序是也调用析构函数为什么会出现这种原因啊!用指针new一个CCreateButton,它一直在内存里存在,为什么成员变量却没有了生命呢??
      

  11.   

    我把这个类放到VC6工程中,m_WndCreate.CreateButton1();后根本没有反应,没有显示任何窗口啊。
      

  12.   

    这是为什么??我一直用vs2008,很少用VC6,我再用VC6试试……
      

  13.   

    因为编译工具的原因,我用VC6新建了一个工程。但问题依然。深切希望有高手可以出来解决。
    VC6源代码:http://download.csdn.net/source/2757695
      

  14.   


    //自己定义的文件,创建按钮和相应函数
    #include "stdafx.h"
    #include "CMyHeadFile.h"
    #include "Resource.h"#define WNDCHILD1 2010
    #define IDB_RABUTTON1 310
    #define IDB_RABUTTON2 311
    #define IDB_RABUTTON3 312
    #define IDB_RABUTTON4 313
    CButton *m_BnRadio1;
    CButton *m_BnRadio2;
    CButton *m_BnRadio3;
    CButton *m_BnRadio4;CCreateButton::CCreateButton(CWnd *pParent /* = NULL */)
    {
    m_WndCreate = NULL;
    m_BnRadio1 = NULL;
    m_BnRadio2 = NULL;
    m_BnRadio3 = NULL;
    m_BnRadio4 = NULL;
    }将定义放到这里就可以了
      

  15.   

    测试发现,在CreateButton1函数和OnBnRadioClked函数中,this指针值不相同。
      

  16.   

    终于找到你的毛病了。晕死啊。
    修改如下:
    void CCreateButton::CreateButton1()
    {
    //新建对话框层
    // m_WndCreate = new CCreateButton;
    Create(NULL,_T("CHILDWINDOW"),WS_DLGFRAME | WS_CHILD | WS_VISIBLE,
    CRect(150,100,650,500),AfxGetMainWnd(),WNDCHILD1);
    //新建4个单选控件
    m_BnRadio1 = new CButton;
    m_BnRadio1.Create(_T("图1"),WS_GROUP | WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
    CRect(0,370,80,395),this,IDB_RABUTTON1);
    m_BnRadio2 = new CButton;
    m_BnRadio2.Create(_T("图2"),WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
    CRect(100,370,180,395),this,IDB_RABUTTON2);
    m_BnRadio3 = new CButton;
    m_BnRadio3.Create(_T("图3"),WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
    CRect(200,370,280,395),this,IDB_RABUTTON3);
    m_BnRadio4 = new CButton;
    m_BnRadio4.Create(_T("图4"),WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
    CRect(300,370,380,395),this,IDB_RABUTTON4);
    m_BnRadio1->SetCheck(true);
    m_BnRadio2->SetCheck(false);
    m_BnRadio3->SetCheck(false);
    m_BnRadio4->SetCheck(false);

    CenterWindow(NULL);
    ShowWindow(SW_SHOW);
    }你在CCreateButton类中,又创建一个m_WndCreate = new CCreateButton;真是莫名奇妙啊。根本不需要它啊。
      

  17.   

    说实话,这个我也不怎么清楚,你看你调用完 CreateButton1()后,是不是退出了CCreateButton类了,大概是因为这样吧,说的可能不对。如果你不是新建一个类,直接在CClassPointDlg类里面实现的话就没有这种情况了。
      

  18.   

    加分吧。其实原因在于Radio创建时指定的父对象不是Radio本身所在的类,而是这个类的一个实例对象,只不过两者是同一个类的实例。
      

  19.   

    谢谢!不过我还有一点疑问:m_WndCreate在类的声明为:
    public:
    CCreateButton *m_WndCreate;
    在CCreateButton::CCreateButton(CWnd *pParent /* = NULL */)
    {
    m_WndCreate = NULL;
            //……
    }
    又把指针置空了,在CCreateButton::CreateButton1()里不new新建一个CCreateButton,怎么可以直接用m_WndCreate新建一个子窗口啊??
      

  20.   

    你这又困惑于类和实例的关系中了。你在CCreateButton类中又定义一个CCreateButton实例。m_WndCreate = NULL;只是将这个实例设置为空,并不是把当前这个类实例设置为空啊。你这个CCreateButton本身就是窗口类了,怎么会在它内部又去定义一个本身类实例呢?
    这个关系还需要自己慢慢去理清,光这么说,估计你一时也绕不出来。
      

  21.   

    我明白了,就是说,我在使用CCreateButton类的时候就自动生成了一个对象,我在类里面再定义一个对象是完全不必要的。对吗?
      

  22.   

    是的。你自己也解释不通啊。这个子对象算什么身份呢?你的功能就是在一个窗口上放四个radio,CCreateButton本身就代表这个窗口,四个radio的父对象应该是它。