Microsoft Foundation Classes-to-ViewKit Porting Strategy
by Ara Jerahian, Applications Engineering
Porting a Windows® application, written with the
Microsoft® Foundation Class (MFC) library, to a native
UNIX base is not a trivial task. However, with some thought
and help from APIs like ViewKit and tools like RapidAppTM,
the translation of your application structure can be
straightforward and the orientation of your objects can, for
the most part, remain unchanged.
The ViewKit application framework is a collection of
classes written in C++ that gives you access to commonly
needed facilities for applications based on Motif. RapidApp
is a user-interface builder that allows users to construct a
Motif interface interactively and to generate a C++ program
based on ViewKit. With these APIs/tools and some
knowledge of application framework paradigms, you can
efficiently translate MFC base Windows code to a ViewKit-based Motif application.
In this article, I will discuss the general mapping of some of
the base Microsoft Foundation Class application objects and
their respective constructs to ViewKit.
Base Classes and Windows
Quite often, different object-oriented application programming approaches can share many of the same concepts in their framework.
Table 1
lists some of the base application MFC objects and their appropriate ViewKit equivalents.
MFC |
ViewKit |
Concept |
CWinApp
InitInstance() |
VkApp
createWindows() |
Provides central facilities |
C[MDI]FrameWnd |
VkWindow/VkSimpleWindow |
Top-level window |
C[MDI]ChildWnd
PreCreateWindow() |
VkSimpleWindow/VkWindow
afterRealizeHook() |
Top-level window |
CDocument
UpdateAllViews() |
VkModel
updateViews() |
Application data object |
CView |
VkComponent |
The presentation of the data in a window |
Table 1: MFC Objects and Their ViewKit Equivalents
At the top of the MFC application hierarchy is the CWinApp
object. The CWinApp base class determines most of the
application's behavior. The equivalent in ViewKit is the
VkApp object. Programs for both cases instantiate a single,
global, derived "App" object from the base classes that
encapsulate the main event loop for the application. One of
the more important members in CWinApp is InitInstance(), a
virtual member function that makes the calls needed to
construct and display the application's main frame window.
VkApp does not share an equivalent member function, but
since a ViewKit application needs a user-defined main()
(one that's not hidden in the underlying API), you can call a
function you have defined in your derived VkApp object
(such as createWindows()) to instantiate and display your
main application window before calling VkApp::run() (also
from main()).
The CMDIFrameWnd (MDI stands for multiple document
interface) object represents the MFC application's main
frame window. In the ViewKit application, the main
application window will most probably be a VkWindow, but
can also be a VkSimpleWindow if a menu is not needed. In
MFC, most child windows of the CMDIFrameWnd will
reside within its confines. Each child window will be in an
active or inactive state, based on whichever has input focus
and is often determined by executing a mouse click in that
window. For SGI, this concept does not
translate easily if a user has Point-to-Type keyboard focus
set. Here, the window manager assumes a window is active
when the mouse pointer is moved over that window, thus
making it difficult for a main menu item to operate on the
"active" window. Thus, the effective scope of the main
VkWindow main menu should have global effects on all of
its child windows, which would basically be other top-level
shells controlled by the main window.
The CMDIChildWnd object represents the MFC
application's MDI child frame window. In the ViewKit
application, the child window will most probably be a
VkSimpleWindow, but can also be a VkWindow, once again
based on whether or not these child windows need menus.
Here, the effective menu scope should only be local to that
window, affecting only the data presented in that child
window. Child windows often include views that present
data to the user and allow interaction with the application
(refer to
"Model/View Architecture"
for more information).
The relationship of a single document interface (SDI) main
frame window and its single child window (CFrameWnd
and CChildWnd objects respectively) differ slightly in
translation to the ViewKit framework. Since there should be
only one instance of a child window in an SDI application,
these child windows are usually kept within the confines of
the main window. In the ViewKit/Motif world, this makes
the SDI child window merely a container within the main
frame of the application, like an XmForm or an
XmBulletinBoard. This container will exist within the
confines and extents of the main window.
Typically, MFC applications contain the application and
frame classes discussed above, plus two other classes that
represent the document and the view. This document-view
architecture is the core of the application framework and is
based on the Model/View/Controller (MVC) classes from
the SmallTalk world
(see Figure 1).
In simple
terms, the document-view (Model/View) architecture
separates data from the user's view of the data. An obvious
benefit is multiple views of the same data (such as stock data
with both a chart and a table view). The derived document
does the actual reading and writing of the document object's
data. The view class represents a window that is contained
inside a frame window (typically a child window to the
application); the derived class interacts with its associated
document class and does the application's display. In MFC,
documents are based on class CDocument and views are
objects typically derived from class CView that manages
user interaction with a document. The MFC framework
manages all interactions among documents, views, and
frame windows and the application object.
ViewKit follows a similar paradigm to support the MVC
architecture. It includes a VkModel abstract class that is
intended to be subclassed. This provides the data members
and any additional functions required to implement the
document. ViewKit components derived from VkComponent
can be used as both views and controllers. These views can
arrange to be notified of changes to the model by registering
a member function with the VkModel::updateCallback list
(this callback registration is automatically handled in MFC
when the virtual CView::OnUpdate function is overloaded
by the derived class). The callbacks on this list can then be
invoked when a subclass of VkModel calls updateViews()
(this is equivalent to the MFC
CDocument::UpdateAllViews() function). This method is
just a convenient way to invoke the functions on the
updateCallback list. Components used as controllers are
expected to send messages to subclasses of VkModel to alter
the state of the model. This protocol must be worked out
between the VkModel subclass and the controller
components. Views and controllers often work closely
enough that, in most cases, a single object can function as
both a controller and a view. This should probably be the
case if the MFC/ViewKit application object structure is to
remain the equivalent.
Figure 1: Relationships between Model, View, and Controller objects
Summary
The ViewKit application framework can be used to cleanly
port a Windows MFC application by understanding the
underlying elements shared between the two frameworks.
Both share the same concept of an application object,
windows, and the model/view architecture. The respective
objects can be easily mapped from one framework to the
other with the goal of minimizing changes to the overall
application structure. By using the ViewKit mappings
described in this article, your MFC application can be thus
cleanly ported to IRIX with few structural changes.
Reference
Young, Douglas A., Object-Oriented Programming with
C++ and OSF/Motif, 2nd ed., Prentice Hall, 1995.