Back to Top

Home/Tutorials

Basic Windows Applications


Welcome to the first episode in my "All Educational Software" masterclass! I know that you are eager to create great applications right away, but before doing that, we need to understand how Windows-based software works.


So, let's dissect the code for a standard Windows API application. The program will display a window, using "minimize", "maximize" and "close" buttons for it, and yes, it will even do something, displaying a message in a random position on the screen.


first application

When we work with the Windows API, we need to use the WndProc function, which handles window-related input; without it, our applications wouldn't be able to react to mouse clicks, etc.

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

{

PAINTSTRUCT ps;

HDC hdc;

switch(message)

{

  case WM_CREATE:

   break;

  case WM_PAINT:

   hdc = BeginPaint (hWnd, &ps);

   EndPaint (hWnd, &ps);

   break;

   case WM_DESTROY:

      PostQuitMessage(0);

      break;

  default:

   break;

  }

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

}

This is the message loop function, which defines a structure that's needed by WM_PAINT, a message that's triggered anytime a function wants to paint a section of the application window.


We also require a handle to the graphics context, and then we choose (using switch) how to handle the received messages, depending on the message type. We could choose to do something when the window is created, for example; how about playing a sound? I didn't do anything here, though, because I wanted to keep the code as simple as possible.


The WM_PAINT message is sent when we move the program window on the screen, for example. In this case, BeginPaint initiates window painting, while EndPaint finishes it.


WM_DESTROY is sent when the window is almost destroyed; we want to use it because we need to insert a "quit" message into the message queue, which will tell Windows that this piece of software requires to be shut down. The last line of code in the function above processes the rest of the messages.


It's time to take a look at the function that does the actual work


int WINAPI WinMain (WINARGS)

{

MSG msg;

char *szClass = "FirstWindowsApplication";

HINSTANCE hi = GetModuleHandle(NULL);

WNDCLASSEX winclass;

winclass.cbSize = sizeof(WNDCLASSEX);

winclass.style = CS_HREDRAW | CS_VREDRAW;

winclass.lpfnWndProc = WndProc;

winclass.cbClsExtra = 0;

winclass.cbWndExtra = 0;

winclass.hInstance = hi;

winclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);

winclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

winclass.hCursor = LoadCursor(NULL, IDC_ARROW);

winclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);

winclass.lpszMenuName = NULL;

winclass.lpszClassName = szClass;

RegisterClassEx(&winclass);

HWND hwnd = CreateWindowEx(0, szClass, "Real Windows Application", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 200, 100, 800, 600, NULL, 0, NULL, NULL);

HDC hdc = GetDC(hwnd);

while(TRUE)

{

  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))

  {

if(msg.message == WM_QUIT)

break;

          TranslateMessage(&msg);

          DispatchMessage(&msg);

  }

TextOut(hdc, rand()%800, rand()%600, "My first Windows Application!", strlen("My first Windoss Application! "));

Sleep(10);

}

ReleaseDC(hwnd, hdc);

return(msg.wParam);

}


We define a generic message, and then we set the name of our window. We retrieve the handle for the specified module, and then we hold the class that we're going to create using "winclass". We get the size of WNDCLASSEX, we set its style, and then we assign the window procedure to WndProc.


There's no need to reserve any extra space in the class and window structures, so we set those to zero. We get the instance handle of the program, and then we set an icon and a title icon for our application.


It's time to load one of the predefined mouse cursors; most people are familiar with IDC_ARROW, so that's what we will use. We set the background color to white, we tell the program to avoid using a menu, we give the class that we're going to use a name, and then we register it.


This is where things start to get interesting! We create a window that's got the desired title, style, position and dimensions (in pixels). We get a handle to the graphics context, and then we run a "while" loop that will do most of the job.


If there's any message in the queue, we need to process it. If there's a WM_QUIT, for example, the application needs to shut down; otherwise, it will send the received keystrokes to Windows and the messages to the window proc.


Everything we've discussed so far was pure API stuff; if you want to play with Windows' API, you're going to copy/paste this code base in your applications a lot! The good news is that we have finally reached the part that does something useful, displaying "My first Windows Application!" on the screen every 10 milliseconds (that would be 100 times per second), in a random position. The last few lines release the dc and tell the application to return to Windows.


Well, I know that the code may look a bit complex, but I wanted you to see how old-school programming is done. Stay tuned, because I'll have a pleasant surprise for you in the next tutorial!