Skip to content

Create and show a basic window

Tim Chang edited this page Jan 26, 2018 · 2 revisions

Lesson 2 : Create and show a basic window

Before we initilize and darw something, we have to create a Win32 window. We will use window.h header to new memory and create our first window.

Create a header for other headers

In order to manage other headers which are used in our project, we create a header named stdafx.h. And there is the content in below.

// stdafx.h
#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>

#include <d3d12.h>
#include <dxgi1_4.h>
#include <D3Dcompiler.h>
#include <DirectXMath.h>
#include "d3dx12.h"

#include <string>
#include <wrl.h>
#include <shellapi.h>

Create a process entry function

Back to the main.cpp, we prepare to create a entry function for our process likes below.

#include "stdafx.h"

_Use_decl_annotations_
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
    return 0;
}

The code above is a basic function for entry. Now we will initialize the window class contains information the window needs.

// Initialize the windows class.

WNDCLASSEX windowClass = { 0 };
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WindowProc;
windowClass.hInstance = hInstance;
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.lpszClassName = L"D3D12Basic";
RegisterClassEx(&windowClass);

RECT windowRect = {0, 0, 800, 600};
AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);

You would find there is a varibale, WindowProc, it shows as not defined. It is a Callback procedure we have to implement. So we will define this function ahead of WinMain and implement it after it. Or you can just put the implementation before WinMain.

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}

Register window class

Now, we have already any information about window, we just need to register the window. You can also call this step as "Create window". The code likes below.

// Create the window and store a handle to it.
HWND hwnd = CreateWindow(
    windowClass.lpszClassName,
    L"D3D12Basic",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    800,
    600,
    nullptr,
    nullptr,
    hInstance,
    nullptr);

Show the window

After creating the window, we just call ShowWindow API to show our window.

ShowWindow(hwnd, nCmdShow);

Main loop

Final, we have to reamin a while loop in order to call our d3d12 component later.

// Main sample loop.
MSG msg = {};
while (msg.message != WM_QUIT)
{
    // Process any messages in the queue.
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

Result

Now, you can press F5 to see the result, it should like below.

Full Code

#include "stdafx.h"

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

_Use_decl_annotations_
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
    // Initialize the windows class.
    WNDCLASSEX windowClass = { 0 };
    windowClass.cbSize = sizeof(WNDCLASSEX);
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc = WindowProc;
    windowClass.hInstance = hInstance;
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowClass.lpszClassName = L"D3D12Basic";
    RegisterClassEx(&windowClass);

    RECT windowRect = {0, 0, 800, 600};
    AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE);

    // Create the window and store a handle to it.
    HWND hwnd = CreateWindow(
        windowClass.lpszClassName,
        L"D3D12Basic",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        800,
        600,
        nullptr,
        nullptr,
        hInstance,
        nullptr);

    ShowWindow(hwnd, nCmdShow);

    // Main sample loop.
    MSG msg = {};
    while (msg.message != WM_QUIT)
    {
        // Process any messages in the queue.
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return 0;
}

// Main message handler for application.
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}