画面モード


アダプタのモードを列挙

図を描画するようになると、アダプタの能力が非常に重要になります
ウィンドウモードの場合は、他のアプリケーションとの連帯関係もあるため
アダプタの現在の設定に、こちらのプログラムがあわせる必要がありますが
DirectX はフルスクリーンモードなどもあるため、アダプタの詳細情報が必要です

初期化処理を行う時に、構造体に解像度や色数などを設定すれば
フルスクリーンモードに移行する時、アダプタのモードを移行します
しかし、設定はハードウェアに依存してしまうため、アダプタの能力が問われます

画面モードの情報は IDirect3D8::EnumAdapterModes() で得られます
このメソッドを使えば、指定したアダプタの画面モードの情報を得られます
HRESULT EnumAdapterModes(
	UINT Adapter , UINT Mode,
	D3DDISPLAYMODE* pMode
);
Adapter には、対象のアダプタインデックスを指定します
Mode は、情報を取得するアダプタモードのインデックスです
pMode は、情報を得る D3DDISPLAYMODE 構造体へのポインタを指定します
成功すれば D3D_OK が、失敗すれば D3DERR_INVALIDCALL が返ります

Mode 引数に指定するアダプタモードのインデックスとは
アダプタが 8 つのモードを提供する場合 0 〜 7 までのインデックス値を表します
このモードのインデックスを 0 からモード数 - 1 まで列挙すれば
全ての画面モードの情報を取得することができます

そのためには、アダプタがサポートするモード数を取得する必要があります
これは IDirect3D8::GetAdapterModeCount() メソッドで得られます

UINT GetAdapterModeCount(UINT Adapter);

Adapter には、対象のアダプタインデックスを指定します
成功すれば利用可能な画面モード数、失敗すれば 0 が返ります
#include <windows.h>
#include <d3d8.h>
#define TITLE 	TEXT("Kitty on your lap")

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	HDC hdc;
	PAINTSTRUCT ps;
	TCHAR strText[1024];
	TEXTMETRIC tm;
	D3DDISPLAYMODE d3ddm;
	static int iCount , iMax;
	static IDirect3D8 * pDirect3D;

	switch (msg) {
	case WM_DESTROY:
		pDirect3D->Release();
		PostQuitMessage(0);
		return 0;
	case WM_CREATE:
		pDirect3D = Direct3DCreate8(D3D_SDK_VERSION);
		iMax = pDirect3D->GetAdapterModeCount(D3DADAPTER_DEFAULT);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd , &ps);
		GetTextMetrics(hdc , &tm);

		for (iCount = 0 ; iCount < iMax ; iCount++) {
			pDirect3D->EnumAdapterModes(D3DADAPTER_DEFAULT , iCount , &d3ddm);
			wsprintf(strText , TEXT("%d × %d : %dHz") ,
				d3ddm.Width , d3ddm.Height , d3ddm.RefreshRate);
			TextOut(hdc , 0 , tm.tmHeight * iCount , strText , lstrlen(strText));
		}

		EndPaint(hWnd , &ps);
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow) {
	MSG msg;
	HWND hWnd;
	WNDCLASS winc;

	winc.style 		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra		= winc.cbWndExtra = 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return 0;

	hWnd = CreateWindow(
		TEXT("KITTY") , TITLE , WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
		CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT ,
		NULL , NULL , hInstance , NULL
	);
	if (!hWnd) return 0;

	while (GetMessage(&msg , NULL , 0 , 0 )) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}


このプログラムは、ウィンドウのクライアント領域に
GDI を用いて、プライマリアダプタの画面モードを列挙します
省略していますが、d3ddm.Format にはサーフェスフォーマットが含まれています

これらの情報を元に、フルスクリーンにモードを移行させることができます
何度も言いますが、フルスクリーンはアダプタに依存します
正しい設定がされていなければ、プログラムは正常に動作しません
フルスクリーンモードに移行する場合は、情報を取得し、正しく移行する必要があります
#include <windows.h>
#include <d3d8.h>
#define TITLE 	TEXT("Kitty on your lap")

IDirect3D8 * pDirect3D;
IDirect3DDevice8 * pD3Device;
D3DPRESENT_PARAMETERS d3dpp;

typedef struct {
	float x , y , z , rhw;
	DWORD diff;
} D3DVERTEX;

LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
	static D3DVERTEX pt[3] = {
		{200 , 10 , 1 , 1 , 0xFFFF0000} ,
		{400 , 200 , 1 , 1 , 0xFFFF0000} ,
		{10 , 200 , 1 , 1 , 0xFFFF0000}
	};

	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		if (!pD3Device) break;
		pD3Device->Clear(0 , NULL , D3DCLEAR_TARGET ,
			D3DCOLOR_XRGB(0xFF , 0xFF , 0xFF) , 1.0 , 0);
		pD3Device->BeginScene();

		pD3Device->SetVertexShader(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
		pD3Device->DrawPrimitiveUP(
			D3DPT_TRIANGLELIST, 1 , pt , sizeof (D3DVERTEX)
		);
		pD3Device->EndScene();
		pD3Device->Present(NULL,NULL,NULL,NULL);
		ValidateRect(hWnd , NULL);
		return 0;
	case WM_KEYDOWN:
		if (GetKeyState(VK_ESCAPE) < 0)
			SendMessage(hWnd , WM_CLOSE , 0 , 0);
		return 0;
	}
	return DefWindowProc(hWnd , msg , wp , lp);
}

int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
			PSTR lpCmdLine , int nCmdShow) {
	MSG msg;
	HWND hWnd;
	WNDCLASS winc;
	D3DDISPLAYMODE d3ddm;

	pDirect3D = Direct3DCreate8(D3D_SDK_VERSION);
	pDirect3D->EnumAdapterModes(D3DADAPTER_DEFAULT , 0 , &d3ddm);

	ZeroMemory(&d3dpp , sizeof (D3DPRESENT_PARAMETERS));
	d3dpp.BackBufferWidth = d3ddm.Width;
	d3dpp.BackBufferHeight = d3ddm.Height;
	d3dpp.BackBufferFormat = d3ddm.Format;
	d3dpp.BackBufferCount = 1;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.Windowed = FALSE;

	winc.style 		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc	= WndProc;
	winc.cbClsExtra		= winc.cbWndExtra = 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("KITTY");

	if (!RegisterClass(&winc)) return 0;

	hWnd = CreateWindow(
		TEXT("KITTY") , TITLE , WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
		CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT ,
		NULL , NULL , hInstance , NULL
	);
	if (!hWnd) return 0;

	pDirect3D->CreateDevice(
		D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL , hWnd ,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING , &d3dpp , &pD3Device
	);

	while (GetMessage(&msg , NULL , 0 , 0 )) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	pDirect3D->Release();
	pD3Device->Release();
	return msg.wParam;
}
このプログラムは、インデックス 0 番の画面モードに移行します
D3DPRESENT_PARAMETERS 構造体の Windowed メンバが FALSE になっていますね
これは、フルスクリーンモードでデバイスを作成することを意味します

筆者の環境では、解像度 640 × 480 ピクセルになります
Esc キーを押せば、プログラムは WM_CLOSE を発行してプログラムを終了します


IDirect3D8::EnumAdapterModes()

HRESULT EnumAdapterModes(
	UINT Adapter , UINT Mode,
	D3DDISPLAYMODE* pMode
);
指定したアダプタの指定した画面モードの情報を取得します

Adapter - 対象のアダプタインデックスを指定します
Mode - 取得するアダプタモードのインデックスを指定します
pMode - 情報を得る D3DDISPLAYMODE 構造体へのポインタを指定します

戻り値 - 成功すれば D3D_OK、失敗すれば D3DERR_INVALIDCALL

IDirect3D8::GetAdapterModeCount()

UINT GetAdapterModeCount(UINT Adapter);

アダプタの画面モードの数を取得します

Adapter - 対象のアダプタインデックスを指定します

戻り値 - 利用可能な画面モード数、失敗すれば 0




前のページへ戻る次のページへ