Windows NT Systems Programming

[ Home | Syllabus |Course Notes]


Graphical User Interfacing


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


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 (p.4-)

There are about 200 Windows 95 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

/*------------------------------------------------------------
   HELLOWIN.C -- Displays "Hello, Windows 95!" in client area
                 (c) Charles Petzold, 1996
  ------------------------------------------------------------*/

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM)  ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
// hinstance is HANDLE to this thread
// hPrevInstance (obsolete)
// szCmdLine - command line parameters
// iCmdShow - initial window mode
     {
     static char szAppName[] = "HelloWin" ;
     HWND        hwnd ;
     MSG         msg ;
     WNDCLASSEX  wndclass ; 

     wndclass.cbSize        = sizeof (wndclass) ;
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ; // redraw on Hor and Ver size changes
     wndclass.lpfnWndProc   = WndProc ; 
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; // predefined icon 
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; // paint background with this 
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     wndclass.hIconSm       = LoadIcon (NULL, IDI_APPLICATION) ;

     RegisterClassEx (&wndclass) ; 

     hwnd = CreateWindow (szAppName,         // window class name 
		            "The Hello Program",     // window caption
                    WS_OVERLAPPEDWINDOW,     // window style // normal style 
                    CW_USEDEFAULT,           // initial x position 
                    CW_USEDEFAULT,           // initial y position
                    CW_USEDEFAULT,           // initial x size
                    CW_USEDEFAULT,           // initial y size
                    NULL,                    // parent window handle
                    NULL,                    // window menu handle
                    hInstance,               // program instance handle
		            NULL) ;		             // creation parameters

     ShowWindow (hwnd, iCmdShow) ; // show window 
     UpdateWindow (hwnd) ; // send WM_PAINT message 

     while (GetMessage (&msg, NULL, 0, 0)) 
// msg is a structure with 
//	hwmd
//	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 ; // return code 
     }

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

     switch (iMsg) 
          {
          case WM_CREATE :
               PlaySound ("hellowin.wav", NULL, SND_FILENAME | SND_ASYNC) ; 
               return 0 ;

          case WM_PAINT : 
	           hdc = BeginPaint (hwnd, &ps) ; 

               GetClientRect (hwnd, &rect) ;

               DrawText (hdc, "Hello, Windows 95!", -1, &rect,
			             DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;

	           EndPaint (hwnd, &ps) ;
               return 0 ;

          case WM_DESTROY :
               PostQuitMessage (0) ; 
               return 0 ;
          }

     return DefWindowProc (hwnd, iMsg, wParam, lParam) ; 
     }

 


Programming Aids


MFC

Encapsulates the WINDOWS API in about 200 C++ classes

 


MFC Naming Conventions

Hungarian notation: prefix denote data type

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 Object


Serialize

void CBirthday::Serialize (CArchive& ar)
{
	CObject::Serialize(ar);	// serialize base class
	if(ar.IsStoring)
		ar << m_day << m_month << m_year;
	else
		ar >> m_day >> m_month >> m_year;
}
// CDocument provide the CArchive for you

AssertValid

#ifdef _DEBUG
void CBirthDay::AssertValid() const
{
	CObject::AssertValid();
	ASSERT (m_day > 0);
	ASSERT (m_month > 0);
	ASSERT (m_year > 0);
	ASSERT (m_day <= 31);
	ASSERT (m_month <= 12);
}
#endif

 


Dump

#ifdef _DEBUG
void CBirthDay:: Dump (CDumpContext& dc) const
{
	CObject::Dump (dc);
	dc << "Birthday =" << m_month << "-" << m_day << "-" << m_year <<endl;
}
#endif

Application Class Archtecture

CCmdTarget -> CWinThread -> CWinApp -> User Application

CDocument


Other Interesting Classes


Afx Functions

non-Class functions available to all objects


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, "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 mssage 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:

See figure 1.5 p. 40


Copyright chris wild 1997.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: September 15, 1997.