Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как получить указатель на CDocument? 
:(
    Опции темы
automax
Дата 6.10.2003, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



Одна из функций WINAPI в качестве параметра берет функцию обратного вызова.

После этого я хочу чтобы действия которые обрабатывает эта функция выводились на форму.

Для этого, я:

Объявляю глобальную переменную типа

Код

CMyDocument * mydoc;  


И в конструкторе, или одном из методов класса CMyDocument инициализирую mydoc=this:

Код

CMyDocument::CMyDocument()  {
               //Действия
             
               mydoc=this;
           
}


После этого я в функции обратного вызова вызываю, один из методов класса CMyDocument, а в нем вызываю UpdateAllViews(NULL), и получаю ошибку:

Код

void callbackfunction() {
               //Код

              mydoc->UpdateAllViews(NULL); //Ошибка чтение памяти
}


Ошибку выдает UpdateAllViews(NULL);
Что-то он не может найти вида
Помогите разобраться. Или если у кого-то есть другой вариант решения этой проблемы то подскажите, пожалуйста.
PM MAIL   Вверх
mr.DUDA
Дата 6.10.2003, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Обычно в таких целях я использую CMainFrame как посредник (он знает обо всех документах и видах):
Код
CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();

pFrame->GetActiveDocument();   // активный документ
pFrame->GetActiveView();           // активный вид

и не нужно тогда объявлять никаких глобальных указателей.


--------------------
user posted image
PM MAIL WWW   Вверх
automax
Дата 6.10.2003, 20:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



Проверил предложенный способ. Теперь ошибка происходит при вызове функции pFrame->GetActiveDocument(); в теле глобальной функции.

Есть у меня предположение, что все это происходит из-за того, что глобальная функция работает не в первичном потоке приложения, с которым связаны документ и вид. А в потоке, который был создан API функцией, которая и вызывает функцию обратного вызова. Но с этим потоком не связан ни один документ. Из-за этого и происходит ошибка.

Может кто поможет решить проблему.
PM MAIL   Вверх
mr.DUDA
Дата 6.10.2003, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



ИМХО, поток здесь ни при чём, т.к. AfxGetMainWnd() обращается к единственному глобальному объекту "theApp.m_pMainWnd".

А есть уверенность, что на момент вызова документ, фрейм и вид уже реально созданы ? Т.е. "pFrame->m_hWnd != NULL" ?


--------------------
user posted image
PM MAIL WWW   Вверх
automax
Дата 6.10.2003, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



Да. Функция запускается гораздо позже.

А вот код:

Код

            CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();

             if (pFrame->m_hWnd!=NULL) {
      CDocument *locdoc=pFrame->GetActiveDocument();  
             }

И ошибка на вызове, GetActiveDocument()
PM MAIL   Вверх
mr.DUDA
Дата 6.10.2003, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Ну что тут можно сказать... Могу только посоветовать посидеть в дебаггере и отловить сбойный участок в исходниках MFC, покопавшись в Call Stack. На крайняк, отказаться от Document/View, или юзать ф-цию MFC вместо callback-функции WinAPI.

Баг совершенно непонятный. Если фрейм существует, и документ с видом присоединены, то как написано в WINFRM.CPP,
Код
CDocument* CFrameWnd::GetActiveDocument()
{
    ASSERT_VALID(this);
    CView* pView = GetActiveView();
    if (pView != NULL)
          return pView->GetDocument();
    return NULL;
}

CView* CFrameWnd::GetActiveView() const
{
     ASSERT(m_pViewActive == NULL ||
          m_pViewActive->IsKindOf(RUNTIME_CLASS(CView)));
     return m_pViewActive;
}


То есть либо нету ни одного вида, либо фрейму плохо стало и он себя любимого ASSERT_VALID(this)'ом выглючивает... Сорц, сорц и ещё раз сорц ! Пора бы глянуть на то, что у тебя в исходниках wink.gif



--------------------
user posted image
PM MAIL WWW   Вверх
DENNN
Дата 7.10.2003, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 3878
Регистрация: 27.3.2002
Где: Москва

Репутация: 1
Всего: 43



Пора бы с самого начала глянуть smile.gif
PM ICQ   Вверх
automax
Дата 7.10.2003, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



В Debug дошел до функции
void CWnd::AssertValid() const;

А именно до строчки
CHandleMap* pMap = afxMapHWND();
ASSERT(pMap != NULL);

В этой функции написано:

// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.

Что это точно означает я не понял. Может что подскажите.

Кстати исходники с пояснениями готов выслать, скажите кому.


PM MAIL   Вверх
mr.DUDA
Дата 7.10.2003, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Ты был прав. Та функция работает в другом потоке, а MC честно предупреждают, что нельзя просто так передавать CWnd из одного потока в другой.


--------------------
user posted image
PM MAIL WWW   Вверх
automax
Дата 7.10.2003, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



Поэтому поводу возникает вопрос? Что же делать?
PM MAIL   Вверх
DENNN
Дата 7.10.2003, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 3878
Регистрация: 27.3.2002
Где: Москва

Репутация: 1
Всего: 43



Цитата
Поэтому поводу возникает вопрос? Что же делать?

Ответ уже написан в коде в комментариях smile.gif
Сказано: передайте параметр HWND и в другом потоке создайте объект CWND через CWND::FromeHandle
PM ICQ   Вверх
automax
Дата 7.10.2003, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



Делаю, но это не помогает. Дело в том, что все способы давали получить объект CMainFrame, но вот получить с помощью этого объекта CDocument не удается. Может все таки кто-то хочет посмотреть исходники. Там всего строчек 100.
PM MAIL   Вверх
mr.DUDA
Дата 7.10.2003, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Конечно, давай посмотрим на исходник. Так легче будет разобраться (или не разобраться wink.gif)


--------------------
user posted image
PM MAIL WWW   Вверх
automax
Дата 7.10.2003, 22:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 30.9.2002

Репутация: нет
Всего: нет



mr.Duda, исходники отправил на e-mail, лови.
PM MAIL   Вверх
mr.DUDA
Дата 7.10.2003, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Значит так. По порядку, что поменял (исходники я тебе уже отослал):
1) функция RasDialCallBackFunc:
Код
    CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
    CDialerDoc *locdoc = (CDialerDoc *)((CDialerView*)pFrame->MyGetView())->MyGetDoc();
    locdoc->SetConnState(temp);

2) объект вид:
Код
class CDialerView : public CFormView
{
public:
    // напрямую получаем указатель на документ, без всяких ASSERT'ов
    CDocument *MyGetDoc() {return m_pDocument;}

3) мейнфрейм:
Код
class CMainFrame : public CFrameWnd
{
public:
    // то же самое
    CView *MyGetView() {return m_pViewActive;}

4) метод CDialerDoc::SetConnState
Код
    // тут нужно просто послать сообщение WM_REDRAW,
    // вместо ООП используем HWND
    CDialerView *view = (CDialerView*)((CMainFrame*)AfxGetMainWnd())->MyGetView();
    ::RedrawWindow(view->m_hWnd, 0, 0, 0);

Коряво. Согласен. Но работает wink.gif

ИМХО, надо было всем эти исходники показать, чтобы народ свои предложения предлагал...


--------------------
user posted image
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0603 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.