Saturday, February 5, 2011

First Win32 application

/****NOTE****
The following code has been borrowed from many sources which I will try to note as I go through this. This blog is to benefit my learning and if it helps others at the same time, all the better. Each author has their own way they like to code and I have taken things from each which makes the most sense to me. I am not just copy and pasting other people's code, I could just give you a link if I was doing that, but I will not claim anything as to be straight from my own mind either.
****ENDNOTE****

The following is a very basic Windows program using no DirectX to start with. This is the basis, the palette, upon which the rest of the DirectX will lay upon. So to start... Open up Microsoft Visual C++ 2010 Express (click the link to download if you do not have it). When you first open up VC++ there is an option on the front screen to open a New Project, or you can click File->New->Project. You will see a screen like that below.
Click Browse to select the folder you want to put the project in, name your project, and select Empty Project, then OK to begin. You will then have an empty project in front of you that needs a file. Select File->New->File... or <CTRL>+<SHIFT>+<A> . Select ".cpp" as the type and name your .cpp file. I will use "main.cpp" to refer to this file from here on. Before we start coding let's go to Project->Properties->Configuration Properties->General->Character Set and change the character set from "Use Unicode Character Set" to "Use Multi-Byte Character Set".

Let's add some code:*/

#include <Windows.h>

#define CLASS_NAME     "First Window"
#define WINDOW_NAME    "First Window"
#define WINDOW_WIDTH    800
#define WINDOW_HEIGHT   600

HINSTANCE hInstance = NULL;
HWND hWnd = NULL;

bool InitWindow( HINSTANCE hInstance, int width, int height );
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );

/*This first part defines some global variables to create this first window. WINDOW_NAME, WINDOW_WIDTH, and WINDOW_HEIGHT are self explanatory. HINSTANCE is a windows type that holds the application instance(the executable module). HWND is a global variable that holds a Windows handle. I'll go more into what this is when we define it in InitWindow() but the handle holds the name, size, and style of the window we are creating.*/

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE      hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    // Initialize the window
    if( !InitWindow( hInstance, WINDOW_WIDTH, WINDOW_HEIGHT))
    {
        MessageBox(NULL, "Initialization Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    
    // Main message loop
    MSG msg = {0};
    while( msg.message != WM_QUIT)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int)msg.wParam;
}

/*That code above is what takes the place of the typical C++ main() function.The first thing we do in our main function is initialize our window. We place the function bool InitWindow() call in an if statement which will pop up a message box error and end our program if initialization fails. We then create a MSG handle which we will use to handle messages (mouse clicks, key strokes, etc.). PeekMessage() can be replaced by GetMessage() however PeekMessage() is faster and is recommended in every game programming book I have read so far.  Now let's define our InitWindow() function there is a lot that goes into it but it's not as difficult as it looks at first:*/

bool InitWindow( HINSTANCE hInstance, int width, int height )

{

    WNDCLASSEX wncl;

    memset(&wncl, 0, sizeof(WNDCLASSEX));
    wncl.cbSize = sizeof(WNDCLASSEX);
    wncl.style = CS_HREDRAW | CS_VREDRAW;
    wncl.lpfnWndProc = WndProc;
    wncl.hInstance = hInstance;
    wncl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wncl.hCursor = LoadCursor(NULL, IDC_ARROW);
    wncl.lpszClassName = CLASS_NAME;
    wncl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wncl))
    {
        MessageBox(NULL, "Window Class Registration Failed!", "Error!",
        MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }


    //Create the window from the class definition above

    hWnd = CreateWindowEx(NULL,

        CLASS_NAME,

        WINDOW_NAME,

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT,

        CW_USEDEFAULT,

        width,

        height,

        NULL,

        NULL,

        hInstance,

        NULL);

    if(!hWnd)

    {

        return false;

    }


    //Display the window

    ShowWindow(hWnd, SW_SHOW);

    UpdateWindow(hWnd);

    return true;
}

/*A lot of new stuff there, all describing your window from the cursor type to Icons used and the background of your window. The explanation for this I think is better left to another post as this one is already getting lengthy. The process you see here you will begin to get used to using DirectX as you Create and Object-> Define the Object->Register the Object. After defining and registering the window class, we then create a RECT object which is defined by the WINDOW_WIDTH and WINDOW_HEIGHT we input as variables to the InitWindow() function and sent to AdjustWindowRect() to resize the window. We then create the window with the call to CreateWindow()*/

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, 
                          WPARAM wParam, LPARAM lParam )
{
    //Handle Messages
    switch(message)
    {
    case WM_KEYDOWN:
        switch(wParam)
        {
        case VK_ESCAPE:
            PostQuitMessage(0);
            break;
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);

 /*You should be able to copy and paste this entry as a whole into your IDE and compile without any modifications. If you receive an error similar to "Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast ... error C2440: '=' : cannot convert from 'const char [13]' to 'LPCWSTR'" Then you have not set your character set to multi-byte. You can use the TEXT("Your text here") function instead but this is tiresome and unnecessary. 

I hope this has helped someone else in creating their first windows application. I recommend this site to get a more in depth understanding of the Win32 application we just created. */
 

No comments:

Post a Comment