Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- The Guide to Clip-4-Win version 3.0 - http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
  
  Let's take a look at a simple example in the directory
  SOURCE\OO.  The example concerned is a simple DBF browser,
  whose source file is BROW.PRG.  If you want to try it, the
  easiest way to build it is to use:
            RMAKE  /dNORC  BROW
  (This ignores any resource compiler you may have.)
  
  Before discussing the source, here's a way to describe this
  application in a form that's easy to refer to later.  Some or
  all of it should be obvious, as should the fact that's it's
  incomplete:
  
  (a) The browse application is a kind of 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.
  
  In each of the above, instead of "has" or "consists of" you
  could say "owns" or "contains".  These are major guides from
  an OO point of view, as you'll see.
  
  Looking at the source, you'll see that the main procedure is:
  
       procedure main()
       local     oApp, oWnd
  
       oApp := BrowseApp{"Clip-4-Win Browser Sample"}
       oApp:oWnd:MenuSetup()
  
       oApp:Start()
  
       oApp:Quit()
  
       return
  
  This code first creates an application object, oApp, of the
  class BrowseApp.  The details of BrowseApp are discussed in a
  while, but one of the actions carried out is to create a
  window.  Next, the above code sets up a menu for the
  application's window.  You can then see that oApp's Start()
  and Quit() methods are invoked, and that's it.
  
  Here's the class BrowseApp, which shows how it sets its oWnd
  instance variable to the MainWindow object:
  
  CLASS BrowseApp INHERIT WApp
       METHOD Create(cText)     INLINE ::oWnd := MainWindow{self, cText}
  ENDCLASS
  
  The WApp class is one of the Clip-4-Win Application Classes,
  and can be found in SOURCE\OO\CLASSES\APP.PRG.  Its Init()
  method invokes its Create() method, which is overridden in
  BrowseApp as you can see above.  The Init() method does a
  number of other things, all of which are fine here, as they
  are in many applications.
  
  From the above you can deduce that WApp shold have an oWnd
  instance variable (it has), and MainWindow's Init() expects
  to be passed the application object and a string.
  
  
  This is the first part of the class MainWindow:
  
  CLASS MainWindow INHERIT WSDIWindow
       METHOD Browse()
  
       METHOD Exit()                                     ;
            INLINE ::oApp:Quit()
  
       METHOD Init(oApp, cText)                          ;
              INLINE super:Init(oApp, cText),            ;
                     ::StatusBar := WStatusBar{self},    ;
                     self
  
       METHOD MenuSetup()
  ENDCLASS
  
  This is simple enough - but you need to know more.  You need
  to know about the class WSDIWindow, and you need to know about
  the methods Browse() and MenuSetup().  There's also the
  class WStatusBar, which in this example is only used to
  display single-line help information for menu items.  Its
  source is in SOURCE\OO\CLASSES\STATBAR.PRG.
  
  
  The WSDIWindow class (in SOURCE\OO\CLASSES\SDIWIN.PRG) is a
  kind of WFrameWindow, which itself is a general-purpose window
  with default mechanisms for any or all of: a menu, a toolbar,
  a client window, a status bar.  The differences provided by
  WSDIWindow are there to make it more specific: it's intended
  to be an application's main (or only) window.  (The more complex
  requirements of an MDI application are discussed later.)
  
  The Browse() method is straightforward, and is essentially
  some declarations (shown as ". . ." below) and error checking,
  together with this:
  
       METHOD Browse() CLASS MainWindow
       local     cFile, oBrowse
       local     cTitle, cAlias
  
       if (cFile := GetOpenFileName( , "*.dbf", "Select a database")) == nil
            return nil
       endif

       if select(StripPath(cFile)) == 0
            use (cFile) new shared
       else
            select (select(StripPath(cFile)))
       endif

       cTitle  := "Clip-4-Win Browse - " + cAlias

       oBrowse := WBrowseDef( self, cTitle, cAlias )
  
       return self
  
  The file is opened SHARED because that's the mode you normally
  want: you should really be programming all Windows apps as
  potentially multi-user.  After all, it's a multi-tasking
  system.  Don't be too surprised if your users want to run the
  same application more than once.
  
  In the above, WBrowseDef( . . . ) returns an object for the browse
  window it creates.  (The source code is in SOURCE\WBROWDEF.PRG.)
  
  This leaves the MenuSetup() method.  The lines may be wrapped
  differently here, but the code is:
  
  METHOD MenuSetup() CLASS MainWindow
  
  MENU IN self
      POPUP "&File"
          MENUITEM "&Browse..."                                         ;
              COMMAND Browse      HELP WHelp{"Browse a file..."}
          MENUITEM SEPARATOR
          MENUITEM "E&xit"                                              ;
              COMMAND Exit        HELP WHelp{"Exit the application"}
      ENDPOPUP
      POPUP "&Help"
          MENUITEM "&About"       HELP WHelp{"About this application"}  ;
              ACTION MessageBox( , "Demo written by John Skelton",      ;
                                   "About", MB_ICONEXCLAMATION + MB_OK)
      ENDPOPUP
  ENDMENU
  
  return self
  
  Some explanations: menus use "&X" to mean an item with an
  underlined "X" that is selected if you type Alt+X; the
  optional HELP clause can put the text in the status bar, if
  you have one; COMMAND and ACTION are similar, but COMMAND
  means a method will be invoked, whereas ACTION evaluates a
  code block.
  
  The COMMAND facility is more powerful than ACTION, as Clip-4-Win's
  Application Classes will search up the owning classes looking
  for the named method.  This is analogous to the way
  inheritance works: you can handle the command at the most
  appropriate level.  When the COMMAND's method is found, it is
  invoked with the relevant object as "self" and the menu item
  as a parameter, in effect as if the menu handler executed
  oTheObj:TheCommand( oMenuItem ).
  
  ACTION is best used for very simple things that really don't
  need the COMMAND mechanism.  In this example, Exit is so
  simple that it could be an ACTION, but most applications have
  rather more to do when asked to exit.
  
  Here, menus are implemented as classes, although the commands used
  above in MenuSetup() don't allow you to see this is so.  This
  is one of the unfortunate consequences of using the above
  "command-oriented" style.  The syntax was chosen to be like
  that used by resource files (and also VO).
  
  Before delving into the OOA/D behind this application, let's
  try a more ambitious version of this app.
  



Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson