TVM Turbo Vision Monitor An Event Debugging Tool for the Turbo Pascal Turbo Vision Application Framework. Copyright 1993 McQuay Technologies TVM - TURBO VISION MONITOR Introduction Building your own TView objects, can be very frustrating. The lack of documentation on event cascading, event concepts, and class behavior based on events makes it difficult to design TView descendants from scratch or modify the behavior of existing classes. Trying to track down what is happening via the IDE watch window or TD is incredibly slow, and in some cases impossible. TVM uses the power of TV to solve this delima. Turbo Vision Monitor (TVM) is a development debugging tool for Turbo Pascal programers that monitors the flow of events and state changes within a Turbo Vision application. The TVM unit allows TView objects to be easily tagged and their methods and behavior monitored in a real time window. TVM can filter events so only certain types of events will be monitored, trap events and halt execution, and log events to a file or the printer. Turbo Vision Monitor comes in two forms, a shareware version and a registered version. The Shareware version includes TPU files for version 6 and 7 of Turbo Pascal, documentation in a file form, and several example programs. The registered version comes with the source code for all TVM files, a printed and expanded version of the documentation, and several example programs. This is the documentation for the shareware version. This document is divided into four sections, an introduction to the product and the shareware liscense, an over view of features and operation, a detailed reference of Classes, procedures and functions, and a basic tutorial on use. CHAPTER TVM - Turbo Vision Monitor INTRODUCTION Turbo Vision Monitor (TVM) is a development debugging tool for Turbo Pascal programers who are working with the Turbo Vision application framework. It can be used to easily monitor the flow of events and within am application and TView objects and to monitor the behavior of TView Objects. TVM is intended to be used during the development of TV programs and the creation of derived TView classes. TVM consists of a unit which is added to a program's uses clause and several procedures which are used to tag objects to be monitored. TVM provides a realtime window in which TV Events can be displayed as they occur and are handed from object to object. TVM can filter events so only certain types of events will be monitored. TVM can trap events and halt execution. TVM can be used to log events to a file or the printer. TVM can also be used to monitor the behavior of TView objects and data passed to and from TView methods SetState(), GetEvent(), PutEvents(). A procedure similar to writeln() is also provided to monitor the flow of data ANYWHERE within the users code. TVM is designed to be useful to the novice programmer as well as the most advanced TV programmer. TVM can be used in five ways, each represent an increasing level of information reporting and complexity. The first and simplist way to use TVM is to display events generated and managed by the main TApplication object. This can be done by simply including the TVM unit in your uses statement. (You can even use your own derived TApplication class TVM will monitor it!) Second, TVM can be easily used to monitor calls to any TView or descendant object's HandleEvent, SetState, Get State, PutEvent, or GetEvent methods. This can be done by simply providing TVM a reference to the object. TVM can display entry and exit information for these methods. Third, the programmer can use TVM's reporting functions to display the status of a TEvent record or the value of a TView or descendant object anywhere within his or her code. This is done by simply placing a reporting statement in the code where an TEvent report is desired. Fourth, the programmer can use a raw reporting function to display the state of any simple data type (byte, word, integer, string, real, longint) anywhere within his or her code. Lastly, the programmer can create a descendant of TVM for which he defines what information will be displayed based on a passed pointer. Anything you can get in two lines of 40 characters, TVM will display. (Requires Scource Code in Registered Version) By using the power of Turbo Vision, TVM is not limited to reporting data in only one way at a time. TVM can display data in ALL the methods described above at once, in one window or multiple windows, in any combination you desire! The only limit is that amount of RAM available. SHAREWARE LISCENSE PERMISSIONS AND RESTRICTIONS TVM is a shareware/sourcing program. Here are our rules for the shareware/sourcing liscense issued with TVM. You have a reasonable amount of time to try out TVM to see if it is beneficial to you. You decide what is a reasonable amount of time. We consider a 30 to 90 day period as reasonable. If you decide that TVM is not useful to you then your only cost is the time you spent evaluating TVM, for which we are grateful. If you find TVM useful, but will use TVM to assist in developing programs for your own personal use, registration is up to you. There are benefits to registering as stated below, however, if these benefits are not desirable, then you need not feel guilty if you decide not to register TVM. However, if you find TVM useful and you will be using TVM in a commercial manner, then registration is required for continued use. In this later situation, even if you do not consider the benefits of registration to be beneficial to you, you must still feel guilty for continued use without registration. We consider commercial use to be the use of TVM to help develop libraries, units or programs that will be used by others within your organization, for sale, or for release as shareware or public domain. A registered copy of TVM can be used by up to 3 people within a single company. Contact us for a price quote on use by more than 3 within a single company. Everyone is liscensed to distribute TVM as a shareware product to others. However no one except McQuay Technologies and its agents are liscensed to distribute the source code for TVM or the source code for any of the units used in TVM for which McQuay Technologies has a copyright. Source code for TVM and the libraries to create TVM are expressly NOT part of the shareware version. Source code is only available for use by registered users of TVM. SHAREWARE REGISTRATION Registration of TVM is $15. When you register TVM you get the following: 1) By mail a disk with the latest version of the source code for TVM. The source code for the TVM is thoroughly documented. The source code for supporting units is provided but is not as well documented. 2) An expanded manual in file format. This exapnded manual covers information related to the source code as well as additional technical information about TVM. 3) By US Mail notification of updates. Source code for minor updates will be available on request for just production costs. Compiled versions of minor updates will be available on a selected set of information networks. Major upgrades if there are any will be available for just $5.00 over production costs and will include source code and changes in the printed manual (if any are required). 4) Priority response on tech support via information networks we support, which is currently AOL, Compuserve, Internet and Chandler Programmers Connection in Chandler (Phoenix) AZ. 5) Peace of mind that you are helping us keep TVM at the leading edge and develop other new utilities and libraries. Registration should be sent to: TVM McQuay Technologies 3116 E. Shea Blvd Suite 111 Pheonix AZ, 85028 Along with $15 send the following information: Name ________________________________________ Address ________________________________________ ________________________________________________ ________________________________________________ Version of Turbo Pascal 6 TP7 BP7 ?___ Disk Format (5 1/4) (3 1/2) Compuserve ID __________________________________ AOL ID _________________________________________ Internet Address _______________________________ COMMENTS: ______________________________________ ________________________________________________ ________________________________________________ CHAPTER TVM - FEATURES TVM works simply by inserting a TWindow object, the TVM Window, into the desktop. This window is then used to report events and behavior of TView objects. Multiple TVM windows can be used at once. The user controls which TView objects will be monitored and the type of monitoring with procedures placed in the source code. Once a program is running, the programmer can in real time alter the nature of reporting on these objects. The following describes the features of the TVM system and the basics of use. THE TVM WINDOW The TVM window has two basic elements, the TVM Menu and the TVM Event list. The TVM Menu is located at the top of the TVM Window and provides access to options which can be used in real time to change how and what events and data is reported. The Event List takes up the remainder of the TVM Window. This Event List is actuall a series of two line reports, each representing the reporting of some event or report of some data. The TVM Window is activated similar to other windows on the desktop. This will vary based on how your program has the desktop set up and what other views are active. If no other view is in a modal state, the TVM can be accessed typically by pressing ALT key and the number key that corresponds to the TVM Windows ID numberof the window, or pressing the F6 key to switch between active windows until you reach the TVM Window. However, TVM works best with a mouse. Using the mouse, if no other view is in a modal state, the TVM Window can be accessed by clicking the mouse anywhere on an exposed part of the TVM window, or by simply moving the mouse slowly over the TVM Menu. Once the TVM Window is active, the TVM Event List can be used by pressing the ESC key, and the Menu can be accessed by press ALT-F10. ™-[_]------ TVM TITLE -----1-[_]I ๘ Reset Options Help Window ๘ <-- TVM Menu ๘ _ ๘ Y ๘ Y<-TVM Report List ๘ Y ๘ _ ๘ ๘ U------------------------------- TVM REPORT LIST The report list is a scrolling list of reports about TEvents, TView states, or data values. Reports are added at the top and scroll down. The Report Buffer can hold about 30 reports (can be changed in source code). With in the report list window, several features are available. First the TVM window can be resized to allow viewing of more reports. The report list can also be scrolled to view past reports. Reports can also be marked by double clicking on a specific report. This is useful for keeping track of a specific reports as they are scrolled. The format of report information varies with the type of event being reported. All reports consist of two lines. The information on these lines will vary but for all reports the first number on the first line is the reports unique ID. As reports are added to the window they are assigned a number, which increments with each report. This provides a quick way to understand the sequence of events. This number can be reset to one with the Reset menu option in the TVM menu bar. In most reports, the first line is an ID line that identifies the report and provides basic information. The second line is typically a data line and provides more detailed information about the report. The following explains the different possible report formats. TEvent Reports - All reports which include information about a TEvent, which includes monitoring of HandleEvent(), GetEvent(), and PutEvent() methods as well as special user TEvent reports have the same format. In addition to the sequence number, TEvent reports also have a symbol right after the sequence number that designates whether the report is a pre or post report. Since the TEvent parameter in TView's HandleEvent method is a VAR parameter, this method can alter the contents of the TEvent passed to it. This is a common technique used in some Classes. TVM allows you to see the value of TEvent on entry and exit of the HandleEvent method. The ฏ symbol indicates this is a pre-report, data being passed to the method, and the The ID line of all TEvent reports is formatted as follows: # NNNN:NNNN/:EVENT:
$<$$> # is the report number. NNNN:NNNN is the address of the TVIEW.OBJECT being monitored. is a 3 char string which the users assigns to the specific method trap for this object which can be used to identify this particular report.
is the decimal and <$$> is the hex value of the EVENT.WHAT field contents. is the name of the type of event that has been trapped based on the value in the EVENT.WHAT field. These identifiers are found in the file EVCMKB.STM and provides description for all standard events. The format of the data line for TEvent reports varies with the type of event. Command and Broadcast events are formatted as follows: Command:
$<$$>
is the decimal value of the EVENT.Command field. <$$> is the hex value of the EVENT.Command field. is a cm?? constant name identifier for this command if known, all standard TV commands are reported. evMouse,evMouseDown,evMouseUp,evMouseMove,evMouseAUto events are formatted as follows: Mouse: N N is the number of the current button being processed, 0 if none. is the type of mouse button click involved if any. evKeyDown events are formatted as follows: [%] ASC
<$$> SCAN [%] is the actual ASCII character if appropriate
is the decimal value for Event.CharCode field. <$$> the hex value for Event.CharCode field. is the decimal value for Event.SCANCODE. the hex value for Event.SCANCODE. provides a kb?? constant name for the KEYCODE if known. TView State Reports - State reports use a different ID line than events which is formated as follows: # NNNN:NNNN//STATE:<$$> # is the event number. NNNN:NNNN is the address of the Object reported. is a 3 character name for event. <$$> is the hex value of the state reported. provides the reason for the state report. "Clear" or "Set" are values returned for a SETSTATE report and identify whether the STATE passed was being set or cleared. CHANGED! means it is a change in state report and nothing means it is just the current state of the object referenced. The data field line for state reports is used for a verbal summary of the bits that are set in the state field of the TView object being monitored. TVM MENU The TVM Menu provides four menu selections, Reset, Options, Help, and Window. ™-[_]------ TVM TITLE -----1-[_]I ๘ Reset Options Help Window ๘ <-- TVM Menu ๘ _ ๘ Y Reset - This menu selection resets the report counter to 1. Help - This menu item allows you to browse a help file summarizing TVMs features. If this help file is not in the current default directory, then a message is displayed in the browser that the help file could not be found. Window - This item is a submenu giving access to two basic TV features for the TVM Window, zooming and moving the window. Control of these follows the standard TV operational mouse and keyboard commands. Options -This menu item provides a way to control the reporting and trap options for objects and reports being trapped by TVM at run time. All the features of TVM and object Traps that can be set in the initial trap procedures can be altered here at run time. This item pops up a submenu with three items: Monitor, Reports, and Objects ™-[_]-------------- TVM Window ------------3-[_]-I ๘ Reset Options Help Window _ ๘ ™----------I Y ๘ ๘ Monitor ๘ Y ๘ ๘ Reports ๘ Y ๘ ๘ Objects ๘ Y ๘ U---------- Y ๘ _ Options/Monitor - This menu item allows some basic operation features of the TVM Window to be modified. Selecting this menu item opens a dialog with three controls, one to control the destination of event logging, one to turn all reporting and trapping off, and one to turn all event tripping off. ™-[_]--------- Main Options -------------I ๘ List To ๘ ๘ [nul_____________] ๘ ๘ Use PRN for printer, ๘ ๘ Use NUL for No Listing, ๘ ๘ Or enter a FileName. ๘ ๘ Trap Options ๘ ๘ [X] Trap On ๘ ๘ [X] Trip On ๘ ๘ ™----I ™--------I ๘ ๘ ๘ Ok ๘ ๘ Cancel ๘ ๘ ๘ U---- U-------- ๘ U---------------------------------------- The List to field can be used to list all TVM reports to the printer or to a file. This is particularly useful when tracing reports that exceeds the TVM report display buffer, or when trying to track down a specific series of events in a long sequence of reports. Entering PRN in this field whill route all TVM reports to the standard list device as well as the TVM window. Entering a filename will route these reports to a file as well as the TVM Window. No checking is done to see if the file exists. Entering NUL will turn off the report logging. The report field allows all TVM reporting to be suspended. This can be effectively used to turn the TVM system on and off. Turning reporting off does not remove the TVM Window, it simply suspends further reporting. If the Trip feature is being used, the Trip field can be effectively used to turn all tripping on and off. This is particularly useful when tripping is being used with multiple objects. This field can be used to suspend tripping with out actually modifying the trip designation of each object. Turning trip off here also will not set the TRIP field used in any conditional break statements. Options/Reports - TVM treats method traps and reports differently. This options allows the reporting behavior of all inline reports to be modified. Selecting this item pops up a report ™-[_]------------- Options -----------------I ๘ Event Flags General Masks ๘ ๘ [ ] evMouseDown [ ] evMouse ๘ ๘ [ ] evMouseUp [ ] evKeyBoard ๘ ๘ [ ] evMouseMove [ ] evMessage ๘ ๘ [ ] evMouseAuto [ ] Clear All ๘ ๘ [ ] evKeyDown ๘ ๘ [X] evCommand Trap Op ๘ ๘ [X] evBroadCast [X] Trap On ๘ ๘ [ ] Trip On ๘ ๘ ™----I ™--------I ๘ ๘ ๘ Ok ๘ ๘ Cancel ๘ ๘ ๘ U---- U-------- ๘ ๘ ๘ U------------------------------------------- Options/Objects - This menu item allows the trapping parameters of any objects being trapped with the TViewTrap() procedure. Selecting this item pops up a dialog that lists all the objects currently being trapped by TVM. ™-[_]----------- Trapped Objects ----------------I ๘™--------------I ๘ ๘๘MyApp [Event] _ ๘ ๘๘Window [Event]š ™------I ๘ ๘๘MyApp [State] š ๘ Edit ๘ ๘ ๘๘ _ U------ ๘ ๘U-------------- ๘ ๘ ™----I™--------I ๘ ๘ ๘ Ok ๘๘ Cancel ๘ ๘ ๘ U----U-------- ๘ U------------------------------------------------ In the scrolling list box is a list of all these objects. The ID name used in the TViewTrap() procedure and the method being trapped is displayed for each object. An object can be selected by using the cursor keys or mouse to scroll the selection bar to highlight the desired item. Then selecting the Edit button opens a dialog that allows the current trapping parameters for the Object and method trap selected to be edited. The dialog for state traps is different than event traps. ™-[_]----------- Trapped Objects ----------------I ๘ ๘ ๘™-[_]------------- Options -----------------I ๘ ๘๘ Event Flags General Masks ๘ ๘ ๘๘ [ ] evMouseDown [ ] evMouse ๘ ๘ ๘๘ [ ] evMouseUp [ ] evKeyBoard ๘ ๘ ๘๘ [ ] evMouseMove [ ] evMessage ๘ ๘ ๘๘ [ ] evMouseAuto [ ] Clear All ๘ ๘ ๘๘ [X] evKeyDown ๘ ๘ UA [X] evCommand Trap O ๘--- ๘ [X] evBroadCast [X] Trap On ๘ ๘ [ ] Trip On ๘ ๘ [X] Pretrap ๘ ๘ [X] PostTrap ๘ ๘ ™-----------I ™-----------I ๘ ๘ ๘ Ok ๘ ๘ Cancel ๘ ๘ ๘ U----------- U----------- ๘ U------------------------------------------- The event trap dialog can be used to modify the filter being applied to events monitored. Either specific events can be added or deleted from the filter, or General Filters, such as all mouse events or no events, can be set. Also the trapping characteristics can be changed. The trap can be set as a Pre or Post trap, or both. The trap can be turned off completly. This does not remove the trap, but simply suspends reporting until it is re-enabled. Also tripping on this specific trap can be set on or off. ™-[_]----------- Trapped Objects ----------------I ๘ ๘ ๘™-[_]--------------- Options ----------------I ๘ ๘๘ Masks Trap Type ๘ ๘ ๘๘ [X] sfVisible (_) Trap On Set ๘ ๘ ๘๘ [X] sfCursorVis ( ) Trap On Change ๘ ๘ ๘๘ [X] sfCursorIns ๘ ๘ ๘๘ [X] sfShadow ๘ ๘ U๘ [X] sfActive ๘-- ๘ [X] sfSelected Trap Options ๘ ๘ [X] sfFocused [X] Trap On ๘ ๘ [X] sfDragging [ ] Trip On ๘ ๘ [X] sfDisabled ™----------I ๘ ๘ [X] sfModal ๘ Ok ๘ ๘ ๘ [X] User$0400 U---------- ๘ ๘ [X] sfExposed ™----------I ๘ ๘ [X] User$1000 ๘ Cancel ๘ ๘ ๘ [X] User$2000 U---------- ๘ ๘ [X] User$4000 ๘ ๘ [X] User$8000 ๘ U-------------------------------------------- The state trap dialog allows the state filter being used to be modified. It also allows the type of trap being used to be modified, with the trap being set to generate a report on every call to the SetState() method or simply calls which change the current state of the object. The trap can also be turned on or off, suspending or re-enabling reports. The trip feature for this state trap can also be turned on or off. HOW TO USE SPECIAL FEATURES When trying to monitor multiple objects, particularly the passing of TEvents from one object to another or monitoring the State of an object, hundreds of reports can be made. This can become confusing as they fly by in the TVM Window, sometimes scrolling out of the buffer before they can be examined. All the reports are needed in order to trace behavior, but typically they are needed only right before and after a specific event. TVM provides two tools to assist in debugging object behavior in such situations, Report Logging and Report Tripping EVENT LOGGING Becuase of concerns over excessive use of heap space by TVM, the TVM Window has a limit on the number of reports that can be retained for display in the TVM Window. However, frequently you will find that the number of reports you would like to manually review exceeds this limit. To assist in such situations, reports can be logged either to the printer or to a file as well as the TVM Window. The reports printed or written to a file have the same format as those displayed, the only difference is there order. In the TVM Window, events are descending. Events logged are done in ascending order. Event logging can be enabled at runtime via the Options/Monitor menu item. Either the standard lst device or a file name can be specified. EVENT TRIPPING Tripping is a technique that can be used to pause program execution on a particular report making it easier to trace behavior. When Tripping is set on for a particular TView report events are reported as usual except those indicated as tripped. When such a report occurs the program is halted (not really, just TVM grabs control in a modal state), a beep is sounded as the event is reported, the event is highlighted, and execution will not proceed until the space bar is pressed. This provides an easy way to slow down events that occur rapidly. Tripping can be enabled at runtime via the Options/Objects menu. Tripping can be made specific to particular objects method. The filtering options for event and state traps can be used to trigger a trip only in very specific circumstances. TVM also provides several tools to enable tripping under software control. One feature is to use the Turbo debugger in conjunction with TVM. See debugging strategies below for more detail. If you desire, via software control you can also start the tripping sequence. In your source code after you have initialized a TV Monitor Window, call this window's SetTrip() method and pass a FALSE value. SetTrip(FALSE). When executed, this will suspend all tripping. Next select the OPTIONS/OBJECTS menu and turn tripping on for the object you are debugging. Since tripping has been suspended, your object will not cause a trip. Now in your code, include a line the uses the SetTrip(TRUE) procedure to restart tripping. Once set, the next event that TVM sees for the object in question will be tripped. CHAPTER Use Of TVM INTRODUCTION Turbo Vision is an event driven object oriented application framework. This means that events are the primary data processed by Turbo Vision. Essentially it is an event manager. It manages the creation and communication of events. These events can be hardware related such as keyboard and mouse actions, or software related events created by other objects such as commands and messages. Within the TV framework, information about these events is delivered to a variety of objects that are event handlers. Each event handler decides if it is to take some action in response to the event based on the information about the event. At the macro level, this event driven framework is a different paradigm for software control. Under traditional paradigms, software control occurs in more or less a linear fashion. Such linear control is fairly easily documented in at least pseudo code and frequently within the source code itself. To follow a programs execution one simply follows the program control as expressed in the source code. But under the event driven paradigm, the programmer uses the Turbo Vision framework to manage the control of his application. The programmer then creates control structures which will respond to or handle the events managed by TV. Turbo Vision provides built in event handlers for many events related to the programs user interface, menus, windows, status lines etc. However, the programmer must provide the event handlers for events related to the functional aspects of his program, database, numerical, file io, etc. Debugging applications with traditional debugging techniques the event driven framework can be simply described as maddening. The reason for this is that the behavior of a program is better defined by tracing the flow of information about events than it is by tracing the source code. Tracing the flow of events with a traditional debugger can be extremely difficult. TdTurbo Vision Monitor provides a tool specifically designed to trace the flow of events within an application. In its simplist form TVM is a tool to monitor the flow of event information in and out of TView Event Handlers. This is done by simply tagging the the TView objects to be monitored. TVM then displays information about the events entering and leaving the TView objects HandleEvent method. TVM allows a program to be executed one event at a time, similar to how a program can be traced using the source line debugger. In its more complicated form, TVM can be used as a scratch pad to record information as a program executes. A variety of reporting procedures are provided that can be placed a strategic points in the source code. These procedures will then display information in the TVM window as the program executes them. These coupled with the above monitoring system can provide a good understanding of a programs behavior in repsonse to the event stream in is provided by Turbo Vision. MONITORING EVENTS AND TVIEW STATES TVM can monitor the HandleEvent(), GetEvent(), PutEvent(), and SetState() methods for any TView Object or an object of a descendant class of TView (See Limitations below). This is done using the TViewTrap procedure. TViewTrap can monitor the above methods in two basic ways, data passing to the method and data passing from the method. For example, two traps can be set up for an object's HandleEvent method one pre and one post. This would then show how event messages were chnaged by the object as they were passed around by the Turbo Vision Event Manager. The syntax for this procedure is as follows: TViewTrap(EMW,P,WhichTrap,TrapWhen, Mask,AName); EMW is a pointer to an initialized TEventMonitorWindow. P is a pointer to and instatiated object of TView class or a descendant. WhichTrap is a constant used to identify which method is to be trapped. Valid values for WhichTrap are: emEventTrap: which traps the HandleEvent() method. emStateTrap: which traps all calls to the SetState() method. emChangeState: which traps calls to the SetState() method only when the request would change the current state of the TView object. emPutEvent: which traps calls to the PutEvent() method. emGetEvent: which traps calls to the GetEvent() method. TrapWhen defines whether the report should include data being passed too the method or passed from the method. Valid values are toPreTrap which reports data passed to method and toPostTrap which reports data passed back by the method. These can be combined. The value (toPostTrap and toPreTrap) will generate a report on entry to and exit from the method. Mask is a value that will be used to filter out events and states. Only events and states included in the mask will be reported. Valid values for this parameter include TV's evXXXX and sfXXXX constants. For example the value evMouse would filter out all events except mouse events. The value (evMouse and evKeyDown) would filter out all events except mouse and keyboard events. A value of $FFFF will filter out no events or states. AName is a string that will be used to identify this specific report. It will be used in the report it self as an ID. The parameters of the method traps set with TViewTrap can be changed at run time from the TVM menu. REPORTING EVENTS AND STATES Event and State information can also be reported directly as well using several TVM procedures. These procedures are placed in the source code and when they are executed, a report is displayed in the TVM Window. This technique is similar to the tried and true technique of including a writeln statement in the source code. Unfortunately, using a writeln statement in a TV application at best is unreadable and can play havoc on the layout of TV views. TVM provides a way to ustilize TV's resources to display such information. TVM provides four procedures to display reports, each providing information about a specific type of data. The Report_Event procedure will display a report about TEvent data passed as a parameter. Its sysntax is: Report_Event (EMW,ID,Event,PointerToObject); EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. Event is a TEvent record. PointerToObject is a pointer to the Object for which this report pretains. The structure of this report is the same as that for trapped HandleEvent methods. The Report_State procedure is intended to report the current value of an TView objects state field. Its syntax is: Report_State (EMW,ID,PointerToObject); EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. PointerToObject is a pointer to the Object for which this report pretains, and is used to fetch the current value of its State field. The structure of this report is the same for reports on trapped SetState methods. The Report_SetState procedure is intended to be used to report the data passed in a SetState() method call. Its syntax is: Report_SetState (EMW,ID,Request,Flag, PointerToObject); EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. PointerToObject is a pointer to the Object for which this report pretains, and is used to fetch the current value of its State field. Request is a word value, that would normally be the value passed to a SetState() method. Flag is a boolean value that would normally be the same as the Enable parameter of the SetState() method. The Report_StateChange is intended to be used to report a requested change in a TView object's state, only when the request would change the object's state, that is the request is different than the objects current state. Its syntax is: Report_StateChange (EMW,ID,Request,PointerToObject); EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. PointerToObject is a pointer to the Object for which this report pretains, and is used to fetch the current value of its State field. Request is a word value, that would normally be the value passed to a SetState() method. When this procedure is called, a report will be displayed only if the value of Request is not set in PointerToObject's state field. The structure of this report is the same for reports on trapped SetState methods. MONITORING SYSTEM VALUES In addition to monitor TV methods and data types, it is also useful to monitor other variables, and report their values. TVM provides two procedures to assist in reporting system data and values of most user variables. The Report_Value procedure provides a very flexible way to report a variety of data values. Its syntax is: Report_Value(EMW,P,ID,Value,ValueSize) EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. P is a pointer value. It can be a pointer to anything but is normally a pointer to an object. The value of P as a pointer is included in the report but is not used to reference any value. Value is a var parameter of either a String, byte, word, integer, longint, pointer, or real datatype. ValueSize is used to determine what the datatype of Value. Valid values for ValueSize are: 0 for string datatypes, 1 for byte values, 2 for word/integer values, 4 for longint and pointer values, and 6 for real values. TVM also provides a standard report for the current system stats. The syntax for this procedure is: Report_SystemState(EMW,ID); EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. This will list the current amount of available heap, largest block of available heap, and the value of the Stack Pointer. SETTING UP TVM WINDOWS Setting up TVM Windows is fairly easy, and you can have multiple windows if it is desirable. TVM provides a predefined variable TVMW, which can be used, or others can be defined in your code. TVM Windows can be set up two ways. The first and easiest is to use the Insert_TVMW function. This function allows the basic setup parameters to be specified and a pointer to a PTVMWindow object to be returned. The syntax for this function is: Insert_EMW (TG, X,Y, Name, Anumber, EventMask) TG is any valid TV group, ussually the DeskTop. X and Y are the upper left coordinates for the window. Name and ANumber are something to identify the window. Event Mask is a general mask applied to the window as a whole. This method should be done only after your main applications TApplication object has been initiated. The TVMW object can be initiated with its init method directly. This should also occur after the main TApplication object has been initialized. This object can then be inserted into the desktop. DEBUGGING STRATEGIES Once you begin to master the use of TVM, you will develop your own techniques for using it to debug your TView methods. However, TVM was designed to be used as a strategic debugging tool. Essentially, this means that debugging occurs in three stages. An initial stage to quickly and easily focus in on one or two methods. A second stage to explore more thoroughly the flow of event and state data through these specific methods. Finally a third stage to trace a methods source code directly using the IDE's debugger and watch window. Stage One monitoring can be done very quickly with the TViewTrap procedure. This requires a minimal amount of modification of your source code, yet it provides a wealth of info to trace an objects behavior. Because TVM can trap and monitor a method based on just a reference to an object, and this trap is SPECIFIC to an object and not the whole class, it is easy to liberally trap a variety of objects. This can be done anywhere with in an objects scope, so the changes to the source code to initiate these traps can be kept cleanly organized for later removal. Monitoring multiple objects makes it easierto track down which object is responsible for undesirable behavior. One feature that is nice is trapping Turbo Visions standard objects (like the MenuBar and TDialog) with out there source code. Once you have narrowed the search to just a few methods, Stage two monitoring will require more attention and changes to your source code. In this stage the various reporting procedures will be inserted at key points in the source. As each procedure is executed, a report is displayed in the TVM Window. These reports can be on standard TEvent and STate data structures, or any Word, Longint, Real, or string variable as well. In some cases, monitoring system resources like heap will be usefull. Using these reports you can beginning to narrow down exactly where in a method's source an error is occuring. Now, in the third stage, you may want to actually use the debugger to trace the source code. TVM provides a way to interact with the IDE debugger. The TVM Window Class has a field called tripped. Normally the value of this field is false. However, when TVM trips a report, and pauses the program execution, this value can be set to true by pressing the Right mouse button or the F7 key. This field can be used in conjuntion with TPs conditional breakpoints. For example, at the beginning of some support routine that you suspect is causing your problem, you could place a conditional break that will only occur when the TVM Window you are using has a true Tripped value. This way you can use the TVM Window to trace your method's behavior using the trip feature, and then when you wnat to trace with the dbugger, press the right mouse button. The field will be set to true and when the conditional break is encountered it will stop the programs execution and place you in the editor at the line the break occured on. TECHNICAL CONSIDERATIONS MEMORY REQUIREMENTS Memory requirements for TVM are quite severe in it's shareware form. The more object methods you monitor the more memory is required. The shareware version of TVM is compiled lean, no range checking, no IO checking, no debug information. TRAPPING LIMITATIONS There is a basic limitation to TVM's ability to monitor TView object methods. TVM can only monitor virtual methods and only when that method is called via a look up in the class Virtual Method Table. For most calls to a virtual method, the reference is made via the VMT. However, Turbo Pascal 6 and 7 do not make calls to virtual methods via the VMT when the reference to the method is qualified by the Class identifier. For example given the following code type MyClass = object procedure AMethod; virtual; end; MyOtherClass = object(MyClass) procedure AMethod; virtual; end; procedure MyClass.AMethod; begin writeln('In MyCLass'); end; procedure MyOtherClass.AMethod; begin write('Not '); MyCLass.AMethod; end; var TestObject : MyOtherClass; begin TestObject.AMethod; end. The call to TestObject.AMethod is made via a reference to MyOtherClass' VMT. However, the call made to MyCLass.AMethod within the method MyOtherClass.AMethod is not made via the VMT. This call is placed directly into the code and not referenced via the VMT. Such references to virtual methods can not be monitored by TVM. Referencing methods in this manner is quite common when creating a descendant of another class. When a person wishes to modify the behavior of an ancestors method by added to the ancestors behavior, this is how the ancestor's method is called. This is used widely in TView objects HandleEvent() method, but very little in the other methods TVM can monitor. Such references are only permitted for methods of an ancestor. Fortunately, most frequently the user will want to monitor a descendant derived from a base TView class. Seldom will this be a problem in monitoring descendants of TView classes. If it does become a problem, the ReportEvent() procedure can be placed in the source code of the descendant. CHAPTER TVM - Tutorial BASIC METHOD MONITORING USING TVIEWTRAP() TVDEMO1.PAS In this tutorial we will use a simple TV application to demostrate the use of TVMs features. TVMDEMO1.PAS is a modified version of one of the example apps used in the TV Guide book. This application opens up and displays a window. Within this window a text file can be displayed and scrolled. In this program a TVM Window is inserted. The HandleEvent method of the main Tapplication object MyApp is monitored. This is done with three simple insertions. First the TVM unit is included in the uses clause. Second, a TVM Window is inserted into the desktop with the insert_TVMW() procedure. Finally the TViewTrap() procedure is used to monitor the HandleEvent procedure of MyApp. When this program is run, the desktop is displayed and an empty TVM Window is displayed. Press the F4. This will open a file view window. Now press F-6 to switch back to the TVM Window. In the window you should see the following 4 event reports. 4 ฏ MyApp 2E93:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 3 ฏ MyApp 2E93:1EB4 :ev:16 $0010 evKeyDown [_] ASC 0 $00 Scan 64 $40 kbF6 2 Command:52 $0034 cmCommandSetChanged 1 ฏ MyApp 2E93:1EB4 :ev:512 $0200 evBroadcast Command:52 $0034 cmCommandSetChanged You may have to enlarge the window or scroll the window to see all four reports. In this case, TVM is monitoring the flow of event messages in and out of the HandlEvent method of the MyApp object. The first report shows the cmCommandSetChanged command being passed to the method in an evBroadcast event. The second report shows this command and event leaving the method unchanged. The third report shows an evKeyDown event being passed to MyApp's HandleEvent method. This report shows that this was intiated by whenthe F6 key was pressed. The next report is NOT a record of this event leaving the method. This likely means that the event was handled by MyApp and cleared. The fourth report shows a cmNext command being passed to MyApp in an evCommand event. How was this cmNext command initiated and what did MyApp do to handle the evKeyDown event? TVM can help answer this question. In the TVMDEMO1.PAS there is a TViewTrap() procedure is commented out right below the TViewTrap() for MyApps HandleEvent method. If this procedure is uncommented, a second trap is installed that monitors MyApps PutEvent() method. Now when the program is run in the fashion above, the following reports can be seen: 6 ฏ MyApp 2E95:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 5 _ MyApp 2E95:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 4 _ MyApp 2E95:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 3 ฏ MyApp 2E95:1EB4 :ev:16 $0010 evKeyDown [_] ASC 0 $00 Scan 64 $40 kbF6 2 Command:52 $0034 cmCommandSetChanged 1 ฏ MyApp 2E95:1EB4 :ev:512 $0200 evBroadcast Command:52 $0034 cmCommandSetChanged In this case, it can been seen that after MyApp receives the F6 evKeyDown event, as shown in report 3, MyApp's PutEvent method is called with the cmNext command, as shown in report 4 (Put Events have solid arrows). This results in a evCommand event being placed in the event que, which is then passed to MyApps HandleEvent method, shown in report 6. Though this provides some insight into how, the cmNext command is generated, it is still not clear if MyApp, the file window, or a TView owned by the file window actually generates the command. However, if we can monitor these other objects we may be able to figure out which is responsible. TVMDEMO2.PAS TVMDEMO2.PAS shows how this can be done. This program is identical to TVMDEMO1 except that a trap has been set to monitor the File Window's HandleEvent and PutEvent methods. If this program is run as described above, the following reports can be seen: 16 Command:50 $0032 cmReceivedFocus 15 ฏ Demo 3ABF:0008 :ev:512 $0200 evBroadcast Command:50 $0032 cmReceivedFocus 14 Command:51 $0033 cmReleasedFocus 13 ฏ Demo 3ABF:0008 :ev:512 $0200 evBroadcast Command:51 $0033 cmReleasedFocus 12 Command:51 $0033 cmReleasedFocus 11 ฏ Demo 3ABF:0008 :ev:512 $0200 evBroadcast Command:51 $0033 cmReleasedFocus 10 Command:7 $0007 cmNext 9 ฏ Demo 3ABF:0008 :ev:256 $0100 evCommand Command:7 $0007 cmNext 8 ฏ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 7 _ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 6 _ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 5 ฏ MyApp 2E99:1EB4 :ev:16 $0010 evKeyDown [_] ASC 0 $00 Scan 64 $40 kbF6 4 Command:52 $0034 cmCommandSetChanged 3 Command:52 $0034 cmCommandSetChanged 2 ฏ Demo 3ABF:0008 :ev:512 $0200 evBroadcast Command:52 $0034 cmCommandSetChanged 1 ฏ MyApp 2E99:1EB4 :ev:512 $0200 evBroadcast Command:52 $0034 cmCommandSetChanged This report shows us the flow of events among and between two objects, MyApp and Demo (File Display Window). The above report list shows the cmNext command being generated by MyApp's PutEvent method in report 6 and 7. Prior to this, no event is received by Demo. In fact, the cmNext command is passed to MyApp as shown in report 8, and then MyApp passes the event to Demo. EVENT MONITORING USING REPORTEVENT() Though the reports shown above provide quite a bit of insight into the flow events and which object may be responding to them, it still would be usefull to understand more indepth how such events are handled within an object's HandleEvent method. As an example for this analysis, use TVMDEMO2.PAS again. This time monitor the zoom command. Run the program, press F4 to create a file window and then press F5 to zoom the window, and then press F6 to switch to the TVM Window. The following reports should be displayed (you will need to enlarge the TVM window or scroll the window to see all of these). 14 ฏ Demo 3ABF:0008 :ev:256 $0100 evCommand Command:7 $0007 cmNext 13 ฏ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 12 _ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 11 _ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:7 $0007 cmNext 10 ฏ MyApp 2E99:1EB4 :ev:16 $0010 evKeyDown [_] ASC 0 $00 Scan 64 $40 kbF6 9 ฏ Demo 3ABF:0008 :ev:256 $0100 evCommand Command:5 $0005 cmZoom 8 ฏ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:5 $0005 cmZoom 7 _ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:5 $0005 cmZoom 6 _ MyApp 2E99:1EB4 :ev:256 $0100 evCommand Command:5 $0005 cmZoom 5 ฏ MyApp 2E99:1EB4 :ev:16 $0010 evKeyDown [_] ASC 0 $00 Scan 63 $3F kbF5 4 Command:52 $0034 cmCommandSetChanged 3 Command:52 $0034 cmCommandSetChanged 2 ฏ Demo 3ABF:0008 :ev:512 $0200 evBroadcast Command:52 $0034 cmCommandSetChanged 1 ฏ MyApp 2E99:1EB4 :ev:512 $0200 evBroadcast Command:52 $0034 cmCommandSetChanged Here, the F5 keydown event is seen in report 5 being passed to MyApps. This iniates a call to MyApp.PutEvent to generate the cmZoom command. This Command event is received by MyApps HandleEvent (report 8) and then passed to Demo (report 9). However, the event is not passed back by either Demo or MyApps. This would indicate that DEMO is responding to the command and clearing the event. But just what does demo do? To understand and trace the flow of events within a HandleEvent() method, several TVM procedures can be used to report information about events and TView states to the TVM Window. These will work similar to how a writeln statement is frequently used to monitor a variables value as it changes. CHAPTER TVM - REFERENCE TTVMonitorWindow class TVM This class is the heart of the TV Monitor System. This class provides the window for all TVM reporting. TTVMonitorWindow -> TWindowWithMenuBar -> TWindow/TMenuBar FIELDS TRIPPED Tripped:boolean; Design Read Only This field is set to true if the right mouse button or the F7 key is pressed after a report has generated a triap, and the TVM Window is waiting for a response to continue program execution. METHODS INIT constructor Init(X,Y:word; WinTitle:String; ANumber:word, ListSize:word); Design Constructor Override: Never Behavior Initializes the Event Window with a call to Twindow.init. Bounds are calculated with X,Y as the upper left corner. The number field (used with ALT key to activate) of the window is set to ANumber. ListSize is used to control the number of reports that a historical record is kept on and can be scrolled within the Window. Reports are deleted on a First In Last Out basis. See also: TWindow.init DONE destructor done; virtual; Design Destructor Override: Never Behavior Closes and Disposes of the Window. REPORTEVENT procedure ReportEvent(Event:Tevent; ID:TMevStr; PointerToObject:pointer); Design Static Override: never Behavior This procedure is used to place a report information about EVENT in the TVM Window using the ID provided. PointerToObject is not used for filtering and is reported as provided. REPORTSTATE procedure ReportState(RType:byte;AState:word;Aflag:boolean; ID:TMevStr;PointerToObject:pointer); Design Static Override: never Behavior This procedure is used to place information about ASTATE in the TVM Window using RType, Aflag, and ID as provided. PointerToObject is not used for filtering and is reported as provided. RType is the type of State condition being reported, i.e. efCurrent, efSet, efChange. If RTYPE <> efChange, then the value of AFLAG is simply reported. However if RTYPE = efChange then AFLAG is used to decide if a report will be made to TVMWindow. A report is made if the following is true ((PointerToObject^.State and AState)>0)=Aflag). This logic is fairly simple. if the State request is already set in the Objects State field, and AFlag is true, a report will be made. If Aflag is false a report will not be made. If the current State of the Object referenced by PointerToObject is not the same as ASTATE, and AFLAG is false, then a report is made, otherwise there is no report. See also: efXXXX REPORTSYSTEM STATE procedure ReportSystemState(ID:TMevStr); Design Static Override: never Behavior This procedure is used to report the amount of heap available and the current Stack Pointer value. Can be used to monitor heap allocation and deallocation. REPORTVALUE procedure ReportValue(P:Pointer; var Value;ValueSize:word; ID:TMevStr); Design Static Override: never Behavior This will report in the TVM Window the contents of Value. Value size is used to determine the type of data passed in Value. 1 - byte, 2 - word, 4 - Longint and pointers. P: is a pointer value included in report. SETMASK procedure SetMask(AMask:word); Design Static Override: never Behavior Can be used under program control to set the current event filter mask for the entire instance of a TVMWindow and all its Event Traps. This option can also be set at run time via the Options menu. SETTONE procedure SetTone(APitch,Alength:word); Design Static Override: not used by TVM Behavior This procedure is used to reset the pitch and length of beep used by TVM. If your machine is fast, you may want to reset the tone length and pitch so you can hear it better. SETTRAP procedure SetTrap(TrapIt:boolean); Design Static Override: never Behavior This can be used to set all reporting off or on for a particular TVM window. This option can also be set at run time via the Options menu. SETTRIP procedure SetTrip(TripIt:boolean); Design Static Override: never Behavior This can be used to set all report tripping off or on for a particular TVM window. This option can also be set at run time via the Options menu. SETOUTPUT procedure SetOutput(DOSFile:String); Design Static Override: never Behavior Sets where report logging where occur. Default on initiation is nul, no report logging. Passing a string with a value of 'PRN' will start logging to the standard list device. Passing a valid filename will start logging to this file. If an invalid file name is passed, then logging is set to NUL. When this routine is called, the current logging destination is closed. The logging target is always opened with a rewrite, which in the case of a file, erases all its former contents. No checking is done to see if the file already exists. TRIP function Trip:boolean; Design Static Override: never Returns true if tripping enabled. TRAP function Trap:boolean; Design Static Override: never Returns true if trapping enabled. MASK function Mask:word; Design Static Override: never Returns the current Event filter mask. Insert_TVMW function TVM Declaration function Insert_TVMWfunction (TG:Pgroup; X,Y:word; Name:string; Anumber:word; EventMask:word; ListSize:word):PTVMonitorWindow; Function This function is used to create and insert a TVM Window into the desktop (or any other PGroup object). It returns a pointer to an TEventMonitorWindow object.(see TTVMonitorWindow.init() ) Delete_TVMW procedure TVM Declaration procedure Delete_TVMW(TG:Pgroup;PEMW:PTVMonitorWindow); Function This procedure is used to remove a TEventMontorWindow object from the desktop (or whatever PGroup it was inserted in. Report_Event procedure TVM Declaration procedure Report_Event (EMW:PTVMonitorWindow; ID:TMevStr; Event:TEvent; PointerToObject:pointer); Function This procedure is used to display a TEvent report in the specified TEventMonitorWindow. Report_SetState procedure TVM Declaration procedure Report_SetState (EMW:PTVMonitorWindow; ID:TMevStr; Request:word; Flag:boolean; PointerToObject:pointer); Function This procedure is used to report the State information in request. This is used to report the information of a call to a SetState method. EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. PointerToObject is a pointer to the Object for which this report pretains, and is used to fetch the current value of its State field. Request is the value that would normally be passed in the SetState() method AState parameter. Flag is the value that would normally be passed in the SetState() enable parameter. TReportProc Datatype TVM Declaration TReportProc = procedure (EMW:PTVMonitorWindow; EntryBP:word; Pobj:Pview; ID:TIdstr; Name:TMethodName); Function This procedure type is used to pass the address of the following reporting procedures. ReportState procedure TVM Declaration procedure Report_State (EMW:PTVMonitorWindow;ID:TMevSTr; PointerToObject:pointer); Function This procedure when executed will insert a report into the EMW Monitor Window. This report will contain information about the value of PointerToObject's state field. ID is used to identify this specific report. Report_StateChange procedure TVM NOT IMPLEMENTED IN BETA SHAREWARE VERSION Declaration procedure Report_StateChange (EMW:PTVMonitorWindow; ID:TMevStr; Request:word; PointerToObject:pointer); Function Used to report a potential change in state. This report is basically the same as Report_SetState except that the report will only be made if the value of Request is not set in PointerToObject's State field. EMW is a pointer to a TVMonitorWindow object, ID is a 3 character string used to identify this report. PointerToObject is a pointer to the Object for which this report pretains, and is used to fetch the current value of its State field. Request is the value that would normally be passed to a SetState() method in the AState parameter. Report_SystemState procedure TVM Declaration procedure Report_SystemState (EMW:PTVMonitorWindow; ID:TMevStr); Function Used to report the current amount of available heap and the value of the Stackptr. Report_Value procedure TVM Declaration procedure Report_Value (EMW:PTVMonitorWindow; P:pointer; ID:TMevStr; var Value; ValueSize:word); Function Used to report the contents of Value using ValueSize to determine the data type of Value. Valid values for ValueSize are: 0 for string datatypes, 1 for byte values, 2 for word/integer values, 4 for longint and pointer values, and 6 for real values. P is a pointer value that will be included in the report line. Frequently used to identifty a particular object. TViewTrap procedure TVM Declaration procedure TViewTrap (EMW:PTVMonitorWindow; P:Pview; WhichTrap, TrapWhen, Mask:word; Aname:TTrapName ); Function This procedure is used to monitor calls to the methods of TView objects. EMW is a pointer to an instatiated object of TTVMonitorWindow type. P is a pointer to an instatiated object of TView type or a descendant. WhichTrap is used to identify which method should be monitored. Valid values include: emEventTrap, emStateTrap, emStateChangeTrap, emPutEventTrap, emGetEventTrap. TrapWhen is used to identify when a report should made. Valid values include toPreTrap and toPostTrap. Mask is the value used to filter which events and state requests will be reported. Valid values for TEvent methods include the TV evXXXX constants and for State methods include the TV sfXXXX constants. Aname is a TMethodName string type that is used in the report to identify this specific trap. See Also: TMethodName, emXXXX constants, and toXXXX constants TVMW Variable TVM Declaration TVMW : PTVMonitorWindow; Function Default Event Monitor Window. Must be instatiated with INIT before use. TVM Chapter TVM Chapter