Resources

Designing Applications with Visual C++ 6.0

Microsoft Solutions Framework

Overview (27/02/2000)

Models, principles + practice to solve business problems

Team model (27/02/2000)

Only starting point, must adapt to own organisation.

Goals: customer satisfaction, delivery within project constraints, meet spec, release after identifying defects, enhanced user performance, smooth deployment

Team roles; product management, program management, development, test, user education, logistics management

Process model (27/02/2000)

Traditional approaches (can't meet needs of current application development.

Waterfall based on milestones - inflexible to changing requirements. Extended analysis periods

Spiral based on iterations - significant admin, frequent product releases -> feelings of instability.

MSF combines both approaches.

Four phases

Milestone driven

For review and synchronisation, not freezing.

Asses progress and identify corrections

Major milestones - externally visible (seen by customers)

Interim milestones - internally visible

Application model (27/02/2000)

Establish definitions, rules and relationships structuring applications

Basis for idea exchange during logical design

Multi-layer, service based approach

Application = net of cooperative, distributed reliable services

Service accessed through published interfaces

Application architecture (27/02/2000)

Conceptual view of application structure based on consumers and suppliers of services

Current apps (client/server) have 2 layers. Don't scale well. Fat clients (contains data processing logic, etc.)

3 layers

No implication of separate computers (although common)

Use of well defined interfaces -> creation of body of reusable components leading to rapid application development.

Highly scalable (provide additional business layer components to service more users)

Design process (27/02/2000)

Conceptual - view problem from business/user perspective to define problem and solution by scenarios. No account for approach or technologies need for solution. Model easily understood by user - analogous to rough house sketches.

Logical - view from project team to define solution as cooperating services. Produces abstract model of solution. Analogous to floor plans and elevations of a house. C++ developers particularly good here (principles of OO development similar to skills required at this stage).

Physical - view from developer's perspective to define services and technologies. Add detail to architecture and reflects real world constraints. Output used to produce components, ui, etc.

Phases overlap, their findings affecting each other.

Design considerations (27/02/2000)

Understanding of project among members of team = key requirement.

Must manage complexity - too little and relevant interactions missed, too much -> overly complicated design.

Modularity - start logical design identifying major system services (collection of processes working together to accomplish task).

Abstraction - distil properties + features of items. Classify items through common characteristics. Concentrate on main characteristics, ignore irrelevancies.

Encapsulation - "black box" performing limited, well defined functions correctly. Packages information (data + process) to only expose what should be seen (do not expose inner states). Expose component aspects via interfaces. Permits systems to be assembled out of parts (frequently pre-existing).

Cohesion & coupling - cohesion is how closely operations within a service are relegated. Aim for high cohesion -> easy abstraction + specification. Coupling applies to relationships between services. Weaker coupling ->freedom of design, limited impact on internal operations of services.

Separate interface & implementation - Interface hides implementation -> implementation to change without impacting rest of system. Developers must realise services provide capabilities that act as contracts of service to other modules. Design interfaces to be "open-ended" - if conditions of interface met then advertised service should be supplied.

Explain elements of applications based on MFC framework (12/3/2000)

MFC = C++ classes + global functions -> simplified, rapid windows app development.

Win32 API = common to all 32 bit Windows platforms. Services include; windows management, controls, shell features, GDI, system services, etc. Time consuming to develop apps via Win32 - hence introduction of MFC, e.g. concept of Windows encapsulated by CWnd.

MFC class member functions have same name as Win32 function they emulate.

MFC hides low level aspects of Windows programming - though access still available via Win32 if required.

Use MFC for all but simplest apps. Development advantages outweigh speed and size overhead. Apps without GUI may be easier to implement without MFC (though they may find MFC utility classes useful).

MFC encapsulates most, not all Win32 functionality. Use Win32 to access low level functionality (e.g. network security).

Platform considerations

Although all use Win32, each have unique characteristics. MFC helps hide many of these. For example NT based around Unicode, Winows95/8 on ANSI. By using TCHAR and associated routines (tcslen, tcscat, etc.) differences between character handling hidden. Differing screen coordinates -NT 32 bit, Windows 16 bit addressing.

MFC Class Hierarchy

Relies heavily on inheritance - CObject = base, provides basic services - serialisation, run-time class identification, diagnostics + debugging support.

CCmdTarget = base of class handling Windows messages.

CWnd = base class of object representing windows.

MFC Categories

Application architecture - basic application elements, e.g. CwinApp

User interface - Elements of apps visible to users. Also includes those encapsulating Windows device contexts and GDI.

Collections - Arrays, lists, maps, etc (both template & non-template)

General purpose - Don't encapsulate Win32 API functionality, e.g. data types - points, rects and strings

ActiveX - Framework to provide ActiveX support

Database - ODBC and DAO wrapper classes

Internet - WinInet APIs (client-side) + Internet Server API (ISAPI) (server side)

Global functions - Afx prefix. Provide general-purpose utilities - e.g. AfxMessageBox

Win32 Application Architecture (12/03/2000)

App consists of one or more processes, which are each, a container for one or more threads (one primary and additional secondary threads). When primary thread stops application terminates.

All Windows apps have an entry point called WinMain(). Once started the app proceeds to register window classes that provide details on how windows are to be created and react to system messages.

Windows Messages = method of communication between OS, application and application components. e.g. to start app the os sends a series of messages to which app responds by initialising itself. Primary task of Windows app is to process these messages - developer writes functions to handle appropriate messages.

Processing messages = each thread that creates a windows has associated message queue. All apps have a main application window and message loop. Message loop retrieves messages from queue and dispatches to handler functions. Unhandled messages passed onto default window procedure (provided by windows) that provides default behaviour (e.g. window minimisation). The PostMessage function sends message to queue asynchronously, while SendMessage sends messages synchronously.

Windows Application Essentials

WinMain function acts as entry-point to program

Register window classes ad associated window procedure

Create instance of applications main window

Implement message loop to relay messages to appropriate handling procedure

Implement window procedure to handle messages.

MFC Application Framework (19/03/2000)

Wraps Win32 API

Provides extra classes representing common application objects + their relationships -> fundamental application behaviour.

Basic framework

Regular vs Extension DLLs

MFC DLLs

Use MFC either through shared DLL or static library. If using dynamic both MFCxx.DLL and MSVCRT.DLL must be available - frequently shipped with app. Shared DLL -> smaller apps (sensible if installing many MFC based apps).

MFC Extension DLLS

If produce classes based on MFC classes and wish to use them in other apps it is common to export them in DLLs. To enable these DLLS to function correctly, e.g. allowing client apps to access functionality of base class the DLL needs to be packaged as an MFC Extension DLL. Option to create extension dll provided by AppWizard during project creation.

MFC Framework message handling

Win32 = supply own window procedure for each registered window class.

MFC = handled by member funcs of application classes (either own or AppWizard generated classes). Messages mapped to funcs by message maps.

Message map = table defined within class definition linking message IDs to handler functions. Recognised four types of messages:

Creating message maps

Any class derived from CCmdTarget can support message maps. Often can be maintained via ClassWizard.

Handler functions declared within special comment blocks


DECLARE_MESSAGE_MAP() macro:

//{{AFX_MSG(CMyApp)

    afx_msg void OnAppAbout();
    
    afx_msg void OnEditPaste();

//}} AFX_MSG

DECLARE_MESSAGE_MAP()

Message map exists between BEGIN_MESSAGE_MAP() and END_MESSAGE_MAP() statements of header file.

Commands mapped by macros within statement

Type Command Notes
Standard Windows ON_WM_XXX (XXX = msg name) None (handled by overloaded functions so don't need provide Handler name)
Command ON_COMMAND Command ID, Handler name
Update ON_UPDATE_COMMAND_UI Command ID, Handler name
Control notification   ON_XXX (XXX = control notification)   Command ID, Handler name

 

ClassWizard generated map entries within section bounded by {{AFX_MSG ... AFX_MSG}} - don't place own entries within this section.

If use ClassWizard to delete message map will remove entry from map + class declaration, but not implementation in .cpp file (as may contain your code).

MFC command routing -> handle message in class most closely associated with it. MFC framework routes commands through CCmdTarget derived objects to see which have handlers.

MFC Document / View Architecture (19/03/2000)

Coordinate application data + its views. Implemented by classes generated by AppWizard.

Document = container class for app data.

View = classes through which user interacts with document.

Document may have many views, changes made in one view reflected across all others.

Views may be implemented from scratch or derived from a control, e.g. trees, lists or edit boxes.

Same drawing logic can be used for both view and print systems.

State saving simplified -> MFC objects derived from CObject that implements serialisation functions.

Apps using document/view architecture derive most benefit from MFC, but MFC can be used without having such a structure.

Can have performance and size costs - not appropriate in all cases, e.g. text file compressor only needs dialog box - main frame window and views not required.

Document/View Objects + related MFC Base Classes

Type Class Notes
Document CDocument Application data
View CView Specifies how document data seen + interacted with
Frame window CFrameWnd Views displayed in frame windows. If SDI frame window = main frame for application.
Document template   CDocTemplate   Controls creation of documents, views and frame windows.
Application CWinApp Controls all above objects, specifies app behaviour (init, cleanup, etc.)

 

Document templates created (during InitInstance() by call to AddDocTemplate() ) + maintained by application object. Associates document class with resources, frame window and view. In MDI keeps track of open documents.

Document object loads, stores + manages app data + funcs to access/manipulate data. Maintains list of associated views, contains function to force all associated views to redraw them.

View represents client area of application. Presents info held in document + allows input via mouse/keyboard. Only associated with one document - provides accessor function to gain access to the document.

SDI / MDI Applications

SDI only one document frame window at a time - e.g. Paint, WordPad.

MDI multiple document windows open simultaneously within main window - e.g. Word, Excel.

Drawing and Printing Architecture (19/03/2000)

Graphics Device Interface (GDI) = output abstraction. Manages data structure called device context - maintains info about current device, e.g. palette, font, pen width, etc.

In MFC the CDC class encapsulates device context + GDI manipulation routines. Derived classes to support specific needs:

CPaintDC to paint invalid regions of client windows

CClientDC - represents client area of window

CWindowDC encapsulates whole window, including frame

CMetafileDC allows drawing to a metafile.

Output of app data handled by views OnDraw() - function must be implemented by developer (AppWizard only provides skeleton). Pointer to CDC passed to OnDraw(), through this device context drawing functions are called.

OnDraw() calls in the framework (26/03/2000)

Document data change -> redraw of view. Typically happens in response to change via a view. Code updating document data should call document member function UpdateAllViews()

Invalid view receives WM_PAINT message. By default handed by views OnPaint() that creates device context to pass to OnDraw().

Printing & Print Preview (26/03/2000)

Very similar to output to screen - GDI is hardware independent. Same functions called to output to screen, printer, etc. - just provide appropriate CDC.

Differences do exist - when printing must divide document into distinct pages shown one at a time, not just showing what is currently visible within a window. Must also be aware of paper size (legal, A4, etc.)

CView provides provides print-related functions to help implement printing.

Evaluate whether access to DB should be encapsulated

Many apps work with large amounts of data frequently managed by RDBMS, such as Oracle or SQL Server. Desktop databases, such as Access, work on similar principles to RDBMS and will often be employed by applications.

Data Access Interfaces

A number of access interfaces (DAO, ODBC, RDO, UDA, OLE DB, ADO) are available through Windows.

Previously strategy based on Data Access Objects (DAO) for access to desktop databases and Remote Data Objects (RDO) that used Open Database Connectivity (ODBC) to access RDBMS.

New strategy based around Universal Data Access (UDA) providing access to all data. Provides high performance access to both relation and non-relational data in a language independent manner. UDA is implemented through ADO that provides a high level interface to OLE DB (a new COM based data access technology).

Should always use UDA when developing new applications. Generally use ADO as it is easy to use, powerful and high performance. Experienced developers can use OLE DB directly for additional performance gains - VC 6 provides OLE DB Templates to ease this route.

Data Access Objects (DAO)

Native interface to Jet, originally designed for use with VB. Provides set of data access objects encapsulating common database objects - tables, queries, recordsets.

Used to access desktop databases such as Access, FoxPro, Paradox. Can be used to access remote sources.

Exposes COM interfaces, but usually encountered through the MFC DAO database classes.

Open Database Connectivity (ODBC)

Common API for client/server data sources, usually RDBMS (SQL Server, Oracle). Consistent interface -> maximum interoperability - same application can use many different RDBMS.

To connect to RDBMS require an ODBC driver supplied by the RDBMS vendor. To cover different RDBMS capabilities and driver implementations there are three levels of driver conformance available:

ODBC drivers installed and configured via ODBC Data Sources applet in control panel. Also used to register Data Source Name (DSN) that is a uniquely named collection of information used by ODBC Driver Manager to connect application to a particular ODBC database. DSNs must be registered on system that will use it - can be stored in a file (file dsn) or the registry (machine dsn). DSNs either installed for a user (user dsn) or computer (system dsn).

ODBC based on SQL. Data accessed from database using SQL statements. Driver translates SQL statements into format required by database.

Provides cursor library allowing iteration across rows of data returned by database.

Using the ODBC API can result in a lot of code, consequently models such as ADO, RDO or the MFC ODBC support classes are more commonly used.

Remote Data Objects (RDO)

Thin object layer to ODBC similar to that used by DAO but without memory requirements needed to support local database. Provides additional features such as server side cursors, disconnected recordsets, asynchronous processing.

Objects exposed through COM. The Data Source Control = ActiveX control encapsulating query and recordset retrieval. Permits browsing of recordset and display using data-bound ActiveX controls such as DBGrid and DBList.

OLE DB

COM interfaces providing uniform access to data stored in diverse information sources, regardless of location or type. Open spec to build on success of ODBC. Access to both relation and non-relational data sources - mainframe and desktop databases, e-mail, file systems, spreadsheets, project management tools, etc.

Three component types; data consumers, service components and data providers.

Data Consumers

Applications or components using data exposed by data providers. Any app using ADO is a data consumer.

Service Components

Process or transport data to extend functionality of data providers. Examples include query processors that generate or optimise queries, cursor engines that consume data from a sequential source to provide scrollable data.

Data Providers

Applications such as SQL Server, Exchange, etc. that expose their data to others. Provide OLE DB interfaces that data consumers or service components can access. A provider is available for ODBC thus making any ODBC data source available to OLE DB data consumers.

ActiveX Data Objects (ADO)

High performance, easy to use API to OLE DB. Small footprint, minimal network traffic and small number of layers between application and data source.

Expose COM Automation interface - accessible to all RAD tools, development tools, databases, scripting languages, etc.

Designed to combine best features of and replace RDO and DAO -> similar conventions.

Provides ADO Data Control - improved version of RDO Data Source Control.

Can transport over HTTP as well as DCOM -> data-centric web applications.

RDBMS Concepts

Currently dominant model for data storage. Stores information as collection of tables together with logical structure establishing relationships between them. Makes organisation of data easy to understand, provides relationally complete language for data definition, retrieval and update, provides integrity rules that define consistent database states.

Elements

Tables are logical groupings of related information made up of rows and columns. A row (or record) contains information about a single table entry (e.g. a book author). Each row consists of multiple named columns (fields) containing a single piece of information about that row, such as the authors first name.

To uniquely identify each row a primary key for the table must be defined. A primary key is a column that is guaranteed to be unique for all rows. RDBMS data integrity rules ensure no two rows can have same key.

Foreign keys define relationships between tables. Foreign key points to key field in a related table. Various relationships are possible - one to one, one to many or many to one.

Structured Query Language

Well defined, ISO standard language for queering, updating and managing RDBMS. Different implementations exist for each RDBMS, all with their own idiosyncrasies.

Via SQL apps can ask database to perform tasks for it, rather than requiring its own application code and processing cycles. Effective SQL minimises the amount of information transferred between the application and RDBMS.

Select

Returns information from database as set of selected rows. Three major sections:

e.g. SELECT * FROM titles WHERE royalty = 10

IN

Used within a WHERE clause to specify a list of acceptable values, for example to list all authors living in Utah or Tennessee issue

SELECT au_lname, state FROM authors WHERE state IN ('UT', 'TN')

BETWEEN

Used within WHERE clause to specify range of values that are acceptable.

LIKE

Used within WHERE clause to find values in a column that match the specified pattern (e.g. LIKE 'Smith' or with wildcards LIKE 'Sm%')

ORDER BY

By default rows are returned in the order they were entered into the database. Optionally can ORDER BY a specified column in ASC (ascending) or DESC (descending) order.

MFC Database Support

MFC provides support for DAO and ODBC. DAO generally used for desktop databases and ODBC to RDBMS.

Both sets of classes based on common programming model, classes often only differ in name + few minor implementation details.

ODBC Class DAO Class Function
CDatabase CDaoDatabase Connection to remote data source / desktop database
CRecordset CDaoRecordset Set of records selected from table in database
CRecordView   CDaoRecordView   Dialog based view directly connected to recordset object

 

CDatabase / CDaoDatabase

Establishes connection to data source. First create database object then call Open() method specifying DSN or database file name to access (based on type accessing) and access method (exclusive, read-only, etc.). For ODBC Microsoft recommend use OpenEx() to specify additional information, such as user name, password and extra options - such as whether to use ODBC cursor library.

CDaoDatbase contains features to make use of Jet functionality. For example can associate collection of CDaoTableDef object with CDaoDatabase - permit Jet tables to be created / modified.

Always Close() connection when finished - connections to data sources expensive.

CRecordset / CDaoRecordset

Comparable to document in document/view architecture - it holds data that a record view object displays.

Enable scrolling, updating (add, delete or edit), filtering, sorting, and paramterising with info obtained at run-time.

Contains member variables corresponding to columns in selected table. Variables update as user moves through recordset. Exchange of info between CRecordset and table columns in data source managed by RFX (Record Filed Exchange). CDaoRecordset exchange managed by DFX (DAO Record Field Exchange). RFX and DFX similar to DDX.

Recordset objects created in association with database object - pass address of latter to constructor of former. If using class derived from CRecordset can pass NULL to constructor, in which case a temporary CDatabase object is created and used by recordset. Can override GetDefaultConnect() to supply connection information to the temporary database object.

Once recordset object created, call Open() to submit query and populate recordset with its result, as in:

rs.Open(Crecordset::dynaset, "SELECT * FROM authors", CRecordset::none);

First param specifies type of cursor, choose from the following:

:

enum description
CRecordset::dynaset Dynamic scrollable record. Data order determined on open. Minimal memory usage - only store keys from result set. Show most changes by other uses, except for insertions.
CRecordset::snapshot Does not display changes made by others - use when wish to ensure data does not change while being manipulated.
CRecordset::dynamic Similar to dynaset, except all changes are visible. Heavy memory footprint.
CRecordset::forwardonly   Read-only recordset that can only be scrolled in forward direction. Fast and little memory requirements.

 

Second param is SQL statement to execute.

Third param is bitmask specifying if recordset properties, such as append-only, read-only, multiple row support, etc.

CDaoRecordset:Open() is very similar, but can only create dynaset, snapshot or Table recordset. Table recordset represents records from single table.

Must Close recordset object before the database object.

CRecordView / CDaoRecordView

Display data from recordset. Derived from CFormView - a view that represents application based upon dialog template.

Can connect dialog box controls to member variables of associated recordset.

Exchange of info between CRecordView and CRecordSet (same with DAO) handled by DDX/DDV. The CWnd::UpdateData() function being called from the view class's OnMove() - executed when user moves from current record. If recordset is not read-only then current record in recordset updated with provided values with RFX/DFX propagating changes to tables in data source.

Database errors

Accessing external resources (such as databases) carries risk of failure. Calls to open database connection or recordset should be in try...catch blocks.

MFC generates special database exception classes (CDBException and CDaoException), similar to CFileException, to provide info on failure.

Creating Database Application with AppWizard

Step 2 of AppWizard specifies database support:

Don't forget to specify data source.

AppWizard will add code to data source specified by step 2. The CMyDBAppSet::GetDefaultSQL() function provides the FROM portion of the SELECT statement.

The GetDefaultConnect() function specifies the data source. Can modify to provide authentication information - removes logon prompt when accessing database.

No CDatabase object created by framework. The CRecordset derived class is passed a NULL to its constructor, thus causing a temporary CDatabase object to be created and used.

Improve application efficiency by removing RFX attributes that are not required. These are columns in the tables being referenced that are not used by your application. Achieve this via ClassWizard, deleting the unwanted entries form the Member Variables tab for the recordset derived class.

Add fields to dialog box template and use ClassWizard to associate them with member variables of the CRecordset derived class.

Can use CRecordset directly if required (i.e. no need to create own derived class in order to access databases).

Filtering and Ordering

Filter by assigning a string specifying the WHERE clause to m_strFilter (defined in CRecordset).

Order by assigning string specifying ORDER BY clause to m_strSort (defined in CRecordset).

Introduction to ActiveX Data Objects (ADO)

Advantages

Easy interface to OLE DB. Exposes Automation objects that abstract OLE DB interfaces -> focus on task not interface. Use with any language that supports Automation - including scripts.

ADO recordsets can be disconnected from data source. These can be passed to other applications and updates made without requiring network traffic / connection to the data source. V. useful in web based apps.

Fewer objects + easier to use compared to DAO or RDO.

Not directly supported by AppWizard - must implement manually.

Object Model

Represents most commonly used features of OLE DB. Three main components:

Differs from DAO and RDO in that objects can be created independently of one another. ADOobjects stored in hierarchical format, but hierarchy de-emphasised - only create objects required for your problem, i.e. create Recordset, Connection or Command without having to create their parent object. ADO implicitly creates required objects for you.

ADO Collections

In addition to main objects, ADO supports 3 collection types:

The ADO Control

Graphical ActiveX control (with navigation buttons) providing easy-to-use interface to help create database applications. Creates connections between providers and data-bound controls. A data-bound control is an ActiveX control with these properties:

Fields of controls bound to ADO Control automatically updated as scrolling through recordset takes place.

To add to application use the Components and Controls Gallery - this will add icon onto controls toolbar and create C++ classes for your project that wrap its Automation interfaces.

Setting Control Properties from Source Code

Adding ADO Control and data-bound controls add several classes to project, such as CAdodc for ADO Data Control and CDataGrid for the data grid bound control both of which feature member functions to manipulate their properties.

Downloads