Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание окна зарегистрированного класса 
:(
    Опции темы
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   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




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


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

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