
Click above to get retro games delivered to your door ever month!
X-Hacker.org- The Guide to Clip-4-Win version 3.0 -
[<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
It's great to have a browser, but wouldn't it be better if you
could browse several files at once? Also, you might want to
browse the same file more than once.
Let's change the specification: now our browser has to be an
MDI application. Strictly speaking, MDI means Multiple
Document Interface, but in practice it's the style used for
lots of applications involving multiple windows that are all
contained in one outer ("frame") window. In any case, you can
say that looking at a browse isn't much different to looking
at a document!
Here's the new (still incomplete) specification:
(a) The browse application is a kind of MDI application.
(b) The application has a main window.
(c) The main window has a (bar) menu.
(d) The bar menu consists of popup menus and menu items.
(e) The menu contains an item to allow a browse to be started,
as well as standard items expected of Windows applications.
(f) The main window has a status (message) bar.
(g) More than one browse can be active at a time, even for the
same file.
Obviously a simple change? Yes, but there are some
shortcomings of the original version now that the spec. has
changed.
This time the source is in SOURCE\OO\BROWMDI.PRG. The
following are the changes that were needed.
The main() procedure has only been changed to add the word
"MDI":
oApp := BrowseApp{"Clip-4-Win MDI Browser Sample"}
BrowseApp is now inherited from WMDIApp instead of WApp:
CLASS BrowseApp INHERIT WMDIApp
METHOD Create(cText) INLINE ::oWnd := MainWindow{self, cText}
ENDCLASS
The class MainWindow is now derived from WMDIFrame:
CLASS MainWindow INHERIT WMDIFrame
The original version of the program simply used a work area as
any simple DOS program might. However, to allow the same file
to be browsed more than once you need either to open it more than
once or open it only once but save/restore the position etc.
when switching browsers. In the general case you could have
multiple files, indexes, filters, scopes, etc., in which case
saving and restoring settings gets very painful - and slow.
Instead, it's easier to open the file more than once.
There are a few caveats, though: you need a unique alias for
each work area, you need to take care about how you open the
file, and your operating system / network software has to
handle locks appropriately. This browser doesn't modify
records, so locks aren't an issue - a later example discusses
this, though.
Inventing a unique alias is basically a chore. One solution
is to use the Clip-4-Win class WTable, which already handles
this, along with some other things which aren't needed here.
Opening the file doesn't require any more care than the
previous sample: it's wise to use SHARED, as before.
To use WTable as a simple way to get a file opened in a new
work area, with a unique alias, the resulting changes to
method Browse() are essentially:
oTable := WTable{self, cFile}
cAlias := oTable:Alias
// . . .
oChild := ::CreateChild( , cTitle)
oChild:Client := WBrowseDef(oChild, , cAlias)
The WTable class defaults to SHARED, uses a new work area, and
opens the file allowing updates. It uses the current RDD,
unless you pass the RDD name to use. See the source in
SOURCE\OO\CLASSES\TABLE.PRG if you're interested in more detail.
The ::CreateChild( ) makes an MDI child window to contain the
browse that's created by WBrowseDef( ). CreateChild( ) is
conveniently part of WMDIFrame.
This particular example doesn't keep track of the browse
objects returned by WDBrowse, because it doesn't need to do
so. If you wanted to, you might add each new browse to an
array, perhaps making that array an instance variable of
MainWindow:
CLASS MainWindow INHERIT WMDIFrame
PROTECT aBrowsers AS ARRAY
// . . .
METHOD Init(oApp, cText) ;
INLINE super:Init(oApp, cText), ;
::aBrowsers := { }, ;
::StatusBar := WStatusBar{self}, ;
self
// . . .
ENDCLASS
Don't forget to initialise the array, e.g. as above.
Why would you make the array part of MainWindow? In OO terms,
this is an ownership (or containing) relationship: logically
the browsers are contained by the main window, so this just
looks the most appropriate place to keep them. If you feel
they belong elsewhere, put them there. However, take a look
at the discussion of OO Analysis/Design first...
The last thing that's changed in the move to MDI is MenuSetup().
MDI applications are supposed to provide two standard menus,
Window and Help, as the last two top-level (bar) menu topics.
The Help topic was already there, so the following has been added
(again, the line wrapping has been changed):
POPUP "&Window"
MENUITEM "&Cascade" ;
COMMAND Cascade ;
HELP WHelp{"Cascade child windows"}
MENUITEM "&Tile" ;
COMMAND Tile ;
HELP WHelp{"Tile child windows"}
MENUITEM "Arrange &Icons" ;
COMMAND ArrangeIcons ;
HELP WHelp{"Arrange Icons of Minimised Children"}
MENUITEM "Close &All" ;
COMMAND CloseAll ;
HELP WHelp{"Close all child windows"}
ENDPOPUP
You can just use the menu command MDIWINDOWPOPUP for the above.
Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson