home *** CD-ROM | disk | FTP | other *** search
- Extending
- Input
- Field
- Types
-
-
-
- "Stay humble. Always answer the phone - no matter who else is in the
- car."
-
- Jack Lemmon
-
-
- One of the most used elements of the Toolkit is the full screen input
- facility. If the Toolkit field types do not meet your exact needs, you
- can create your own custom field types. This chapter explains how.
-
-
- The Input Object Hierarchy
- The objects FormOBJ and WinFormOBJ are used to manage and control full
- screen input. You may recall that the method AddItem is used to add
- individual input fields to the form. AddItem accepts any of the input
- fields shown in the TOTIO Object Hierarchy on page 11.5. As the diagram
- illustrates, all IO objects are descended from the root object Base-
- IOOBJ. If you want to create new input field objects which can be
- managed by the form objects, the new objects must be descended from
- BaseIOOBJ, or any object descended from BaseIOOBJ.
-
- The BaseIOOBJ object includes the following data and methods, which are
- inherited by all descendant objects:
- ItemIOOBJ = object
- vBoundary: tCoords;
- vHotKey: word;
- vID: word;
- vActive: boolean;
- {methods ...}
- constructor Init;
- procedure SetActiveStatus(Selectable:boolean);
- function Active:boolean;
- function GetHotKey: word;
- procedure SetHotkey(HK:word);
- function GetID: word;
- procedure SetID(ID:word);
- function Visible: boolean; VIRTUAL;
- procedure Display(Status:tStatus); VIRTUAL;
- function Select(K:word; X,Y:byte):tAction; VIRTUAL;
- function ProcessKey(InKey:word;X,Y:byte):tAction; VIRTUAL;
- function Suspend:boolean; VIRTUAL;
- destructor Done; VIRTUAL;
- end; {ItemIOOBJ}
-
- Note: the BaseIOOBJ also includes signal-related methods. These are
- discussed in a later section.
-
- 20-2 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- The vBoundary variable identifies the (X1,Y1) and (X2,Y2) coordinates
- of the field. When the user clicks the left mouse button during full-
- form input, the form object scans the list of active input objects and
- moves the user to the input object with coordinates corresponding to
- the mouse cursor position. Any descendant field should therefore update
- the vBoundary variable to indicate the physical location of the field.
- The other three BaseIOOBJ variables identify the field's hotkey, ID and
- whether the field is active or selectable. These variables are managed
- by the BaseIOOBJ methods SetActiveStatus, Active, GetHotkey, SetHotkey,
- SetID and GetID. All these methods are suitable for any field type, and
- should not need modification in descendant objects. Just inherit them
- and use them!
-
- The virtual methods, highlighted in bold, are specific to each descen-
- dant object. As a minimum, any descendant objects should redefine these
- bold methods -- they are the main methods called by the form object
- during full-screen input.
- Apart from special hotkeys and navigation control keys, all the user
- input fields are visible. That is, the user can see them. As the TOTIO
- Hierarchy Diagram illustrates, all visible fields are descended from
- VisibleIOOBJ, which is, in turn, descended from BaseIOOBJ. In addition
- to the BaseIOOBJ objects just discussed, the VisibleIOOBJ objects
- inherit the following methods:
-
- procedure SetLabel(Lbl:string);
- procedure SetMessage(X,Y:byte; Msg:string);
- procedure WriteMessage;
- procedure WriteLabel(Status:tStatus); VIRTUAL;
- As their names suggest, these methods are used to set and display
- labels and messages. Labels are displayed to the immediate left of a
- field and act as a field title. A message is the field's descriptive
- text which is displayed when the user moves to the field. Under normal
- circumstances you will not need to modify these methods. They are
- appropriate to any field type.
-
-
-
- Creating New Field Types
- When you want to create a new field object, you must decide which
- existing field object has the properties most closely resembling the
- new field type you want to create. For example, if the field includes
- data input, then you would probably create a descendant of CharIOOBJ.
- However, if the field has multiple lines (like a radio button or list),
- then the new object would best be a descendant of MultiLineIOOBJ. If
- none of the existing fields come anywhere close, create a descendant
- from VisibleIOOBJ.
-
-
-
- Extending Input Field Types 20-3
- --------------------------------------------------------------------------------
-
- To illustrate the principles, a new boolean object will be created.
- This object will display two different options, e.g. Yes or No, True or
- False, Live or Die, etc. The field will display one of the options, and
- when the user presses the space bar or clicks the mouse, the field will
- flip to the other option.
-
- Since the boolean object does not process individual character input,
- and does not occupy multiple lines, the best object to descend from is
- VisibleIOOBJ. The following methods are inherited from VisibleIOOBJ and
- do not need to be modified:
- procedure SetActiveStatus(Selectable:boolean);
- function Active:boolean;
- function GetHotKey: word;
- procedure SetHotkey(HK:word);
- function GetID: word;
- procedure SetID(ID:word);
- procedure SetLabel(Lbl:string);
- procedure SetMessage(X,Y:byte; Msg:string);
- procedure WriteMessage;
- procedure WriteLabel(Status:tStatus); VIRTUAL;
- function Visible: boolean; VIRTUAL;
-
- As well as replacing Init and Done, the primary inherited methods which
- need to be over-written are Display, Select, Processkey and Suspend.
- These four methods are called by the form object during full screen
- input. Additionally, if you want the new boolean object to function
- stand-alone, i.e. without being part of a form, an Activate method
- should be added. Activate will display the field and process user input
- until [KEYCAP] or [KEYCAP] is pressed.
- In keeping with the Toolkit style, SetValue and GetValue methods should
- also be added. These methods are used to set the object's default
- value, i.e. which option to display when the field is activated, and to
- get the user-selected value after input is complete.
-
- The new boolean object will need to include three data variables: the
- two strings that represent the true and false settings, and a boolean
- to record the object's actual value.
- After all the methods and data have been included, the definition of
- the new BooleanIOOBJ is as follows:
-
- BooleanIOOBJ = object (VisibleIOOBJ)
- OnString: StringBut;
- OffString: StringBut;
- vInput: boolean;
- {methods...}
- Constructor Init(X,Y:byte; Yes,No:stringbut);
- function GetValue: boolean;
- procedure SetValue(On:boolean);
- procedure Activate;
-
-
-
- 20-4 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- procedure Display(Status:tStatus); VIRTUAL;
- function Select(K:word; X,Y:byte):tAction; VIRTUAL;
- function ProcessKey(InKey:word;X,Y:byte):tAction; VIRTUAL;
- function Suspend:boolean; VIRTUAL;
- destructor Done; VIRTUAL;
- end; {BooleanIOOBJ}
-
-
- In the following sections, each method is individually discussed:
-
-
-
- Extending Input Field Types 20-5
- --------------------------------------------------------------------------------
-
- Init
-
- The primary responsibilities of the Init method are to set the values
- of the true and false strings, and to update the vBoundary variable
- with the location of the field. In keeping with the other input fields,
- the Init method is passed the (X,Y) coordinate of the leftmost charac-
- ter. By finding the length of the longest string, the method can com-
- pute the rightmost (X,Y) coordinate. The method detail is, therefore,
- as follows:
- constructor BooleanIOOBJ.Init(X,Y:byte; Yes,No:stringbut);
- {}
- var L:byte;
- begin
- VisibleIOOBJ.Init;
- OnString := Yes;
- OffString := No;
- L := length(OnString);
- if L < length(OffString) then
- L := length(OffString);
- with vBoundary do
- begin
- X1 := X;
- X2 := X + pred(L);
- Y1 := Y;
- Y2 := Y;
- end;
- vInput := true;
- end; {BooleanIOOBJ.Init}
-
-
-
- SetValue and GetValue
- These methods are short and to the point. All they do is set or return
- the value of the field, and are defined as follows:
-
- function BooleanIOOBJ.GetValue: boolean;
- {}
- begin
- GetValue := vInput;
- end; {BooleanIOOBJ.GetValue;
-
- procedure BooleanIOOBJ.SetValue(On:boolean);
- {}
- begin
- vInput := On;
- end; {BooleanIOOBJ.SetValue}
-
-
-
-
- 20-6 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- Display
-
- Display is a virtual method which must be declared with a single passed
- parameter of type tStatus. tStatus is an enumerated type with the mem-
- bers HiStatus, Norm and Off, and the value is used to indicate whether
- the field is highlighted (the field the user is currently editing),
- normal (one of the other fields in a form), or inactive (cannot be
- selected).
- The primary responsibility of Display is to display the field contents
- in the appropriate color. The first task is to decide the display
- attribute. To be consistent with the other input objects, the field
- should ascertain the attribute by calling a TOTIO^ function method.
- TOTIO controls the colors for field labels and messages, button fields,
- group fields, list fields, and single line fields. In this case, the
- single line field colors are appropriate. Refer to page 11-40 for a
- full discussion of IOTOT.
-
- The BooleanIOOBJ method Display is implemented as follows:
- procedure BooleanIOOBJ.Display(Status:tStatus);
- {}
- var Att: byte;
- begin
- case Status of
- HiStatus: Att := IOTOT^.FieldCol(2);
- Norm: Att := IOTOT^.FieldCol(1);
- Off: Att := IOTOT^.FieldCol(4);
- end; {case}
- with vBoundary do
- if vInput then
- Screen.WriteAT(X1,Y1,Att,padleft(OnString,succ(X2-X1),' '))
- else
- Screen.WriteAT(X1,Y1,Att,padleft(OffString,succ(X2-X1),' '));
- end; {BooleanIOOBJ.Display}
-
-
-
- Select
- The Select method is called by the form object whenever the user tries
- to enter the field. The method is responsible for displaying the field
- contents as well as the field's label and message. Select is also
- responsible for moving the cursor to the field.
-
- Select is actually a function method which returns a member of the
- enumerated type tAction. tAction is used to instruct the form object on
- how to proceed, and includes the members None, NextField, PrevField,
- Finished, Escaped, Refresh, Signal, Enter, Help, Stop1..Stop9. Under
- normal circumstances, Select should return a value of None. This
-
-
-
-
- Extending Input Field Types 20-7
- --------------------------------------------------------------------------------
-
- instructs the Toolkit to proceed as normal. The majority of the other
- members are used by "buttons", which the user selects to finish the
- input session or to ask for help.
-
- The BooleanIOOBJ method Select is implemented as follows:
- function BooleanIOOBJ.Select(K:word; X,Y:byte):tAction;
- {}
- begin
- Display(HiStatus);
- WriteLabel(HiStatus);
- WriteMessage;
- Screen.GotoXY(vBoundary.X1,vBoundary.Y1);
- Select := none;
- end; {BooleanIOOBJ.Select}
-
-
-
- ProcessKey
- When a field is active, the form object repeatedly passes the user
- input to the highlighted object. This continues until the user moves to
- another field, or presses a key which indicates the user wants to fin-
- ish the input session.
-
- The form object calls the field's method ProcessKey and passes the user
- input to it. The ProcessKey method then updates the value of the field
- based on the user's input. In the case of the BooleanIOOBJ field, the
- field will flip to the other string whenever the keys [KEYCAP] [KEYCAP]
- or [KEYCAP] are pressed. The field will also flip if the mouse is
- clicked on the field. The Toolkit responds extremely quickly to a mouse
- press, and it is a good idea to delay for a tenth of a second when the
- mouse has been clicked. This overcomes the problem of the field flip-
- ping a dozen or more times each time the user clicks the mouse.
- ProcessKey is a function method which returns a member of the enumer-
- ated type tAction. Under normal circumstances, the function should
- return a value of None, which indicates that the form object should
- continue passing keys to the field.
-
-
-
- Note: if you were creating a different input field type, you might
- want to return a value of NextField when the current field became
- full. This instructs the form object to suspend the current field
- and select the next field.
-
-
-
- The BooleanIOOBJ method ProcessKey is implemented as follows:
-
-
-
-
- 20-8 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- function BooleanIOOBJ.ProcessKey(InKey:word;X,Y:byte):tAction;
- {}
- begin
- if (InKey = 513)
- or (InKey = 32)
- or (inKey = 328)
- or (InKey = 336) then
- begin
- vInput := not vInput;
- Display(HiStatus);
- end;
- if InKey = 513 then {absorb mouse}
- delay(100);
- ProcessKey := None;
- end; {BooleanIOOBJ.ProcessKey}
-
-
-
- Suspend
- The Suspend method is called by the form object when the user wants to
- terminate input or move to another field. Suspend is responsible for
- displaying the field and label in the normal attribute, and for remov-
- ing the field message. All these tasks are performed by the inherited
- VisibleIOOBJ method Suspend.
-
- Suspend is actually a function method which returns a boolean value.
- This provides a mechanism for not allowing the user to leave the field.
- If Suspend returns False, the form object stays in the field. This
- facility should only be used when the user has entered some invalid
- input, and it is good practice to display a message stating how the
- user can correct the problem.
- A user cannot enter an invalid value in a BooleanIOOBJ, and so Suspend
- will always return True. The method Suspend is implemented as follows:
-
- function BooleanIOOBJ.Suspend:boolean;
- {}
- begin
- Suspend := VisibleIOOBJ.Suspend;
- end; {BooleanIOOBJ.Suspend}
-
-
- Activate
-
- The Activate method provides a way to use the object as a stand-alone
- field, i.e. not as part of a form. Activate is responsible for select-
- ing the field, getting input, and passing the input to ProcessKey.
- Activate should repeatedly pass input to ProcessKey until the user
- presses [KEYCAP] or [KEYCAP] to indicate the end of input. The method
- Suspend should then be called to deselect the field.
-
-
-
- Extending Input Field Types 20-9
- --------------------------------------------------------------------------------
-
- The BooleanIOOBJ method Activate is implemented as follows:
-
- procedure BooleanIOOBJ.Activate;
- {}
- var
- Action: tAction;
- begin
- Action := Select(0,0,0);
- with Key do
- begin
- repeat
- GetInput;
- Action := ProcessKey(LastKey,LastX,LastY);
- until ((LastKey = 324) or (LastKey = 13)) and Suspend;
- end;
- end; {BooleanIOOBJ.Activate}
-
-
-
- Done
-
- Since BooleanIOOBJ has no dynamic data of its own, all Done needs to do
- is call VisibleIOOBJ's method Done, as follows:
- destructor BooleanIOOBJ.Done;
- {}
- begin
- VisibleIOOBJ.Done;
- end; {BooleanIOOBJ.Done}
-
-
-
-
- That's the new BooleanIOOBJ defined. The full source code is contained
- in the file EXTIO.PAS.
-
-
- Using BooleanIOOBJ
-
- Since BooleanIOOBJ is inherited from BaseIOOBJ, it can be used in full
- form input just like any other input object. Listed below is the demo
- program EXTDEM7.PAS which shows the new object in action. This demo
- program is actually an adaptation of DEMIO2.PAS discussed in chapter
- 11. Figure 20.1 illustrates the generated display.
- Program ExtendedDemoSeven;
-
- Uses DOS,CRT,
- totFAST, totIO1, totIO2, extIO;
-
-
-
-
- 20-10 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- Var
- Name: LateralIOOBJ;
- Phone: PictureIOOBJ;
- Price: FixedRealIOOBJ;
- Status: BooleanIOOBJ;
- Keys: ControlkeysIOOBJ;
- Manager: FormOBJ;
- Result: tAction;
-
- procedure InitVars;
- {}
- begin
- with Name do
- begin
- Init(35,5,20,40);
- SetLabel('Vendor Name');
- end;
- with Phone do
- begin
- Init(35,7,'(###) ###-####');
- SetLabel('Tel');
- SetRules(JumpIfFull);
- end;
- with Price do
- begin
- Init(35,9,8,2);
- SetLabel('Unit Price');
- SetValue(250.0);
- SetMinMax(0.1,12250.0);
- SetRules(EraseDefault);
- end;
- with Status do
- begin
- Init(35,11,' Nice Guy ',' Jerk ');
- SetLabel('Category');
- end;
- Keys.Init;
- end; {InitVars}
- begin
- ClrScr;
- Screen.TitledBox(15,3,65,13,76,79,78,2,' Quicky Input Demo ');
- Screen.WriteCenter(25,white,'Press TAB to switch fields
- and press ESC or F10 to end');
- InitVars;
- with Manager do
- begin
- Init;
- AddItem(Keys);
-
-
-
-
- Extending Input Field Types 20-11
- --------------------------------------------------------------------------------
-
- AddItem(Name);
- AddItem(Phone);
- AddItem(Price);
- AddItem(Status);
- Result := Go;
- if Result = Finished then
- {update the database..}
- else
- {call Esc routine};
- end;
- end.
-
-
-
- Figure 20.1 [SCREEN]
- Using
- BooleanIOOBJ
-
-
-
- Understanding Signals
- In sophisticated input forms, the data input by a user in one field may
- affect the data of some related fields on the form. Signals provide
- this capability in the Toolkit.
-
-
-
- Signal Theory
- The BaseIOOBJ object includes the following three signal-related meth-
- ods:
-
- procedure RaiseSignal(var TheSig:tSignal); VIR-
- TUAL;
- procedure ShutdownSignal(var BaseSig:tSignal);
- VIRTUAL;
- procedure HandleSignal(var BaseSig:tSignal; var NewSig:tSignal); VIR-
- TUAL;
- The totIO1 unit includes the record tSignal, which is defined as fol-
- lows:
-
- tSignal = record
- ID: word;
- MsgType: word;
- case word of {variant record}
- 0: (MsgPtr: pointer);
- 1: (MsgLong: longint);
- 2: (MsgWord: word);
- 3: (MsgInt: integer);
-
-
-
-
- 20-12 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- 4: (MsgByte: byte);
- 5: (MsgChar: char);
- end;
-
- tSignal is a variant record which can be used to store any data which
- needs to be communicated between input fields.
- An input field's object methods Select, ProcessKey, and ProcessEnter
- are function methods which return a value of type tAction. If any of
- these methods return a value of SIGNAL, the form object will immedi-
- ately call that input object's RaiseSignal method. This method is
- passed a variable parameter of type tSignal. The variable is updated
- with the information which needs to be passed to other fields. Each
- signal has an ID, and the ID should be assigned a non-zero value. In a
- situation where more than one signal can be raised, this ID will indi-
- cate to the other fields which signal is being raised. The signal's
- MsgType field can be used to provide further information about the
- signal, and usually indicates the format of the data being passed with
- the signal, e.g. a 1 might indicate a longint, a 2 might indicate a
- word, etc.
-
-
-
- Note: Input objects which are descended from CharIOOBJ inherit the
- virtual function method ProcessEnter. This method is passed no
- parameters, and returns a value of type tAction. The method is
- called whenever the user presses [KEYCAP]. It is typically used to
- raise a signal or move the user to the next field.
-
-
-
- When a field raises a signal, the form manager passes the signal to the
- next field in the form. This is achieved by calling the next field's
- method HandleSignal. This method is passed the tSignal variable raised
- by the originating field. The HandleSignal method can inspect the sig-
- nal ID and, if appropriate, respond to the signal. If the field han-
- dling the signal knows that the signal is not intended for any other
- field, it can update the signal ID with a value of 0. This tells the
- form object that the signal has been handled, and the signal is dis-
- carded. Otherwise, the signal is passed to each input field in turn
- until one of the fields sets the ID to 0, or until all the fields have
- been passed the signal.
-
- When the signal has been handled or passed to every other field, the
- originating field's ShutdownSignal method is called. This method can be
- used to dispose of any data that was created specifically for the sig-
- nal, and for any other housekeeping.
-
-
-
-
- Extending Input Field Types 20-13
- --------------------------------------------------------------------------------
-
- Any object which handles a signal can optionally raise a signal of its
- own. The HandleSignal method is passed two parameters of type tSignal.
- The first parameter is the original signal raised by another field. The
- second parameter is an empty signal which the handling field can update
- with its own signal. The form object inspects the second signal
- returned by the field's HandleSignal method, and if the ID is set to a
- non-zero value, a new signal is raised and passed to the other fields.
- Only when this new signal has been handled will the form manager con-
- tinue with the processing of the original signal.
-
-
-
- A Signal Example
- The way to use signals is best illustrated by example. In this section
- a demo program will be developed which prompts the user to input some
- directories, as a precursor to installing some software. The user is to
- be prompted to input five different directories, one for the programs,
- one for the doc files, etc. Like Turbo Pascal's own Install program,
- each of the input fields needs to be updated if the user enters a new
- default directory into the first field.
-
- To solve this problem, two new field objects must be created, and both
- of them will be descended from StringIOOBJ. One object will be used to
- prompt the user to input the default directory, and will raise a signal
- when the user changes the field value. The other object will be used
- for the input of the other directories, and will include a method to
- handle the signal raised by the first object.
- In this example, the first object is called MasterStringIOOBJ, and it
- will raise a signal whenever the user enters a new directory. The new
- object is declared as follows:
-
- TYPE
- MasterStringIOOBJ = object (StringIOOBJ)
- vLastInput: string;
- {methods}
- constructor Init(X,Y,FieldLen: byte);
- function ProcessEnter: tAction; VIRTUAL;
- function Select(K:word; X,Y:byte): tAction; VIRTUAL;
- procedure RaiseSignal(var TheSig:tSignal); VIRTUAL;
- procedure ShutdownSignal(var BaseSig:tSignal); VIRTUAL;
- function Suspend:boolean; VIRTUAL;
- destructor Done; VIRTUAL;
- end; {MasterStringIOOBJ}
-
- The new object should only raise a signal when the user has changed the
- value of the field. The new string variable vLastInput is used to
- record the value of the string when the field is selected. The value of
-
-
-
-
- 20-14 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- vLastInput can then be compared to vInputStr (the edited field value)
- when the user tries to leave the field or presses [KEYCAP]. The method
- Select is therefore declared as follows:
-
- function MasterStringIOOBJ.Select(K:word; X,Y:byte): tAction;
- {}
- begin
- vLastInput := vInputStr;
- Select := StringIOOBJ.Select(K,X,Y);
- end; {MasterStringIOOBJ.Select}
-
- The object needs to raise a signal when the user presses [KEYCAP]. The
- method ProcessEnter is implemented as follows:
-
- function MasterStringIOOBJ.ProcessEnter: tAction;
- {}
- begin
- if vLastInput <> vInputStr then {need to signal}
- ProcessEnter := Signal
- else
- ProcessEnter := none;
- end; {MasterStringIOOBJ.ProcessEnter}
- If the value of the string has changed, SIGNAL is returned, otherwise
- NONE is returned.
-
- The object also needs to raise a signal when the method Suspend is
- called, and the value of the field has changed. Now we are faced with a
- problem, because Suspend cannot directly raise a signal. Suspend
- returns a boolean value to indicate whether the field can be suspended,
- not a tAction value. The trick is to return a boolean value of False,
- indicating that the user may not leave the field, and then stuff the
- keyboard with the keystrokes [KEYCAP] [KEYCAP]. The Toolkit will not
- allow the user to leave the field, the [KEYCAP] key will then be pro-
- cessed, thereby raising a signal via the ProcessEnter method, and
- finally, the [KEYCAP] key will be processed to move the user to the
- next field. The Suspend method is implemented as follows:
- function MasterStringIOOBJ.Suspend:boolean;
- {}
- begin
- if vLastInput <> vInputStr then {need to signal}
- begin
- Suspend := false;
- Key.StuffBuffer(13); {Enter}
- Key.StuffBuffer(9); {Tab}
- end
- else
- Suspend := StringIOOBJ.Suspend;
- end; {MasterStringIOOBJ.Suspend}
-
-
-
-
- Extending Input Field Types 20-15
- --------------------------------------------------------------------------------
-
- The RaiseSignal method must update the signal variable with the infor-
- mation required by the other fields, i.e. the string representing the
- new directory entered by the user. The RaiseSignal method is
- implemented as follows:
-
- procedure MasterStringIOOBJ.RaiseSignal(var TheSig:tSignal);
- {}
- begin
- with TheSig do
- begin
- ID := SignalNewDirectory;
- MsgType := length(vInputStr);
- MsgPtr := @vInputStr;
- end;
- vLastInput := vInputStr;
- end; {MasterStringIOOBJ.RaiseSignal}
- The signal ID is set to SignalNewDirectory -- a constant assigned the
- value of 1. The MsgType field is set to indicate the length of the
- string, and the variant record MsgPtr is updated to point to the user
- input string. This signal, therefore, provides sufficient data for the
- dependent fields to ascertain the new directory.
-
- In this example, no dynamic data is created for the signal, and so the
- ShutdownSignal method doesn't need to do anything.
-
- Now let's turn our attention to the object which needs to respond to
- the signal raised by MasterStringIOOBJ. In this example, we will name
- the new object SlaveStringIOOBJ, and it will inherit all the properties
- of StringIOOBJ. The only method (in addition to Init and Done) which
- needs to be updated is HandleSignal. This method needs to check the
- value of the Signal and update the value of the field with the new
- directory string. The signal field MsgType stores the length of the new
- string, and the field MsgPtr points to the new string.
-
- The HandleSignal method is implemented as follows:
- procedure SlaveStringIOOBJ.HandleSignal(var BaseSig:tSignal; var NewS-
- ig:tSignal);
- {}
- var temp:string;
- begin
- with BaseSig do
- begin
- if (ID = SignalNewDirectory) then
- begin
- move(MsgPtr^,Temp,succ(MsgType));
- if Temp <> vInputStr then
- begin
- vInputStr := Temp;
-
-
-
-
- 20-16 Extending the Toolkit
- --------------------------------------------------------------------------------
-
- Display(Norm);
- end;
- end;
- end;
- end; {SlaveStringIOOBJ.HandleSignal}
-
-
-
- To recap, two new field objects have been created. A MasterStringIOOBJ
- field raises a signal when its value is changed, and SlaveStringIOOBJ
- fields change their value accordingly. The on-disk demo file EXT-
- DEM8.PAS includes the full solution to the problem. Figure 20.2 illus-
- trates the output generated by this program.
-
-
- Figure 20.2 [SCREEN]
- Raising
- Signals
-
-
- Review the source code of the DirWinOBJ object in totDIR for another
- example of how fields can communicate with signals.