What this does then is basically to emulate the functionality of the program that is initially produced when you first run AppWizard, and so may act as the basis of an SDI WinApp.
It don't do much, but it still does a bit more than a pure generic template should, since there is some code included to allow the rescaling of the scalable area either with a dialog box or by clicking and dragging with the mouse in the are itself. These will probably be taken out before any other coding starts and so maybe shouldn't be there in the irst place, but they are, so there.
This code should be fairly readily understandable by most people with a good grounding in C++ although of course the details of the Classes will need explanation.
The Model class will contain everything concerned with data and data processing. For example, in the case of a wordprocessor these will be dealing with the document itself and will include things such as loading and saving from disk, arranging the document in memory and retreiving, setting or altering parts of the document.
The View class will contain the bulk of the functionality connected with the GUI. This means essentially drawing the contents of the window and also handling events such as key presses and mouse clicks and drags. There may be more than one view to allow the data to be looked at in different way i.e. in the case of a spreadsheet as a table or a graph. There may also be some dialog boxes connected with the App, these may be thought of a sub-views (see also about the Resource File below).
Finally, bringing everything together is the Controller. Classicaly it's a single class which sets up and runs the App and then acts as the interface between the OS and all the various other parts of the program. However, due to the nature of MS-Windows, these two things are carried out by different classes, and so there is no Controller class as such, but instead, all of the various bits are stuck in the Controller module.
The way in which the Controller acts as the OS-to-program interface is as follows: WinApps are event driven. That means that for a lot of the time they may be sitting there doing nothing, but every so often the WinOs will send a message to notify them that something has happened (an Event) to which they must respond.
These Windows messages are normally defined as WM_SOMEMESSAGE and may be things like WM_KEYPRESSED, WM_MOUSEDRAGGED, etc. The Controller then will need to be able to intercept all of these various Windows messages that get sent by the OS and then it must decide what to do i.e., which particular function should be called to handle what. This is done by the Message Map which simply maps one Window Message to one function (see the Controller section below for more on this.)
Finally there will need to be some other miscellaneous items, such as a Windows Resource (*.RC) file to include information on things like dialog boxes, icons and menus, and also all the various other modules and classes which may be utilised by any or all of of the MVCs.
In figure 1 this interaction is shown diagramatically.
________ __________ | | | c:\ | | dialog | _________ | | | boxes | | | | | |________| ----| model | |__________| ____ _____|______ / |_________| _|__|_ | | | |--- | |______|----| OS |---| controller | | __________ |____| |____________|--- ____|____ | :::::::: | | \ | | |__________| -----------------------------| view | |_________| FIG. 1 The interaction between the Controller, Model View and OS.
[i] First of all it's not even stricly true. If you create program called 'draw' with AppWizard, as well as the drawdoc.cpp and drawview.cpp there is also a draw.cpp which does in fact do a lot of the usual controller functions.
[ii] Secondly, the message map is spilt into two parts, one in drawdoc.cpp and one drawview.cpp, and this is quite simply, an increadibly stupid thing to do. The message map is the true core of the Controller. It takes the raw messages from the Windows OS and decides which function in which class should handle them. Even in something as simple as the Scribble App outlined in the MSVC Welcome Guide they come across problems with this, when they realise that one of their messages does not neatly go into either.
[i] First of all the OS will send message to the Controller that a click and drag with the mouse is occuring.
[ii] The Controller will have to call the View to tell it to handle this click and drag.
[iii] The View will need to redraw the Window with the selected text marked out somehow (noramlly in inverse video.)
[iv] Everytime the mouse is moved a little bit, [ii] and [iii] will be repeated.
[v] Once the button is released the Controller will be informed and will need to call the View in order to find out which text has been selected.
[vi] When the selected text is cut Controller must first tell the Model to remove the text from the document and then tell the View to redraw the screen using this updated document.
See here for a walk through of part of the
Model code.
I've tried to make the drawing as generic as possible. Figure 2a shows the three main screen areas and Fig. 2b attempts to demonstrate how the scrollabel window looks at these one segment at a time.
____________________________ ____________________________ | | | ======================== | | table | | |=======================|| | | __________________ | | || __________________ || | | | | | | || | | || | | | page | | | || | | || | | | | | | || | | || | | | _____________ | | | || | _____________ | || | | | | | | | | || | | | | || | | | | frame | | | | || | | | | || | | | | | | | | || | | | | || | | | | | | | | ======================== | | | |_____________| | | | | |_____________| | | | | | | | | | | | | | | | | | | | | | | | | | | | |__________________| | | |__________________| | | | | | | | | | |____________________________| |____________________________| Figure 2a: The three main Figure 2b: A scrollable parts of the screen Window overlaying the screenThere are three main regions to the viewable area are the 'table' 'page' and 'frame'.
i. The page is the main drawing area. What goes on here is what gets printed, which is after all normally the end result of everything. The units are in 0.1mms and the origin is the top LH corner with the y-axis positive pointing down.
ii. The purpose of the table is to set the page neatly on the screen and to help setting the scrolling area of the window. It has the same units as the page and the origin is simply that of the page with an added offset.
ii. Finally, the frame gives a scalable drawing area, that allows the axes to be set to any value, direction e.t.c. This same thing could have been implemented by using various windows commands to the make the Window itself all scaled, but this then stops a lot of other commands working, for example, setting the origin at the bottom LH corner means that any region commands (such as IsPointInRegion()) no longer work.
See here for a walk through of part of the View
code.
In MFC this is done by a derived CWindow class, which is separate to the main application class, CApp. However, they are both put in the Controller module since they both most logically seem to fit here.
See here for a walk through of part of the
Controller code.
Well, actually no, as they do in fact sort of fit in correctly to the framework. They can be thought of as mini self-contained views that do their own little jobs and also possibly exchange data with either one of the Model, View or Controller. As an example, a File Open dialog box will pass back the name and path of the file to be opened, allowing the actual file opening to be be carried out by the Model.
This idea of multiple views is in fact completely kosher and is fundamental to the MVC way of thinking. Most large WinApps will have a single Model class, but several View classes to allow the data to be examined in different ways. For example a spreadsheet will have the grid View for typing in and modifying data but then also several other Views to represent the same data as graphs of varying types (pie, block, line etc.) By separating the Model and View we have a convenient way of eliminating code overlap.
Each dialog box has it's own class and of course Window set up. The Windows are not drawn so much as defined in the Resource (*.RC) file using a sort of pseudo code. The good news though is that almost every Windows compiler comes with a nice little App which allows these to be created graphically, usually by dragging elements (buttons, list boxes, etc) into place and giving them an ID. Once back in the code you simply call the required MFC function with the element's ID as a parameter and off you go manipulating data at will. This all leads to a relativly straight forward way of getting it done. A bit like Visual Basic really!
click here to download a ZIP of the WinApp Template code.
It should compile on any version of MSVC from 1.52 (the most up to date
16 bit version) upwards to whatever it's at now (5.0, 6.0??). This
code will however be most stable on any 32 bit version, most of the
work I've done has been on MSVC 2.0 for no reason other than I happen
to have a full registered copy of it.