//
// SDI Frame
//
// The framework for any
// Single-Document-Interface
// application
//
//
// #include
//
/* windows.h contains *all* of
the things we need for this demo */
#include "windows.h"
//
// #define
//
//
// prototypes
//
/* this is the prototype for our Window
Procedure: it is called by Windows (the O/S)
(hence the CALLBACK) and it returns a
LRESULT (long). It's parameters are a
HWND (handle to a window), a UINT (unsigned integer,
which represents the message), a WPARAM
(a special unsigned integer that contains extra
information about the message being sent) and finally
a LPARAM (a special long which also contains information
about the messge being sent) */
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
//
// globals
//
/* in this example, szAppName is the windows title.
The TCHAR is an unsigned short and is necessary for
portability between Windows 9x and Windows NT. The same
is true for the TEXT() macro, which could be replaced
by a lot of things, eg: _T() or __T() or T() */
TCHAR szAppName[] = TEXT("SDI Frame");
/* the szWinClass is necessary later when we register
the window class */
TCHAR szWinClass[] = TEXT("WIN_CLASS");
//
// WinMain(...)
//
/* the WinMain(...) function is the entry point
for all Win32 API programs (except MFC). It is the
Windows equivalent of main(...).
It returns an integer value and the WINAPI could
have been PASCAL or any other equivalent calling-convention.
It's parameters are two instances (the first one is the
current instance and the second one is the now obsolete
previous instance, which is no longer used), a command-line
(how to deal with this is in the next tutorial) and an
integer dictating how to show the window (either Maximised or
Minimised) */
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR lpCmdLine,
int nCmdShow)
{
MSG msg; // a struct used in the passing of messages
WNDCLASS wc; // a window class struct, see below
HWND hwnd; // a handle-to-a-window, see below
/* the window class struct is the first step in setting up
a window. all of the attributes are set before the class is
registered. Each window class can be used to create more than
one window. Also, there are predefined controls that have their
own class and, as you will see, their own Window Procedure. These
controls include: Edit Boxes, Combo Boxes, Scroll Bars, etc. */
wc.cbClsExtra = 0; // specify how many bytes extra space is required for every window derived from this window class
wc.cbWndExtra = 0; // specify how many bytes extra space is required for this window
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); // background colour
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // cursor, this is usually the default
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // icon, this can be changed using resources (shown in the next tutorial)
wc.hInstance = hInstance; // the current instance of the program is passed to the instance of the class
wc.lpfnWndProc = WinProc; // the window procedure used by this class, usually has a more distinguishing name
wc.lpszClassName = szWinClass; // the name of this class
wc.lpszMenuName = NULL; // the name of the menu to be attached to the window, null until next tutorial
wc.style = CS_HREDRAW | CS_VREDRAW; // these 'class styles' mean that the window will be redrawn whenever it is resized vertically or horizontally
if( !RegisterClass(&wc)) // register the class, and test if it fails
{
MessageBox(NULL, TEXT("Error registering class"), TEXT("ERROR"), MB_OK);
return 0;
}
hwnd = CreateWindow(szWinClass, // the class as specified in the one we just registered
szAppName, // the title of the window
WS_OVERLAPPEDWINDOW, // the window style (there are usually a lot more of these
CW_USEDEFAULT, // the left co-ord of the window
CW_USEDEFAULT, // the top co-ord of the window
CW_USEDEFAULT, // the width of the window
CW_USEDEFAULT, // the height of the window
(HWND) NULL, // a handle to the parent window
(HMENU) NULL, // a handle to the window's menu
(HINSTANCE) hInstance, // the instance of the window (which is the instance of the app)
(void *) NULL); // any extra information (I think it is passed to the window when it is created in the lParam of the WM_CREATE message?)
// WM_CREATE message has been sent to the window
ShowWindow(hwnd, nCmdShow); // shows the window, using the specified command (Maximised, Minimised, etc)
UpdateWindow(hwnd); // the window is updated (a WM_PAINT message is sent to the window
while (GetMessage(&msg, (HWND) NULL, 0, 0)) // while there is a message to retrieve, and that message is not WM_QUIT
{
TranslateMessage(&msg); // some messages need translating
DispatchMessage(&msg); // send the message to the window
}
return msg.wParam; // return the message struct's wParam
}
//
// WinProc(...)
//
/* every window must have a function that Windows (the O/S) calls.
It uses a switch statement to test which message it is receiving */
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(msg)
{
case WM_PAINT:
/* the following two lines are the minimum
that has to be done for every program */
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
/* between those two lines you could have
outputted text etc. */
return 0;
case WM_DESTROY:
/* if the quit message is not posted then the while
that we created in WinMain(...) will not quit and the
application will disappear from view but will still be
resident in memory */
PostQuitMessage(0);
break; // pass to DefWindowProc(...) as well
}
/* takes care of all of the messages that we didn't catch
in our Window Procedure */
return DefWindowProc(hwnd, msg, wParam, lParam);
}