Доброго времени суток.
Есть необходимость получить фрейм у объекта класса наследованного от CDialog и заменить его своим, который наследован от CMDIChildWnd (CFrameWnd). Подскажите как это сделать, если это вообще возможно.
Здравствуйте, cupuyc., Вы писали:
C>Доброго времени суток. C>Есть необходимость получить фрейм у объекта класса наследованного от CDialog и заменить его своим, который наследован от CMDIChildWnd (CFrameWnd). Подскажите как это сделать, если это вообще возможно.
Встречный вопрос, уважаемый cupuyc, — что и с какой целью делается?
Не могли бы подробнее изложить, чего требуется добиться???
Возможно, существует более верное решение...
Вполне возможно, что Вам надо выбирать не наследника от CDialog, а наследника от CFormView
Ответ на вопрос — как получить окно главного "фрейма":
::AfxGetApp()->GetMainWnd();
Дочерний MDI "фрейм" (CMDIChildWnd) с конкретным диалоговым окном не связан никак.
Из общих предков у CMDIChildWnd и CDialog — только "классическое" окно, представленное классом CWnd (но это вряд-ли чем-то Вас выручит).
Здравствуйте, 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().
Здравствуйте, cupuyc., Вы писали:
C>Мне нужно в модальное диалоговое окошко вставить элемент ActiveX.
С этой задачей, как я понимаю, все получилось. Или же возникли какие-либо проблемы?
C>Я автоматизирую MS Word. Я добился поднятия всего этого счастья в обычных окнах (CMDIChildWnd), но теперь мне нужно, что бы первое поднявшееся окно как бы стопарило программу пока его не закроют. Что собственно и делает CDialog при вызове его функции DoModal().
То есть сервером OLE-automation является MS Word, а клиентом — Ваша программа на MFC. Верно?
Что же мешает решить данную проблему, просто за счет вызова модального диалогового окна, в котором "бежит" прогресс-бар (он бежит до окончания переноса инфы в MS Word, либо до окончания переноса инфы из ворда)?
После обмена инфой с вордом, это диалоговое окно закрывается Вашим приложением. Как идея?
При этом обмен инфой с MS Word — сделать в отдельном (рабочем) потоке...
Что делает элемент ActiveX, указанный Вами выше, и какая его роль в обмене инфой с MS Word?
Здравствуйте, AlexGin, Вы писали:
AG>Здравствуйте, cupuyc., Вы писали:
C>>Мне нужно в модальное диалоговое окошко вставить элемент ActiveX. AG>С этой задачей, как я понимаю, все получилось. Или же возникли какие-либо проблемы?
Нет, с этой задачей я не справился. У меня получилось только запихнуть сервер автоматизации ворда в свой фрейм наследованный от CMDIChildWnd. В кач-ве вьюшки я использую наследника от CScrollView.
AG>То есть сервером OLE-automation является MS Word, а клиентом — Ваша программа на MFC. Верно?
Все верно.
AG>Что же мешает решить данную проблему, просто за счет вызова модального диалогового окна, в котором "бежит" прогресс-бар (он бежит до окончания переноса инфы в MS Word, либо до окончания переноса инфы из ворда)? AG>После обмена инфой с вордом, это диалоговое окно закрывается Вашим приложением. Как идея?
Собственно, так я и сделал пока идет обработка документа сервером ворда.
AG>Что делает элемент ActiveX, указанный Вами выше, и какая его роль в обмене инфой с MS Word?
Я открываю документ с помощью ворда в своей программе. Встраиваю ворд как элемент ActiveX и обрабатываю его методами сервера автоматизации. Далее, после того как документ обработан и готов к показу, я его отображаю как дочернее окошко своей программы. Вот в этот самый момент мне и нужна модальность. Что бы программа не выполнялась далее, а застопорилась пока пользователь не закроет окошко с сервером форда.
Все это счастье с автоматизацией ворда разрабатывается в отдельной dll — библиотеке.
Здравствуйте, cupuyc., Вы писали:
C>Здравствуйте, AlexGin, Вы писали:
AG>>Здравствуйте, cupuyc., Вы писали:
C>>>Мне нужно в модальное диалоговое окошко вставить элемент ActiveX. AG>>С этой задачей, как я понимаю, все получилось. Или же возникли какие-либо проблемы? C>Нет, с этой задачей я не справился. У меня получилось только запихнуть сервер автоматизации ворда в свой фрейм наследованный от CMDIChildWnd. В кач-ве вьюшки я использую наследника от CScrollView.
Под понятием "элемент ActiveX" — как правило, понимается нейкий GUI контрол. Конечно, это может быть и НЕ ГРАФИЧЕСКИЙ элемент (в т.ч. и сервер автоматизации). Я сначала подумал, что это какая-то графическая штуковина (как-то связанная с Вашей задачей), но не сам OLE-сервер MS Word.
AG>>То есть сервером OLE-automation является MS Word, а клиентом — Ваша программа на MFC. Верно? 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 — библиотеке.
А откуда загружается это счастье (то есть длл-ка)?
В данный момент я смотрю в сторону функций класса CWnd::RunModalLoop() и CWnd::EndModalLoop().
Вызвал для своего дочернего окна RunModalLoop после его создания, вот тут:
... после открытия, программа останавливается как мне и нужно. Но по закрытию вылетает ошибка чтения памяти. Очевидно, что не все так просто. В классе CBaseOleWordFrame написал следующее:
Здравствуйте, 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 и в этом похожи друг на друга, обе позволяют (на мой взгляд) реализовать требуемый Вам функционал. Однако, естественно — конечный выбор за Вами...
Здравствуйте, AlexGin, Вы писали:
AG>P.S.2. Возвращаясь к Вашим вопросам — здесь, на мой взгляд, есть два варианта: a) идти до конца по выбранному Вами пути; b) взять за основу именно "клиент сервера OLE-automation" и оставить "составной документ". Конечно, обе эти технологии базируются на COM/OLE и в этом похожи друг на друга, обе позволяют (на мой взгляд) реализовать требуемый Вам функционал. Однако, естественно — конечный выбор за Вами...
Спасибо, за ответ. Может быть поделитесь ссылочкой на материалы по теме клиент сервера OLE-automation. Или может есть примеры кода?
Вполне возможно, правильным выбором в Вашей ситуации было бы просто погуглить по ключевым словам "compound document" MFC: https://www.google.by/#q=%22compound+document%22+MFC&spell=1
возможно, посмотреть по этой же теме — что есть на codeguru/codeproject...
В книге Круглинский, Уингоу, Шеферд "Программирвание на Visual C++ 6 для профессионалов", есть описание практического применения данной технологии (в главе COM, Automation, ActiveX и OLE) — в статье "Управление приложением Microsoft Excel". Предполагаю, что MS Word будет не сильно отличаться. Ну и та ссылка на codeproject, что я давал здесь выше.
Вот и пример кода, из одного нашего проекта (переносит телефонную книгу в MS Excel):
Спасибо за информацию, но этот вариант я откинул сразу, на этапе проектировки т.к. он не подходит для нашего проекта. Походу я просто не понял сразу про что Вы
Все же буду мучаться с RunModalLoop и выкачкой сообщений. Вот тут нашел пару полезных ссылок по моему вопросу:
Здравствуйте, cupuyc., Вы писали:
C>... после открытия, программа останавливается как мне и нужно. Но по закрытию вылетает ошибка чтения памяти. Очевидно, что не все так просто. В классе CBaseOleWordFrame написал следующее:
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.