Вы находитесь на странице: 1из 5

let’s create a new Windows application to begin programming.

The following code snippet shows the


main entry point for a Windows program.

#include <windows.h>

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,


PSTR szCmdLine, int iCmdShow)
{

return (1);

This code will compile in Visual C++; however, we are far from creating a fully functional Windows
application. Before creating a fully functional Windows program, we must register a window class, which
defines the attributes of the window.
Registering a Window Class

The window class contains details such as the class name, menus, the callback for messages, and several
other pieces of data. To declare a window class, we use the WNDCLASS type. A typical window class
would look like the following.
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = FrameWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON));
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1)
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szFrameClass;

The first variable in the WNDCLASS structure we must fill in indicates the style of the window class. A
wide variety of options can be used for the style. I’ve chosen the basic values of CS_HREDRAW and
CS_VREDRAW, which will redraw the screen when the width or height of the client window has been
changed.

The lpfnWndProc variable is the pointer to the window procedure FrameWndProc, which is our message
handler. Our message handler will process any messages sent by the system.
Next, we set the variable cbClsExtra to 0 because we do not want to allocate extra bytes of memory
beyond the WNDCLASS size. The cbWndExtra variable is set to 0 because we do not need extra memory
allocated for the window instance. The hInstance variable is set to our program instance.

The hIcon variable sets the default icon for the application. To set this variable we must use the function
LoadIcon, which returns the handle of an icon. The first parameter for the LoadIcon function is the
current program instance, which is hInstance. The second parameter is the resource ID of the icon,
which is MAKEINTRESOURCE(IDI_ICON).
The hCursor variable sets the default cursor for the window. In our case we load a default cursor using
the function LoadCursor. This function requires two parameters, the first being the current instance,
which should be NULL, and the second being the resource ID of the cursor, which in this case is
IDC_ARROW. In both the LoadIcon and LoadCursor functions, the first parameter is of the HINSTANCE
type. We set this first parameter as NULL for the LoadCursor function to indicate we want to use the
standard Windows cursors rather than specifying custom resources. The hInstance variable requires the
handle of this instance, which is the hInstance from our WinMain.

The hbrBackground variable sets the background color for the window. We use the color (HBRUSH)
(COLOR_APPWORKSPACE + 1) and cast it as an HBRUSH type. The HBRUSH is a handle to a brush object.

The next variable, lpszMenuName, controls the menu that is to be loaded for the window class. We do
not need this parameter, so we can set it to NULL.

And finally, the last variable in the WNDCLASS structure we must fill in, the lpszClassName variable is the
name of the window class, which in our case is MdiFrame. Later, when we are going to create a window,
we will need to reuse this name, so it is a good idea to keep it simple. It is a good idea to declare our
szFrameClass variable at the top of the source code as a global variable. In the global section we will
declare an TCHAR called szFameClass.

TCHAR szFrameClass[] = TEXT ("MdiFrame") ;

Now that all the fields in the WNDCLASS structure are filled in, it is time to register a new window class
by calling the function RegisterClass and passing the wndclass variable we just filled in. If the registration
of the class is successful, a non-zero number will be returned. If the function fails, 0 will be returned.
With this in mind, the next piece of source code attempts to register a window class and displays an
error message if it fails.

if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Error: Cannot Register Class"),
szAppTitle, MB_ICONERROR);
return 0;
}

As you can see, registering the window class is fairly simple. To display the error
message, I simply used the MessageBox function to display a basic error message. The
MessageBox function requires four parameters: a handle to a window (HWND), two null-
terminated strings of the LPCTSTR type, which include the main message and the caption
text respectively, and an int for the type. It is a good idea to declare our title of a window
variable at the top of the source code as a global variable. In the global section we will declare an TCHAR
called szAppTitle.

TCHAR szAppTitle[] = TEXT ("SIMATIC Manager") ;

We don’t need any elaborate message boxes for the time being, so a basic MB_OK or OK
button message box with an error icon will suit our current needs.
Creating a Window
After registering the window class we must create a window on the screen using the CreateWindow
function. There are 11 simple parameters in this function, the first being the LPCTSTR lpClassName,
which as the parameter name suggests is our class name, "MdiFrame". The second parameter is another
LPCTSTR called lpWindowName, which is a string identifying the name of the window in the title bar. For
this parameter we will use the value "SIMATIC Manager" stored in the variable szAppTitle. After the
lpWindowName parameter, we set the style of the window using DWORD styles. There are many
options to choose from when setting the style of the window; we will use the default options
WS_OVERLAPPEDWINDOW and WS_CLIPCHILDREN for simplicity’s sake. The WS_OVERLAPPEDWINDOW
style creates a window with a title bar and Minimize and Maximize buttons. The WS_CLIBCHILDREN style
allows the window to clip its children.
The next two parameters are of the int type and identify the starting X and Y coordinates for the
window. After the starting locations are the width and height of the window as the int type. The eighth
parameter is hWndParent, which is of the HWND type. This parame ter is used when a child window
must be created. Since this window is the parent, we can keep this parameter as NULL. The next
parameter is of the HMENU type. If we wanted to load a menu we would use the LoadMenu function
and return a value into this parameter; however, we do not need this functionality at the moment and
therefore this parameter should be NULL for the time being. Later we will discuss how to create, display,
and add functionality to menus. After the hMenu parameter we include the current instance, which in
our case is hInstance. The final parameter is an LPVOID called lpParam. This parameter is sometimes
used when creating a multiple-document interface (MDI).We will make this parameter NULL.

Now that we’ve filled in the CreateWindow function, it is a good idea to declare our handle of a window
variable at the top of the source code as a global variable. In the global section we will declare an HWND
called ghMainWnd. We will place our CreateWindow code after the RegisterClass function is called.

ghMainWnd = CreateWindow (szFrameClass, szAppTitle,


WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);

It is a good idea to test the returned window value for NULL after calling the CreateWindow function. If
the creation of the window fails, NULL is returned and we must display an error message and exit the
program. As with all errors, we will use the MessageBox function to display the error and return 0 to
indicate an error occurred. The following code displays our window creation error checking.
if (ghMainWnd== NULL)
{
MessageBox (NULL, "Error: Failed to Create Window", szAppTitle, MB_OK);
return (0);
}
Displaying the Window
After the CreateWindow call returns, the window has been created internally in Windows. What
this means basically is that Windows has allocated a block of memory to hold all the information
about the window that you specified in the CreateWindow call, plus some other information, all
of which Windows can find later based on the window handle.

However, the window does not yet appear on the video display. Two more calls are needed. The
first is

ShowWindow(ghMainWnd, SW_SHOWMAXIMIZED);

The first argument is the handle to the window just created by CreateWindow. The second
argument determines how the window is to be initially displayed on the screen, whether it's
normal, minimized, or maximized. The user probably selected a preference when adding the
program to the Start menu. The value you receive from WinMain and pass to ShowWindow is
SW_SHOWNORMAL if the window is displayed normally, SW_SHOWMAXIMIZED if the
window is to be maximized, and SW_SHOWMINNOACTIVE if the window is just to be
displayed in the taskbar.

The ShowWindow function puts the window on the display. If the second argument to
ShowWindow is SW_SHOWNORMAL, the client area of the window is erased with the
background brush specified in the window class. The function call

UpdateWindow(hwndFrame);

then causes the client area to be painted. It accomplishes this by sending the window procedure
(that is, the FrameWndProc function in S7tgtopx.cpp) a WM_PAINT message. We'll soon examine
how FrameWndProc deals with this message.

The Main Loop


After creating the window , showing it and updating it we must write the main loop for the software.
The main loop we will create will run indefinitely. With each pass through the loop we will check for a
WM_QUIT message, which we will program as a break out of the loop. To accomplish this we must first
declare a variable called msg of the MSG data type. The MSG data type contains information about
messages being sent from the program.

MSG msg;

We will now tamper with three lines of code that are common to all Windows. The code is the
standard message loop:

while (GetMessage (&msg, NULL, 0, 0))


{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Here's how we change it for an MDI application:

while (GetMessage (&msg, NULL, 0, 0) > 0)


{
//if (hDlgModeless == 0 ¦¦ !IsDialogMessage (hDlgModeless, &msg))
//{
if (!TranslateMDISysAccel (hwndClient, &msg) &&
!TranslateAccelerator (ghMainWnd, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//}
}