BRWMON1.TXT

Free, open source code to use with Harbour/miniGUI 2.6.7
by Jos Arturo Garca Vzquez
arturogarciavazquez@yahoo.com.mx  -  write "HMGforum - your text" in subject.
I know I need to improve my English.
If I write so cryptic, please, read the code (code is small).


------------------------------------------------------------------------------
Set of routines to simulate OnChange event for right click in a BROWSE control
------------------------------------------------------------------------------


   What if your program automatically shows secondary database info depending
on record selected by end user at the primary database, but he (the user)
click with the right button... this not jump to your ON CHANGE event code.

   The user could think that the info he is seeing is correct!

   Left click launch correctly the ON CHANGE event. Apparently, Right click
no changes the pointer's RECNO(), even with SET BROWSESYNC ON, this seems to
be the fact why ON CHANGE event is not launched.

   It will be a good idea for you to read about SET BROWSESYNC ON/OFF  and
DEFINE BROWSE. The philosophy of SET BROWSESYNC OFF is opposite to this new
set of functions, so only use them when you need.

REMEMBER:

-> this is only a patch, a provisional workaround!
Keep looking for news on miniGUI official v 2.6.7 ->
As usual, miniGUI lets develop very powerful programs.
Thanks, Mr. Roberto Lopez! Also thanks to the Harbour & MinGW teams !

-> This process uses a timer wich periodically compares the VALUE property
   of the browse object with its database RECNO() and jumps to a function
   you can write in your own code in order to handle that record resync
   and call your update process, just the same way you do with left click.


While this code is usable, it always will be considered Beta.

	BRWMonitorBegin()
	BRWMonitorTimerPause()
	BRWMonitorTimerResume()

	BRWMonitorTimerRelease()
	BRWMonitor()

Write on top of you PRG -> #include "BrwMon1.prg" <- to make them avaliable
to your code.



------------------------------------------------------------------------------
BRWMonitorBegin()
Creates a timer object and starts the monitoring of database(s).
------------------------------------------------------------------------------
Sintax:
BRWMonitorBegin( <cWindowName> , <arrayBrowseObjects> , <cUserFunction> ,
                 <nIntervalMilliseconds> )

<cWindowName> is the name of the window used to create a timer in order
   to monitor the record pointer for each database specified in
   <arrayBrowseObjects>

<arrayBrowseObjects> is an array with the specifics of each browse object to
   monitor in the following format:

   {
      { <cWindowName1> , <cBrowseName1> , <cDatabaseAliasName1> }  ,  ;
      { <cWindowName2> , <cBrowseName2> , <cDatabaseAliasName2> }  ,  ;
      ...
   }

<cUserFunction> is an user defined function specified surrounded with quotes
   and without parenthesis wich be called internally every time the monitor
   detects a diference between

   <cWindowNameN>.<cBrowseNameN>.VALUE   and   its respective   RECNO()

   caused when an end user selects a record in the main database with the
   right button of the mouse (which not trigger the ON CHANGE event).

   Please, see "Notes for <cUserFunction>" section for information about
   parameters automatically passed to this User Defined Function and
   related details.

<nIntervalMilliseconds> 
   Is the period of time to use as INTERVAL in the timer to monitor
   your databases.

   Please, see "Notes for <nIntervalMilliseconds>" section.

Return: Nil



------------------------------------------------------------------------------
BRWMonitorTimerPause()
Set timer of monitoring process in pause mode. (Disable the timer)
------------------------------------------------------------------------------
Sintax:
BRWMonitorTimerPause( <cWindowName> )

<cWindowName> Is the same window name you used to create the timer with
   BRWMonitorBegin().

   Please, see "Notes for BRWMonitorTimerPause() & BRWMonitorTimerResume()"
   section.

Return: Nil



------------------------------------------------------------------------------
BRWMonitorTimerResume()
Resumes the monitoring process. (Re-enable the timer)
------------------------------------------------------------------------------
Sintax:
BRWMonitorTimerResume( <cWindowName> )

<cWindowName> Is the same window name you used to create the timer with
   BRWMonitorBegin().

   Please, see "Notes for BRWMonitorTimerPause() & BRWMonitorTimerResume()"
   section.

Return: Nil



------------------------------------------------------------------------------
BRWMonitorTimerRelease()
Stops and destroys the monitoring process. (Release the timer)
------------------------------------------------------------------------------
Sintax:
BRWMonitorTimerRelease( <cWindowName> )

<cWindowName> Is the same window name you used to create the timer with
   BRWMonitorBegin().

   It is not necesary to call this function when <cWindowName> is released
   in your program.

Return: Nil



------------------------------------------------------------------------------
BRWMonitor()
Enable/Disable the process of the BRW monitor set of functions.
------------------------------------------------------------------------------
Sintax:
BRWMonitor( [ <nNewValue> ] )  ->  <nPreviousValue>

<nNewValue> It's Optional, but if specified must be 0 or 1.

   0 - causes an inmediate return (with no process at all) of these functions.

   1 - these functions do their job normally. This is the default initial
       value.

   The first time this function is called, it creates a PUBLIC variable for
   internal control purposes with a value of 1. If <nNewValue> is specified,
   its value is applied after that.

   This function is intended for debug purposes, and you'll not need it normally.

Return: the value in the PUBLIC control variable prior to set <nNewValue>.





------------------------------------------------------------------------------
   "Notes for BRWMonitorTimerPause() & BRWMonitorTimerResume()"
------------------------------------------------------------------------------

   Monitoring with a timer is a "LIVE PROCESS", so keep that in mind when
you plain to APPEND BLANK, REINDEX or whatever action that moves your
record pointers.

   ALWAYS, prior to do that, make a call to BRWMonitorTimerPause() and you
can only make a call to BRWMonitorTimerResume() when you are absolutely
sure that you will return to the main event loop inmediately, so your
User Defined Function can properly handle any pointer updates required.

   In the other hand, ONLY IF YOU ARE SURE that your current process and
your UserDefinedFunction dont be in conflict if they occur simultaneously,
then you can make a call to BRWMonitorTimerResume() in any place you want
(or you need).

   Probably the first method is safer.



------------------------------------------------------------------------------
   "Notes for <nIntervalMilliseconds>"
------------------------------------------------------------------------------

   This consideration applies only when you specify BRWMonitorBegin() statement
in your main code BEFORE the @...BROWSE / DEFINE BROWSE statements are executed
at run time.

   INTERVAL Value *must* be high enough to let @...BROWSE / DEFINE BROWSE
statements be runtime executed (this happend very quickly and I really think
this not need to be a concern).

   At the same time, INTERVAL Value needs to be low enough to be nice to the
end user when he/she clicks the right button.



------------------------------------------------------------------------------
   "Notes for <cUserFunction>"
------------------------------------------------------------------------------

   Inside this user defined function you are able to update the visuals of a
secondary database.

   Your user defined function *must* receive 2 parameters of type array
<alBrowseObjectList>  and  <arrayBrowseObjects>

   The first array is a list of logicals .T./.F. indicating with .T. if a
browse pointer (VALUE property) has been changed and differs of its respective
RECNO(). This is the information you need to a) Update your dbf record pointer
AND, b) Update the visuals of a secondary database.

   The second array parameter received for your user defined function is the
same array you provided with your Browse Objects List.

   To avoid problems with recursive calls, BRWMonitorTimerPause() is executed
just before your user defined function is called.

   Your user defined function *must* return a .T. or .F.

   But only when .T. is returned, a call to BRWMonitorTimerResume() is made.


