19-intro to mfc - simon fraser university to mfc.pdfmfc versus swing the obvious difference - mfc is...
TRANSCRIPT
CMPT 212Introduction to MFC andWindows Programming
Spring 2007
What is MFC?
MFC: Microsoft Foundation Classes MFC is a framework built on top of standard
windows C++ libraries Provides the user with a number of classes
that make windows programming easier
Windows Programming Based on event-driven architecture Console applications - the program tells (“drives”)
the user when and what to enter Windows applications - the user “drives” the
program by interacting with it The program thus interacts with the user by
handling events and waiting for new events fromthe user
What Does This Mean to theProgrammer? Flow of logic is no longer as explicit Need to design the system more carefully to ensure
it always behaves in a graceful and reasonablemanner no matter what the user does This applies to console applications as well, however since
the user actions are typically less restricted in Windowsapplications this means the code has to handle more useractions appropriately
MFC versus Swing The obvious difference - MFC is for Win32 C++, Swing is for
Java MFC is an abstraction / improvement of Win32 GUI
programming Swing is an abstraction / improvement of AWT Swing is considerably younger than MFC, and as such is
easier to use and is more elegant Swing has listeners, MFC has message maps
One of the reasons why MFC is uglier / trickier MFC has its own “resource definition language”; Swing does
not
Event-Driven Programming inWindows (1 / 4) Done by using a message map:
A message map is a mapping of possibleactions(message identifiers) the user can do to messagehandlers - functions that handle the messageappropriately
The coder defines what messages the applicationshould listen for and what message handlers to call
Event-Driven Programming inWindows (2 / 4) Does the coder have to handle all types of
messages? No, Windows provides default message handlers for all
standard message identifiers (for the particular objects,like windows)
User can override this behavior Coders can also define their own message
identifiers and the corresponding message handlers
Event-Driven Programming inWindows (3 / 4) A message map looks like so:
BEGIN_MESSAGE_MAP(ownerClassName, baseClassName)…// Mappings go here
END_MESSAGE_MAP()
A default mapping:ON_WM_PAINT() // Calls OnPaint()
A custom mapping:ON_COMMAND(ID, foo) // Calls foo()
Event-Driven Programming inWindows (4 / 4) When to override default message handlers (such
as OnPaint())? When you want to provide different functionality, such as
your own way to paint a window ON_COMMAND(), used with user-defined message
identifiers, is commonly used for handling menuselections
We will come back to these in a bit
The Hungarian Notation Used to make variable names
more explicit - prefix doubleswith a ‘d’, classes with a ‘C’,etc
Makes it easier to read thecode (if you know what theprefixes mean, of course)
The table on the right is frompage 32 of your MFC textbook
ar - array b - BOOL/bool c - char C - class d - double l - long lp - long pointer m_ - class member variable n or i - integer p - pointer s - string sz - string with null termination s_ - static class member
Creating an MFC Project inVC++ 6.0 (1 / 4) Select “File -> New…” from the menu Click on the “Projects” tab Select “Win32 Application” and fill in the project
name / location Do not use Wizards, select “An empty project” on
the next screen and click “Finish”
Creating an MFC Project inVC++ 6.0 (2 / 4) Add a .h and a .cpp file As usual, your .h file should contain the specification and
.cpp the implementation Enable MFC (Project -> Settings -> General -> Microsoft
Foundation Classes -> Use MFC in a Shared DLL) In your .cpp, #include <afxwin.h> Code your program, extending existing MFC classes such as
CFrameWnd and CWinApp
Creating an MFC Project inVC++ 6.0 (3 / 4) The class that extends CWinApp is the one
responsible for launching your application (it is theentry point)
Typically it is very simple - it opens the mainwindow and passes control to it
You can do other initialization here such as settingup data structures
Creating an MFC Project inVC++ 6.0 (4 / 4) Typically you will have a class that extends
CFrameWnd, this is the class that is responsible fordisplaying a window
In the simple example from the textbook, this classcreates a window with a textbox in the center
Closer Look atthe Example (1 / 3)BOOL InitInstance() {
m_pMainWnd = new CWelcomeWindow();
m_pMainWnd->ShowWindow( m_nCmdShow );
m_pMainWnd->UpdateWindow();
return TRUE;
}
Overrides the default InitInstance() from CWinApp Creates a new window, displays and updates it Returns TRUE to signify success of initialization
Closer Look atthe Example (2 / 3) Create(NULL, "Welcome", WS_OVERLAPPEDWINDOW,
CRect(100, 100, 300, 300)); Creates a standard window (the NULL and the
WS_OVERLAPPEDWINDOW flag) with title “Welcome”, withits top left corner at (100,100) and bottom right at (300,300)
Just as in Java (0,0) is the top left corner, y-coordinateincreases as you go down and x-coordinate increases as yougo right
Closer Look atthe Example (3 / 3) m_pGreeting->Create("Welcome to Visual C++
with MFC!", WS_CHILD | WS_VISIBLE |WS_BORDER | SS_CENTER, CRect( 40, 50, 160,100 ), this);
Creates the window holding the text “Welcome to …”; theother arguments are the window style (note the ORed flags),location, and owner
In this particular case the style is child window, visible, with aborder and with centered-text justification by default
Menus andResources (1 / 4) When a menu item is selected it sends a programmer-
defined message These messages are typically prefixed with “IDM_” (M for menu) Need to be defined somewhere Defined as macros using #define, not const Programmer-defined messages should have values between
1024 and 65545, 0 - 1023 are reserved for windows messages They are then handled by adding appropriate entries to the
message map
Menus andResources (2 / 4) To handle a particular message the programmer
should add the following to the message map:ON_COMMAND(IDM_MSGID, DoSomething); When the message with id IDM_MSGID is received, the
method DoSomething() is executed Can also handle a range of messages:
ON_COMMAND_RANGE(START, END, Process);
When the message with id between START and END isreceived, the method Process(UINT id) is executed
Menus andResources (3 / 4) Defining a menu:
Can either write the resource file by hand or use the VC++IDE interface
Looking at the source of the resource file:Food MENU{
POPUP "File"
{MENUITEM "Exit", IDM_EXIT}
…} Defines the “Exit” item of the “File” menu and assigns it
IDM_EXIT id
Menus andResources (4 / 4) A menu with two items:
POPUP "Beverage"{
MENUITEM "Ginger Ale", IDM_GINGERALE
MENUITEM "Root Beer", IDM_ROOTBEER
}
Similarly, creates a “Beverage” menu with items “Ginger Ale”and “Root Beer” with corresponding IDs
A single resource file may contain more than one menu Resource files are written in resource definition language that is
actually not C++ More on resources later
Revisiting theMessage Map (1 / 2)
For the menu example, the map looks likethis:BEGIN_MESSAGE_MAP(CMenusWin, CFrameWnd)
ON_COMMAND(IDM_EXIT, OnExit)
ON_COMMAND_RANGE(IDM_CHICKEN,
IDM_ROOTBEER, OnDoFood)
…
END_MESSAGE_MAP()
Note the mapping from message identifier(s) tothe message handler
Revisiting theMessage Map (2 / 2)
A small modification is required to thecorresponding .h: Need to add DECLARE_MESSAGE_MAP() to the
end of the class declaration This refers to the message map in the .cpp file Why?
MFC preprocessor “magic”
ON_COMMAND
An example of how to use ON_COMMAND:afx_msg void CMenusWin::OnExit()
{
SendMessage(WM_CLOSE);
}
This particular example exits the program. It doesso by sending another message that is handledby the parent class, namely the “close window”message
ON_COMMAND_RANGE
An example of how to useON_COMMAND_RANGE:afx_msg void CMenusWin::OnDoFood(UINT nFood) {
switch (nFood){case IDM_CHICKEN: tally(m_nChicken, 2.25); break;case IDM_FISH: tally(m_nFish, 1.80); break;…}}
MFC Conventions forMessage Handlers
Prefixed with afx_msg Begin with “On” and followed by the
message type (e.g. “Exit”) No parameters, return type is void For ON_COMMAND_RANGE, as we’ve just
seen, takes in a single unsigned integer asits sole argument
Dialog Boxes (1 / 3)
Typically used to either get small pieces ofinformation from the user (e.g. username /password) or to report progress / error to theuser
Are less flexible and simpler than regularwindows
To make a dialog box in MFC your classshould extend CDialog (rather thanCFrameWnd as before)
Dialog Boxes (2 / 3)
Often dialog boxes are displayed as modal -while the dialog is open no other window ofthe particular application can gain focus This is referred to as application modal In some special applications you might encounter
system modal dialogs - you cannot do anythingelse until these are closed As you have probably guessed these should be used
only when absolutely necessary
Dialog Boxes (3 / 3)
Not very different in terms of code incomparison to windows: Inherit CDialog (instead of CFrameWnd) Define a message map and the necessary ids /
handlers Define an entry point as before (a class that
inherits from CWinApp and overridesInitInstance())
CEdit and CButtonControls (1 / 3)
The third example in the textbook introducesthese two controls and uses them in a dialog
CEdit is the basic edit text box (thinkJTextField, from Swing)
CButton is the basic button (think JButton,from Swing)
CEdit and CButtonControls (2 / 3) Both inherit from CWnd, and as such support some
common operations such as getting and setting thecurrently displayed text: GetWindowText(buffer, size);
SetWindowText(buffer);
Of course the way the text will be displayed isspecific to the given component: Button simply displays the text Edit text box allows you modify this text by interacting with
it
CEdit and CButtonControls (3 / 3)
Having a look at the resource file (availablein the book / online) we see that: IDC_NUMBER is an edit text box that supports
numbers only IDC_ADD is a default button for this dialog IDC_TOTAL is a read-only edit text box that does
not have a tab-stop IDC_CLEAR is a regular button that does not
have a tab-stop
itoa() and atoi() These two functions have a very simple
purpose Translate from an integer to a C-style string (itoa
= int to “string”) Translate from a C-style string to an integer (atoi
= “string” to int) Handy for quick conversions, but not hard to
write your own (e.g. using stringstream orsprintf())
Not specific to MFC alone
Grabbing Controlsfrom a Dialog (1 / 2)
Allows to get a handle to a control inside thecurrent dialog window Grab the IDC_NUMBER edit text box: CEdit *pNum = (CEdit *) (GetDlgItem(IDC_NUMBER));
Can also use the overloaded version onregular windows by passing it the pointer tothe parent window as the first parameter,followed by the id
Grabbing Controlsfrom a Dialog (2 / 2)
Once you have the pointer to the control youcan use it to manipulate the control:pNum->SetWindowText( "" ); // clear inputpNum->SetFocus(); // next input to Number
This is handy, as you don’t need to define aclass member for every single control thatyou might need to access at some point inyour code