During lengthy processing I like to display progress of the processing to the user.
To achieve this goal, I made a simple method of displaying horizontal progress bar in a form of string made of small square characters (in my case chr(254) in ASCII table for code pages 437 and 852). I was very glad when I found progress bar control in HMG. When I tried it, I was disappointed with its performance and erratic behavior. Reading through the other users experiences on HMG forum and other places on the Internet, I realized that the root of the problem lies not in HMG but in Windows OS.
Therefore, I used workaround as described in https://derekwill.com/2014/06/24/combat ... ogressbar/ to make control to display properly. This method is not very pretty but it's effective. OK, main thing is that the control is giving accurate information about the process flow.
My next question was the speed of execution within the process, i.e. how big is overhead. Therefore I wrote this rather simple test to compare loop execution times for the following cases: without displaying progress bar (only counter), displaying progress bar control and displaying label with the string of characters.
Code: Select all
#include 'hmg.ch'
PROCEDURE ProgTest
/*
*/
PRIVATE cProgCh
SET CODEPAGE TO ENGLISH
cProgCh := chr(254)
DEFINE WINDOW wProgTest ;
AT 10, 10 ;
WIDTH 420 HEIGHT 250 ;
TITLE "Progress Indicator Testing" ;
ICON NIL CHILD CURSOR NIL ;
ON INTERACTIVECLOSE NIL ;
ON GOTFOCUS NIL ;
ON LOSTFOCUS NIL
DEFINE LABEL lbSteps
PARENT wProgTest
ROW 20
COL 10
VALUE "Enter number of steps for the test loop"
WIDTH 220
HEIGHT 20
END LABEL
DEFINE TEXTBOX tbSteps
PARENT wProgTest
ROW 18
COL 250
HEIGHT 20
VALUE 0
WIDTH 100
INPUTMASK '999,999,999'
FORMAT 'E'
MAXLENGTH 9
DATATYPE NUMERIC
MAXLENGTH 9
ONGOTFOCUS wProgTest.tbSteps.CaretPos := 8
ONENTER wProgTest.btExecute.SetFocus
RIGHTALIGN .T.
VISIBLE .T.
TABSTOP .T.
END TEXTBOX
DEFINE CHECKBOX cbProgBar
PARENT wProgTest
ROW 80
COL 10
CAPTION 'Progress bar'
VALUE .F.
WIDTH 100
HEIGHT 20
TOOLTIP 'Check if you want to test progress bar as progress indicator.'
VISIBLE .T.
TABSTOP .T.
END CHECKBOX
DEFINE PROGRESSBAR pbFlow
ROW 80
COL 110
WIDTH 270
HEIGHT 20
RANGEMIN 1
RANGEMAX 100
VALUE 1
TOOLTIP ""
HELPID Nil
VISIBLE .f.
VERTICAL .F.
END PROGRESSBAR
DEFINE CHECKBOX cbLablBar
PARENT wProgTest
ROW 100
COL 10
CAPTION 'Label bar'
VALUE .F.
WIDTH 100
HEIGHT 20
TOOLTIP 'Check if you want to test label as progress indicator.'
VISIBLE .T.
TABSTOP .T.
END CHECKBOX
DEFINE LABEL lbFlow
PARENT wProgTest
ROW 100
COL 110
VALUE ""
WIDTH 10
HEIGHT 50
FONTCOLOR {0,76,153}
END LABEL
DEFINE BUTTON btExecute
ROW 180
COL 110
WIDTH 200
HEIGHT 25
ACTION {TestInd(), wProgTest.tbSteps.SetFocus}
CAPTION "Execute"
TOOLTIP "Accept entered parameters and execute test."
TABSTOP .T.
VISIBLE .T.
END BUTTON
END WINDOW
wProgTest.tbSteps.SetFocus
wProgTest.Center
wProgTest.Activate
RETURN NIL
//*---->
FUNCTION TestInd
/*
*/
nKfLb := 0
nSteps := wProgTest.tbSteps.Value
nStart:= SECONDS()
IF wProgTest.cbProgBar.Value
cTest := wProgTest.cbProgBar.Caption+' as progress indicator'
wProgTest.pbFlow.RangeMax := nSteps
wProgTest.pbFlow.Visible := wProgTest.cbProgBar.Value
ELSEIF wProgTest.cbLablBar.Value
cTest := wProgTest.cbLablBar.Caption+' as progress indicator'
wProgTest.lbFlow.Visible := wProgTest.cbLablBar.Value
wProgTest.lbFlow.Width := wProgTest.Width-wProgTest.lbFlow.Col
nKfLb := (wProgTest.lbFlow.Width/wProgtest.lbFlow.FontSize)/105
ELSE
cTest := 'Without progress indicator'
END
FOR nI := 1 TO nSteps
IF wProgTest.cbProgBar.Value
IF nI==wProgTest.pbFlow.RangeMax
wProgTest.pbFlow.RangeMax := wProgTest.pbFlow.RangeMax + 1
wProgTest.pbFlow.Value := nI + 1
wProgTest.pbFlow.RangeMax := wProgTest.pbFlow.RangeMax - 1
ELSE
wProgTest.pbFlow.Value := nI + 1
ENDIF
wProgTest.pbFlow.Value := nI
ELSEIF wProgTest.cbLablBar.Value
nRatio := INT((nI/nSteps)*100)
wProgTest.lbFlow.Value := REPLICATE(cProgCh,INT(nRatio*nKfLb))+' '+LTRIM(STR(nRatio))+'%'
END
wProgTest.btExecute.Caption := 'Step '+LTRIM(STR(nI))+' of '+LTRIM(STR(nSteps))
DO EVENTS
NEXT
MsgInfo(cTest+' -> '+LTRIM(STR(SECONDS() - nStart))+ " seconds",'TEST DURATION')
wProgTest.pbFlow.Visible := wProgTest.cbProgBar.Value := .F.
wProgTest.lbFlow.Visible := wProgTest.cbLablBar.Value := .F.
wProgTest.btExecute.Caption := "Execute"
RETURN NIL
//*---->
Also, I noticed that maximum value for the progress bar control property RangeMax is 65,535 (2^16). If you set greater value, you get the value of the complement in the RangeMax (e.g. for 70,000 steps RangeMax will be set to 70,000-65,535=4,465) and the progress bar will be filled long before the process ends.
In my opinion, for the time being, progress bar control is useable for displaying of processing of less than 5,000 steps. After that amount, I would rather use only counter or label with string of characters. One can only hope that in the future this problem will be resolved and progress bar control will be really usable in HMG.
Finally, test execution results (in seconds) are in the attachment, for those who are interested.