MarcoChiesi Ответов: 3

Сбой после использования cprintdialog


Проблема возникает на 64 - битной версии Windows. Если я запускаю приложение (сборка в режиме отладки), вызывая:
CPrintDialog dlg
ДЛГ.Метод domodal
затем я выбираю отменить, когда я выхожу из приложения, я получаю сбой на wincore.cpp строка 415
Проблема не возникает, если приложение строится в режиме выпуска, но я хотел бы сохранить его в режиме отладки.
Есть ли какая-нибудь зацепка?

Что я уже пробовал:

DeleteDC(dlg.m_pd.hDC) не работает, потому что он терпит неудачу

3 Ответов

Рейтинг:
1

Jochen Arndt

Это не крах, но утверждение брошено. Утверждения выдаются только в отладочных сборках. Они в основном используются для информирования вас во время разработки о том, что произошло что-то странное (читай: разработчик допустил серьезную ошибку).

При упоминании номера строки в исходном файле MFC, например wincore.cpp, вы также должны упомянуть используемую версию VS или лучше открыть этот файл (он находится по адресу VC\atlmfc\src\mfc) и добавьте имя функции и содержимое строки.

С моим wincore.cpp версия строки с 412 по 414 являются

CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
ASSERT(pWnd != NULL);					
ASSERT(pWnd==NULL || pWnd->m_hWnd == hWnd);
с AfxWndProc() функция.

Запустите программу из отладчика и проверьте стек вызовов, когда происходит утверждение, чтобы узнать, для какого окна вызывается функция.

Читайте также о компании Класс CPrintDialog[^] и проверьте, применим ли ваш код. Поскольку вы создаете диалоговое окно печати в стеке, оно удаляется при выходе из области действия. Тогда утверждение для этого окна возникнет раньше, а не при закрытии приложения. Таким образом, реальная причина для утверждения может быть где-то еще в вашем приложении.

Для получения более подробной справки вы должны опубликовать полную функцию, использующую диалоговое окно печати. Что-то вроде
void SomeClass::SomeFunc()
{
    BOOL bPrintSetupOnly = FALSE;
    CPrintDialog dlg(bPrintSetupOnly);
    if (dlg.DoModal() == IDOK)
    {
        // do something here

        // If dlg.m_pd.hDC has not been assigned to a member variable
        if (!bPrintSetupOnly) // or GetDefaults, or GetPrinterDC has been called
            DeleteDC(dlg.m_pd.hDC);
        // Otherwise do it when not used anymore 
        //  (at least when this SomeClass instance destroyed).
        // But that requires tracking the state (clear member variable after deleting)
        //  and deleting it also on top of this function when not NULL
    }
}


MarcoChiesi

Спасибо, что ответили. Я разрабатываю программное обеспечение с VS2010 на своем ПК WXP, потому что мне нужно, чтобы это программное обеспечение также могло работать на XP (я заметил, что разработка на W7 делает это программное обеспечение не работающим на XP). Все в порядке, но я заметил проблему при тестировании программного обеспечения на ПК с W10. Поэтому я написал очень маленькое тестовое программное обеспечение с простым окном с простой кнопкой, которая просто делает:

CPrintDialog dlg(TRUE);
ДЛГ.Метод domodal();
DeleteDC(dlg.m_pd.hDC);

Итак, я уже написал весь код целиком :)
Я знаю, что построение в релизе заставляет утверждение исчезнуть, но переход к версии выпуска для всего большого программного обеспечения, которое я разрабатываю, создает несколько проблем в других местах, поэтому я пытаюсь сохранить отладочную версию.

Вот что у меня есть на линии 415 и рядом в винкоре:

WNDPROC AFXAPI AfxGetAfxWndProc()
{
#ifdef _AFXDLL
return AfxGetModuleState()->m_pfnAfxWndProc;
#еще
возврат &AfxWndProc;
#endif
}

Еще раз спасибо!

Jochen Arndt

Некоторые заметки (которые не решат проблему).

Вы можете разрабатывать приложения для XP при запуске VS на Win 7 или Win 10.

Использование простого тестового приложения-хорошая идея, потому что оно упрощает поиск проблем.

При создании CPrintDialog с bPrintSetupOnly = TRUE и не запрашивая DC по функциям, никакой DC не будет создан. Так что нет никакой необходимости вызывать DeleteDC.

Установка отладочных версий требует установки отладочных версий стандартных библиотек C/C++ и библиотек DLL MFC (или статической ссылки на них). Но вам не разрешается публиковать такие отладочные сборки, поскольку версии отладочных библиотек DLL не являются распространяемыми. Однако допускается установка на различные системы для целей тестирования.

Ваш фрагмент кода из wincore.cpp не включает в себя никаких утверждений.

Создайте тестовое приложение на W10 и запустите его в отладчике. Затем проверьте стек вызовов, когда происходит утверждение.

Рейтинг:
1

KarstenK

Когда ошибка происходит в предоставленной строке кода, чем возможны некоторые причины ошибок. Во-первых: установите hDC в конструкторе на 0, чтобы избежать любого ненужного вызова!!!

пробовать:

- многократное удаление hDC (убедитесь, что он только вызывается однажды
- некоторые багги манипуляции с dlg.m_pd

if(dlg.m_pd.hDC !=0) 
{
  DeleteDC(dlg.m_pd.hDC);
  dlg.m_pd.hDC = 0;
  dlg.m_pd = 0;//if possible or somewhere else.
}
Отнеситесь к ошибке серьезно, потому что ошибка может быть только симптомом большей проблемы. (Я узнал это на собственном горьком опыте)


MarcoChiesi

Спасибо, что ответили. Я попробовал это сделать, но утверждение не исчезает (dlg.m_pd=0; не принимается компилятором). Как я уже писал в другом комментарии, это всего лишь простая тестовая программа для исследования этого вопроса и применения возможного решения в моем большом программном обеспечении.

Рейтинг:
0

Member 13707190

У меня точно такая же проблема. Когда CPrintDialog.DoModal() или CPrintDialog.Вызывается функция GetDefaults (), а затем утверждение срабатывает при выходе приложения. Это происходит в кодовой базе, которая изначально была разработана в VC6 (toolset v60). Проблема возникает, когда код строится с помощью VS2010 (набор инструментов v100).


CHill60

должно ли это быть решением проблемы?