This tutorial is part of a Collection: 04. DirectX 12 - Braynzar Soft Tutorials
14694
views
02. Creating a Window
Before we can start drawing with directx, we need to create a window to draw on. In this tutorial we will create a window using the Win32 API that direct3d can draw in.
BzTut02.rar 1.02 mb
2280 downloads
##New Declarations## We need a window handle, which is stored in a structure called ***HWND***. We create a global window handle and call it *hwnd*. To create a window, we need to fill out a WNDCLASSEX structure. The next line is a string which is the name of the class. You can call it whatever you want. After that is the title of our window, the text in the title bar of the window when it's not in full screen mode. // Handle to the window HWND hwnd = NULL; // name of the window (not the title) LPCTSTR WindowName = L"BzTutsApp"; // title of the window LPCTSTR WindowTitle = L"Bz Window"; Next we have the width and height of our window. If we set FullScreen to "true", the width and height will change to the width and height of the monitor. // width and height of the window int Width = 800; int Height = 600; // is window full screen? bool FullScreen = false; Now we have a couple functions. The first function is the function we will call to create our window. After that we have our main loop. The main loop is the heart of our program. It is where we will check for windows messages, update our game logic, and render our frame. // create a window bool InitializeWindow(HINSTANCE hInstance, int ShowWnd, int width, int height, bool fullscreen); // main application loop void mainloop(); The last declaration we have in our stdafx.h file is the callback function for windows messages, called WndProc. // callback function for windows messages LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); Our WinMain function has been updated to call the InitializeWindow function and mainloop function. int WINAPI WinMain(HINSTANCE hInstance, //Main windows function HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // create the window if (!InitializeWindow(hInstance, nShowCmd, Width, Height, FullScreen)) { MessageBox(0, L"Window Initialization - Failed", L"Error", MB_OK); return 0; } // start the main loop mainloop(); return 0; } Now we have our InitializeWindow function. In this function, the first thing we will do is check if we want fullscreen. If we do, we get the monitors width and length and set the global width and length to that. bool InitializeWindow(HINSTANCE hInstance, int ShowWnd, int width, int height, bool fullscreen) { if (fullscreen) { HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); MONITORINFO mi = { sizeof(mi) }; GetMonitorInfo(hmon, &mi); width = mi.rcMonitor.right - mi.rcMonitor.left; height = mi.rcMonitor.bottom - mi.rcMonitor.top; } Next we fill out a WNDCLASSEX structure. This structure will describe our window. WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2); wc.lpszMenuName = NULL; wc.lpszClassName = WindowName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); After we fill out this structure, we must register the class calling the **RegisterClassEx** function if (!RegisterClassEx(&wc)) { MessageBox(NULL, L"Error registering class", L"Error", MB_OK | MB_ICONERROR); return false; } Now we create our window with the class we just registered by calling the **CreateWindowEX** function. hwnd = CreateWindowEx(NULL, WindowName, WindowTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL); If we were unsuccessful in getting a window handle, we will return false and show an error message. if (!hwnd) { MessageBox(NULL, L"Error creating window", L"Error", MB_OK | MB_ICONERROR); return false; } If we want full screen, we will need to remove the window style. If you are working on only a single monitor, you i suggest you debug in windowed mode. debugging fullscreen applications using a single monitor can be a huge bitch if you hit a breakpoint or an exception while the window is fullscreen. if (fullscreen) { SetWindowLong(hwnd, GWL_STYLE, 0); } Finally we show the window and update the window, then return true. ShowWindow(hwnd, ShowWnd); UpdateWindow(hwnd); return true; } Next we have our main loop, "mainloop()". We zero out the memory for a MSG object. this MSG object will hold any windows message that the **PeekMessage** function gets. If we find a message, we translate the message then dispatch it. This is just so windows doesn't think our program stopped responding. If we did not find a message, we run our game code and continue the loop. void mainloop() { MSG msg; ZeroMemory(&msg, sizeof(MSG)); while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { // run game code } } } The last thing is our windows procedure callback. We had to give this function to the windows class when we created it. This is so we can get windows messages that are sent from Windows, such as key presses, mouse movements, or window resizing. For now, all we are checking for are the escape key, and if the x button on the top right of the window has been pressed. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_KEYDOWN: if (wParam == VK_ESCAPE) { if (MessageBox(0, L"Are you sure you want to exit?", L"Really?", MB_YESNO | MB_ICONQUESTION) == IDYES) DestroyWindow(hwnd); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); }
in the beginning of the tutorial you say " we need to create a windows class" this was confusing when i read your download file you used the stdafx file so just thought maybe make that more clear for others who come to this tutorial?
apart from that great tutorial as always i look forward to the rest of them for DirectX12
on Mar 21 `16
AaronSmith
your right, that is confusing. i pretty much just copied this tutorial from the directx 11 one since its the same, with some minor changes. i'll change that because saying class is confusing
on Mar 21 `16
iedoc
I don't know why, but the code doesn't spit out any error except the only window i can create after finishing part 2 is the window that says "Error creating window". Apparently that's because it failed to get a window handle and i've looked around every corner of google and could not find a fix for it. It's very frustrating since this is a very good tutorial set and i would like to follow it since i am very new to "making a game engine". Thanks!
on Feb 02 `19
JuiceBox
Do you run the sample code successfully? I think the error reason may be that you set "hWnd" as input parameter of WndProc function (as what is written in stdafx.h) while use "hwnd" in the body of this function.
on May 07 `19
yetsun
Sign in to comment