OpenInsight's Windows 95 Features and Controls (Functions/Subroutines/Programs)

OpenInsight for Workgroups simulates selected Windows 95 controls and features including tabbed dialog boxes[#TDB], hot spots[#HS],wizards[#WZ], and gas gauge[#GG].

 

Tabbed Dialog Boxes

Windows 95 brought another enhancement to the user interface by introducing tabbed dialog boxes. In OpenInsight for Workgroups, tabbed dialogs can be created using a multi-page form, check boxes with .BMPs, radio buttons, a group box control, QuickEvents and procedural event handlers, and some fancy coding.

The window below is provided in the EXAMPLES application.

Setting Up the Form

Create a multi-page form; create one check box for each page of the form, and create a group box.

 

The each check box must use the bitmap can use the bitmap TAB10822 that is registered in the repository. In addition, each check box must be named in a special way to use the example code. The name of the check box controls  must use the format  PAGE_x_TAB 

where x = the page number associated with the tab. The check box controls are used to display the tabs because check boxes can display bitmaps.

 

Any control that needs to appear on all pages should end with  _FIX .  For example, the group box in the example in named GB_FRAME_FIX (accept for the check box controls).

 

These special naming conventions are used during the window s CREATE event to locate the controls that needs to be persistent or fixed on all pages of the form.

 

The text for the group box is set to "          " (a whole bunch of spaces equal to the length of the tabs) so that the tabs, when pressed, don't have a line under them from the group box.  The window is then sized to display correctly without a scroll bar (which is hidden by the CREATE event handler).

The Code

There are 2 event handlers on this window used to implement the tab feature: one for the CREATE event and one for the PAGE event. In addition, each tab (on GOTFOCUS) uses a QuickEvent to send a PAGE event to the window specifying which page to go to.

 

In the CREATE event handler, the check-boxes are destroyed and recreated as radio buttons; the reason is that radio buttons have a default behavior of allowing only one to be selected at a time and that is the behavior that tabs have as well. The structure of the controls is defined in the insert PS_EQUATES (in the SYSPROCS table).  The following code destroys a check-box control and recreates it as a radio button:

/* this code assumes that the variable Ctrl is set to the control ID to be re-created as a radio button */

declare subroutine Utility

$insert PS_Equates

Struct = Get_Property(Ctrl, "ORIG_STRUCT")

Utility("DESTROY", Ctrl)

Struct<1,PSPOS_TYPE$> = PSCTL_RADIOBMP$

Utility("CREATE", Struct)

Refer to the code for more information.

 

The following properties are used in the CREATE event handler:

CTRLMAP list of controls on the window
ORIG_STRUCTinternal structure of the controls
PREVIOUS previous prompt in the tabbing order
NEXT next prompt in the tabbing order
IMAGECLIP clip the image if it is too large
DRAWTEXT any text after "" (vertical bar) is drawn on the bitmap

(ie. tabs)
PAGELIST list of pages that control appears on; -1 means all pages
VPOSITION 1:@fm:1:@fm:1 hides scroll bar
VISIBLE window is created invisible to suppress flicker during setup
FOCUS sets focus to a particular control; note that the tabs act on GOTFOCUS

The code for the CREATE event handler follows:                                                                      

declare function   Get_Property

declare subroutine Set_Property, Utility, Send_Event

 

$insert PS_Equates

equ TRUE$  to 1

equ FALSE$ to 0

/* tab controls must start with "PAGE_" and end with "_TAB" with a number in between representing the page number associated with the tab */

equ TAB_PREFIX$    to  "PAGE_"

equ TAB_SUFFIX$    to  "_TAB"

* any control that should appear on all pages should end with "_FIX"

equ FIX_SUFFIX$    to  "_FIX"

* put up hourglass during processing

Utility("CURSOR", "H")

/* build list of properties to set; setting multiple properties at once is faster than setting them individually */

Ctrls = ""

Props = ""

Vals  = ""

* get list of all controls on the window

CtrlList = Get_Property(@window, "CTRLMAP")

cCtrls   = count(CtrlList, @fm) + (CtrlList # "")

TabList  = ""

for iCtrl = 1 to cCtrls

  Ctrl = CtrlList<iCtrl>

  * is the control "fixed"?  (ie. should it appear on every page)

  if Ctrl [neg(len(FIX_SUFFIX$)), len(FIX_SUFFIX$)] = FIX_SUFFIX$ then

    /* by setting the list of pages to "-1", the control will appear

      on each page */

    Ctrls := Ctrl      : @rm

    Props := "PAGELIST": @rm

    Vals  := -1        : @rm

  end

  * is the control a tab?

  if Ctrl [index(Ctrl, ".", 1) + 1, len(TAB_PREFIX$)] = TAB_PREFIX$ and    Ctrl[neg(len(TAB_SUFFIX$)),len(TAB_SUFFIX$)] = TAB_SUFFIX$ then

    * build a list of tabs (all tab processing is done later)

    TabList←1> = Ctrl

  end

next iCtrl

* get control structures and tab order for each of the tabs

convert @fm to @rm in TabList

cTabs      = count(TabList, @rm) + (TabList # "")

List       = Get_Property(TabList: @rm: TabList: @rm: TabList, str("ORIG_STRUCT": @rm, cTabs): str("PREVIOUS": @rm, cTabs): str(@rm: "NEXT", cTabs) [2,9999])

StructList = field(List, @rm, 1, cTabs)

PrevList   = field(List, @rm, cTabs + 1, cTabs)

NextList   = field(List, @rm, cTabs * 2 + 1, cTabs)

convert @rm to @fm in TabList

convert @rm to @fm in StructList

convert @rm to @fm in PrevList

convert @rm to @fm in NextList

* page tab processing

for iTab = 1 to cTabs

  Tab = TabList<iTab>

  /* page tabs require two pieces of work to be done:

    (1) the tab is placed on the form as a check-box; a check-box has

        an "up" (off) and a "down" (on) state but it is not related to

        any other controls (the other tabs); to relate the tabs such

        that only one can be "down" at a time, each tab must be

        destroyed and recreated as a radio button (only one radio

        button can be selected at a time);

    (2) each page has a circular tab order; this means that you tab

        from the page tab to the first control on the page through the

        last control on the page and back to the page tab; since you

        can not set up multiple separate tab orders using the form

        designer, you must specify the tab order in the form designer

        in the following manner: page-tab 1, controls on page 1,

        page-tab 2, controls on page 2, etc.; this event handler will

        then dynamically rearrange the tabs destroy checkbox

  Utility("DESTROY", Tab)

  * change structure to specify radio button

  StructList<iTab,PSPOS_TYPE$>  = PSCTL_RADIOBMP$

  StructList<iTab,PSPOS_VALUE$> = (iTab = 1)

  * after the new tab (radio button) is created, set it to clip its

  * image, draw the tab "label", and appear on every page

  Ctrls := Tab        : @rm: Tab       : @rm: Tab       : @rm

  Props := "IMAGECLIP": @rm: "DRAWTEXT": @rm: "PAGELIST": @rm

  Vals  := 1          : @rm: 1         : @rm: -1        : @rm

  * re-arrange tab order

  * the first control on page n (where n is the page represented by the

  * tab control being processed) is the NEXT property of the tab; the

  * last control on page (n-1) is the PREVIOUS property of the tab

  * except if n=1 then the PREVIOUS property represents the last control

  * on the last page of the form

  if iTab = cTabs then

    NextPage = 1

  end else

    NextPage = iTab + 1

  end

  * circularly link the tabs with their pages

  Ctrls := Tab               : @rm: Tab           : @rm

  Props := "PREVIOUS"        : @rm: "NEXT"        : @rm

  Vals  := PrevList<NextPage>: @rm: NextList<iTab>: @rm

next iTab

* create radio buttons to replace check boxes

Utility("CREATE", StructList)

* set min-scroll pos equal to max scroll pos to hide scroll bar

VPos = 1: @fm: 1: @fm: 1

* hide the scroll bar, make the window visible and start on the first page

Ctrls := @window    : @rm: @window  : @rm:  SYSTEM 

Props := "VPOSITION": @rm: "VISIBLE": @rm: "FOCUS"

Vals  := VPos       : @rm: TRUE$    : @rm: TabList<1>

* set all properties at once

Set_Property(Ctrls, Props, Vals)

* restore cursor

Utility("CURSOR", "A")

return 0

 

The code for the PAGE event handler follows:

declare subroutine Forward_Event, Set_Property

equ TRUE$  to 1

equ FALSE$ to 0

/* tab controls must start with "PAGE_" and end with "_TAB" with a           number in between representing the page number associated with the tab */

equ TAB_PREFIX$    to  "PAGE_"

equ TAB_SUFFIX$    to  "_TAB"

* handle the page event

Forward_Event(PageAction)

* radio buttons do not auto-check on gotfocus so explicitly set the check

Set_Property(@window: ".": TAB_PREFIX$ : Get_Property(@window, "VPOSITION")

 <1>: TAB_SUFFIX$, "CHECK", TRUE$)

return 0

 

The GOTFOCUS QuickEvent for each check box sends a PAGE event to the window specifying which page to go to.

If you have any questions on this code, be sure to post them on the threaded discussion database at www.revelation.com.

 

OpenInsight s Implementation of Hot Spots

Hot spots, or graphical navigators, are special locations on a form s background, which when clicked, trigger the execution of a user-defined response, or event handler. The hot spot location can be identified with balloon help and is usually associated with something distinctive in a form s background. The event handler associated with clicking the hot spot can be procedural (code specified) or non-procedural (using a QuickEvent). Hot spots are implemented using properties, defining bitmaps for controls, and defining an event handler for a click event.

There are three requirements for creating a hot spot:

           the form must use a bitmap for the background;

           you must create the hot spot as a push-button or a check box control; and

           whether you choose a push-button or check box control, the Bitmap Entity  Transparent  must be selected.

Optionally, to display balloon help for the hot spot, clear the Combine Text/Bitmap option and enter balloon text in the Text edit line (for example, |TEXAS ) in the Properties dialog box for the selected control.

The bitmap selected for the form s background, generally has a picture in it that you want to use as the location of a hot spot. For example, in a map of the United States, each state can contain a hot spot. When you pause the mouse cursor over a state, balloon help might provide the name of the state. In addition, when you click the state, you might display an OpenInsight report containing quarterly sales figures.

The procedure that follows provides general steps for creating a hot spot.

Procedure:  To Create a Hot Spot

1.     Select a bitmap for the form s background with the Tiled option selected. Alternatively, the Clipped option may be used.

2.     Position a push-button or check box on the form where you want to place a hot spot.

3.     In the Push Button or Check Box Properties dialog box, select the  Transparent  bitmap supplied by OpenInsight and the Clip option.

4.     To display balloon help at runtime, clear the Combine Text/Bitmap option for the control and enter balloon help text in the Text edit line. The balloon help text must be precede by the vertical bar  |  , for example, |TEXAS.

 

 

Create an event handler for the CLICK event for the push-button or check box control, using either a QuickEvent or a procedural event handler, to provide a response to when an end user clicks on the hot spot.

 

 

Wizards

Wizards provide a great user interface (UI) for processes involving a series of steps. The user is prompted to provide information and make choices through a series of screens that facilitate an information gathering process required to perform a task. The new Data Warehousing wizard is an example of this type of interface. The following information provides information about using the Wizard Designer.

The Create Wizard menu option in the UI workspace executes a wizard which lets you design other wizards. The Wizard Designer creates a multi-part OpenInsight form which when executed can prompt the user for input in order to perform a task or operation. The new wizard form can then be modified in the Form Designer. The Wizard function implements the features specified in the new wizard form. The wizard form uses the QuickEventOption "Execute a procedure" to call the Wizard function. The functionality exposed by the Wizard function is described below:

 

 

First ParameterFunctionality
'Init' Called from the CREATE event of the wizard.  Initializes the wizard, determines the tab order for each page, and sends the PAGE event to the wizard to initialize page 1.
'Back' Called from the CLICK event of the BACK button.  Re-enables the NEXT button if necessary and sends the PAGE event to the wizard to move to the previous page.
'Next' Called from the CLICK event of the NEXT button.  Re-enables the BACK button if necessary and sends the PAGE event to the wizard to move to the next page.
'Page' Called from the PAGE event of the wizard.  Sets the tab order for the page that is being displayed.
'Finish'   Called from the CLICK event of the FINISH button.  Closes the wizard.
'Cancel' Called from the CLICK event of the CANCEL button.  Closes the wizard.
'Select Text' Called from the GOTFOCUS event of edit lines on the wizard.  Highlights the text in the edit control by setting the SELECTION property. Optionally sends a CHANGED event to the edit control, allowing the 'Required' processing (see below) to be executed.
'Required' Called from the CHANGED event of edit lines and list boxes on the wizard.  Disables the NEXT button if no data is present or enables the NEXT button if data is present.
'Browse' Called from the CLICK event of a Browse button.  Browse buttons are automatically placed on the "File browse"-style sheets.

 

Additional QuickEvent parameters:

First Parameter Additional Parameters 
'Select Text' CtrlEntID             (optional, defaults to current focus) Pass the name of the edit control
  FakeChanged (optional, defaults to false) Pass true to generate a CHANGED event for the edit control
'Required' CtrlEntID             (optional, defaults to current focus) Pass the name of the edit or listbox control
'Browse' (files CtrlEntID             Pass the name of the edit control that displays the file name
  Type Pass the literal 'File'
  Mode    Pass the literal 'Open' or 'Save'
  InitDir   (Optional, defaults to OpenInsight directory) Pass the initial directory
  Filter      (Optional, defaults to 'All Files (*.*)/*.*/') Pass the filter definition; see Utility("CHOOSEFILE") for more information.
'Browse' (dir's)     CtrlEntID             Pass the name of the edit control that displays the file name
  Type      Pass the literal 'Dir'
  Title       (optional, defaults to none)
  InitDir   (optional, defaults to OpenInsight directory) Pass the initial directory

                               

Gas Gauge Control

 

The gas gauge control or progress indicator provides visual feedback to the end user about the progress of some task that is being processed.  InOpenInsight for Workgroups this control is provided via the creative use of the Set_ and Get_Property functions, two controls, and a little fancy mathematics. The code that updates the gas gauge is usually called from the process whose progress you want to reflect. For example, when you use the new Web_Publisher to convert an OpenInsight form executable to an HTML page,  you can monitor the progress of the conversion process by watching the gas gauge control in the status line of that window. Gas gauges usually appear in dialog boxes and on MDI frames.

What s included here is a brief discussion of how to setup a gas gauge control and the code for the sample window below. This window simulates the work of the indicator via the CLICK event for the button on the window, which is not what you would normally do, but it provides a simple example to illustrate the code involved.

kb0124_4.jpg

The window above contains a small static text control which overlays the editline. The static text control is used as a template for the  stripes  that fill in the edit line. The size of the static text control is not very important at this point as it is resized later in the code. You may have to adjust the left alignment of the static control later so that the gas gauge lines up correctly within the edit line. Refer to the figure below.

kb0124_5.jpg

Set the following properties:

window 3D true
editline disabledtrue
static textdisabledtrue
visible false  

 

                                select a background color for the progress

Now for the code .

Code is used in two places - in the CREATE event for the window that contains the indicator and in a stored procedure that manages the indicator.

On the CREATE event for the window you do all of your preliminary setup work:

1.     You get a list of the properties of the static text control and the size of the editline.

2.     The original static text gets destroyed and an array of invisible static text controls is created based on the size of the editline.

3.     The first element in the array is positioned at the beginning of the editline.

The code for the CREATE event for the example window above follows:

declare function utility

$insert Ps_Equates

equ STRIPES_NUMBER$ to 20

indStrct = get_property(@window : ".TB_", "ORIG_STRUCT")

indSize = get_property(@window : ".EL_", "SIZE")

nameBase = indStrct<1, PSPOS_NAME$>

* we don't need the old one any more

notUsed  = utility("DESTROY", @window : ".TB_")

indStrct<1, PSPOS_WIDE$> = int(indSize<3> / STRIPES_NUMBER$ + .5) - 1

xOffSet = indStrct<1, PSPOS_X$>

* sets of the structure for the static text control

for i = 1 To STRIPES_NUMBER$

     indStrct<1, PSPOS_NAME$> = nameBase : I

     indStrct<1, PSPOS_X$> = (i - 2) * (indStrct<1, PSPOS_WIDE$> |

          + 1) + xOffSet

     * creates a new stripe

     notUsed = utility("CREATE", indStrct)

next I

* sets a user-defined property used to monitor the progress to 0%

x = set_property(@window, "@PERCENT", 0)

RETURN 0

The following code would usually be called from the procedure you want to manage the indicator.  In the example, the CLICK event for the button triggers the display of the  stripes .  The following occurs in the code:

1.             The user-defined property used to monitor the progress is incremented.

2.             A check is made to make sure you don t overfill/underfill the editline.

3.             You setup as many static text controls as you need to display the progress, but less than STRIPES_NUMBERS$.

4.             And most importantly, you set the VISIBLE properties for all the static text controls needed. This property is set for all the controls at one time to avoid the screen from flashing.

declare function max, min

equ STRIPES_NUMBER$ to 20

Param1 = get_property(@window, "@PERCENT") + .05

nextStripe = int(Param1 * STRIPES_NUMBER$)

* make sure we are within the range

nextStripe = max(min(nextStripe, STRIPES_NUMBER$), 0)

Ctrls = ""

Vals  = ""

for i = 1 to STRIPES_NUMBER$

     Ctrls := @window : ".TB_" : i : @rm

     Vals  := (i Le nextStripe)     : @rm

next i

x = set_property(Ctrls, "VISIBLE", Vals)

x = set_property(@window, "@PERCENT", Param1)

RETURN 0

  • kb/kb_articles/kb0124.txt
  • Last modified: 2024/01/30 13:36
  • by 127.0.0.1