Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание окна зарегистрированного класса 
:(
    Опции темы
Brodyaga
Дата 27.1.2010, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Всем здравствуйте!
Хочу создать окно зарегестрированого класса с помощью MFC.
Создаю класс наследник от CWnd.
Далее в функции Create передаю имя зарегестрированного оконного класс:
Код

InitRichInkDLL();
RECT rc;
GetClientRect(&rc);
CChildWnd* ChildWnd=new CChildWnd();
ChiledWnd->Create(WC_RICHINK,NULL,WS_VISIBLE|WS_CHILD|WS_VSCROLL, rc, this,(UINT)1);

Вставляю этот код в функции OnInitDialog. Программа вылетает на функции Create.

Если делаю без MFC на чистом WinApi, то всё работает. Сначала переопределяю оконную процедуру, а затем в событии щелчка мышкой по форме делаю следующее:
Код

InitRichInkDLL();
RECT    rc;
GetClientRect(hWnd, &rc);
HWND hWnd2 = CreateWindow(WC_RICHINK, NULL, WS_VISIBLE | WS_CHILD | WS_VSCROLL,
rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, hWnd, NULL, hInst, NULL);

Так всё работает. Что я делаю не правильно в первом варианте?
PM MAIL   Вверх
Earnest
Дата 28.1.2010, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  27.1.2010,  23:12 Найти цитируемый пост)
Программа вылетает на функции Create.

Куда вылетает-то? В окно? Ты же программист...
Цитата(Brodyaga @  27.1.2010,  23:12 Найти цитируемый пост)
Сначала переопределяю оконную процедуру, а затем в событии щелчка мышкой по форме делаю следующее:

Видишь, у тебя разница не только в применении MFC: во втором варианте ты создаешь контрол  не на ининциализации диалога, а по щелчку мыши. Может, в этом дело?
А вообще, надо понимать, что сабклассинг в MFC - это не совсем сабклассинг АПИ. MFC подставляет всем контролируемым окнам одну и ту же оконную процедуру (из которой по Default уже вызывается родная процедура класса). Тут тоже могут быть тонкости. Но из приведенной тобой информации ничего не ясно. Возьми отладчик и сходи внутрь Create.


--------------------
...
PM   Вверх
Brodyaga
Дата 28.1.2010, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

идишь, у тебя разница не только в применении MFC: во втором варианте ты создаешь контрол  не на ининциализации диалога, а по щелчку мыши.


Потому что сообщение WM_CREATE вообще не приходит...
PM MAIL   Вверх
Earnest
Дата 29.1.2010, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Кому не приходит и в каком варианте?


--------------------
...
PM   Вверх
Brodyaga
Дата 29.1.2010, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



В обоих вариантах. если оконную процедуру диалога переопределяю(WM_CREATE) и если просто на событие MFC диалога подписываюсь (OnCreate)
PM MAIL   Вверх
Earnest
Дата 29.1.2010, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Т.е. диалогу не приходит? Собственно, на WM_CREATE рано еще контролы создавать. Это нужно делать на WM_INITDOALOG (в MFC-варианте - на OnInitDialog).


--------------------
...
PM   Вверх
Brodyaga
Дата 25.2.2010, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Earnest, суть такая, что я хочу создать окно, определённого в системе класса и разместить его на диалоге наследованном от класса CDialog.
Хотел сделать это в OnInitDialog средствами MFC. Это у меня не получилось, тогда я решил попробовать на чистом WinApi. Для этого переопределил оконную процедуру(в методе OnInitDialog) у диалога. Подписался там на сообщения WM_CREATE и WM_INITDIALOG, но они в оконную процедуру не пришли. Тогда подписался на сообщение щелчка мыши и без MFC создал нужное мне окно так:
Код

InitRichInkDLL();
RECT    rc;
GetClientRect(hWnd, &rc);
HWND hWnd2 = CreateWindow(WC_RICHINK, NULL, WS_VISIBLE | WS_CHILD | WS_VSCROLL,
rc->left, rc->top, rc->right - rc->left, rc->bottom - rc->top, hWnd, NULL, hInst, NULL);

Всё получилось!

Вопрос1: как создать окно зарегистрированного в системе класа средствами MFC?
Вопрос2: в какой момент и ГДЕ мне переопределить оконную процедуру, чтобы сообщения WM_CREATE и WM_INITDIALOG успели прийти в неё?

Жду помощи!
PM MAIL   Вверх
Andrey44
Дата 26.2.2010, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

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



Цитата(Brodyaga @  25.2.2010,  21:13 Найти цитируемый пост)
Вопрос1: как создать окно зарегистрированного в системе класа средствами MFC?

Код

MyRichEdit richEdit;
richEdit.Create(.......);

Цитата(Brodyaga @  25.2.2010,  21:13 Найти цитируемый пост)
Вопрос2: в какой момент и ГДЕ мне переопределить оконную процедуру, чтобы сообщения WM_CREATE и WM_INITDIALOG успели прийти в неё?
Код

class MyRichEdit : public CrichEditCtrl
{
     BOOL MyRichEdit::PreCreateWindow(CREATESTRUCT& cs)
{
   // Create a window with border
   cs.style |= WS_BORDER;

   // Size the window to 1/3 screen size and center it
   cs.cy = 300;
   cs.cx = 300;
   cs.y = 10;
   cs.x = 20;

   return CrichEditCtrl::PreCreateWindow(cs);
}
};




--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Brodyaga
Дата 26.2.2010, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

MyRichEdit richEdit;
richEdit.Create(.......);


Это именно создасться окно класса MyRichEdit. А если для зареганова оконного класса в системе нет MFC-шного класса? как тогда быть?

Цитата

class MyRichEdit : public CrichEditCtrl
{
     BOOL MyRichEdit::PreCreateWindow(CREATESTRUCT& cs)
{
   // Create a window with border
   cs.style |= WS_BORDER;

   // Size the window to 1/3 screen size and center it
   cs.cy = 300;
   cs.cx = 300;
   cs.y = 10;
   cs.x = 20;

   return CrichEditCtrl::PreCreateWindow(cs);
}
};

Создал метод BOOL PreCreateWindow(CREATESTRUCT& cs) и поставил там брекпоинт. При отображении диалога на экране, программа не перешла по этому брекпоинту...


Сам диалог где хочу разместить окно зарегестрированного в системе класса показываю так:
Код

 pDialog= new CMyDialog(this);
        
 BOOL ret = pDialog->Create(IDD_DIALOG1);

 if(!ret)
   AfxMessageBox(L"Ошибка при создании диалога");

 pDialog->ShowWindow(SW_SHOW);


Кстати.. сейчас вычитал, что CDialog не наследует PreCreateWindow от CWnd..

Это сообщение отредактировал(а) Brodyaga - 26.2.2010, 11:23
PM MAIL   Вверх
Earnest
Дата 1.3.2010, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  26.2.2010,  10:54 Найти цитируемый пост)
Это именно создасться окно класса MyRichEdit. А если для зареганова оконного класса в системе нет MFC-шного класса? как тогда быть?

1. Передать имя класса в CWnd::Create (кажется, первый параметр)
2. Написать свой класс (наследник от наиболее подходящего MFC-класса) и переопределить для него либо PreCreateWindow, либо написать свой вариант Create (не виртуальный, только с нужными параметрами).
Все это по сути одно и то же, т.к. сводится к 1 пункту.

Цитата(Brodyaga @  26.2.2010,  10:54 Найти цитируемый пост)
Создал метод BOOL PreCreateWindow(CREATESTRUCT& cs) и поставил там брекпоинт. При отображении диалога на экране, программа не перешла по этому брекпоинту...

Ты все время нас путаешь: где и что ты создаешь. Есть диалоги и есть контролы. Это две большие разницы. Диалогу действительно не приходит PreCreateWindow, т.к. окно создается не через CreateWindow и не в MFC. Но WM_CREATE перехватить реально, хотя лучще всего все-таки для диалога делать все инициализации в OnInitDialog.
Далее, если ты добавляешь контрол на диалог в редакторе ресурсов, то PreCreate тоже не получишь.

Цитата(Brodyaga @  25.2.2010,  22:13 Найти цитируемый пост)

Вопрос1: как создать окно зарегистрированного в системе класа средствами MFC?

1) Можно положить контрол на шаблон диалога в редакторе ресурсов (Custom Control), обязательно правильно указав имя его Window-класса
2) Можно динамически, в OnInitDialog, через Create - написала выше как.

Цитата(Brodyaga @  25.2.2010,  22:13 Найти цитируемый пост)

Вопрос2: в какой момент и ГДЕ мне переопределить оконную процедуру, чтобы сообщения WM_CREATE и WM_INITDIALOG успели прийти в неё?

Оконную процедуру диалога? Нигде. В MFC ты не переопределяешь оконную процедуру, ты добавляешь обработчики в стандартную процедуру, которая одна на все окна (почти). Насчет WM_CREATE не совсем уверена, но по-моему все точно так как и для остальных окон - просто нужно написать обработчик в своем классе (и добавить в карту сообщений). OnInitDialog - виртуальная, просто переопределяешь ее в своем классе-диалоге.


--------------------
...
PM   Вверх
Brodyaga
Дата 2.3.2010, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Ты все время нас путаешь: где и что ты создаешь. Есть диалоги и есть контролы. Это две большие разницы. Диалогу действительно не приходит PreCreateWindow, т.к. окно создается не через CreateWindow и не в MFC. Но WM_CREATE перехватить реально, хотя лучще всего все-таки для диалога делать все инициализации в OnInitDialog.
Далее, если ты добавляешь контрол на диалог в редакторе ресурсов, то PreCreate тоже не получишь.

Переопределяю этот метод у диалога естественно, на котором хочу разместить окно зарегистрированного в системе класса. Но создаю этот диалог я в MFC, я же написал как, вот:
Цитата

Код

 pDialog= new CMyDialog(this);
        
 BOOL ret = pDialog->Create(IDD_DIALOG1);

 if(!ret)
   AfxMessageBox(L"Ошибка при создании диалога");

 pDialog->ShowWindow(SW_SHOW);


IDD_DIALOG1-это идентификатор диалога, на котором я хочу разместить окно зарегистрированного класса(WC_RICHINK).
Функцию PreCreateWindow я хотел переопределить, для того, чтобы в ней переопределить оконную процедуру диалога этого (IDD_DIALOG1) и успеть в переопределённой оконной процедуре обработать событие WM_CREATE или WM_INITDIALOG для создания с помощью WinApi окна на этом диалоге зарегестрированного в системе класса, так как не знаю, как это сделать с помощью MFC  в функции OnInitDialog().

Цитата

1) Можно положить контрол на шаблон диалога в редакторе ресурсов (Custom Control), обязательно правильно указав имя его Window-класса

Так пробовал. Не получилось. Окно зарегистрированного в системе класса не появилось на диалоге.

Цитата

2) Можно динамически, в OnInitDialog, через Create - написала выше как.

Вот так мне и надо было, чтобы через MFC, тогда и оконную процедуру не надо переопределять, так как всё с помощью MFC можно было бы сделать, но... попробовал так, программа вылетела в диалог с ошибкой в wincore.cpp файле.
Код

InitRichInkDLL();
CWnd* Wnd=new CWnd();
Wnd->Create(WC_RICHINK,NULL,WS_VISIBLE|WS_CHILD|WS_VSCROLL,rc,this,137);


Цитата

Оконную процедуру диалога? Нигде. В MFC ты не переопределяешь оконную процедуру, ты добавляешь обработчики в стандартную процедуру, которая одна на все окна (почти).

А я переопределил для диалога нормально, вот так:
Код

fnOldInkControl = (WNDPROC) SetWindowLong (this->GetSafeHwnd(), GWL_WNDPROC, (DWORD) MyProc);


Цитата

Насчет WM_CREATE не совсем уверена, но по-моему все точно так как и для остальных окон - просто нужно написать обработчик в своем классе (и добавить в карту сообщений).

Пробовал так, написал обработчик OnCreate(LPCREATESTRUCT lpCreateStruct) и добавил в карту... по брекпоинту при создании этого диалога программа не переходит(Напоминаю, может не совсем понятно... это обработчик события создания диалога на котором я хочу разместить окно зарегистрированного в системе класса - IDD_DIALOG1).

Цитата

OnInitDialog - виртуальная, просто переопределяешь ее в своем классе-диалоге.

Это да, с этим всё нормально. Теперь мне в этой функции надо создать окно зарегестрированного в системе класса с помощью MFC, что не получается через предложенный вами способ(CWnd::Create), что именно случается в этом случае я писал выше.

Почему может не работать предложенный вами вариант?
PM MAIL   Вверх
Earnest
Дата 2.3.2010, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  2.3.2010,  17:45 Найти цитируемый пост)
А я переопределил для диалога нормально, вот так:

Я не говорила "невозможно". Кошерно нельзя, да и не надо.

Цитата(Brodyaga @  2.3.2010,  17:45 Найти цитируемый пост)
Так пробовал. Не получилось. Окно зарегистрированного в системе класса не появилось на диалоге.

Значит, что-то сделано неправильно - способ рабочий, пробовала. Может, забыл вызвать инициализацию библиотеки (InitRichInkDLL())? Это надо делать пораньше, до создания диалога (можно в его конструкторе).

Цитата(Brodyaga @  2.3.2010,  17:45 Найти цитируемый пост)
Вот так мне и надо было, чтобы через MFC, тогда и оконную процедуру не надо переопределять, так как всё с помощью MFC можно было бы сделать, но... попробовал так, программа вылетела в диалог с ошибкой в wincore.cpp файле.

Цитата(Brodyaga @  2.3.2010,  17:45 Найти цитируемый пост)
Почему может не работать предложенный вами вариант? 

Я же не телепат, однако. Что за ошибка-то?

В PreCreateWindow делать этого просто нельзя - на то оно и PreCreate, а что касается ошибки, то с ней и надо разбираться, т.к. идеологически вариант правильный. 
Такое ощущение, что ты бессистемно тычешься, пробуя разные варианты и бросая их при первой же неудаче. Переходить к следующему варианту нужно только тогда, когда ты поймешь, почему предыдущий не может работать - или заставишь его заработать. Итак, правильных путей ровно 2: через редактор ресурсов и через Create (в OnInitDialog). А теперь давай попробуем понять, что же не так с Create?



--------------------
...
PM   Вверх
Brodyaga
Дата 2.3.2010, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Значит, что-то сделано неправильно - способ рабочий, пробовала. Может, забыл вызвать инициализацию библиотеки (InitRichInkDLL())? Это надо делать пораньше, до создания диалога (можно в его конструкторе).

В конструкторе и инициализирую, просто привёл в одном месте для ясности.

Цитата

В PreCreateWindow делать этого просто нельзя - на то оно и PreCreate

в PreCreateWindow я хотел переопределить оконную процедуру диалога(IDD_DIALOG1), чтобы в ней успеть поймать сообщение WM_CREATE или WM_INITDIALOG и там уже с помощью WinApi  создать окно зареганного класса на диалоге этом, так как с помощью MFC не знал как.

Цитата

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

Так и есть, я мечусь между двумя вариантами:
1. в OnInitDialog создать окно зареганного в системе класса с помощью MFC.
2. переопределить оконную процедуру диалога до прихода в неё сообщений WM_CREATE или WM_INITDIALOG и в обработчике этих сообщений создать окно зареганного в системе класса с помощью WinApi (так как с помощью WinApi я знаю как, есть пример и всё работает)

Сейчас тогда добиваем первый вариант. Ошибка, которая вылазит при вызове функции CWnd::Create:
Цитата

Debug Assertion Failed!
File:
f:\sp\vctools\vc7libsce\ship\atlmfc\src\mfc\wincore.cpp
Line: 2598

PM MAIL   Вверх
Earnest
Дата 3.3.2010, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



У меня в этой строке никакого ASSERT нет.
Строку приведи, куда ссылается ASSERT (а лучше функцию целиком). Кто тебе сказал, что у меня тот же компилятор и та же версия MFC?

Добавлено через 1 минуту и 4 секунды
Цитата(Brodyaga @  2.3.2010,  18:21 Найти цитируемый пост)
в PreCreateWindow я хотел переопределить оконную процедуру диалога(IDD_DIALOG1),

В PreCreate это делать рано, т.к. окно еще не создано. Даже если бы оно приходило диалогу.

Добавлено через 4 минуты
Вот еще увидела:
Цитата(Brodyaga @  2.3.2010,  17:45 Найти цитируемый пост)
CWnd* Wnd=new CWnd();
Wnd->Create(WC_RICHINK,NULL,WS_VISIBLE|WS_CHILD|WS_VSCROLL,rc,this,137);

Ты создаешь локальную переменную и после выхода из функции ее теряешь. И как ты собираешься управлять окно (и удалить потом этот объект)? Указатель на динамический контрол нужно где-то хранить, в диалоге, например.
Но причиной ASSERT это вряд ли является.



--------------------
...
PM   Вверх
Brodyaga
Дата 3.3.2010, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Ты создаешь локальную переменную и после выхода из функции ее теряешь. И как ты собираешься управлять окно (и удалить потом этот объект)? Указатель на динамический контрол нужно где-то хранить, в диалоге, например.
Но причиной ASSERT это вряд ли является.

Да это всё понятно, я для теста просто написал на коленке, мне сейчас главное, чтобы окно показалось на диалоге.

Код

BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
    // return TRUE if command invocation was attempted
{
    UINT nID = LOWORD(wParam);
    HWND hWndCtrl = (HWND)lParam;
    int nCode = HIWORD(wParam);

    // default routing for command messages (through closure table)

    if (hWndCtrl == NULL)
    {
        // zero IDs for normal commands are not allowed
        if (nID == 0)
            return FALSE;

        // make sure command has not become disabled before routing
        CTestCmdUI state;
        state.m_nID = nID;
        OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
        if (!state.m_bEnabled)
        {
            TRACE(traceAppMsg, 0, _T("Warning: not executing disabled command %d\n"), nID);
            return TRUE;
        }

        // menu or accelerator
        nCode = CN_COMMAND;
    }
    else
    {
        // control notification
        ASSERT(nID == 0 || ::IsWindow(hWndCtrl));             <-------------------------------Вот тут вылетает, Ln 2598

        if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
            return TRUE;        // locked out - ignore control notification

        // reflect notification to child window control
        if (ReflectLastMsg(hWndCtrl))
            return TRUE;    // eaten by child

        // zero IDs for normal commands are not allowed
        if (nID == 0)
            return FALSE;
    }

#ifdef _DEBUG
    if (nCode < 0 && nCode != (int)0x8000)
        TRACE(traceAppMsg, 0, _T("Implementation Warning: control notification = $%X.\n"),
            nCode);
#endif

    return OnCmdMsg(nID, nCode, NULL, NULL);
}


Мне кажется дело в ID который я передаю в функцию Create. Я туда передаю ID диалога на котором хочу отобразить окно зареганного в системе класса. это ведь верно?

Это сообщение отредактировал(а) Brodyaga - 3.3.2010, 10:39
PM MAIL   Вверх
Earnest
Дата 4.3.2010, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  3.3.2010,  11:31 Найти цитируемый пост)
Мне кажется дело в ID который я передаю в функцию Create. Я туда передаю ID диалога на котором хочу отобразить окно зареганного в системе класса. это ведь верно?

Нет, неверно. В функцию Create нужно передавать ID, который будет присвоен контролу, и по которому ты в любой момент сможешь его достать.
Но я не вижу, где ты его передаешь. Это волшебное число 137 что ли? Если так, то проблема вряд ли в этом.
Ты мог бы посмотреть отладчиком значения переменных ID и hWndCtrl какое именно условие не выполняется.

Кроме того, ранее ты говорил, что вылетаешь на строчек с функцией Create, так причем тут OnCommand? Действительно ли этот вызов находится во фрейме Create (т.е. где-то внутри Create -> посмотри стек). Если так, то похоже, что контрол при создании шлет извещение диалогу (проверь, что this в этот момент показывает на твой диалог), причем шлет его неправильно (не соблюдает соглашения о содержании WPARAM\LPARAM). Или может это твоя подкрутка?

В любом случае это не фатальная ошибка, если нажать Ignore, все должно продолжать работать, но ты этот видимо не пробовал.
Проверь, но в любом случае разобраться с Assert ом надо, ибо он указавает на некошерность поведения. 


--------------------
...
PM   Вверх
Brodyaga
Дата 4.3.2010, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Нет, неверно. В функцию Create нужно передавать ID, который будет присвоен контролу, и по которому ты в любой момент сможешь его достать.
Но я не вижу, где ты его передаешь. Это волшебное число 137 что ли? Если так, то проблема вряд ли в этом.

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

Цитата

Ты мог бы посмотреть отладчиком значения переменных ID и hWndCtrl какое именно условие не выполняется.

Значение ID почемуто 10003, hWndCtrl тоже не пустое. Следовательно второе условие не выполняется.

Цитата

Кроме того, ранее ты говорил, что вылетаешь на строчек с функцией Create, так причем тут OnCommand? Действительно ли этот вызов находится во фрейме Create (т.е. где-то внутри Create -> посмотри стек). Если так, то похоже, что контрол при создании шлет извещение диалогу (проверь, что this в этот момент показывает на твой диалог), причем шлет его неправильно (не соблюдает соглашения о содержании WPARAM\LPARAM). Или может это твоя подкрутка?

да, в этот момент hwnd равно hwnd моего диалога. никакой подкрутки нет...

Цитата

В любом случае это не фатальная ошибка, если нажать Ignore, все должно продолжать работать, но ты этот видимо не пробовал.
Проверь, но в любом случае разобраться с Assert ом надо, ибо он указавает на некошерность поведения. 

Я это пробовал, всеровно вылетает.
PM MAIL   Вверх
Andrey44
Дата 5.3.2010, 06:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

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



Цитата(Brodyaga @  4.3.2010,  21:26 Найти цитируемый пост)
137 - это id диалога на котором я хочу разместить созданное окно. а как узнать какой id должен быть у контрола? как узнать, что нужно вместо 137 передать?

Прочти хотя бы одну книгу по MFC или по WinAPI, тогда не будешь задавать таких вопросов.


--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
Earnest
Дата 5.3.2010, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  4.3.2010,  22:26 Найти цитируемый пост)
137 - это id диалога на котором я хочу разместить созданное окно. а как узнать какой id должен быть у контрола? 

Любой, ты его сам назначаешь. Странно, если передаешь ты 137, а получаешь 10003... возможно это уведомление от другого контрола? Есть у тебя на диалоге контрол с таким ID? Или это все же этот?
А что касается hWndCtrl - стало быть, не выполняется IsWindow(hWndCtrl), т.е. не знает система такого окна. Нужно выяснить, кто посылает эту хрень. Я стек просила посмотреть.

Цитата(Brodyaga @  4.3.2010,  22:26 Найти цитируемый пост)
Я это пробовал, всеровно вылетает. 

Но ведь в другом месте? Где?

Добавлено через 4 минуты и 14 секунд
Кстати, о птичках... В WinAPI варианте ты никакого ID не передавал! Так зачем это делать в MFC-выарианте? Все параметры должны быть такие же, с учетом разницы hWnd - pWnd! Кто его знает, что у тебя за контрол? Например, тултипы тоже без ID создаются. Передай-ка вместо 137 0. И книжки почитай, не помешает...


--------------------
...
PM   Вверх
Brodyaga
Дата 5.3.2010, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Кстати, о птичках... В WinAPI варианте ты никакого ID не передавал! Так зачем это делать в MFC-выарианте? Все параметры должны быть такие же, с учетом разницы hWnd - pWnd! Кто его знает, что у тебя за контрол? Например, тултипы тоже без ID создаются. Передай-ка вместо 137 0.

Передавал.. тамже вылетает, с id равным 10003...

Цитата

Любой, ты его сам назначаешь. Странно, если передаешь ты 137, а получаешь 10003... возможно это уведомление от другого контрола? Есть у тебя на диалоге контрол с таким ID? Или это все же этот?

Нету контрола с таким id. Скорее это при создании такой id назначается этому контролу. В варианте с переопределением оконной процедуры и созданием контрола на диалоге с помощью WinApi, тоже после создания в оконную процедуру поступают сообщения WM_COMMAND с 10003 id.

Цитата

А что касается hWndCtrl - стало быть, не выполняется IsWindow(hWndCtrl), т.е. не знает система такого окна. Нужно выяснить, кто посылает эту хрень. Я стек просила посмотреть.


Похоже после вызова этой функции идут сообщения WM_COMMAND в форму

Код

HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass,
  cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
  cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);


По стеку понять чтото не могу, просто вызов от одной функции к другой передаётся, как посмотреть откуда вызов то был:
Код

>    MyProg.exe!CWnd::OnCommand(unsigned int wParam = 10003, long int lParam = 405527168) Line: 2598, Byte Offsets: 0x104    C++
    MyProg.exe!CWnd::OnWndMsg(unsigned int message = 273, unsigned int wParam = 10003, long int lParam = 405527168, long int* pResult = 0x182bd738) Line: 2066, Byte Offsets: 0x6c    C++
    MyProg.exe!CWnd::WindowProc(unsigned int message = 273, unsigned int wParam = 10003, long int lParam = 405527168) Line: 2052, Byte Offsets: 0x48    C++
    MyProg.exe!AfxCallWndProc(CWnd* pWnd = 0x002c6550, HWND__* hWnd = 0x7c078200, unsigned int nMsg = 273, unsigned int wParam = 10003, long int lParam = 405527168) Line: 283, Byte Offsets: 0x24c    C++
    MyProg.exe!AfxWndProc(HWND__* hWnd = 0x7c078200, unsigned int nMsg = 273, unsigned int wParam = 10003, long int lParam = 405527168) Line: 451, Byte Offsets: 0xe8    C++
    0xf000fffc    

Но думаю вызов посылает контрол диалогу при создании. Потому что при создании самого диалога, он тоже сообщения со своим id посылается родителю(другому, главному диалогу), правда в этот раз id корректный, тот который указан в ресурсе и всё проходит без ошибок.

Цитата

Но ведь в другом месте? Где?

в этом же, просто при нажатии Ignore, программа проходит дальше, но потом снова присылается это сообщение с теми же параметрами и в этом же месте уже вылетает. (В варианте с переопределением оконной процедуры и созданием контрола на диалоге с помощью WinApi оно тоже несколько раз присылается, а после него ещё идут сообщения WM_COMMAND с id=10006 и id=10000)

Это сообщение отредактировал(а) Brodyaga - 5.3.2010, 13:17
PM MAIL   Вверх
Earnest
Дата 5.3.2010, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  5.3.2010,  14:16 Найти цитируемый пост)
По стеку понять чтото не могу, просто вызов от одной функции к другой передаётся, как посмотреть откуда вызов то был:

Просто смотри дальше вниз, где-то должен быть твой Create.... но иногда среда может врать, съезжает у нее чего-то... я так понимаю, библиотека с контролом не твоя и кода нет.

Цитата(Brodyaga @  5.3.2010,  14:16 Найти цитируемый пост)
, но потом снова присылается это сообщение с теми же параметрами и в этом же месте уже вылетает.

Тоже самое сообщение тоже можно проигнорировать. Нажми Ignore столько раз, сколько нужно - либо пройдешь, либо вылетишь не на ASSERT, а на что-то посерьезнее. Я это к тому, что нужно проверить, стоит ли пытаться обойти эту бяку, или твой контрол вообще нельзя через MFC создавать. Дело в том, что MFC подменяет оконную процедуру, а в контроле может наступить какой-нибудь конфликт в связи с этим.

Можно еще попробовать сделать так: создавать через ::CreateWindow, как ты уже делал, но тоже в OnInitDialog. Нет никакой необходимости ради этого подменять процедуру диалога. Тогда ты получишь hWnd, но можно легко сделать из него CWnd*, если оно надо. Вызывая апишную функцию для создания контрола, ты избегаешь установки хука на создание контрола, подмены процедуры и т.д. Если получится, можно при желании сделать для этого контрола MFC обертку (с собственной функцией Create).



--------------------
...
PM   Вверх
Brodyaga
Дата 5.3.2010, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Просто смотри дальше вниз, где-то должен быть твой Create.... но иногда среда может врать, съезжает у нее чего-то... я так понимаю, библиотека с контролом не твоя и кода нет.

Это всё что есть. Библиотека не моя, примеры её использования есть только на WinApi.

Цитата

Тоже самое сообщение тоже можно проигнорировать. Нажми Ignore столько раз, сколько нужно - либо пройдешь, либо вылетишь не на ASSERT, а на что-то посерьезнее.

Это первое, что я попробовал. Вылетает именно на ASSERT, так как на следующую после него строку я поставил брекпоинт, после первого игнора на него программа переходит, но после второго вылетает не переходя на поставленный брекпоинт.

Цитата

Можно еще попробовать сделать так: создавать через ::CreateWindow, как ты уже делал, но тоже в OnInitDialog. Нет никакой необходимости ради этого подменять процедуру диалога. Тогда ты получишь hWnd, но можно легко сделать из него CWnd*, если оно надо. Вызывая апишную функцию для создания контрола, ты избегаешь установки хука на создание контрола, подмены процедуры и т.д.

А вот тут самое интересное. Я потому и сталподменять процедуру диалога, так как если это делать в OnInitDialog, то вылетает в том же месте(на ASSERT в wincore.cpp, Ln 2598) с теми же симптомами. А при переопределении оконной процедуры диалога всё работает. Подозреваю, что это изза того, что я не передаю управление старой оконной процедуре с помощью CallWindowProc после своих действий, а при ненужных мне сообщениях передаю управление DefWindowProc.

Кстати при WM_COMMAND туда же сообщение уходит:
Код

...
    case WM_COMMAND: wNotifyCode = HIWORD(wParam);
                                       wID=LOWORD(wParam);


    default: return DefWindowProc(hWnd, msg, wParam, lParam);
...

И всё нормально.

Сейчас попробовал отдать управление старой оконной процедуре диалога. Тоесть после создание окна контрола в WM_INITDIALOG, как и раньше присылаются сообщения WM_COMMAND с id=10003, но в мою переопределённую процедуру, но оттуда я отдаю управление старой процедуре:
Код

...
    case WM_COMMAND: wNotifyCode = HIWORD(wParam);
                                       wID=LOWORD(wParam);
                                       return CallWindowProc(fnOldMyDialogProc,hWnd, msg, wParam, lParam);

    default: return DefWindowProc(hWnd, msg, wParam, lParam);
...

Вылетело с теми же симптомами, что и раньше!(тоесть всё там же на Ln2598). Что скажете?

Это сообщение отредактировал(а) Brodyaga - 5.3.2010, 16:12
PM MAIL   Вверх
Earnest
Дата 9.3.2010, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Brodyaga @  5.3.2010,  17:10 Найти цитируемый пост)
Это первое, что я попробовал. Вылетает именно на ASSERT, так как на следующую после него строку я поставил брекпоинт, после первого игнора на него программа переходит, но после второго вылетает не переходя на поставленный брекпоинт.

Куда вылетает-то? Ты используешь "вылетает" для самых разных ситуаций, попробуй пойми. Есть ASSERT'ы, есть исключения. Дело в том, что обойти первый ассерт довольно легко. Иногда сам факт останова на ASSERT (т.е. появление MessageBox) вызывает дальнейшие проблемы. Ибо нет после того ASSERT'а ничего фатального, на первый взгляд... Но нужно понять точно. Фактически, получается, что контрол посылает WM_COMMAND с LPARAM, которая не является окном... Странно, конечно.
Попробуй обойти так: В диалоге переопредели OnCommand и отфильтруй это сообщение (т.е. если флаг стоит и сообщение от этого контрола сразу выходим). Проще всего сделать это с помощью флага, который будет ставится перед созданием контрола, а потом сниматься. Это чтобы по-быстрому проверить. Если поможет, то можно будет думать о том, чтобы менее криво сделать. 


--------------------
...
PM   Вверх
Brodyaga
Дата 9.3.2010, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Куда вылетает-то? Ты используешь "вылетает" для самых разных ситуаций, попробуй пойми.

Никуда. Просто программа прекращает своё выполнение.

Сделал так:
Код

BOOL CMyDialog::OnCommand(WPARAM wParam,LPARAM lParam)
{
    int wNotifyCode = HIWORD(wParam);
    int wID=LOWORD(wParam);

    HWND hWndCtrl = (HWND)lParam;
    HWND hWndControl=Wnd->GetSafeHwnd();

    if(flag && (wID==10003 || wID==10008))
        return ::DefWindowProc(this->GetSafeHwnd(),WM_COMMAND,wParam,lParam);

    return CDialog::OnCommand(wParam,lParam);
}


Wnd - это объект типа CWnd*, обёртка для моего контрола. Создаю так:
Код

Wnd->Create(WC_RICHINK,NULL,WS_VISIBLE|WS_CHILD|WS_VSCROLL,rc,this,0);


ID равный 10008 включил, так как с ним потом тоже пошли сообщения, при обработке которых CDialog::OnCommand(wParam,lParam), вылетало всё на том же ASSERT'е. Правда после нажатия Ignor в этот раз прога продолжила своё выполнение без проблем.. ну да ладно.. всеровно решил управление ::DefWindowProc передать.
Вообщем так заработало, но что интересно hWndCtrl(ID элемента управления посылающего сообщение) и hWndControl(ID контрола) никогда не равны между собой. hWndCtrl всегда меняется.. тоесть сообщения всегда приходят от разных элементов управления.. Я думал что их контрол должен слать моему диалогу... разве не так?
PM MAIL   Вверх
Earnest
Дата 10.3.2010, 10:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Строго говоря, да. Но это всего лишь соглашение - что при посылке WM_COMMAND в LPARAM должен быть HWND посылающего контрола. А соглашение можно и нарушить. Это ведь сам контрол делает, т.е. его автор. И чего он там написал - хз. По твоим словам получается, что LPARAM содержит совсем не HWND, а какую-то другую фигню. Осталось непонятным, откуда берутся ид-ры 10003 и 10008, которые не ты назначаешь. Посмотри Спаем на контрол после создания диалога - возможно он содержит вложенные элементы или сам состоит из нескольких частей... Еще интересно, чему равен NotifyCode, число из любопытства.
Кстати, я думаю, что вызов DefWindowProc можно простить, вернуть просто TRUE (или FALSE) - вряд ли там есть какая-то разумная обработка, раз соглашение о параметрах нарушено.


--------------------
...
PM   Вверх
Brodyaga
Дата 10.3.2010, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Еще интересно, чему равен NotifyCode, число из любопытства.

Всегда 0. Хоть с каким ID(10003, 10008)

Также там ещё приходят сообщения с 10006 и 10000, но с ними не вылетает.

Цитата

Посмотри Спаем на контрол после создания диалога - возможно он содержит вложенные элементы или сам состоит из нескольких частей...

Не приходилось таким пользовался, это программа шпион специальная? дайте название конкретной программки тогда
PM MAIL   Вверх
Earnest
Дата 11.3.2010, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Да так и называется - Spy. Есть в поставке Visual Studio. Очень удобно для исследования окон, как своих, так и чужих.


--------------------
...
PM   Вверх
Brodyaga
Дата 11.3.2010, 14:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Боюсь это не поможет... У меня программа запускается на эмуляторе...
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




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


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

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