Let's create a simple typical C++ Windows application from scratch. Its interface will consist of a dialog window with two buttons. A click on the first button leads to a display of a message while a click on the second button leads to the application termination. The application contains a resource file with Windows Controls captions, sizes, styles, and fonts.
First of all, you must create a source C++ file and name it main.cpp
. This file will contain the main function:
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include "resource.h" BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CLOSE: EndDialog(hwndDlg, 0); return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_BTN_QUIT: EndDialog(hwndDlg, 0); return TRUE; case IDC_BTN_TEST: MessageBox(hwndDlg, "Message text", "Information", MB_ICONINFORMATION); return TRUE; } } return FALSE; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc); }
Tip
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.
The first line is the definition of the WIN32_LEAN_AND_MEAN
macro, which disables the inclusion of rarely-used Windows header files. The next two lines include the header file with the Windows API functions' declaration and the header file with application resources identifiers.
The DialogProc
function processes messages sent to our modal dialog. These messages contain information about events that occurred. The message identifier is passed to the function in the uMsg
parameter. The wParam
and lParam
parameters are used for additional message-specific information. The hwndDlg
parameter defines the dialog window that has received the message.
The DialogProc
function processes the following messages:
WM_CLOSE
: This message is caused by a click on the standard close window button.WM_COMMAND
with theIDC_BTN_QUIT
parameter: This message is caused by a click on the Quit button.WM_COMMAND
with theIDC_BTN_TEST
parameter: This message is caused by a click on the Test button.
The WM_CLOSE
and WM_COMMAND
with IDC_BTN_QUIT
parameter messages causes the application to terminate. The WM_COMMAND
with the IDC_BTN_TEST
parameter message causes the standard message box displaying.
The function which is defined next is WinMain
. This function will be called when the application launches. The DialogBox
Windows API function is called here to create a modal dialog window. We pass the hInstance
variable to this function with a handle to the module whose executable file contains the resources of the created dialog. These resources are read-only embedded data in a binary file.
Next, the DialogBox
function parameter is a pointer to the null-terminated string that specifies the dialog template in the resource data. The MAKEINTRESOURCE
macro is used here to convert the DLG_MAIN
identifier of the integer type to the null-terminated string. This identifier is defined in the resource.h
header file.
The third parameter of the DialogBox
function is the handle of the parent window that owns the dialog window. This is equal to the NULL
value in our case that means the absence of a parent window.
The last parameter of the function is a pointer to the dialog window procedure to process messages. We pass the pointer to the DialogProc
function for this parameter.
User interface elements and their parameters can be described in the resource file. All data from this file will be embedded into executable files and these will be available when the application runs.
Let's add this resource file to our project (resource.rc
):
#include "resource.h" DLG_MAIN DIALOGEX 6, 5, 138, 75 CAPTION "Typical Windows Application" FONT 10, "Tahoma" STYLE 0x10CE0804 BEGIN CONTROL "&Message", IDC_BTN_TEST, "Button", 0x10010000, 46, 15, 46, 15 CONTROL "&Quit", IDC_BTN_QUIT, "Button", 0x10010000, 46, 45, 46, 15 END
You can see the inclusion of the resource.h
header in the first line of the resource file. The user interface element identifiers are defined in this header file. These identifiers are used to provide access from C++ code to resource data.
The DLG_MAIN
element of the DIALOGEX
type is defined in the next line. This element represents the dialog template with the position and size dialog window parameters. All statements in the next lines define the appearance of the dialog box and its elements.
The next line of the resource file contains the CAPTION
statement. This statement defines the title of the dialog box. The FONT
statement defines the font size and typeface for the dialog text font. The STYLE
statement defines the window style of the dialog box.
The dialog box buttons are defined between the BEGIN
and END
statements. These parameters are defined for each button as follows:
Type of the user interface element (this is equal to
CONTROL
)Caption of the element
Element identifier
Class of the element (this is equal to
Button
)Window style of the element
Position (x, y) and size (width, height)
The third file is a header for the binding resource identifiers and C++ code (resource.h
):
#include <windows.h> #define DLG_MAIN 100 #define IDC_BTN_TEST 101 #define IDC_BTN_QUIT 102
The dialog box and buttons' identifiers are specified here.
The compilation rules are required to build our application. The rules describe algorithms to compile sources and link object files together to assembly executable files and libraries. This kind of algorithm is present in common IDEs, such as Visual Studio. However, it is often hidden inside the graphical user interface and is not available for change. You have the ability to control each step of the building application algorithm with the GNU Make utility.
You can perform each compilation step manually by calling the compiler and linker from the command line interface. However, the rules in the GNU Make utility file can automate these operations.
This is the simplest variant of the rules of the GNU Make utility file to build our application (Makefile
):
win32-app.exe: main.cpp resource.rc.res.o g++ -o win32-app.exe main.cpp resource.rc.res.o resource.rc.res.o: resource.rc windres -o resource.rc.res.o -i resource.rc clean: rm -f *.o win32-app.exe
Notice that there is a tabulation under each command. Tabulation and spaces are not the same for the GNU Make utility and this is often subjected to criticism.
The Makefile syntax will be described in detail in the later part of this book. It consists of targets (specified under the colon), and commands for producing these targets at the next line. The file list after the colon consists of files on which the target depends. These files are called prerequisites. The target will be rebuilt by the make
command if one of its prerequisite files has been changed.
The following targets are specified in this Makefile
:
The final executable file, that is,
win32-app.exe
The object file with application resources, that is,
resource.rc.res.o
The utility target to remove temporary files, that is,
clean
The MinGW C++ compiler application name is g++. The compiler for the Windows resource files is windres
. Each GNU utility has detailed information about command line options and developers' feedback. Running the GNU utility from the Windows command prompt or Bash shell with the --help
option will lead to displaying this information. This is the example of the same GNU utility run.
$ g++ --help
The clean
utility target is required to remove all files generated by the compiler and linker. The rm
command is called to perform this task. You can use the clean
target to rebuild the application after changing source files. Just perform this target and then build your application.
Now we are ready to compile our first application with MinGW software. First of all, you must run the command shell. There are several ways to do this. The simplest one is by launching the command shell from the Windows Start menu. Just type the cmd
or bash
command in the menu's Search field. Furthermore, there are a lot of file managers with integrated command shells which you will be comfortable to work with. Far Manager is one of these.
You will see a window with the command line shell. Several useful commands for directory navigation have been installed with MinGW software:
cd <dir>
: This command changes the current directory to the specified one.For example, to change the directory to
C:\Projects
, type the following command line:$ cd /c/Projects
pwd
: This command writes the absolute pathname of the current directoryls
: This command lists the current directory contents
Change the current directory to the project one. The C:/
path equals to the /c
path in the Bash shell. This is due to the specific Unix environment's integration with Windows filesystems. Type the make
command after changing the current directory. This is all that you need to do for compiling and linking applications. You get the executable binary after the GNU Make utility is executed successfully. Retype the make
command to rebuild the application after changing any of the source files. It may be helpful to remove all the files, which were already generated by the compiler and linker, by using the make
clean
command before rebuilding the application.