Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- FUNCky - Norton Guide http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]

  It is possible to set up an internal buffer area called the mouse stack
  so that the user can use the mouse to point and click on the get they
  want to edit. The mouse get system comprises a few routines that
  interact with each other in order to allow the user to click on gets.
  Clipper never intended to have mouse support so a few programming
  considerations had to be overcome. The first problem is determining
  where the gets are on screen. This is accomplished via the function
  m_stack(). m_stack() is an internal memory buffer area where you define
  the screen regions that will allow a get to be activated if the mouse
  cursor is in one of those regions when the button is clicked. The
  m_stack() function has room for 75 entries. each entry contains 5
  parameters, the first parameter is the get number that entry is
  associated with. The next four entries are the row/col coordinates that
  define the region that the mouse cursor has to be in when the user
  clicks on the button to activate the get defined in parameter one.
  The stack must always be in sequential order. If an entry contains a -1
  then the end of the stack is assumed and no more checking is done.

  The call to m_stack() would be defined as follows:

        m_stack(<get #>,<top_row>,<left_col>,<bot_row>,<right_col>)

  When you define your gets, you usually have a prompt associated with
  each get, whereas:

        @ 10,0 say "Enter Name: " get Fname

  The prompt would be at row 10, column 0, and would say:

        Enter Name:

  The area just after the prompt would be highlighted or delimited so that
  the user can fill it in. Since this is the first get you defined in the
  program, it is also the first entry you would define in your m_stack().
  To initialize the mouse get stack requires that you first initialize it
  with the m_stacknew() function. m_stacknew() simply fills all 75 places
  with -1, which denotes the stack is empty. The length of the prompt in
  the example is 12 characters long starting at row 10, col 0. That would
  make the prompt area for get one from row 10, col 0 to row 10, col 11.
  so to define this first prompt would require a sequence of calls to
  m_stack() as follows:

        m_stacknew()            && initialize the stack
        m_stack(1,10,0,10,11)   && get number, and row/col of prompt 1

  Now to add more prompts, you just add more calls to m_stack with get #2,
  #3, #4 and so on. So a sequence of gets could be defined as follows:

        @ 10,0 say "Enter First..:" get Fname
        @ 11,0 say "Enter Last...:" get Lname
        @ 12,0 say "Address......:" get Address
        @ 13,0 say "City.........:" get City
        @ 14,0 say "Phone Number.:" get Phone 

  * there are five prompts, they can be defined to m_stack() as follows:

        m_stacknew()            && initialize the stack
        m_stack(1,10,0,10,13)   && prompt area for get #1
        m_stack(2,11,0,11,13)   && prompt area for get #2
        m_stack(3,12,0,12,13)   && prompt area for get #3
        m_stack(4,13,0,13,13)   && prompt area for get #4
        m_stack(5,14,0,14,13)   && prompt area for get #5

  Now the internal mouse get stack is filled with the five prompt
  coordinates. The next consideration is how to find out when the
  mouse button has been clicked while you are in the read. Normally,
  once you are in a read you have no more control over program execution
  until the user exits the read. However, there is a little sleight of
  hand that we can do while in the read using the SET KEY TO command.
  The sleight of hand involves using SET KEY TO to point an obscure
  key to a procedure that will activate the desired get based on the
  row/column coordinates defined in the m_stack() data area. I like to
  use ALT/= (inkey value 387), since the key combo ALT/= is difficult to
  maneuver on the keyboard. The trick to using the mouse for this is
  to use the mousetrap() function to redefine the left or right button to
  be equal to the inkey value 387 (or ALT/=). therefore, if the user
  presses a button that is assigned the value 387, the SET KEY TO
  procedure will be run while inside the read because the mouse button
  stuffs a 387 into Clipper's keyboard buffer. Once inside the set key to
  procedure, all you need to do is call the m_activate() function. It
  will grab the location of the mouse cursor, compare it to all the row and
  column coordinates you defined in the m_stack() area, and will activate
  the appropriate get if the mouse cursor is contained in one of the
  regions you defined. If the m_activate() function encounters a -1 while
  scanning the data area, it will assume that all prompt coordinates
  failed the compare, and will return .F. - If a match is found, then the
  get is activated, and a .T. is returned. All you need to do in the
  SET KEY TO procedure is return to the read. When you return, the
  appropriate get will activate if need be.

  Now this may all seem a bit convoluted, but it works alarmingly well,
  and is really quite simple. To finish our example, all that need be
  done is to define the SET KEY TO procedure. It would be as follows:

        SET KEY 387 TO CLICKGET && set key to procedure that will activate
        mousetrap(0,387)        && set the left button to key 387
        m_trapset()             && set the mousetrap
        read                    && and now issue the read.

  And that will complete the set up for the read. The last thing to do
  is write the SET KEY TO procedure. All that is necessary is a PROC
  that calls the function m_activate(). like so:

        PROC CLICKGET
        para d1,d2,d3

                m_activate()

        return

  And that is all that's needed in the SET KEY TO procedure. m_activate()
  will do all the work for you. You just need to do all this gymnastics
  to get around Clipper's inability to handle the mouse....but it works.

  Now, since m_activate() returns .T. or .F. depending on whether or not
  a get is activated, you can tell if the mouse cursor was indeed inside
  one of the prompt areas you defined. If m_activate() returns .T., you
  know that a get has to be activated, and you should return to the read
  right away. However, if m_activate() returns .F., then you know that
  the mouse cursor was in another area of the screen when the user clicked.
  It just so happens that you might have a little box on the screen that
  has the word 'SAVE' in it. Now, if m_activate() returns .F., you just
  might want to check to see if the mouse cursor was inside the box with
  the word 'SAVE' in it, and if it was, well, why not stuff a CTRL/W into
  the buffer? - that would effectively save the users data....Hmmmm
  lets see....

        PROC CLICKGET
        para d1,d2,d3

                if m_activate()         && if .T., have to return right now
                        return
                elseif m_region(24,0,24,20)     && this area says save
                        keyboard chr(3)         && stuff a PGDN, to save...
                elseif m_region(24,21,24,41)    && this area says ESCAPE
                        keyboard chr(27)        && well, then ESCAPE!
                else
                        m_squeak()              && otherwise just beep em!
                endif

        return

  That way you could have prompts all over the screen that could do all
  sorts of neat things that only you could dream up! - by the way, the
  program SAMPLE.PRG uses exactly this method to bring up the browse
  window when you click on the browse box. The m_stack() system has a
  few more functions, they are outlined here:

        m_stacknew()            && initialize the mouse get stack
        m_stack()               && define the prompt/get coordinates
        m_stackget()            && save the mouse stack
        m_stackput()            && restore the mouse stack
        m_stacknum()            && retrieve a value from the stack
        m_activate()            && activate the appropriate get

  Other get related functions may assist you:

        active()                && get active get NUMBER
        activate()              && activate get number <nn>
        getvar()                && get variable associated to get # <nn>
        savegets()              && save your gets
        restgets()              && restore your gets

See Also: m_stack() m_activate() m_stacknew()

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