Windows Architecture Common User Interface Share UI functional libraries Built-in dispatcher for windows / menus Windows Messaging Windows Messaging = Queued Input Usual DOS program would use polling Windows: all the messages are transferred to the responsible applications. No need to control and check the state of a device every single moment of time. All you have to do is to design the response. Independent Input/Output DOS: each application should have its own device driver Windows: shared GDI (Graphics Device Interface). The interface is responsible for the output. You should not think about the monitor’s model used. Event-driven Programming Usual DOS program: the main thing is main(). Hierarchical structure. Windows application: all the functions are designed to respond to the events. Events: mouse-click, timer, functions etc. It is not necessary to process all the events. We can let Windows respond to them. Ways of messages get generated Hardware level: interrupts. Responsible is: ISR (Interrupt Service Routine) ISR: input data gets formatted and stored Another internal subroutine then extracts the data stored in registers and places it into the messages into hardware queue of messages. Each event forces a new message to be created. Sometimes a set of events is reflected in one single message. Type of queue FIFO (first-in, first-out). Objectives of a message Messaging is a fundamental mechanism of communication between programs inside Windows. All the messages are generated by one of 3 different sources: 1. Hardware level events: kbd, mouse, timer. Often are called enqueued events since they always go through the hardware queue of messages. Objectives of a message 2. Dispatcher of windows. Messages are generated to reflect user actions – windows resize operation, cursor movement, menu selection. An example of an event sent more often – WM_PAINT which means that the current window should be refreshed (redrawn). Objectives of a message 3. Individual windows can also send messages to other windows. Example: a directive for a text window to be cleared: WM_SETTEXT. Text window uses the same mechanism to report about text changed event by sending EN_CHANGE. All the messages use mnemonic identifiers like WM (Windows Message), EN (Edit Notification) etc. All them (constants) are defined in windows.h Extraction of windows.h #define WM_NULL #define WM_CREATE #define WM_DESTROY #define WM_MOVE #define WM_SIZE … 0x0000 0x0001 0x0002 0x0003 0x0005 What the message actually is The message of Windows is a C structure called MSG that includes 6 different fields: Typedef struct tag MSG { HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; Description of a message HWND hwnd – each window in Windows has its own unique identifier. The value in this field represent the window descriptor the message is addressed to. UINT message – unsigned integer that keeps the identifier of a message (like WM_PAINT), representing the type of a message Description of a message WPARAM wParam – an additional information that can be found useful to process a message. For example it can keep the identifier of an item in a menu selected. Each type of a message uses this field on its own purpose. 32 bits. LPARAM lParam – is used like wParam, having extra information. 64 bits. Depending on the type of a message one (wParam) or both (wParam and lParam) can be used. Description of a message DWORD time – the value of the system clock of the moment the message was generated. This is used to place the message into the right position in the queue. POINT pt - cursor’s position on the screen when the message was generated. Windows Programming Ideology Using Software Developer’s Kit (SDK) which means use of Windows API MFC Windows Application’s Architecture Each application is a collection of windows What the window is? A square area that has properties and other areas. Client and non-client areas – each window has parts Windows is responsible for (nonclient area) and also parts your own application is responsible for (client area). Style of a Window WS_OVERLAPPEDWINDOW - is used for the “main” window, top level window. It can be resized and moved to any part of the screen. There is no parent window for such type of window. WS_POPUPWINDOW – is used for dialog windows. They usually have parent window, but can “flow” in front of the parent window and can be moved to any part of the screen. WS_CHILDWINDOW – is used for control elements. Command button is a child window the same way text window or scrolling bars are. It can be moved only in parent window’s area. WS_OVERLAPPEDWINDOW WS_POPUPWINDOW WS_CHILDWINDOW How does the program work (API) 1. Initialization 2. Realization 3. Calling the loop of messages 4. Responding to the messages Three first are always done by WinMain(). It is the entry point for any Windows program. The 4th task is implemented by function called WndProc() (actually can you call it the way you want, it does no matter. Inside the WinMain() - Initialization To define the class of the window choose the name of it like “MyWindowClass”. Then it should be associated with the style of a window (for example WS_OVERLAPPEDWINDOW) and with the procedure that will process all the messages for window class. When this is done, Windows will use your definition of a class as a template during the creation of an instance of your class on demand. Inside the WinMain() - Initialization To define a class an instance of WNDCLASS should be created first. WNDCLASS is a structure that incorporated different field that need to be filled. The most important fields are name of the class and address of the function (that will be created) to organize the responding action to the messages. Below is a short instance of such a code: static char MyClassName [] = “MyClass”; WNDCLASS wc; wc.lpfnWndProc = WndProc; wc.lpszClassName = MyClassName; // … all the other fields omitted Inside the WinMain() - Initialization WndProc was the address of the procedure that will receive the Windows message. Other 8 fields should be filled as well (like icon, mouse cursor type etc.) Windows takes the control. The process is called registration of a class and is performed by Windows API function RegisterCalss() : RegisterClass ($wc); Inside the WinMain() - Realization After the class is registered the window has to be created by calling API function CreateWindow() that receives 11 parameters. If CreateWindow() terminates successfully then the window’s descriptor is returned. Descriptor is used for future operations with window. An example follows Inside the WinMain() - Realization HWND hwnd = CreateWindow ( MyClassName, “ Hi Mom “, // title WS_OVERLAPPEDWINDOW, // style CW_USERDEFAULT, // left upper corner CW_USERDEFAULT, // left upper corner CW_USERDEFAULT, // width CW_USERDEFAULT, // height NULL, // parent NULL, // menu hInstance, // program’s descriptor NULL); // extra data Inside the WinMain() - Realization When the main window is created, couple more things should be done before your program can be executed. Initially your window is not visible. ShowWindow (hwnd, nCmdShow); hwnd - is the descriptor that was returned back by CreateWindow(). Second parameter, nCmdShow is one of the parameters, that WinMain() receives by itself. Values define is the window active, minimized or maximized. WM_PAINT has the lowest priority and it can take some time before the window will be actually shown by default. To force this action: UpdateWindow (hwnd); Which tell the Windows “do it now!” Inside the WinMain() – The loop Almost done but not yet – the message dispatching should be set since the program will take the messages and process them. GetMessage(). When it is called, it receives adm address of the MSG structure. If there is a message waiting in the line for your program to be processed, windows makes all the fields of MSG filled and the WinMain() gets the TRUE value. On the other hand if the WM_QUIT is waiting in the queue then GetMessage() returns FALSE and the program is terminated. Inside the WinMain() – The loop In general the loop will look like follows: MSG msg; while(GetMessage($msg,NULL,0,0,)) { // process messages } // terminate the process if the // GetMessage() has returned // us WM_QUITE message The real code TranslateMessage ($msg); DispatchMessage ($msg);