Как определить имя класса для создания дочернего окна?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Ranmych
Сообщения: 6
Зарегистрирован: 30 апр 2009, 15:50

Есть некий диалог, к нему привязан класс. Если создаю модальное окно, то оно все работает. Но хочется чтобы этот диалог был помещен в клиентскую область как дочернее окно.

Первый параметр в CreateWindow это зарегистрированное имя класса.
С предопределенными классами а-ля "button" все понятно, с динамической регистрацией своего тоже.

Но как определить имя класса, диалог для которого нарисован в Visual C++ и там же к нему этот класс пристегнут?

И как получить пойнтер на WNDPROC этого класса, которую тоже надо указать в CreateWindow? Ведь Visual С++ делает ее приватным параметром и у родительского класса окна нет туда доступа.

Заранее огромное спасибо.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Воплотить в жизнь то, что ты задумал не так просто. В COM есть понятия композитного контрола (это как раз и есть диалог, вмонтированный в другой диалог), так вот ATL содержит кучу дополнительного кода для того, чтобы правильно обрабатывать клавиши, двигать фокусы и резайзить этот внутренний диаложик. Если бы были простые способы это реализовать, скорее всего они были бы использованы в ATL.

Вижу 3 варианта:

1. Сделать FormView (это подходит только в том случае, если удовлетворит условиям задачи).

2. Если действительно нужен диалог-в-диалоге, то проще создать свой ActiveX composite control и встроить его.

3. Третий вариант только если два первых не подошли - делать всё ручками на уровне Win32 API.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ranmych
Сообщения: 6
Зарегистрирован: 30 апр 2009, 15:50

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

Хотя, возможно, я пошел по неправильному пути и есть другие способы размещения в главном окне жестко фиксированного окна? Кроме рисования диалога?
Слышал что такое удобно делать с помощью ActiveX, но сначала хочу нормально изучить базовую работу с окнами, а потом уже браться за надстройки.
Аватара пользователя
WinMain
Сообщения: 929
Зарегистрирован: 14 янв 2005, 10:30
Откуда: Москва
Контактная информация:

Это делается с помощью функции CreateDialog, которая позволяет создавать окно диалога в немодальном режиме. Этому диалогу можно указать стиль WS_CHILD вместо WS_POPUP, тогда диалог становится как бы дочерним элементом для родительского окна.
Ranmych
Сообщения: 6
Зарегистрирован: 30 апр 2009, 15:50

Да. Я же написал.
"Первый параметр в CreateWindow это зарегистрированное имя класса.
С предопределенными классами а-ля "button" все понятно, с динамической регистрацией своего тоже. "
Это у меня получается и создать и получать сообщения в родительском классе.

Вопрос: Как этого же добится для уже созданного в Visual C++ диалога?

Вот такой код работает на ура, создает окно.
static WNDCLASS G;

G.hInstance = GetModuleHandle(NULL);
G.hbrBackground = (HBRUSH) (COLOR_BTNFACE);
G.lpfnWndProc = (WNDPROC) CChildWindowProc;
G.lpszClassName = "grafik";

ATOM A=RegisterClass(&G);

HWND hWndG=CreateWindow("grafik","grafik",WS_CHILD | WS_VISIBLE | WS_DLGFRAME, 0, 0, 1000, 400, this->m_hWnd, HMENU(10001), GetModuleHandle(NULL), NULL);
А вот этот код выдает ошибку при компиляции
// Объявляем класс окна для графика
class CGrafikView : public CDialog
{
....
static LRESULT CWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
....
}

// Статическая функция для вызова оконной функции конкретного объекта
static LRESULT CGrafikView::CWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){

return : :D efWindowProc(hWnd, msg, wParam, lParam);

}


// Этот код в функции Create родительского окна
static WNDCLASS G;

G.hInstance = GetModuleHandle(NULL);
G.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
G.lpfnWndProc = (WNDPROC) CGrafikView::CWindowProc;
G.lpszClassName = "grafik";

ATOM A=RegisterClass(&G);

HWND hWndD=CreateWindow("grafik","grafik",WS_CHILD | WS_VISIBLE | WS_DLGFRAME, 0, 0, 1000, 400, this->m_hWnd, HMENU(10001), GetModuleHandle(NULL), NULL);
Ошибка звучит так:
d:\Work\C Projects\Port thread\Port thread\GrafikView.cpp(33): error C2724: 'CGrafikView::CWindowProc' : 'static' should not be used on member functions defined at file scope

Не понимаю откуда она появляется, что означает и как исправить?

Если я правильно понимаю, то этот класс диалога регистрируется автоматически при запуске программы и у него должно быть свое имя.
Если я пытаюсь регистрировать этот класс в конструкторе, вот так:
ClassName = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW),
(HBRUSH) ::GetStockObject(GRAY_BRUSH),
::LoadIcon(NULL, IDI_APPLICATION));
То при исполнении выдается ошибка и класс не регистрируется.

То есть весь предыдущий код (который выдает ошибку при компиляции) и не должен работать корректно, а должен иметь вид:
HWND hWndD=CreateWindow(<сюда подставляем имя класса диалога>,"grafik",WS_CHILD | WS_VISIBLE | WS_DLGFRAME, 0, 0, 1000, 400, this->m_hWnd, HMENU(10001), GetModuleHandle(NULL), NULL);
Вот собственно и вопрос. Откуда взять имя этого диалога?
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Нет никакого смысла объявлять свою WindowProc для своего Dialog класса. Если ты наследуешься от CDialog, то там уже есть такая функция. Если её хочешь переопределить, то использую макросы а-ля MESSAGE_MAP, который внутри, собственно говоря и создают свою MessageProc.

По поводу ошибки компиляции. Ключевое слово static должно использоваться при объявлении метода, но не может быть использовано при определении метода. Убери его оттуда - функция всё равно останется статической. Это особенности синтаксиса С++.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ranmych
Сообщения: 6
Зарегистрирован: 30 апр 2009, 15:50

Я думал, что ее надо вписывать в структуру WNDCLASS для регистрации из класса родительского окна, и, поскольку, родная WindowProc является приватной, то определил публичную функцию для доступа к ней из класса родительского окна.
Но теперь понимаю, что этот класс диалога уже обязан быть где-то зарегистрирован иначе просто не выведется даже как модальный.
И все, что требуется, это узнать имя класса для вызова CreateDialog. При этом и все другие функции работы с окнами хотят это зарегистрированное имя или ATOM. Как же его узнать?
Вот и вызов GetClassInfo,
BOOL GetClassInfoEx(
HINSTANCE hinst,
LPCTSTR lpszClass,
LPWNDCLASSEX lpwcx
);
который заполняет WNDCLASS, тоже хочет пойнтер на это имя или атом (lpszClass).


О, да. Огромное спасибо за замечание про static, виновата моя невнимательность при прочтении Страуструпа и привычка к простому Си :(
В будущем на эти грабли уже не наступлю.
Ответить