Project

General

Profile

Progress Indicator Widget and OCX Replacement

The 4GL doesn't offer a progress bar control out of the box. As a workaround slider widget can be used as a replacement. Another solution we have seen at our customers was the use of OCX controls. The commonly used ones is Microsoft's ProgressBar from the Windows Common Control library.

PROGRESS-BAR

To simplify the modernization of applications that use OCX components, which are bound to the Windows OS and can't be easily moved in the web, we implemented a PROGRESS-BAR widget as an extension to the 4GL language. The widget can be used as any other 4GL widget, see below for an example.

DEFINE VARIABLE hProgBar AS HANDLE NO-UNDO.

CREATE PROGRESS-BAR hProgBar 
   ASSIGN
     FRAME = FRAME F:HANDLE
       ROW    = 3.62
       COLUMN = 5
       HEIGHT = 1.2
       WIDTH  = 104
       VISIBLE = TRUE.

/* PROGRESS-BAR methods and attributes */
hProgBar:OLE-DROP-MODE = 1.
hProgBar:PB-APPEARANCE = 1.
hProgBar:PB-BORDER-STYLE = 0.
hProgBar:PB-ORIENTATION = 0.
hProgBar:PB-SCROLLING = 1.
hProgBar:PB-MAX = 100.
hProgBar:PB-MIN = 0.
hProgBar:PB-VALUE = 30.
hProgBar:PB-MOUSE-POINTER = 3.
hProgBar:OLE-DRAG().
hProgBar:PB-REFRESH().

/* PROGRESS-BAR mouse events */
ON "MOUSE-CLICK" OF hProgBar 
DO:
    MESSAGE "Click!".
END.

The extension only exists in FWD, it doesn't work in OpenEdge. The API of the PROGRESS-BAR widget is compliant with Microsoft ProgressBar OCX (VB 6.0 common control). This make the conversion process more straightforward.

Attributes

Attribute Name OCX Name Handle Type Return Type Read Only Default Description
PB-APPEARANCE Appearance PROGRESS-BAR INTEGER N 0 Returns/sets whether or not controls, Forms or an MDIForm are painted at runtime with 3-D effects.
AppearanceConstants: cc3D=1 ccFlat=0
PB-BORDER-STYLE BorderStyle PROGRESS-BAR INTEGER N 0 Returns/sets border style for an object.
BorderStyleConstants - ccFixedSingle=1 ccNone=0
PB-ENABLED Enabled PROGRESS-BAR LOGICAL N FALSE Returns/sets a value that determines whether the control can respond to user-generated events.
PB-MIN Min PROGRESS-BAR DECIMAL N 0.0 Returns/sets a control's minimum value.
PB-MAX Max PROGRESS-BAR DECIMAL N 100.0 Returns/sets a control's maximum value.
PB-VALUE Value PROGRESS-BAR DECIMAL N 0.0 Returns or sets a control's current Value property
PB-MOUSE-ICON MouseIcon PROGRESS-BAR CHARACTER N UNKNOWN Sets a custom mouse icon.
PB-MOUSE-POINTER MousePointer PROGRESS-BAR INTEGER N 0 Returns/sets the type of mouse pointer displayed when over part of an object.
MousePointerConstants - ccArrow=1 ccArrowHourglass=13 ccArrowQuestion=14 ccCross=2 ccCustom=99 ccDefault=0 ccHourglass=11 ccIBeam=3 ccIcon=4 ccNoDrop=12 ccSize=5 ccSizeAll=15 ccSizeEW=9 ccSizeNESW=6 ccSizeNS=7 ccSizeNWSE=8 ccUpArrow=10
OLE-DROP-MODE OLEDropMode PROGRESS-BAR INTEGER N 0 Returns/Sets whether this control can act as an OLE drop target.
OLEDropConstants - ccOLEDropManual=1 ccOLEDropNone=0
PB-ORIENTATION Orientation PROGRESS-BAR INTEGER N 0 Returns/sets a value that determines whether the Progress Bar is displayed vertically or horizontally.
OrientationConstants - ccOrientationHorizontal=0 ccOrientationVertical=1
PB-SCROLLING Scrolling PROGRESS-BAR INTEGER N 0 Returns/sets a value that determines whether the control displays progress with a standard segmented bar or a smooth bar.
ScrollingConstants - ccScrollingSmooth=1 ccScrollingStandard=0

Methods

Method Name OCX Name Handle Type Return Type Parameters Description
OLE-DRAG OLEDrag PROGRESS-BAR NO-RETURN-VALUE N/A Start an OLE drag/drop event with the given control as the source.
PB-REFRESH Refresh PROGRESS-BAR NO-RETURN-VALUE N/A Refresh control.

Mouse events

Event Name OCX Name Affected Widget Description
MOUSE-CLICK Click PROGRESS-BAR Triggered when mouse is clicked
MOUSE-DOWN MouseDown PROGRESS-BAR Triggered when one of the mouse button is down.
MOUSE-MOVE MouseMove PROGRESS-BAR Triggered when mouse pointer is moved over control area.
MOUSE-UP MouseUp PROGRESS-BAR Triggered when one of the mouse button is up.

The OCX procedures to handle mouse events looks like:

PROCEDURE <event-proc-prefix>.Click : 
END PROCEDURE.

PROCEDURE <event-proc-prefix>.MouseDown : 
    DEFINE INPUT PARAMETER Button AS INTEGER.
    DEFINE INPUT PARAMETER Shift AS INTEGER.
    DEFINE INPUT PARAMETER x AS INTEGER.
    DEFINE INPUT PARAMETER y AS INTEGER.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.MouseMove : 
    DEFINE INPUT PARAMETER Button AS INTEGER.
    DEFINE INPUT PARAMETER Shift AS INTEGER.
    DEFINE INPUT PARAMETER x AS INTEGER.
    DEFINE INPUT PARAMETER y AS INTEGER.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.MouseUp : 
    DEFINE INPUT PARAMETER Button AS INTEGER.
    DEFINE INPUT PARAMETER Shift AS INTEGER.
    DEFINE INPUT PARAMETER x AS INTEGER.
    DEFINE INPUT PARAMETER y AS INTEGER.
END PROCEDURE.

OCX mouse events procedures parameters:

Attribute Name OCX Name Handle Type Return Type Read Only Description
OCX-MOUSE-BUTTON Button PROGRESS-BAR INTEGER Y Returns which, if any, of the mouse buttons has changed state.
OCX-SHIFT Shift PROGRESS-BAR INTEGER Y Returns state of all modal keys, such as ALT, CTRL, META, and the mouse buttons just after the event occurred.
OCX-MOUSE-X x PROGRESS-BAR INTEGER Y Returns the horizontal x position of the event relative to the source component.
OCX-MOUSE-Y y PROGRESS-BAR INTEGER Y Returns the vertical y position of the event relative to the source component.

When PROGRESS-BAR is used like a 4gl extension widget a typical definition of mouse events triggers looks like:

on "mouse-click" of progBar 
do:
    message "Click!".
end.

on "mouse-down" of progBar 
do: 
   define variable Button as integer.
   define variable Shift as integer.
   define variable x as integer.
   define variable y as integer.

   Button = progBar:ocx-mouse-Button.
   Shift  = progBar:ocx-mouse-Shift.
   x = progBar:ocx-mouse-x.
   y = progBar:ocx-mouse-y.

   message "MouseDown!" x y Button Shift.
end.

on "mouse-move" of progBar 
do: 
   define variable Button as integer.
   define variable Shift as integer.
   define variable x as integer.
   define variable y as integer.

   Button = progBar:ocx-mouse-Button.
   Shift  = progBar:ocx-mouse-Shift.
   x = progBar:ocx-mouse-x.
   y = progBar:ocx-mouse-y.

   message "MouseMove!" x y Button Shift.
end.

on "mouse-up" of progBar 
do: 
   define variable Button as integer.
   define variable Shift as integer.
   define variable x as integer.
   define variable y as integer.

   Button = progBar:ocx-mouse-Button.
   Shift  = progBar:ocx-mouse-Shift.
   x = progBar:ocx-mouse-x.
   y = progBar:ocx-mouse-y.

   message "MouseUp!" x y Button Shift.
end.

OLE Drag & Drop events

Event Name OCX Name Affected Widget Description
OLE-START-DRAG OLEStartDrag PROGRESS-BAR Occurs when an OLE drag-drop operation is initiated either manually or automatically.
This event is initiated as soon as the control's OLEDrag() method is invoked.
If a value is not assigned to the Data parameter then the GetData method of the DataObject initiates the OLESetData event to obtain the data.
OLE-SET-DATA OLESetData PROGRESS-BAR Occurs at the drag-drop source control when the drop target requests data that was not provided to the DataObject.
This event is initiated when the target control requests data and the DataObject does not have data for that format because delayed rendering was used in the OLEStartDrag event.
OLE-DRAG-OVER OLEDragOver PROGRESS-BAR Occurs when the mouse is moved over the target control during an OLE drag-drop operation.
OLEDropMode property must be set to 1 (OLEDropModeManual) for the OLEDragOver event to occur.
The Effect parameter is passed to this event from the OLEDragOver event (target control).
Note: If the State parameter is set to 2 (Leave), indicating the pointer is outside of the control, then the X and Y parameters will be set to zero.
OLE-GIVE-FEEDBACK OLEGiveFedback PROGRESS-BAR Provides visual feedback through the pointer, by the source control for a drag-drop operation.
If the DefaultCursors parameter is set to False, use the MousePointer property of the Screen object to specify the customized pointer.
Fired after every OLEDragOver event to allow the source component to provide visual feedback to the user.
OLE-DRAG-DROP OLEDragDrop PROGRESS-BAR Occurs when data is dropped onto the control.
The OLEDropMode property must be set to 1 (OLEDropModeManual) for the OLEDragOver event to occur.
The OLEDragOver event occurs at the target control when the mouse button is released. After this event occurs, call the GetFormat method of the DataObject to query whether or not the desired format is available, then call the GetData method of the DataObject to retrieve the data.
The Effect parameters are passed to this event from the OLEStartDrag event (source control).
OLE-COMPLETE-DRAG OLECompleteDrag PROGRESS-BAR Occurs at the source control after an OLE drag-drop operation has been completed or canceled.
This is the last event to occur in an OLE drag-drop operation.
The Effect parameter value is passed in from the target control's OLEDragDrop event.
If the Effect parameter contains a value of 0, the drag-drop operation did not complete successfully.

The OCX procedures to handle OLE events looks like:

PROCEDURE <event-proc-prefix>.OLECompleteDrag : 
    DEFINE INPUT-OUTPUT PARAMETER Effect AS INTEGER.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.OLEDragDrop : 
    DEFINE INPUT-OUTPUT PARAMETER Data AS COM-HANDLE.  /* IVBDataObject */
    DEFINE INPUT-OUTPUT PARAMETER Effect AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER Button AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER Shift AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER x AS DECIMAL.
    DEFINE INPUT-OUTPUT PARAMETER y AS DECIMAL.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.OLEDragOver : 
    DEFINE INPUT-OUTPUT PARAMETER Data AS COM-HANDLE.  /* IVBDataObject */
    DEFINE INPUT-OUTPUT PARAMETER Effect AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER Button AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER Shift AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER x AS DECIMAL.
    DEFINE INPUT-OUTPUT PARAMETER y AS DECIMAL.
    DEFINE INPUT-OUTPUT PARAMETER State AS INTEGER.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.OLEGiveFeedback : 
    DEFINE INPUT-OUTPUT PARAMETER Effect AS INTEGER.
    DEFINE INPUT-OUTPUT PARAMETER DefaultCursors AS LOGICAL.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.OLESetData : 
    DEFINE INPUT-OUTPUT PARAMETER Data AS COM-HANDLE.  /* IVBDataObject */
    DEFINE INPUT-OUTPUT PARAMETER DataFormat AS INTEGER.
END PROCEDURE.

PROCEDURE <event-proc-prefix>.OLEStartDrag : 
    DEFINE INPUT-OUTPUT PARAMETER Data AS COM-HANDLE.  /* IVBDataObject */
    DEFINE INPUT-OUTPUT PARAMETER AllowedEffects AS INTEGER.
END PROCEDURE.

OCX OLE events procedures parameters:

Attribute Name OCX Name Handle Type Return Type Read Only Description
COM-DATA Data PROGRESS-BAR COM-HANDLE Y Returns DataObject and instance of IVBDataObject COM interface
OCX-MOUSE-BUTTON Button PROGRESS-BAR INTEGER Y Returns which, if any, of the mouse buttons has changed state.
OCX-SHIFT Shift PROGRESS-BAR INTEGER Y Returns state of all modal keys, such as ALT, CTRL, META, and the mouse buttons just after the event occurred.
OLE-X x PROGRESS-BAR DECIMAL Y Returns the horizontal x position of the event relative to the source component.
OLE-Y y PROGRESS-BAR DECIMAL Y Returns the vertical y position of the event relative to the source component.
OLE-EFFECT Effect PROGRESS-BAR INTEGER N Returns drop Effect
OLEDropEffectNone = 0
OLEDropEffectCopy = 1
OLEDropEffectMove = 2
OLEDropEffectScroll = -2147483648
OLE-STATE State PROGRESS-BAR INTEGER N Returns OLE state.
Enter = 0
Leave = 1
Over = 2
OLE-DEFAULT-CURSORS DefaultCursors PROGRESS-BAR LOGICAL N If the DefaultCursors parameter is set to False, use the MousePointer property of the Screen object to specify the customized pointer.
OLE-ALLOWED-EFFECTS AllowedEffects PROGRESS-BAR INTEGER N Gets which drag-and-drop operations are allowed by the originator (or source) of the drag event.
One of the Effects values.
OLE-DATA-FORMAT DataFormat PROGRESS-BAR INTEGER N Clipboard format.
CFText = 1
CFBitmap = 2
CFMetafile = 3
CFDIB = 8
CFPalette = 9
CFEMetafile = 14
CFFiles = 15
CFRTF = -16639

DataObject is an instance of IVBDataObject COM iterface. Actually two COM interfaces are used in a drag-drop operation, IVBDataObject and IVBDataObjectFiles.

IVBDataObject properties and methods:

NO-RETURN-VALUE <com-handle>: Clear (  )
Property Get:    [ Com-Handle-Var = ] <com-handle>:Files. /* Returns IVBDataObjectFiles COM interface */
[ <anytype>-Var = ] <com-handle>: GetData (Integer-sFormat AS SHORT ).
[ Logical-Var = ] <com-handle>: GetFormat (Integer-sFormat AS SHORT ).
NO-RETURN-VALUE <com-handle>: SetData (<anytype>-vValue, <anytype>-vFormat ).

IVBDataObjectFiles properties and methods:

NO-RETURN-VALUE <com-handle>: Add (Character-bstrFilename, <anytype>-vIndex ).
NO-RETURN-VALUE <com-handle>: Clear (  ).
Property Get:    [ Integer-Var = ] <com-handle>:Count.
Property Get:    [ Character-Var = ] <com-handle>:Item ( Integer-lIndex ).
NO-RETURN-VALUE <com-handle>: Remove ( <anytype>-vIndex ).

When PROGRESS-BAR is used like a 4gl extension widget a typical definitions of OLE events triggers looks like:

on "ole-complete-drag" of progBar 
do:
   define variable Effect as integer.

   effect = progBar:ole-effect.
   message "OLECompleteDrag" Effect.
end.

on "ole-drag-drop" of progBar 
do:
   define variable Data as component-handle.
   define variable Effect as integer.
   define variable Button as integer.
   define variable Shift as integer.
   define variable x as decimal.
   define variable y as decimal.

   data = progBar:com-data.
   effect = progBar:ole-effect.
   Button = progBar:ocx-mouse-Button.
   Shift  = progBar:ocx-mouse-Shift.
   x = progBar:ole-x.
   y = progBar:ole-y.

   message "OLEDragDrop" Button Shift Effect x y.
end.

on "ole-drag-over" of progBar 
do:
   define variable Data as component-handle.
   define variable Effect as integer.
   define variable Button as integer.
   define variable Shift as integer.
   define variable x as decimal.
   define variable y as decimal.
   define variable State as integer.

   data = progBar:com-data.
   effect = progBar:ole-effect.
   Button = progBar:ocx-mouse-Button.
   Shift  = progBar:ocx-mouse-Shift.
   x = progBar:ole-x.
   y = progBar:ole-y.
   state = progBar:ole-state.

   message "OLEDragOver" Button Shift Effect x y State.
end.

on "ole-give-feedback" of progBar 
do:
   define variable Effect as integer.
   define variable DefaultCursors as logical.

   effect = progBar:ole-effect.
   DefaultCursors = progBar:ole-default-cursors.
   message "OLEGiveFeedback" Effect DefaultCursors.
end.

on "ole-set-data" of progBar 
do:
   define variable Data as component-handle.
   define variable DataFormat as integer.

   data = progBar:com-data.
   dataFormat = progBar:ole-data-format.
   message "OLESetData" DataFormat.
   Data:Clear().
end.

on "ole-start-drag" of progBar 
do:
   define variable Data as component-handle.
   define variable AllowedEffects as integer.

   data = progBar:com-data.
   AllowedEffects = progBar:ole-allowed-effects.
   message "OLEStartDrag" AllowedEffects.
   Data:GetData(15).
   Data:Files.
   Data:Item(0).
end.

Standard 4GL members

Besides the members introduced in FWD, the widget also supports the following standard 4GL members. Please consult the official OpenEdge documentation.

BGCOLOR
COLUMN
FGCOLOR
FONT
FRAME
FRAME-COL
FRAME-ROW
FRAME-X
FRAME-Y
HEIGHT-CHARS
HEIGHT-PIXELS
HELP
HIDDEN
INSTANTIATING-PROCEDURE
LABEL
LABEL-FONT
LOAD-MOUSE-POINTER
MENU-KEY
MENU-MOUSE
MOUSE-POINTER
MOVE-AFTER-TAB
MOVE-TO-BOTTOM
MOVE-TO-TOP
NAME
NEXT-SIBLING
NEXT-TAB-ITEM
PARENT
POPUP-MENU
PREV-SIBLING
PREV-TAB-ITEM
PRIVATE-DATA
ROW
SCREEN-VALUE
SENSITIVE
SIDE-LABEL-HANDLE
TAB-POSITION
TAB-STOP
TYPE
VISIBLE
WIDGET-ID
WIDTH
WIDTH-CHARS
WIDTH-PIXELS
WINDOW
X
Y

Conversion

FWD is capable to automatically convert the usages of Microsoft's progress bar control from the Windows Common Controls library.
To enable the conversion create the file <procedurefile.p>.ext-hints with the following structure.

<extension>
   <ocx control-frame="CtrlFrame" control-frame-handle="chCtrlFrame" com-handle="chCtrlFrame:ProgressBar" target-handle="hProgressBar" target-widget="progress-bar" />
   <drop-procedure name="control_load" />
</extension>

The xml element ocx defines the CONTROL-FRAME hosting the progress bar control (control-frame), the com handle (control-frame-handle) of the control frame,
com handle property (com-handle) for referencing the progress bar in the control frame and the handle (target-handle) for the converted progress bar widget.

The xml element drop-procedure defines all the functions and internal procedures declared in <procedure.p> file that contain the OCX initialization code.

To give an example, the following code sample will convert with the xml configuration given above.

define variable CtrlFrame as widget-handle no-undo.
define variable chCtrlFrame as component-handle no-undo.

procedure control_load :
define variable UIB_S    as logical    no-undo.
define variable OCXFile  as character  no-undo.

OCXFile = search( "progbar.wrx":U ).
  assign
    chCtrlFrame = CtrlFrame:com-handle
    UIB_S = chCtrlFrame:LoadControls( OCXFile, "ProgressBar":U).
end procedure.

run control_load.
chCtrlFrame:ProgressBar:Value = 45.

procedure CtrlFrame.ProgressBar.Click :
   ...
end procedure.

Examples

Create PROGRESS-BAR widget

create progress-bar progBar 
   assign
     frame = frame f:handle
       row    = 3.62
       column = 5
       height = 1.2
       width  = 104
       visible = true.

Set properties

progBar:ole-Drop-Mode = 1.
progBar:pb-Appearance = 1.
progBar:pb-Border-Style = 0.
progBar:pb-Orientation = 0.
progBar:pb-Scrolling = 1.
progBar:pb-Max = 100.
progBar:pb-Min = 0.
progBar:pb-Value = 30.
progBar:pb-Mouse-Pointer = 3.

Test progress indicator

procedure test_progress :
define variable icount as integer no-undo.

do iCount = 1 to progBar:pb-Max :
    progBar:pb-Value = iCount.
    progBar:pb-Refresh( ).
end.
end procedure.

Mouse DOWN trigger

on "mouse-down" of progBar 
do: 
   define variable Button as integer.
   define variable Shift as integer.
   define variable x as integer.
   define variable y as integer.

   Button = progBar:ocx-mouse-Button.
   Shift  = progBar:ocx-mouse-Shift.
   x = progBar:ocx-mouse-x.
   y = progBar:ocx-mouse-y.

   message "MouseDown!" x y Button Shift.
end.

Complex example


© 2019 Golden Code Development Corporation. ALL RIGHTS RESERVED.

progress-bar.png (5.25 KB) Marius Gligor, 10/31/2019 05:38 AM