Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 июня!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Программисты долго мучаются с кодом прогаммы, изучают С++, WinAPI функции, MSDN. Потом пишут банальную систему защиты или навешивают банальный протектор, а крэкеры и реверсеры справляются с такой защитой за 5 минут. В итоге, продажи программы почти нулевые. Чтобы такого не допустить, тут самому надо немного поднабрать опыта отладки, реверсинга, тот же отладчик Ollydbg изучить или дизассемблер IDA Pro. Но где искать по крохам эти знания? Нет, конечно можно годами "методом тыка" разбираться, но куда быстрее видеокурс специальный посмотреть. Вот тут он есть: ссылка. Автор курса с большим опытом и объясняет понятно, я из этого курса много узнал про то как работает компьютер, процессор, про инструменты специальные и как с ними работать. Мои коллеги программисты на работе ничего такого и не знают, теперь я им нос утру.

MCF и OpenGL.

"Подать сюда MFС!!! - кричил он, топая всеми 4-мя лапами."

Сижу тут как-то, программку сочиняю, тут смотрю, царь зверей пожаловал. Вопрос задать пришел. Спрашивает как же OpenGL в MFC то вставить? Сначала думал отмажусь, потом смотрю, настойчивый такой царь попался. Письма шлет, желает знать как же все-таки её туда вставить-то. Вот и решил я примерчик на MFC состроить дабы цари меньше утруждали себя, а больше на солнышке бы нежились, чтоб у царей спокойно и хорошо все было, тогда и нам, простым зверушкам жить хорошо будет. И так поехали.

Для начала сделаем приложение MFC как диалог. Я назвал его BitScroll. Как это делать? Смотрите шаги по MFC.

Теперь, при помощи визарда добавим функцию

BOOL CBitScrollDlg::PreCreateWindow(CREATESTRUCT& cs)
 
 {
 
 	cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
 
 	return CDialog::PreCreateWindow(cs);
 
 }
 
 

Помните, мы устанавливали слиль окна в функции CreateWindow ? Так вот это действие по смыслу тоже самое. Напомню как это выглядело в Win32API:

hWnd = CreateWindow("Skeleton", "Skeleton", WS_OVERLAPPEDWINDOW |
 
 	 WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 50, 50,700, 400, NULL,
 
 	 NULL, hInst ,NULL);
 
 

Теперь обратимся к функции OnInitDialog(). В ней сначала вызывается функция базового класса, т.е. CDialog, а потом устанавливаются иконки для диалога. Давайте вставим наш код между иконками и CDialog::OnInitDialog().

SetWindowPos(&wndTop, 0, 0, WIDTH, HEIGHT, SWP_NOMOVE);
 
 pDC = GetDC();
 
 CenterWindow();
 
 Init();
 
 SetTimer(1,SPEED, NULL);
 
 

Теперь посмотрим, что мы сделали. Сначала сделаем окно нужного нам размера (макросы WIDTH и HEIGHT объявлены так #define WIDTH 640 и #define HEIGHT 480 в заголовочном файле).

Затем получим контекст для рисования. Установимся в центр вселеной и... вот, тут самое интересное, тут мы вызываем нашу собственную функцию, которая будет инициализировать OpenGL (напоминаю, что тоже самое делала ф-ция Initial в программе на Win32API).

А потом включаем таймер, чтобы обеспечить анимацию. Обратимся теперь к Init(). Выглядит она итак:

void CBitScrollDlg::Init()
 
 {
 
 	CRect rect;
 
 	HGLRC hrc;
 
 	if (!bSetupPixelFormat())
 
 		return;
 
 	hrc = wglCreateContext(pDC->GetSafeHdc());
 
 	ASSERT(hrc != NULL);
 
 	wglMakeCurrent(pDC->GetSafeHdc(), hrc);
 
 
 
 	GetClientRect(&rect);
 
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 
 	glClearDepth(1.0);
 
 	glDepthFunc(GL_LESS);
 
 	glEnable(GL_DEPTH_TEST);
 
 	glShadeModel(GL_SMOOTH);
 
 	glMatrixMode(GL_PROJECTION);
 
 	glLoadIdentity();
 
 	gluPerspective(45.0f, (GLfloat)rect.right /
 
 		(GLfloat)rect.bottom, 0.1f, 100.0f);
 
 	glMatrixMode(GL_MODELVIEW);
 
 
 
 }
 
 

Что мы тут делаем? Прежде всего вызываем ф-ию SetupPixelFormat(), это опять наша функция и мы посмотрим ее чуть позже.

Далее, как и раньше, получаем контекст рендеринга (маленькая деталь, ранее pDC(а точнее эта переменная называлась hDC) была объявлена как static HDC hDC, сейчас контекст рисования является пременной типа CDC, а ф-ция wglCreateContext и другие ф-ции OpenGL требуют в качестве аргумента переменную типа HDC. Поэтому мы получаем этот hardware context с помощью pDC->GetSafeHdc()).

Затем делаем этот контекст текущим и настраиваем область отображения, так как это делалось в Initial() (Win32API)

Функция bSetupPixelFormat() содержит следующее:

BOOL CBitScrollDlg::bSetupPixelFormat()
 
 {
 
 	static PIXELFORMATDESCRIPTOR pfd =
 
 	{
 
 		sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
 
 		1, // version number
 
 		PFD_DRAW_TO_WINDOW | // support window
 
 		PFD_SUPPORT_OPENGL | // support OpenGL
 
 		PFD_DOUBLEBUFFER, // double buffered
 
 		PFD_TYPE_RGBA, // RGBA type
 
 		24, // 24-bit color depth
 
 		0, 0, 0, 0, 0, 0, // color bits ignored
 
 		0, // no alpha buffer
 
 		0, // shift bit ignored
 
 		0, // no accumulation buffer
 
 		0, 0, 0, 0, // accum bits ignored
 
 		32, // 32-bit z-buffer
 
 		0, // no stencil buffer
 
 		0, // no auxiliary buffer
 
 		PFD_MAIN_PLANE, // main layer
 
 		0, // reserved
 
 		0, 0, 0 // layer masks ignored
 
 	};
 
 
 
 	int pixelformat;
 
 
 
 	if ((pixelformat = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd)) == 0)
 
 	{
 
 		MessageBox("ChoosePixelFormat failed");
 
 		return FALSE;
 
 	}
 
 
 
 	if (SetPixelFormat(pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE)
 
 	{
 
 		MessageBox("SetPixelFormat failed");
 
 		return FALSE;
 
 	}
 
 	return TRUE;
 
 }
 
 

Как не трудно заметить, она почти полностью взята из Win32API приложения за исключением того, что hDC заменена на pDC->GetSafeHdc()

Теперь добавим в нашу программку обработчик от таймера (мы его недавно сделали в ф-ции Init())

void CBitScrollDlg::OnTimer(UINT nIDEvent)
 
 {
 
 	DrawScene();
 
 	CDialog::OnTimer(nIDEvent);
 
 }
 
 

Все тривиально. По смыслу ясно, что каждый раз, когда срабатывает обработчик таймера (а делает он это часто) рисуется сцена. Таким образом получается анимация. Посмотрим на эту ф-цию:

void CBitScrollDlg::DrawScene()
 
 {
 
 	static GLfloat angle = 0;
 
 	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
 	glLoadIdentity();
 
 	glTranslatef(0.0f, 0.0f, -2.0f);
 
 	glRotatef(angle, 1.0f, 0.5f, 0.3f);
 
 	glBegin(GL_QUADS);
 
 	glColor3f(1.0f, 0.0f, 1.0f);
 
 	glVertex3f(-0.5f, 0.5f, 0.0f);
 
 	glColor3f(1.0f, 1.0f, 1.0f);
 
 	glVertex3f(0.5f, 0.5f, 0.0f);
 
 	glColor3f(0.0f, 1.0f, 1.0f);
 
 	glVertex3f(0.5f, -0.5f, 0.0f);
 
 	glColor3f(0.0f, 0.0f, 1.0f);
 
 	glVertex3f(-0.5f, -0.5f, 0.0f);
 
 	glEnd();
 
 	glFinish();
 
 	SwapBuffers(wglGetCurrentDC());
 
 	angle += 0.5f;
 
 }
 
 

По моему проще уже некуда. Я надеюсь, что все ясно.

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

Эти вещи надо сделать в 2-х обработчиках OnClose и OnDestroy. Посмотрим на них:

void CBitScrollDlg::OnClose()
 
 {
 
 	// TODO: Add your message handler code here and/or call default
 
 	HGLRC hrc;
 
 	KillTimer(1);
 
 	hrc = ::wglGetCurrentContext();
 
 	::wglMakeCurrent(NULL, NULL);
 
 	if (hrc)
 
 		::wglDeleteContext(hrc);
 
 	CDialog::OnClose();
 
 }
 
 

и

void CBitScrollDlg::OnDestroy()
 
 {
 
 	CDialog::OnDestroy();
 
 	// TODO: Add your message handler code here
 
 	HGLRC hrc;
 
 	KillTimer(1);
 
 	hrc = ::wglGetCurrentContext();
 
 	::wglMakeCurrent(NULL, NULL);
 
 	if (hrc)
 
 		::wglDeleteContext(hrc);
 
 }
 
 

Она приактически одинаковые. Работают так же как и case WM_CLOSE в Win32API. Т.е. убиваем таймер, получаем контекст рендеринга, если он есть - удаляем его.

Ну вот и все. Еще добавлю, что в проекте есть ф-ция OnSize для обработки изменений размеров окна. В данном случае она не нужна, но если вставлять OpenGL в SDI или MDI, то она вам понадобится.





<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU Проект ReactOS