Windows apps are event driven apps. An event can be an external or internal input to an app. Event driven apps run a message loop, which parses incoming events and then calls appropriate functions corresponding to that event. Code::Blocks default code generated by Win32 GUI project wizard generates a boilerplate code of an event driven app.
In order to understand event driven programming we shall be using following example to learn and understand it. We shall be using native Win32 API for this example. Win32 API is the base of several toolkits. Thus we should have an understanding of it in order to understand other toolkits.
Let's create another GUI app and name it App10
. Replace wizard generated code with the following code. Also enable Unicode support as per the steps laid out in the previous example. As the code snippet is large we'll understand and paste it in editor window in several steps.
The following code snippet shows the header declaration, global variable declaration, and declaration of callback function:
#include <windows.h> #define ID_BTN_CLICK_ME 100 // This function is called by the Windows function DispatchMessage() LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); // Make the class name into a global variable TCHAR szClassName[ ] = TEXT("CodeBlocksWindowsApp");
In the following snippet we'll define the WinMain()
function. We will define an object of WNDCLASSEX
structure inside the WinMain()
function. This structure takes several inputs. With wincl.lpfnWndProc
we have assigned a callback function WindowProcedure()
to the wincl
object. This instructs app to call that function for event processing. Finally the wincl
object will get registered with the RegisterClassEx()
function. Once the object is registered successfully we create a window of that class using the
CreateWindowEx()
function.
We will display newly created window using the
ShowWindow()
function. After the window is displayed we will run an event processing loop using the GetMessage()
function inside a while
loop. All incoming events are then sent to the WindowProcedure()
function by DispatchMessage()
function.
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { HWND hwnd; // This is the handle for our window MSG messages; // Here messages to the application are saved WNDCLASSEX wincl; //Data structure for the windowclass // The Window structure wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; // Callback function wincl.style = CS_DBLCLKS; // Catch double-clicks wincl.cbSize = sizeof (WNDCLASSEX); // Use default icon and mouse-pointer wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; // No extra bytes after the window class wincl.cbWndExtra = 0; // structure or the window instance // Use Windows's default colour as the background of the window wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; // Register the window class, and if it fails quit the program if (!RegisterClassEx (&wincl)) return 0; // The class is registered, let's create the window hwnd = CreateWindowEx ( 0, // Extended possibilites for variation szClassName, // Classname TEXT("App for Windows"), // Title Text WS_OVERLAPPEDWINDOW, // default window CW_USEDEFAULT, // Windows decides the position CW_USEDEFAULT, // where the window ends up on the screen 300, // The programs width 250, // and height in pixels HWND_DESKTOP, // The window is a child-window to desktop NULL, // No menu hThisInstance, // Program Instance handler NULL // No Window Creation data ); // Make the window visible on the screen ShowWindow (hwnd, nCmdShow); // Run the message loop. It will run until GetMessage() returns 0 while (GetMessage (&messages, NULL, 0, 0)) { // Translate virtual-key messages into character messages TranslateMessage(&messages); // Send message to WindowProcedure DispatchMessage(&messages); } // Return value of PostQuitMessage() return messages.wParam; }
The WM_CREATE
event is sent out by Windows OS when a window is being created. We will then create a button using the CreateWindow()
function.
We shall be processing button press by processing the WM_COMMAND
event in the WindowProcedure()
function. We will then display a message box whenever this button is clicked.
Finally we will be processing the WM_DESTROY
event, which will be issued whenever window is being destroyed. A return value of 0
will be posted with the PostQuitMessage()
function emitting a WM_QUIT
event to the message queue.
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {switch (message) // handle the messages { case WM_CREATE: CreateWindow(TEXT("button"), TEXT("Click Me!"), WS_VISIBLE | WS_CHILD, 20, 50, 80, 25, hwnd, (HMENU) ID_BTN_CLICK_ME, NULL, NULL); break; case WM_COMMAND: if (LOWORD(wParam) == ID_BTN_CLICK_ME) { MessageBox(hwnd, TEXT("Hello World!"), TEXT("Information"), MB_OK | MB_ICONINFORMATION); } break; case WM_DESTROY: PostQuitMessage (0); // send a WM_QUIT to the message queue break; default: // for messages that we don't deal with return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }
This completes our Windows app. Hit F9 key (an alternative to clicking on the build and then run icon in build toolbar) to build and run this app. Following screenshot will be presented:
To solve this problem, GUI toolkit was developed. The GUI toolkit simplifies development process allowing reuse of code and a smaller code base. It also contains complex GUI control (for example, rich text control, HTML control, and so on).
3.143.5.15