To understand how MFC implements a Windows application, you need to understand the architecture of the Win32 platform and the applications that run on it. In this lesson, you will learn about the basic structure and operation of a Win32 application.
After this lesson, you will be able to:Estimated lesson time: 30 minutes
- Describe the relationship between processes, threads, and applications.
- Describe the role of messages within the Windows operating system.
- Describe the essential steps required to create a basic Win32 application.
A proper understanding of the target platform is essential to developing effective applications. This section explains the architectural elements of the Win32 operating systems that will enable you to write well-behaved applications and take full advantage of the operating system services.
An application written for Windows consists of one or more processes. A process, in the simplest terms, is an instance of an executing program. A process has an address space and resources assigned to it, and one or more threads run in the context of the process.
A thread is the basic unit to which the operating system allocates processor time and is the smallest piece of code that can be scheduled for execution. A thread runs in the address space of the process and uses resources allocated to the process.
A process always has at least one thread of execution, known as the primary thread. You can create additional secondary threads to carry out background tasks, to take advantage of the multitasking capabilities of Windows 32-bit operating systems. Using more than one thread in an application is known as multithreading.
When an application is started, the operating system creates a process and begins executing the primary thread of that process. When this thread terminates, so does the process. This primary thread is supplied to the operating system by the startup code in the form of a function address. All Windows applications define an entry-point function named WinMain(). The address of the WinMain() function is supplied as the primary thread.
The application then proceeds to create windows, which will constitute the user interface. Before windows can be displayed on the screen, the different types of window classes need to be registered with the operating system. Window classes are templates that supply the details of how windows are to be created. In the window class registration process, windows are associated with a window procedure through which you can specify what the window displays and how the window is to respond to user input by determining how the window will respond to system messages.
Whereas a window is the primary form of communication between the user and the application, internal communications between the operating system, applications, and application components are conducted through various types of system messages. For example, when creating an instance of an application, the operating system sends a series of messages to the application, which responds by initializing itself. Keyboard and mouse activity cause the operating system to generate messages and send them to the proper application. The primary task of a Windows-based application can be seen as the processing of the messages that it receives. This processing involves the routing of messages to their intended target windows and the execution of expected responses to those messages according to the messages' types and parameters. It is the task of the application developer to map these messages to the functions that will handle them and to provide an appropriate response to the message.
Each thread of execution that creates a window is associated with a message queue. A message queue is a data structure in which the operating system will store messages for a window. All Windows applications have a main application window and all main application windows have a message loop. A message loop is program code that retrieves messages from the message queue and dispatches the messages to the appropriate window procedure. The window procedure might provide application-specific handling for the message or pass the message on to the default window procedure—a system-defined function that provides default processing for messages. For example, a message sent to notify the application that the user minimized the application's main window will be handled in the same way by virtually all applications. In such a case, the default window procedure handling is appropriate.
Figure 3.3 shows how messages are queued in the system and processed by the application. Notice how messages might be generated by the PostMessage() and SendMessage() functions as well as by hardware events. You might use these Win32 API functions or, more likely, their MFC counterparts CWnd::PostMessage() and CWnd::SendMessage() to send Windows messages to or from your application. The PostMessage() function places a message in the message queue associated with a window, and returns without waiting for the window to process the message. SendMessage() sends a message to a window and does not return until the window procedure has processed the message.
Figure 3.3 Windows NT message processing
Our discussion of Windows application architecture can be summarized by the following essential tasks that you must perform when creating a Win32 application:
This practice exercise will show you how to use Visual C++ to create a simple, non-MFC Windows application that illustrates how to implement the preceding five tasks.
In this lesson, you learned about the basic architecture of an application running on the Win32 platform and the basic steps required to implement a simple Windows application using the Win32 API.
A process can be defined as an instance of an executing program. Each process has at least one thread of execution known as the primary thread. When an application is run, a new process is created, and the address of the application's WinMain() function is passed to the operating system. The WinMain() code is run on the primary thread of the process.
A Windows application waits for messages generated by hardware events, system events, or other applications and components. Messages are processed by procedures associated with the application window objects. The developer provides these procedures in order to supply an application with its desired behavior.