Re[2]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 11.03.14 15:30
Оценка: +1
Возможно, вот это Вам поможет:
http://www.codeproject.com/Articles/1724/Some-handy-dialog-box-tricks-tips-and-workarounds
как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 11.03.14 12:43
Оценка:
Доброго времени суток.
Есть необходимость получить фрейм у объекта класса наследованного от CDialog и заменить его своим, который наследован от CMDIChildWnd (CFrameWnd). Подскажите как это сделать, если это вообще возможно.
Re: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 11.03.14 15:16
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>Доброго времени суток.

C>Есть необходимость получить фрейм у объекта класса наследованного от CDialog и заменить его своим, который наследован от CMDIChildWnd (CFrameWnd). Подскажите как это сделать, если это вообще возможно.

Встречный вопрос, уважаемый cupuyc, — что и с какой целью делается?
Не могли бы подробнее изложить, чего требуется добиться???
Возможно, существует более верное решение...

Вполне возможно, что Вам надо выбирать не наследника от CDialog, а наследника от CFormView

Ответ на вопрос — как получить окно главного "фрейма":

::AfxGetApp()->GetMainWnd();


Дочерний MDI "фрейм" (CMDIChildWnd) с конкретным диалоговым окном не связан никак.
Из общих предков у CMDIChildWnd и CDialog — только "классическое" окно, представленное классом CWnd (но это вряд-ли чем-то Вас выручит).
Re[2]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 12.03.14 06:24
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Здравствуйте, cupuyc., Вы писали:


C>>Доброго времени суток.

C>>Есть необходимость получить фрейм у объекта класса наследованного от CDialog и заменить его своим, который наследован от CMDIChildWnd (CFrameWnd). Подскажите как это сделать, если это вообще возможно.

AG>Встречный вопрос, уважаемый cupuyc, — что и с какой целью делается?

AG>Не могли бы подробнее изложить, чего требуется добиться???
AG>Возможно, существует более верное решение...

AG>Вполне возможно, что Вам надо выбирать не наследника от CDialog, а наследника от CFormView


AG>Ответ на вопрос — как получить окно главного "фрейма":


AG>

AG> ::AfxGetApp()->GetMainWnd();


AG>Дочерний MDI "фрейм" (CMDIChildWnd) с конкретным диалоговым окном не связан никак.

AG>Из общих предков у CMDIChildWnd и CDialog — только "классическое" окно, представленное классом CWnd (но это вряд-ли чем-то Вас выручит).

Мне нужно в модальное диалоговое окошко вставить элемент ActiveX. Я автоматизирую MS Word. Я добился поднятия всего этого счастья в обычных окнах (CMDIChildWnd), но теперь мне нужно, что бы первое поднявшееся окно как бы стопарило программу пока его не закроют. Что собственно и делает CDialog при вызове его функции DoModal().
Re[3]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 12.03.14 06:37
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Возможно, вот это Вам поможет:

AG>http://www.codeproject.com/Articles/1724/Some-handy-dialog-box-tricks-tips-and-workarounds

спасибо за ссылку, но не помогло.
Re[3]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 12.03.14 12:51
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>Мне нужно в модальное диалоговое окошко вставить элемент ActiveX.

С этой задачей, как я понимаю, все получилось. Или же возникли какие-либо проблемы?

C>Я автоматизирую MS Word. Я добился поднятия всего этого счастья в обычных окнах (CMDIChildWnd), но теперь мне нужно, что бы первое поднявшееся окно как бы стопарило программу пока его не закроют. Что собственно и делает CDialog при вызове его функции DoModal().

То есть сервером OLE-automation является MS Word, а клиентом — Ваша программа на MFC. Верно?

Что же мешает решить данную проблему, просто за счет вызова модального диалогового окна, в котором "бежит" прогресс-бар (он бежит до окончания переноса инфы в MS Word, либо до окончания переноса инфы из ворда)?

После обмена инфой с вордом, это диалоговое окно закрывается Вашим приложением. Как идея?

При этом обмен инфой с MS Word — сделать в отдельном (рабочем) потоке...

Что делает элемент ActiveX, указанный Вами выше, и какая его роль в обмене инфой с MS Word?
Re[4]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 12.03.14 14:27
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Здравствуйте, cupuyc., Вы писали:


C>>Мне нужно в модальное диалоговое окошко вставить элемент ActiveX.

AG>С этой задачей, как я понимаю, все получилось. Или же возникли какие-либо проблемы?
Нет, с этой задачей я не справился. У меня получилось только запихнуть сервер автоматизации ворда в свой фрейм наследованный от CMDIChildWnd. В кач-ве вьюшки я использую наследника от CScrollView.

AG>То есть сервером OLE-automation является MS Word, а клиентом — Ваша программа на MFC. Верно?

Все верно.


AG>Что же мешает решить данную проблему, просто за счет вызова модального диалогового окна, в котором "бежит" прогресс-бар (он бежит до окончания переноса инфы в MS Word, либо до окончания переноса инфы из ворда)?

AG>После обмена инфой с вордом, это диалоговое окно закрывается Вашим приложением. Как идея?
Собственно, так я и сделал пока идет обработка документа сервером ворда.

AG>Что делает элемент ActiveX, указанный Вами выше, и какая его роль в обмене инфой с MS Word?

Я открываю документ с помощью ворда в своей программе. Встраиваю ворд как элемент ActiveX и обрабатываю его методами сервера автоматизации. Далее, после того как документ обработан и готов к показу, я его отображаю как дочернее окошко своей программы. Вот в этот самый момент мне и нужна модальность. Что бы программа не выполнялась далее, а застопорилась пока пользователь не закроет окошко с сервером форда.

Все это счастье с автоматизацией ворда разрабатывается в отдельной dll — библиотеке.
Re[5]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 12.03.14 17:42
Оценка:
Здравствуйте, cupuyc., Вы писали:

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


AG>>Здравствуйте, cupuyc., Вы писали:


C>>>Мне нужно в модальное диалоговое окошко вставить элемент ActiveX.

AG>>С этой задачей, как я понимаю, все получилось. Или же возникли какие-либо проблемы?
C>Нет, с этой задачей я не справился. У меня получилось только запихнуть сервер автоматизации ворда в свой фрейм наследованный от CMDIChildWnd. В кач-ве вьюшки я использую наследника от CScrollView.
Под понятием "элемент ActiveX" — как правило, понимается нейкий GUI контрол. Конечно, это может быть и НЕ ГРАФИЧЕСКИЙ элемент (в т.ч. и сервер автоматизации). Я сначала подумал, что это какая-то графическая штуковина (как-то связанная с Вашей задачей), но не сам OLE-сервер MS Word.

AG>>То есть сервером OLE-automation является MS Word, а клиентом — Ваша программа на MFC. Верно?

C>Все верно.

Вот неплохие рекомендации — может пригодатся:
http://www.codeproject.com/Articles/34998/MS-Office-OLE-Automation-Using-C

Обратите внимание на:

With MFC, use the Visual C++ ClassWizard to generate "wrapper classes" from the Microsoft Office type libraries. These classes, as well as other MFC classes, such as COleVariant, COleSafeArray, and COleException, simplify the tasks of Automation. This method is usually recommended over the others, and most of the Microsoft Knowledge Base examples use MFC.

ИМХО — это примерно то, что Вам требуется. В современных студиях: меню Project/Add Class там MFC и затем "MFC Class from TypeLib"; в открывшемся окне выбираем (add class from) -> File — открываем файл — например: C:\Program Files\Microsoft Office\Office12\EXCEL.EXE — и далее берем требуемые компоненты...

AG>>Что делает элемент ActiveX, указанный Вами выше, и какая его роль в обмене инфой с MS Word?

C>Я открываю документ с помощью ворда в своей программе. Встраиваю ворд как элемент ActiveX и обрабатываю его методами сервера автоматизации. Далее, после того как документ обработан и готов к показу, я его отображаю как дочернее окошко своей программы. Вот в этот самый момент мне и нужна модальность. Что бы программа не выполнялась далее, а застопорилась пока пользователь не закроет окошко с сервером форда.
Что мешает сделать — через импорт библиотеки Type Library — этот же функционал в наследнике CDialog?

C>Все это счастье с автоматизацией ворда разрабатывается в отдельной dll — библиотеке.

А откуда загружается это счастье (то есть длл-ка)?
Re[6]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 13.03.14 07:14
Оценка:
del
Отредактировано 01.03.2018 15:04 cupuyc. . Предыдущая версия .
Re[7]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 13.03.14 08:59
Оценка:
В данный момент я смотрю в сторону функций класса CWnd::RunModalLoop() и CWnd::EndModalLoop().
Вызвал для своего дочернего окна RunModalLoop после его создания, вот тут:

...
    child->Create(NULL, title, WS_OVERLAPPEDWINDOW | WS_CHILD, 
        CFrameWnd::rectDefault, NULL, &mContext);

    child->InitialUpdateFrame( doc, TRUE );

    DWORD dwFlags = MLF_SHOWONIDLE;
    child->RunModalLoop(dwFlags);  
...


... после открытия, программа останавливается как мне и нужно. Но по закрытию вылетает ошибка чтения памяти. Очевидно, что не все так просто. В классе CBaseOleWordFrame написал следующее:

void CBaseOleWordFrame::OnClose() 
{
    this->EndModalLoop(IDCANCEL);
    this->DestroyWindow();
}


но программа все равно падает в файле WINCORE.cpp в функции CWnd::RunModalLoop() на строке:

    if (!ContinueModal())
    goto ExitModal;
Re[7]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 13.03.14 10:04
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>Спасибо за ссылку, но я уже все это прошерстил. Но воспользовался вот этой ссылкой http://support.microsoft.com/kb/238611/en-us .

Эта технология называется — "составной документ" (compound document):

"Container" as the type of compound document support in step 3. You can accept all other defaults.


C>>>Я открываю документ с помощью ворда в своей программе. Встраиваю ворд как элемент ActiveX и обрабатываю его методами сервера автоматизации. Далее, после того как документ обработан и готов к показу, я его отображаю как дочернее окошко своей программы. Вот в этот самый момент мне и нужна модальность. Что бы программа не выполнялась далее, а застопорилась пока пользователь не закроет окошко с сервером форда.

Я предполагал у Вас несколько другую технологию (не "составной документ", а "клиент сервера OLE-automation").

C>Наверное я чего то не знаю. Но мне нужна организация документ — вид + класс — контейнер наследованный от COleClientItem для хранения обьекта AxtiveX насколько я понял. А как это реализовать в наследнике от CDialog я, к сожалению, не представляю. Буду рад помощи.

Я бы все-таки предложил Вам реализовать функционал Вашего приложения, в рамках "клиента сервера OLE-automation", где сервером OLE является MS Word. Это проще в реализации и поможет избежать тех проблем, с которыми Вы столкнулись. Я успешно применил именно эту технологию — "client of OLE-automation" (правда с MS Excel) во многих моих проектах на MFC (в том числе и на dialog-based — где главное окно представлено классом — наследником от CDialog). При этой технологии приложение MS Word запускается как отдельная программа (по соответствующему вызову из нашего приложения), при этом данные в нее передает/читает наше приложение. Конечно, если у Вас какие-то специфические требования, мой совет может оказаться и не в тему

P.S. Просто вариант "составной документ" более привязан в своей реализации к архитектуре Doc/View (документ/вид), которая так популярна в MFC. Однако, эта архитектура, ИМХО, является как-бы пережитком прошлого, который просто-напросто достался "тяжелым наследством" современной библиотеке MFC. Попутно замечу, что MS в рамках библиотеки классов .NET, которая увидела свет позже, чем MFC, отказалась от Doc/View.

P.S.2. Возвращаясь к Вашим вопросам — здесь, на мой взгляд, есть два варианта: a) идти до конца по выбранному Вами пути; b) взять за основу именно "клиент сервера OLE-automation" и оставить "составной документ". Конечно, обе эти технологии базируются на COM/OLE и в этом похожи друг на друга, обе позволяют (на мой взгляд) реализовать требуемый Вам функционал. Однако, естественно — конечный выбор за Вами...
Re[8]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 13.03.14 10:23
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>P.S.2. Возвращаясь к Вашим вопросам — здесь, на мой взгляд, есть два варианта: a) идти до конца по выбранному Вами пути; b) взять за основу именно "клиент сервера OLE-automation" и оставить "составной документ". Конечно, обе эти технологии базируются на COM/OLE и в этом похожи друг на друга, обе позволяют (на мой взгляд) реализовать требуемый Вам функционал. Однако, естественно — конечный выбор за Вами...


Спасибо, за ответ. Может быть поделитесь ссылочкой на материалы по теме клиент сервера OLE-automation. Или может есть примеры кода?
Re[8]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 13.03.14 10:26
Оценка:
Вполне возможно, правильным выбором в Вашей ситуации было бы просто погуглить по ключевым словам "compound document" MFC:
https://www.google.by/#q=%22compound+document%22+MFC&spell=1
возможно, посмотреть по этой же теме — что есть на codeguru/codeproject...
Re[9]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 13.03.14 10:55
Оценка:
По технологии клиент сервера OLE-automation:

В книге Круглинский, Уингоу, Шеферд "Программирвание на Visual C++ 6 для профессионалов", есть описание практического применения данной технологии (в главе COM, Automation, ActiveX и OLE) — в статье "Управление приложением Microsoft Excel". Предполагаю, что MS Word будет не сильно отличаться. Ну и та ссылка на codeproject, что я давал здесь выше.

Вот и пример кода, из одного нашего проекта (переносит телефонную книгу в MS Excel):


#include "CApplication.h"
#include "CRange.h"
#include "CWorksheet.h"
#include "CWorkbooks.h" 
#include "CWorksheets.h"  

// OleExcel.h : header file- for support OLE-Automation functions (PhoneBook-client, Excel-server).
//
 
/////////////////////////////////////////////////////////////////////////////
// COleExcel class

class COleExcel 
{
//    typedef CTypedPtrArray<CObArray, CPBRecord*> CPBRecArray;  
// Construction
public:
    COleExcel();
    void Create();
    virtual ~COleExcel();

protected:
    CApplication* m_pApp;
    CRange*        m_pRange;
    CWorksheet*    m_pWorksheet;
    CWorkbooks*    m_pWorkbooks;
    CWorksheets*   m_pWorksheets;
.........
public:
    bool ExcelOleLoad(bool bShowMessage = true); 
    long ExcelOleExport(class CPBRecord* pPBRCaption, CPBRecordsArray& PBRecArray); 
    long ExcelOleImport(class CPBRecord* pPBRCaption, CPBRecordsArray& PBRecArray); 
};

Файлы "CApplication.h","CRange.h","CWorksheet.h","CWorkbooks.h","CWorksheets.h" — сгенерированы студией, при импорте Type Library

Вот вызов и загрузка MS Excel:

bool COleExcel::ExcelOleLoad(bool bShowMessage)
{
    // if Excel is already running, attach to it, otherwise start it
   LPDISPATCH pDisp;
   LPUNKNOWN pUnk;
   CLSID clsid;
   int iResult;  // for AfxMessageBox - when Attaching to Excel.

   ::CLSIDFromProgID(L"Excel.Application", &clsid); // from registry
   if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)
   {
      if(pUnk->QueryInterface(IID_IDispatch, (void**)&pDisp) != S_OK)
      {
        AfxMessageBox("Ошибка запроса QueryInterface - IDispatch !");
        return(false);
      }
      m_pApp->AttachDispatch(pDisp);
      pUnk->Release();
      /* AfxMessageBox("Attach complete !"); */ 

      if (bShowMessage)
      {
        iResult = AfxMessageBox(
            "При переносе в раскрытую рабочую книгу 'Excel', возможна потеря Ваших текущих данных. Переносить ?",
            MB_YESNO);

        if(iResult != IDYES)
            return(false);
      }
   } 
   else
   {
        if(!m_pApp->CreateDispatch("Excel.Application"))
        {
            AfxMessageBox(
                "Программа 'MS Excel' отсутствует, либо старая версия (ранее 'Excel-97') !");

            return(false);
        }
        /* AfxMessageBox("Create complete !"); */
   }
   m_pApp->put_Visible(TRUE);
   return(true);
}
Re[10]: как получить фрейм обьекта CDialog
От: AlexGin Беларусь  
Дата: 13.03.14 11:03
Оценка:
Вот — перенос из MS Excel (в нашу программу):

long COleExcel::ExcelOleImport(bool bAddPNPrefix, CStringArray* pArrNames, CStringArray* pArrPNums)
{
    if ((!pArrNames) || (!pArrPNums))
        return 1L;

    // Import SMS-Mass list:
    LPDISPATCH pRange; 
    LPDISPATCH pWorkbooks;
    LPDISPATCH pWorkbook;
    try
    {
        CWnd* pWnd = CWnd::FindWindow("XLMAIN", NULL);
        if (pWnd != NULL)
        {
            /* AfxMessageBox("Excel window found !"); */
            pWnd->ShowWindow(SW_SHOWNORMAL);
            pWnd->UpdateWindow();
            pWnd->BringWindowToTop();
        }

        m_pApp->put_SheetsInNewWorkbook(1);
   
        pWorkbooks = m_pApp->get_Workbooks();
        m_pWorkbooks->AttachDispatch(pWorkbooks);

        pWorkbook = NULL;
        if (m_pWorkbooks->get_Count() == 0)
        {
            // Add returns a Workbook pointer, but we
            //  don't have a Workbook class
            pWorkbook = m_pWorkbooks->Add(); // Save the pointer for
                                            //  later release
        }
        LPDISPATCH pWorksheets = m_pApp->get_Worksheets();
        if(pWorksheets == NULL)
        {
            AfxMessageBox("Error GetWorksheet !");
            return 1L;
        }
        m_pWorksheets->AttachDispatch(pWorksheets);
        LPDISPATCH pWorksheet = m_pWorksheets->get_Item(COleVariant((short)1));

        m_pWorksheet->AttachDispatch(pWorksheet);
        m_pWorksheet->Select(); 
 
        CString strRangeName, strRangePhoneNum;

        long lExcelColName = 1;
        long lRow = 2L; // Start row

        for (UINT i = 0; i < MAX_EXCEL_ROWS; i++, lRow++) 
        {
            strRangeName.Format("B%u", lRow); 
            strRangePhoneNum.Format("E%u", lRow); 
            
            pRange = m_pWorksheet->get_Range(COleVariant(strRangeName));
            m_pRange->AttachDispatch(pRange);
            _bstr_t bstrName = m_pRange->get_Value();  
            CString strName = LPCTSTR(bstrName);

            pRange = m_pWorksheet->get_Range(COleVariant(strRangePhoneNum));
            m_pRange->AttachDispatch(pRange);
            _bstr_t bstrPhoneNum = m_pRange->get_Value();  
            CString strPhoneNum = LPCTSTR(bstrPhoneNum);
            if(IsValidStringField(strName) && IsValidStringField(strPhoneNum))
            {
                pArrNames->Add(strName);
                if (bAddPNPrefix)
                    CorrectPNPrefix(strPhoneNum);
                pArrPNums->Add(strPhoneNum);
            }
             
        }
        return 0L;        
    }
    catch(COleException* p)
    { 
        OleErrorMsg(p);
        // cleanup 
        if (pWorkbook != NULL)
        {
            pWorkbook->Release();
        }
        return 1L;  // Error occur
    }
}


А это — перенос из нашей программы:
long COleExcel::ExcelOleExport(CPBRecord* pPBRCaption, CPBRecordsArray& PBRecArray) 
{   // Телеф-книга для 'MS-Excel':
    long iExcelRow;     // Row's counter (current Excel's row)
    CString strRange;   // Fill data - grid in the 'MS-Excel'
    
    // LPDISPATCH pRange;
    LPDISPATCH pWorkbooks;
    LPDISPATCH pWorkbook;
    try
    {
        CWnd* pWnd = CWnd::FindWindow("XLMAIN", NULL);
        if (pWnd != NULL)
        {
            /* AfxMessageBox("Excel window found !"); */
            pWnd->ShowWindow(SW_SHOWNORMAL);
            pWnd->UpdateWindow();
            pWnd->BringWindowToTop();
        }

        m_pApp->put_SheetsInNewWorkbook(1);
   
        pWorkbooks = m_pApp->get_Workbooks();
        m_pWorkbooks->AttachDispatch(pWorkbooks);

        pWorkbook = NULL;
        if (m_pWorkbooks->get_Count() == 0)
        {
            // Add returns a Workbook pointer, but we
            //  don't have a Workbook class
            pWorkbook = m_pWorkbooks->Add(); // Save the pointer for
                                            //  later release
        }
        LPDISPATCH pWorksheets = m_pApp->get_Worksheets();
        if(pWorksheets == NULL)
        {
            AfxMessageBox("Error GetWorksheet !");
            return 1L;
        }
        m_pWorksheets->AttachDispatch(pWorksheets);
        LPDISPATCH pWorksheet = m_pWorksheets->get_Item(COleVariant((short)1));

        m_pWorksheet->AttachDispatch(pWorksheet);
        m_pWorksheet->Select();
   
        /* Filling data grid-table in the 'MS Excel': */  
        SetPhoneBookHeader(pPBRCaption);

        iExcelRow = 2;
        long lSize = PBRecArray.GetSize();
        for(long i = 0; i < lSize; i++, iExcelRow++)
        { 
            CPBRecord* pRec = PBRecArray[i];
            SetPhoneBookLine(pRec, iExcelRow, true);
        } 

        // cleanup  
        if (pWorkbook != NULL)
        {
            pWorkbook->Release();
        }
        return 0L;
    }
    catch(COleException* p)
    { 
        OleErrorMsg(p);
        // cleanup 
        if (pWorkbook != NULL)
        {
            pWorkbook->Release();
        }
        return 1L;  // Error occur
    }
}

В общем — идеи все ясны
Пример реализации — надеюсь понятен
Re[11]: как получить фрейм обьекта CDialog
От: cupuyc.  
Дата: 13.03.14 11:38
Оценка:
Спасибо за информацию, но этот вариант я откинул сразу, на этапе проектировки т.к. он не подходит для нашего проекта. Походу я просто не понял сразу про что Вы
Все же буду мучаться с RunModalLoop и выкачкой сообщений. Вот тут нашел пару полезных ссылок по моему вопросу:

http://forum.sources.ru/index.php?s=ed4c3583a14eb3fdec24c08256d1a824&amp;showtopic=224422&amp;st=15
http://www.rsdn.ru/forum/mfc/46330.hot
Автор: SirAlex
Дата: 17.04.02

http://www.rsdn.ru/forum/winapi/731322.hot
Автор:
Дата: 22.07.04
Re[8]: как получить фрейм обьекта CDialog
От: Аноним  
Дата: 14.03.14 17:00
Оценка:
Здравствуйте, cupuyc., Вы писали:

C>... после открытия, программа останавливается как мне и нужно. Но по закрытию вылетает ошибка чтения памяти. Очевидно, что не все так просто. В классе CBaseOleWordFrame написал следующее:


C>
C>void CBaseOleWordFrame::OnClose() 
C>{
    this->>EndModalLoop(IDCANCEL);
    this->>DestroyWindow();
C>}
C>


C>но программа все равно падает в файле WINCORE.cpp в функции CWnd::RunModalLoop() на строке:


C>
C>    if (!ContinueModal())
C>    goto ExitModal;
C>


Для фреймов вызывается delete this в PostNcDestroy.
Для устранения падения переопределить PostNcDestroy и удалять C++ объект руками, после разрушения окна.

С CMDIChildWnd ничего хорошего не получится.
Модальность подразумевает недоступность меню/тулбаров главного фрейма, недоступность переключения MDI child'ов.
Вызов RunModalLoop просто переносит цикл обработки сообщений из CWinThread::Run в твою функцию, но качает он по прежнему — можно лазить в меню и т.п.
Модальность диалогов в MFC достигается disable главного фрейма, а точнее вызовом BeginModalState/EndModalState.
Засада с MDI child в том, что он child главного фрейма (внук, если уж совсем педантично).

Не знаю, можно ли в doc/view для doctеmplаte задать создание top level CFrameWnd вместо CMDIChildWnd.
По идее внутренности doc/view не должны быть слишком уж завязаны на MDI, т.к. оно используется и в SDI, где обычное CFrameWnd.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.