Windows Systems Programming: Spring 2002

[ Home | Syllabus | Course Notes | Assignments | Search]


Windows Programming Model and C++

Some useful links


Console Window User Interfaces

SINGLE FOCUS OF USER INPUT <=> SINGLE POINT OF PROGRAM CONTROL

 


Graphical User Interfaces

Pioneering work of XEROX PARC (Palo Alto Research Center) 1970's


Some Implications

 


Visual C++ Development Environment

fig1.jpg (134691 bytes)


Multiple Locus of Control

Route input request to proper program segment

Last fits nicely with an object oriented approach using inheritance.

Complex windows "objects" can be built and reused easily.

 


Windows Programming Model

message2.jpg (34686 bytes)

There are about 200 Windows NT/9x messages.

Each message starts with "WM_"


Message Parameters

  1. HANDLE of windows to which message is directed
  2. Message ID: e.g. WM_PAINT, WM_LBUTTONDOWN
  3. wParam: 32 bit WORD parameter
  4. lParam: 32 bit long parameter

SDK style Windows Program

 // "C" program 
#include <windows.h> 

LONG WINAPI WndProc (HWND, UINT, WPARAM, LPARAM); 

int WINAPI WinMain  (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
// hinstance is HANDLE to this thread
// hPrevInstance (obsolete)
// szCmdLine - command line parameters
// iCmdShow - initial window mode

{
    WNDCLASS wc; 
    HWND hwnd;
    MSG msg;

    wc.style = 0;                                   // Class style
    wc.lpfnWndProc = (WNDPROC) WndProc;     // Window procedure address
    wc.cbClsExtra = 0;                              // Class extra bytes
    wc.cbWndExtra = 0;                              // Window extra bytes
    wc.hInstance = hInstance;                       // Instance handle
    wc.hIcon = LoadIcon (NULL, IDI_WINLOGO);        // Icon handle
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);      // Cursor handle
    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Background color
    wc.lpszMenuName = NULL;                         // Menu name
    wc.lpszClassName = "MyWndClass";                // WNDCLASS name

    RegisterClass (&wc); 
	

    hwnd = CreateWindow ( 
        "MyWndClass",               // WNDCLASS name
        "SDK Application",          // Window title
        WS_OVERLAPPEDWINDOW,        // Window style
        CW_USEDEFAULT,              // Horizontal position
        CW_USEDEFAULT,              // Vertical position        
        CW_USEDEFAULT,              // Initial width
        CW_USEDEFAULT,              // Initial height
        HWND_DESKTOP,               // Handle of parent window
        NULL,                       // Menu handle
        hInstance,                  // Application's instance handle
        NULL                        // Window-creation data
    );

    ShowWindow (hwnd, nCmdShow); 
    UpdateWindow (hwnd); // send WM_PAINT message

    while (GetMessage (&msg, NULL, 0, 0)) { 
// msg is a structure with 
//	hwnd
//	message ID
//	wParam,lParam
//	time
//	pt - mouse position
// returns false if WM_QUIT
        TranslateMessage (&msg);
	// have system perform keyboard translation on raw input 
        DispatchMessage (&msg);
	 //pass message back to windows which passes to appropriate window procedure
    }
    return msg.wParam; 
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
    LPARAM lParam) 
{
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message) { 
    
    case WM_PAINT: 
        hdc = BeginPaint (hwnd, &ps);
        Ellipse (hdc, 0, 0, 200, 100);
        EndPaint (hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage (0); 
        return 0;
    }
    return DefWindowProc (hwnd, message, wParam, lParam); 
}

Experiments


MFC

Encapsulates the WINDOWS API in about 200 C++ classes

mfcClass1.jpg (120272 bytes)


MFC Naming Conventions

Hungarian notation: prefix denote data type

ansf
Prefix DataType
b bool
c char
cx,cy distance hor/ver
dw DWORD
h HANDLE
l LONG
n int
p pointer
pt CPoint or POINT
str CString
sz zero-delimited string
w WORD
wind CWnd
m_ data member of class
lp long pointer

CObject

Mother of all Objects


Application Class Archtecture

CCmdTarget -> CWinThread -> CWinApp -> User Application

CDocument


Other Interesting Classes


Afx Functions

non-Class functions available to all objects


Let's build our first MFC application "by hand" to see all the parts
- later on we'll do the same thing using the appwizard of visual c++

Hello MFC: the header

(header file here)

//***********************************************************************
//
//  Hello.h
//
//***********************************************************************

class CMyApp : public CWinApp // derive our application
{
public:
    virtual BOOL InitInstance (); // Override this function 
};

class CMainWindow : public CFrameWnd // derive our window 
{
public:
    CMainWindow (); // override this too 

protected: // access these protected functions
    afx_msg void OnPaint (); // allows us to paint our own window 
    DECLARE_MESSAGE_MAP () // macro to set up Message Mapping 
};

Hello MFC: the implementation

(source file here) and (compilation directions here)

//***********************************************************************
//
//  Hello.cpp
//
//***********************************************************************

#include <afxwin.h> 
#include "Hello.h"

CMyApp myApp; // instantiate my application 

/////////////////////////////////////////////////////////////////////////
// CMyApp member functions

BOOL CMyApp::InitInstance ()
{
    m_pMainWnd   = new CMainWindow; // create a  new window and point to it
    m_pMainWnd->ShowWindow (m_nCmdShow);
    m_pMainWnd->UpdateWindow ();
    return TRUE; // FALSE would shut down the program 
}

/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions

BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd) // macros for defining the map 
    ON_WM_PAINT () // only message we need  to process 
END_MESSAGE_MAP ()

CMainWindow::CMainWindow ()
{
    Create (NULL, _T ("The Hello Application")); // use defaults for the other parameters 
}

void CMainWindow::OnPaint ()
{
    CPaintDC dc (this); // get a device context for "this" window 
    
    CRect rect;
    GetClientRect (&rect); // find out how big the window is 

    dc.DrawText ("Hello, MFC", // Draw this Text
	 -1, //  which is terminated by the null character
	 &rect,	// in this rectangle
        DT_SINGLELINE | DT_CENTER | DT_VCENTER); // on a single line in the center 
}

Message Maps

Correlates messages with member functions - set of MACROS
(could use "vtables" - virtual function tables - to but would be more expensive in memory).

  1. Declare Message Map
  2. Create and Initialize (identifies both base and derived classes)
  3. Override message member functions

Macros in "afxmsg_.h" add the appropriate entries in the message map.

Naming conventions:

MESSAGES: all caps start with WM_
e.g.
WM_PAINT

MemberFunctions: start with On use lower case except capitalize beginning of words
e.g.
OnPaint

MACROS: ALL CAPS starting with ON_WM_
e.g.
ON_WM_PAINT

Message Handling prototypes:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point)

These arguments are derived from the wParam and lParam in the message

Can add User defined Messages:

ON_MESSAGE(WM_SETTEXT, OnSetText)

ON_COMMAND: for menu selections

ON_UPDATE_COMMAND: to keep UI objects in sync

"afx_msg" is really commentary - implies virtual function override but outside vtable mechanism.

DECLARE_MESSAGE_MAP: usually last entity in class definition.

 


DECLARE_MESSAGE_MAP: under the hood

Adds three members to the class declaration:

  1. private array of AFX_MSPMAP_ENTRY structures named _messageEntries:
    contains info correlating message and their handlers
  2. static AFX_MSGMAP structure named messageMap:
    contains pointer to base class's messageMap structure
  3. virtual function GetMessageMap that returns address of messageMap

BEGIN_MESSAGE_MAP macro implements GetMessageMap function and initializes messageMap.

macros in between fill in the _messageEntries array

END_MESSAGE_MAP: adds NULL entry terminator

Thus:

// in the class declaration
DECLARE_MESSAGE_MAP( )

// in the class declaration
private:
	static const AFX_MSGMAP_ENTRY _messageEntries[ ] ;
protected:
	static const AFX_MSGMAP messageMap;
	virtual const AFX_MSGMAP* GetMessageMap( ) const;

// in the class implementation
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)

// in the class implementation
const AFX_MSGMAP* CMainWindow::GetMessageMap( ) const
	{ return &CMainWindow::messageMap;}
const AFX_MSGMAP CMainWindow::messageMap = {
	&CFrameWnd::messageMap,
	&CMainWindow::_messageEntries[0]
}

ON_WM_PAINT ( )
END_MESSAGE_MAP

const AFX_MSGMAP_ENTRY CMainWindow::_messageEntries[ ] = {
	{ WM_PAINT, 0, 0, 0, AfxSig_vv,
		(AFX_PMSG)(AFX_PMSGW)(void (CWnd::*)(void)) OnPaint },
	{0, 0, 0, 0, AfxSig_end, (AFX_PMSG) 0 }
};

 


Searching for a Message Handler

To Dispatch a Message:

msgMap.jpg (41188 bytes)


 


Copyright chris wild 1999-2002.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: January 27, 2002.