在运行时创建派生控件导致断言

时间:2018-01-27 22:24:50

标签: mfc runtime dynamically-generated derived-class

我试图在运行时创建一个控件,但它会导致断言,而我不知道导致它的原因。我正在使用的控件是来自此链接的Tree ComboBox Control:https://www.codeproject.com/Articles/187762/Tree-ComboBox-Control

我添加了注册类的代码,如下所示:

CTreeComboBox::CTreeComboBox()
    ...
{
    ...

    RegisterWindowClass();
}

CTreeComboBox::~CTreeComboBox()
{
    m_BrushAlert.DeleteObject();
}


BOOL CTreeComboBox::RegisterWindowClass()
{
    WNDCLASS wndcls;
    HINSTANCE hInst = AfxGetInstanceHandle();

    if (!(::GetClassInfo(hInst, _T("TreeComboBox"), &wndcls)))
    {
        wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wndcls.lpfnWndProc = ::DefWindowProc;
        wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
        wndcls.hInstance = hInst;
        wndcls.hIcon = NULL;
        wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
        wndcls.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
        wndcls.lpszMenuName = NULL;
        wndcls.lpszClassName = _T("TreeComboBox");

        if (!AfxRegisterClass(&wndcls))
        {
            AfxThrowResourceException();
            return FALSE;
        }
    }

    return TRUE;
}

我尝试在运行时使用测试程序中的以下代码创建控件:

BOOL CTestComboBoxDlg::OnInitDialog()
{
    ...

    m_ComboBox2.CreateEx(WS_EX_CLIENTEDGE, _T("TreeComboBox"), _T(""), WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
        CRect(0, 0, 100, 50), this, 100000, NULL);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

我也尝试使用按钮单击事件创建控件,认为我应该让GUI完成初始化,但是会发生同样的错误:

void CTestComboBoxDlg::OnBnClickedButton1()
{
    m_ComboBox2.CreateEx(WS_EX_CLIENTEDGE, _T("TreeComboBox"), _T(""), WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,
        CRect(0, 0, 100, 50), this, 100000, NULL);
}

当我运行程序时,它停在以下行的dbgrptt.cpp文件中:

     __try
            {
                if (_CRT_ASSERT == nRptType && _InterlockedIncrement(&_crtAssertBusy) > 0)
                {
                    /* use only 'safe' functions -- must not assert in here! */

                    _ERRCHECK(_itoa_s(nLine, szLineMessage, DBGRPT_MAX_MSG, 10));

                    OutputDebugStringA("Second Chance Assertion Failed: File ");
                    OutputDebugStringA(szFile ? szFile : "<file unknown>");
                    OutputDebugStringA(", Line ");
                    OutputDebugStringA(szLineMessage);
                    OutputDebugStringA("\n");

  It stop here===>  _CrtDbgBreak();
                    retval=-1;
                    __leave;
                }

如果我使用Visual Studio GUI编辑器手动创建控件,程序运行正常,所以我不确定是什么错。你能帮我弄清楚如何在运行时创建这个控件吗?

注意:如果您要运行代码并使用MFC,请将语句:TRACE1(_T("Item selected: %s\n"), GetItemText(hItem));更改为文件ComboTreeCtrlExt.cpp中的TRACE(_T("Item selected: %s\n"), GetItemText(hItem));

1 个答案:

答案 0 :(得分:1)

回答我自己的问题。将以下代码从CTreeComboBox::PreSubclassWindow()移至CTreeComboBox::OnCreate()

CRect rect(0, 0, 0, 0);
DWORD dwStyle =  WS_POPUP | WS_BORDER;
CWnd* pWnd = &m_Tree;
pWnd->CreateEx(0, WC_TREEVIEW, NULL, dwStyle, rect, GetParent(), 0, NULL);
m_Tree.Init(this);

GetClientRect(rect);
SetDroppedWidth(rect.Width());
SetDroppedHeight(m_nDroppedHeight);

dwStyle = CBS_DROPDOWNLIST & GetStyle();
ASSERT(CBS_DROPDOWNLIST == dwStyle);