Использование полноэкранного режима D3D8

В предыдущем уроке мы научились создавать и отображать простейшие примитивы (треугольники) в двухмерном пространстве. Они были нам необходимы для наглядного представления настоящего урока. Теперь мы научимся использовать D3D8 в полноэкранном режиме. Данная тема не освещена в известных мне источниках, так что надеюсь вам данный урок тоже поможет и будет полезен.

Для использования D3D8 в полноэкранном режиме нам необходимо знать, как необходимо производить инициализацию, кроме того, нам будет необходимо научиться производить обнаружение доступных видео режимов.

Создадим для этого примера и последующей работы диалоговое окно следующего вида :

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

Для работы этого диалога нам необходима вызвать функцию его отображения в функции AppInit () :


if(!DialogBox (hThisInst, MAKEINTRESOURCE(IDD_STARTUP), 0 , 
			(DLGPROC) StartUp_dlg_proc)) return false;

создать несколько необходимых переменных, которые мы будем использовать для хранения информации о том, используем ли мы полный экран, если НЕТ, то нам понадобятся две переменные для хранения выбраного размера окна, а если ДА, то струтура для хранения данных об выбранном режиме экрана :


bool isFullScreen=false;		// is our app Full screen or not
int ScreenX=0, ScreenY=0;	// use this if 'not'
D3DDISPLAYMODE d3ddm;		// use this if 'yes'

а также создать для этого диалога функцию обработки сообщений :


//-----------------------------------------------------------------------------
// Name: StartUp_dlg_proc ()
// Desc: 
//-----------------------------------------------------------------------------
BOOL CALLBACK StartUp_dlg_proc (HWND hWndD, UINT message, WPARAM wParam, LPARAM lParam)
{
	HWND hSMlist = GetDlgItem (hWndD, IDC_SCREENMODESW);
	HWND hFSMlist = GetDlgItem (hWndD, IDC_SCREENMODESFS);

	switch (message)
	{
	case WM_INITDIALOG:
		{
		SendDlgItemMessage (hWndD, IDC_WINDOWED, BM_SETCHECK, 1, 0);

		ComboBox_ResetContent (hSMlist);
		ComboBox_ResetContent (hFSMlist);

		ComboBox_AddString (hSMlist, "300 x 200");
		ComboBox_AddString (hSMlist, "320 x 240");
		ComboBox_AddString (hSMlist, "400 x 300");
		ComboBox_AddString (hSMlist, "512 x 384");
		ComboBox_AddString (hSMlist, "640 x 400");
		ComboBox_AddString (hSMlist, "640 x 480");
		ComboBox_AddString (hSMlist, "800 x 600");
		ComboBox_AddString (hSMlist, "1024 x 768");
		ComboBox_AddString (hSMlist, "1280 x 1024");
		ComboBox_SetCurSel (hSMlist, 5);


		LPDIRECT3D8 p_d3dt = Direct3DCreate8 (D3D_SDK_VERSION);
		D3DDISPLAYMODE d3ddm2;
		int allVideoModes = p_d3dt->GetAdapterModeCount (D3DADAPTER_DEFAULT);
		for (int i=0; i<allVideoModes; i++)
		{
			p_d3t->EnumAdapterModes (D3DADAPTER_DEFAULT, i, &d3ddm2);
			char str[30];
			int bpp=0;
			if(d3ddm2.Format == D3DFMT_X1R5G5B5) bpp=16;
			if(d3ddm2.Format == D3DFMT_R5G6B5) bpp=16;
			if(d3ddm2.Format == D3DFMT_A1R5G5B5) bpp=16;
			if(d3ddm2.Format == D3DFMT_A4R4G4B4) bpp=16;
			if(d3ddm2.Format == D3DFMT_X4R4G4B4) bpp=16;
			if(d3ddm2.Format == D3DFMT_R8G8B8) bpp=24;
			if(d3ddm2.Format == D3DFMT_X8R8G8B8) bpp=32;
			if(d3ddm2.Format == D3DFMT_A8R8G8B8) bpp=32;
			sprintf(str,
 				"%dx%dx%d _ %dhz",
				d3ddm2.Width, d3ddm2.Height, 
				bpp, d3ddm2.RefreshRate);
			ComboBox_AddString (hFSMlist, str);
		};
		_RELEASE_ (p_d3dt);
		ComboBox_SetCurSel (hFSMlist, 0);

		EnableWindow (hSMlist, true);
		EnableWindow (hFSMlist, false);

		}
		break;
	case WM_COMMAND:  
		switch (LOWORD(wParam))
		{
		case IDC_WINDOWED:
			EnableWindow (hSMlist, true);
			EnableWindow (hFSMlist, false);
			break;
	
		case IDC_FULLSCREEN:
			EnableWindow (hSMlist, false);
			EnableWindow (hFSMlist, true);
			break;

		case IDOK:
			isFullScreen=false;
			if(SendDlgItemMessage(hWndD,
					IDC_FULLSCREEN, 
					BM_GETCHECK, 0, 0)) 
							isFullScreen=true;
			
			if(isFullScreen)
			{
				LPDIRECT3D8 p_d3dt = Direct3DCreate8 (D3D_SDK_VERSION);
				int dwItem = ComboBox_GetCurSel (hFSMlist);
				p_d3dt->EnumAdapterModes (D3DADAPTER_DEFAULT, 
								dwItem, &d3ddm);
				_RELEASE_ (p_d3dt);
			}
			else
			{
				int dwItem = ComboBox_GetCurSel (hSMlist);
				if(dwItem==0) ScreenX=300, ScreenY=200;
				if(dwItem==1) ScreenX=320, ScreenY=240;
				if(dwItem==2) ScreenX=400, ScreenY=300;
				if(dwItem==3) ScreenX=512, ScreenY=384;
				if(dwItem==4) ScreenX=640, ScreenY=400;
				if(dwItem==5) ScreenX=640, ScreenY=480;
				if(dwItem==6) ScreenX=800, ScreenY=600;
				if(dwItem==7) ScreenX=1024, ScreenY=768;
				if(dwItem==8) ScreenX=1280, ScreenY=1024;
			};

			EndDialog (hWndD, true);
			break;

		case IDCANCEL:
			EndDialog (hWndD, false);
			break;
		};
	default:
		break;
	};
	return false;
};

Данная функция обработки весьма простая и я надеюсь здесь все понятно, единственные важные строки, в которых мы производим обнаружение доступных нам видеорежимов :


LPDIRECT3D8 p_d3dt = Direct3DCreate8 (D3D_SDK_VERSION);
D3DDISPLAYMODE d3ddm2;
int allVideoModes = p_d3dt->GetAdapterModeCount (D3DADAPTER_DEFAULT);
for (int i=0; i<allVideoModes; i++)
{
	p_d3dt->EnumAdapterModes (D3DADAPTER_DEFAULT, i, &d3ddm2);
	char str[30];
	int bpp=0;
	if(d3ddm2.Format == D3DFMT_X1R5G5B5) bpp=16;
	if(d3ddm2.Format == D3DFMT_R5G6B5) bpp=16;
	if(d3ddm2.Format == D3DFMT_A1R5G5B5) bpp=16;
	if(d3ddm2.Format == D3DFMT_A4R4G4B4) bpp=16;
	if(d3ddm2.Format == D3DFMT_X4R4G4B4) bpp=16;
	if(d3ddm2.Format == D3DFMT_R8G8B8) bpp=24;
	if(d3ddm2.Format == D3DFMT_X8R8G8B8) bpp=32;
	if(d3ddm2.Format == D3DFMT_A8R8G8B8) bpp=32;
	sprintf(str, "%dx%dx%d _ %dhz", d3ddm2.Width, d3ddm2.Height, bpp, d3ddm2.RefreshRate);
	ComboBox_AddString (hFSMlist, str);
};
_RELEASE_ (p_d3dt);

Здесь -

-- мы сначала создаем временный интерфейс D3D8, необходимый нам для получения информации о доступных видеорежимах ( LPDIRECT3D8 p_d3dt = Direct3DCreate8 (D3D_SDK_VERSION); ),
-- затем получаем общее их количество ( int allVideoModes = p_d3dt->GetAdapterModeCount (D3DADAPTER_DEFAULT); ),
-- и последнее - для каждого видеорежима мы получаем данные которые его описывают (как то ширина, высота, глубина цвета - точнее формат поверхности, и частоту обновления) ( p_d3dt->EnumAdapterModes (D3DADAPTER_DEFAULT, i, &d3ddm2); )

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

 

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


	if(isFullScreen)
	{
		hWnd = CreateWindowEx (
			WS_EX_TOPMOST,
			APPNAME,
			APPTITLE,
			WS_POPUP,
			0, 0, 
			d3ddm.Width,
			d3ddm.Height,
			NULL,
			NULL,
			hThisInst,
			NULL);
	}
	else
	{
		int sx = GetSystemMetrics (SM_CXSCREEN);
		int sy = GetSystemMetrics (SM_CYSCREEN);

		hWnd = CreateWindowEx (
			WS_EX_TOPMOST,
			APPNAME,
			APPTITLE,
			WS_OVERLAPPED | WS_SYSMENU,
			sx/2-ScreenX/2, sy/2-ScreenY/2,
			ScreenX,
			ScreenY,
			NULL,
			NULL,
			hThisInst,
			NULL);
	};

And also with different parameters we should do initialization D3D8 :


	p_d3d = Direct3DCreate8 (D3D_SDK_VERSION);

	D3DPRESENT_PARAMETERS d3dpp; 
	ZeroMemory (&d3dpp, sizeof(d3dpp));

	if(isFullScreen)
	{
		d3dpp.BackBufferWidth = d3ddm.Width;
		d3dpp.BackBufferHeight = d3ddm.Height;
		d3dpp.BackBufferCount = 3;
		d3dpp.FullScreen_RefreshRateInHz = d3ddm.RefreshRate;
	}
	else
		p_d3d->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &d3ddm);

	d3dpp.Windowed = !isFullScreen;
	d3dpp.BackBufferFormat = d3ddm.Format;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

Здесь нам интересны строчки инициализации полноэкранного режима.

-- сначала устанавливаем ширину и высоту экрана,
-- количество вторичных буферов,
-- частоту обновления экрана,

-- потом устанавливаем флаг того, что мы не будем использовать оконное приложение ( d3dpp.Windowed = false;   //   ! isFullScreen )
-- и задаем формат, нам необходимый,
-- и метод обновления экрана.

 

Все остальное остается без изменений.

На этом данный урок заканчивается...



Опубликовал admin
28 Окт, Четверг 2004г.



Программирование для чайников.