軟件光柵化渲染器二

在上節完成了數學庫後,這節先寫出所需要的基本窗口結構。

win32的窗口很好建立,系統會自己生成代碼,然後我們再對代碼進行些許修改。

全局變量:

const int SCREEN_WIDTH = Screen::Width;
const int SCREEN_HEIGHT = Screen::Height;

//屏幕寬度和高度   
const int BITS = 32;				//每個像素的位數  
HDC screen_hdc;
HWND screen_hwnd;
HDC hCompatibleDC; //兼容HDC  
HBITMAP hCompatibleBitmap; //兼容BITMAP    
BITMAPINFO binfo; //BITMAPINFO結構體  
HINSTANCE ghInstance;


在原有基礎上添加了幾個方法:

void Display();
void SrcInit();
HWND Start(HINSTANCE hInstance, int nShowCmd, string wcName, string title);
void Update(HWND hwnd);
void Destroy(string wcName, HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lParam);


主函數:

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
	//1.創建窗口
	string windowClassName = "MyWindow";
	string title = "3DRender";
	HWND hwnd = Start(hInstance, nShowCmd, windowClassName, title);

	//時間初始化
	DWORD curTime = GetTickCount();
	DWORD preTime = GetTickCount();
	//2.消息循環
	MSG msg = { 0 };
	SrcInit();
	while (msg.message != WM_QUIT)
	{
		//獲取消息
		if (PeekMessage(&msg, 0, NULL, NULL, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			curTime = GetTickCount();
			if (curTime - preTime > 30)
			{
				preTime = curTime;
				Update(hwnd);
			}
		}
	}

	//3.遊戲結束
	Destroy(windowClassName, hInstance);
	return 0;
}


事件回調

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_KEYDOWN:
	{
	}
	break;
	default:
		return DefWindowProc(hwnd, message, wparam, lParam);
	}
	return 0;
}



HWND Start(HINSTANCE hInstance, int nShowCmd, string wcName, string title)
{

	ghInstance = hInstance;
	//1.創建窗口類
	WNDCLASSEX wndClass = {};
	wndClass.cbSize = sizeof(WNDCLASSEX);
	wndClass.style = CS_HREDRAW | CS_VREDRAW;
	wndClass.lpfnWndProc = WndProc;
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;
	wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndClass.lpszMenuName = NULL;
	wndClass.lpszClassName = wcName.c_str();

	//2.註冊窗口類
	assert(RegisterClassEx(&wndClass));

	//3.創建窗口
	HWND hwnd = CreateWindow(wcName.c_str(), title.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);

	//4.調整大小,移動,顯示,更新
	if (!hwnd)
	{
		return FALSE;
	}

	RECT  rectProgram, rectClient;
	GetWindowRect(hwnd, &rectProgram);   //獲得程序窗口位於屏幕座標
	GetClientRect(hwnd, &rectClient);      //獲得客戶區座標
										   //非客戶區寬,高
	int nWidth = rectProgram.right - rectProgram.left - (rectClient.right - rectClient.left);
	int nHeiht = rectProgram.bottom - rectProgram.top - (rectClient.bottom - rectClient.top);
	nWidth += SCREEN_WIDTH;
	nHeiht += SCREEN_HEIGHT;
	rectProgram.right = nWidth;
	rectProgram.bottom = nHeiht;
	int showToScreenx = GetSystemMetrics(SM_CXSCREEN) / 2 - nWidth / 2;    //居中處理
	int showToScreeny = GetSystemMetrics(SM_CYSCREEN) / 2 - nHeiht / 2;
	MoveWindow(hwnd, showToScreenx, showToScreeny, rectProgram.right, rectProgram.bottom, false);

	memset(&binfo, 0, sizeof(BITMAPINFO));
	binfo.bmiHeader.biBitCount = BITS;      //每個像素多少位,也可直接寫24(RGB)或者32(RGBA)  
	binfo.bmiHeader.biCompression = BI_RGB;
	binfo.bmiHeader.biHeight = -SCREEN_HEIGHT;
	binfo.bmiHeader.biPlanes = 1;
	binfo.bmiHeader.biSizeImage = 0;
	binfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	binfo.bmiHeader.biWidth = SCREEN_WIDTH;



	//獲取屏幕HDC  
	screen_hwnd = hwnd;
	screen_hdc = GetDC(screen_hwnd);

	//獲取兼容HDC和兼容Bitmap,兼容Bitmap選入兼容HDC(每個HDC內存每時刻僅能選入一個GDI資源,GDI資源要選入HDC才能進行繪製)  
	hCompatibleDC = CreateCompatibleDC(screen_hdc);
	hCompatibleBitmap = CreateCompatibleBitmap(screen_hdc, SCREEN_WIDTH, SCREEN_HEIGHT);
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hCompatibleDC, hCompatibleBitmap);

	ShowWindow(hwnd, nShowCmd);
	UpdateWindow(hwnd);

	return hwnd;
}

void SrcInit()
{
	//資源加載
}
void Update(HWND hwnd)
{
	//渲染更新
	Display();
}
void Display()
{
	////將顏色數據打印到屏幕上,這下面兩個函數每幀都得調用  
	SetDIBits(screen_hdc, hCompatibleBitmap, 0, SCREEN_HEIGHT, Buffer, (BITMAPINFO*)&binfo, DIB_RGB_COLORS);
	BitBlt(screen_hdc, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, hCompatibleDC, 0, 0, SRCCOPY);
}
void Destroy(string wcName, HINSTANCE hInstance)
{

	//5.註銷窗口類
	UnregisterClass(wcName.c_str(), hInstance);
}

然後會看到:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章