Проблема с CTabCtrl
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 11.03.19 11:34
Оценка:
Я на свой диалог повесил табконтрол IDC_TAB1 (тип CTabCtrl, переменная m_IDC_TAB1).
На этот табконтрол я поместил две закладки--"Исходные НУ" и "Расчёт". Каждой из этих закладок соответствует по одной странице (диалогу). Обе эти страницы пока пустые (без компонентов), так как я хотел бы, чтобы первоначально просто нормально бы работал этот табконтрол.

Первоначально табконтрол находится на странице "Исходные НУ". При нажатии на страницу "Расчёт" в отладчике появляется два раза сообщение--в функции OnTcnSelchangingTab1 и в функции OnTcnSelchangeTab1:

Debug Assertion Failed!
Program: C:\WINDOWS\SYSTEM32\mfc110d.dll

File: f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\winocc.cpp

Line: 329


После этого тем не менее происходит переход и отображение диалога "Расчёт".

Если же на диалоге "Расчёт" нажать на страницу "Исходные НУ", то также в отладчике будет два раза появляться точно такое же сообщение об ошибке--в функции OnTcnSelchangingTab1 и в функции OnTcnSelchangeTab1, после чего происходит переход и отображение диалога "Исходные НУ".

В чём причина этого? Как сделать так, чтобы этого сообщения не появлялось?

Код:

BOOL CSO_LifeTimeDlg::OnInitDialog()
{
    CNUDialog *pNUPage;
    CCalcDialog *pCalcPage;

    CDialogEx::OnInitDialog();
    // Добавление пункта "О программе..." в системное меню.

    // IDM_ABOUTBOX должен быть в пределах системной команды.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != NULL)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // Задает значок для этого диалогового окна. Среда делает это автоматически,
    //  если главное окно приложения не является диалоговым
    SetIcon(m_hIcon, TRUE);            // Крупный значок
    SetIcon(m_hIcon, FALSE);        // Мелкий значок

    // TODO: добавьте дополнительную инициализацию
    TCITEM  TabItem;
    TabItem.mask = TCIF_TEXT;
    TabItem.pszText = "Исходные НУ";
    m_IDC_TAB1.InsertItem(0,&TabItem);
    TabItem.pszText = "Расчёт";
    m_IDC_TAB1.InsertItem(1,&TabItem);
    pNUPage = new CNUDialog(this);
    pCalcPage = new CCalcDialog(this);
    TabItem.mask = TCIF_PARAM;
    TabItem.lParam = (LPARAM)pNUPage;
    m_IDC_TAB1.SetItem(0,&TabItem);
    TabItem.mask = TCIF_PARAM;
    TabItem.lParam = (LPARAM)pCalcPage;
    m_IDC_TAB1.SetItem(1,&TabItem); 
    return TRUE;  // возврат значения TRUE, если фокус не передан элементу управления
}


void CSO_LifeTimeDlg::OnTcnSelchangeTab1(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: добавьте свой код обработчика уведомлений
    int  nTab = m_IDC_TAB1.GetCurSel();
    TC_ITEM  tci;
    tci.mask = TCIF_PARAM;
    m_IDC_TAB1.GetItem(nTab,&tci);
    ASSERT(tci.lParam);
    CWnd *pWnd = (CWnd*)tci.lParam;
    //
    pWnd->ShowWindow(SW_SHOW); // здесь выскакивает сообщение об ошибке
    *pResult = 0;
}


void CSO_LifeTimeDlg::OnTcnSelchangingTab1(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: добавьте свой код обработчика уведомлений
    int  nTab = m_IDC_TAB1.GetCurSel();
    TC_ITEM  tci;
    tci.mask = TCIF_PARAM;
    m_IDC_TAB1.GetItem(nTab,&tci);
    ASSERT(tci.lParam);
    CWnd *pWnd = (CWnd*)tci.lParam;
    //
    pWnd->ShowWindow(SW_HIDE); // здесь выскакивает сообщение об ошибке
    *pResult = 0;
}
1613 г. = 2024 г.
Re: Проблема с CTabCtrl
От: qaz77  
Дата: 11.03.19 12:18
Оценка: 4 (1)
Здравствуйте, RussianFellow, Вы писали:

Здесь надо для дочерних диалогов Create вызывать.
ASSERT вылезает из-за того, что ShowWindow зовется при m_hWnd == NULL.

RF>
RF>    TCITEM  TabItem;
RF>    TabItem.mask = TCIF_TEXT;
RF>    TabItem.pszText = "Исходные НУ";
RF>    m_IDC_TAB1.InsertItem(0,&TabItem);
RF>    TabItem.pszText = "Расчёт";
RF>    m_IDC_TAB1.InsertItem(1,&TabItem);
RF>    pNUPage = new CNUDialog(this);
RF>    pCalcPage = new CCalcDialog(this);
RF>    TabItem.mask = TCIF_PARAM;
RF>    TabItem.lParam = (LPARAM)pNUPage;
RF>    m_IDC_TAB1.SetItem(0,&TabItem);
RF>    TabItem.mask = TCIF_PARAM;
RF>    TabItem.lParam = (LPARAM)pCalcPage;
RF>    m_IDC_TAB1.SetItem(1,&TabItem);


Еще надо посмотреть в редакторе ресурсов, чтобы для дочерних диалогов стояли стили child и control parent.

Точно нужен таб контрол в диалоге?
Если на диалоге только странички (нет какой-то общей части), то гораздо проще и приятнее пользоваться связкой CPropertySheet + CPropertyPage.

P.S. Код ужасен.
Re[2]: Проблема с CTabCtrl
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 11.03.19 14:31
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>Здравствуйте, RussianFellow, Вы писали:


Q>Здесь надо для дочерних диалогов Create вызывать.

Q>ASSERT вылезает из-за того, что ShowWindow зовется при m_hWnd == NULL.

Да, верно--посмотрел своё предыдущее решение, там тоже на табконтроле диалоги размещаются--действительно, нужно вызвать для pNUPage и pCalcPage сначала функции Create, потом функции SetWindowsPos, а затем функции ShowWindow (для pNUPage как для страницы первой вкладки с параметром SW_SHOW, для pCalcPage как для страницы последующей вкладки с параметром SW_HIDE). И всё заработало!

Спасибо за подсказку!
1613 г. = 2024 г.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.