FWH 1908: Meter Control Enhancements
Posted: Wed Sep 25, 2019 2:22 pm
FWH 1908 introduces many enhancements to the existing TMeter class. The existing syntax for creating Meter control is:
The meter is displayed as a horizontal bar.
BARCOLOR <nClrBar> (default CLR_BLUE) is used to display the progress.
COLORS <nClrPane> (default oWnd:nClrPane) is used to display the remaining part.
Both the colors need to be RGB color constants.
Enhancements:
1) Both <nClrBar> and <nClrPane> can now be any combination of the following:
a) Standard RGB colors (present behaviour continues)
b) Alpha colors (transparent) Range 0x01000000 to 0xffffffff
c) Color Gradient (as arrays) consisting of RGB colors and Alpha colors
d) Brush objects of bitmaps/images or any other style
e) Bitmap/Image file or resource.
and
f) Codeblocks returning any colors or gradients. This enables changing colors during the progress depending on the progress or other variables.
2) PROMPT <cText> can also be a codeblock.
All the codeblocks are evaluated with progress expressed as a fraction (0.0 to 1.0) as parameter.
Examples of Usage:
3) Fix: UPDATE clause had no effect. Now working
4) New clause BORDER <nBorderClr>
nBorderClr can be an RGB color constant or array of {color,width} or a Pen Object. If specified, border is drawn around the meter using the color and thickness.
5) New Optional clause BMPARRAY
If this clause is specified, <nClrBar> and <nClrPane> can be assigned with bitmap handles or bmp files. The meter will display an array of 5 or 10 of these bitmaps depending on the relative width of the control. Progress is displayed with the first bitmap and remaining part is displayed with second bitmap. If only colors are specified, STAR shaped bitmaps are generated internally and displayed using the colors specified.
Sample:
Sample Code (relevant part) fwh\samples\meter01.prg
Incidentally, this sample demonstrates the new feature of displaying outlined text (hollow text). This is the code:
Next enhancement:
Circular Meter:
For this we need to add the clauses:
For this to work well, the SIZE <nWidth> and <nHeight> need to equal or nearly equal.
By default, the appearance is like a pie chart.
If innerdia is specified, either in pixels or as a ratio (0.1 to 0.9) to the outer diameter, the inner circle is painted separately with fillcolor.
If no fillcolor is specified, the inner circle is left transparent.
In this case also, the three colors nClrBar, nClrPane and nFillColor can be
a) RGB colors
b) alpha colors
c) gradients of RGB colors (alpha color gradients not supported)
d) Brush objects
e) Images
and also
f) codeblocks returning any color.
Sample of Circular Meters
Source code: (relevant part)
fwh\samples\meter02.prg
Now the full syntax:
Circular Meter without creating as Control:
It is also possible to draw circular meters, in any window, dialog or inside any other control, without actually creating a meter contol, by using this function:
The following example demonstrates using this function:
Sample code:
Code: Select all
@ <nRow>, <nCol> METER [ <oMeter> VAR ] <nActual> ;
[ TOTAL <nTotal> ] ;
[ SIZE <nWidth>, <nHeight> ];
[ OF <oWnd> ] ;
[ <update: UPDATE > ] ;
[ <lPixel: PIXEL > ] ;
[ FONT <oFont> ] ;
[ PROMPT <cPrompt> ] ;
[ <lNoPercentage: NOPERCENTAGE > ] ;
[ <color: COLOR, COLORS> <nClrPane>, <nClrText> ] ;
[ BARCOLOR <nClrBar>, <nClrBText> ] ;
[ <lDesign: DESIGN> ] ;
BARCOLOR <nClrBar> (default CLR_BLUE) is used to display the progress.
COLORS <nClrPane> (default oWnd:nClrPane) is used to display the remaining part.
Both the colors need to be RGB color constants.
Enhancements:
1) Both <nClrBar> and <nClrPane> can now be any combination of the following:
a) Standard RGB colors (present behaviour continues)
b) Alpha colors (transparent) Range 0x01000000 to 0xffffffff
c) Color Gradient (as arrays) consisting of RGB colors and Alpha colors
d) Brush objects of bitmaps/images or any other style
e) Bitmap/Image file or resource.
and
f) Codeblocks returning any colors or gradients. This enables changing colors during the progress depending on the progress or other variables.
2) PROMPT <cText> can also be a codeblock.
All the codeblocks are evaluated with progress expressed as a fraction (0.0 to 1.0) as parameter.
Examples of Usage:
Code: Select all
BARCOLOR { |n| ARGB( n, CLR_HBLUE ) }
PROMPT { |n| TRANSFORM( nSecs * ( 1 - n ) / n, "### Secconds remaining" ) }
4) New clause BORDER <nBorderClr>
nBorderClr can be an RGB color constant or array of {color,width} or a Pen Object. If specified, border is drawn around the meter using the color and thickness.
5) New Optional clause BMPARRAY
If this clause is specified, <nClrBar> and <nClrPane> can be assigned with bitmap handles or bmp files. The meter will display an array of 5 or 10 of these bitmaps depending on the relative width of the control. Progress is displayed with the first bitmap and remaining part is displayed with second bitmap. If only colors are specified, STAR shaped bitmaps are generated internally and displayed using the colors specified.
Sample:
Sample Code (relevant part) fwh\samples\meter01.prg
Code: Select all
nRow := 50
@ nRow, 40 METER aMeter[ 1 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
COLOR "..\bitmaps\backgrnd\beach.bmp", CLR_BLACK ;
BARCOLOR "..\bitmaps\backgrnd\pebbles.bmp", CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE
nRow += 90
@ nRow, 40 METER aMeter[ 2 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
COLOR 0x60ffffff, CLR_BLACK ;
BARCOLOR 0x60ff0000, CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_WHITE UPDATE
nRow += 90
@ nRow, 40 METER aMeter[ 3 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
COLOR {{ 0.5, CLR_GRAY, CLR_WHITE },{ 0.5, CLR_WHITE, CLR_GRAY } }, CLR_BLACK ;
BARCOLOR {{ 0.5, CLR_GREEN, CLR_HGREEN },{ 0.5, CLR_HGREEN, CLR_GREEN }, 0 }, CLR_BLACK ;
TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE
nRow += 90
@ nRow, 40 METER aMeter[ 3 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
COLOR {{ 0.5, 0xf0505050, 0x80FFFFFF },{ 0.5, 0x80ffffff, 0xf0505050 }, 0 }, CLR_BLACK ;
BARCOLOR {{ 0.5, 0xf0004000, 0x8000ff00 },{ 0.5, 0x8000ff00, 0xf0004000 }, 0 }, CLR_BLACK ;
TOTAL nTotal FONT oFont BORDER CLR_WHITE UPDATE
nRow += 90
@ nRow, 40 METER aMeter[ 4 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
COLOR {{ 0.5, CLR_GRAY, CLR_WHITE },{ 0.5, CLR_WHITE, CLR_GRAY }, .f. }, CLR_BLACK ;
BARCOLOR {{ 0.5, 0x002000, 0x80ff80 },{ 0.5, 0x80ff80, 0x002000 }, 2 }, CLR_BLACK ;
TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE
nRow += 90
bAct := { |n| n /= 2, { { 0.5-n, CLR_GREEN, CLR_GREEN }, { .25, CLR_GREEN, CLR_HGREEN }, ;
{ .25, CLR_HGREEN, CLR_GREEN }, { n, CLR_GREEN, CLR_GREEN } } }
bRem := { |n| n /= 2, { { n, CLR_GRAY, CLR_GRAY }, { .25, CLR_GRAY, CLR_HGRAY }, ;
{ .25, CLR_HGRAY, CLR_GRAY }, { 0.5-n, CLR_GRAY, CLR_GRAY } } }
@ nRow, 40 METER aMeter[ 5 ] VAR nActual SIZE 720,45 PIXEL OF oDlg ;
COLOR bRem, CLR_BLACK ;
BARCOLOR bAct, CLR_BLACK ;
TOTAL nTotal FONT oFont BORDER CLR_BLACK UPDATE
nRow := 600
@ nRow, 250 METER nActual SIZE 300,60 PIXEL OF oDlg ;
BARCOLOR CLR_HRED, CLR_WHITE ;
TOTAL nTotal FONT oFont UPDATE BMPARRAY
Code: Select all
oDlg:bPainted := <|hDC|
local nRow := 20
oDlg:SayHollow( "BITMAP BRUSHES", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
nRow += 90
oDlg:SayHollow( "ALPHA COLORS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
nRow += 90
oDlg:SayHollow( "GRADIENTS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
nRow += 90
oDlg:SayHollow( "ALPHA COLOR GRADIENTS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
nRow += 90
oDlg:SayHollow( "HOTIZONTAL GRADIENTS", { nRow, 25, nRow + 30, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
nRow += 90
oDlg:SayHollow( "COLOR ANIMATION", { nRow, 25, nRow + 30, 760 }, nil, oBold, CLR_GREEN, nil, CLR_WHITE, 3 )
nRow := 570
oDlg:SayHollow( "RATINGS", { nRow, 40, nRow + 25, 760 }, nil, oBold, CLR_HRED, nil, CLR_WHITE, 3 )
return nil
>
Circular Meter:
For this we need to add the clauses:
Code: Select all
CIRCULAR [INNERDIA <nDia>] [FILLCOLOR <nInnerColor>]
By default, the appearance is like a pie chart.
If innerdia is specified, either in pixels or as a ratio (0.1 to 0.9) to the outer diameter, the inner circle is painted separately with fillcolor.
If no fillcolor is specified, the inner circle is left transparent.
In this case also, the three colors nClrBar, nClrPane and nFillColor can be
a) RGB colors
b) alpha colors
c) gradients of RGB colors (alpha color gradients not supported)
d) Brush objects
e) Images
and also
f) codeblocks returning any color.
Sample of Circular Meters
Source code: (relevant part)
fwh\samples\meter02.prg
Code: Select all
#define MANGOES "https://img.huffingtonpost.com/asset/5c1225351f0000f00626a771.jpeg?ops=scalefit_630_noupscale"
#define APPLES "https://cdn.images.express.co.uk/img/dynamic/109/590x/Apple-links-587431.jpg"
#define GRAPES "https://img-aws.ehowcdn.com/350x235p/s3-us-west-1.amazonaws.com/contentlab.studiod/getty/f36944f5be3843ddafebd89b1dca105f.jpg"
//-------------
nRow := 100
@ nRow, 40 METER aMeter[ 1 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
COLOR "..\bitmaps\backgrnd\beach.bmp", CLR_BLACK ;
BARCOLOR "..\bitmaps\backgrnd\pebbles.bmp", CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_BLACK ;
CIRCULAR INNERDIA 0.5 ;
UPDATE
@ nRow, 300 METER aMeter[ 2 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
COLOR {{ 0.5, CLR_GRAY, CLR_HGRAY },{ 0.5, CLR_HGRAY, CLR_GRAY }}, CLR_BLACK ;
BARCOLOR {{ 0.5, CLR_GREEN, CLR_HGREEN },{ 0.5, CLR_HGREEN, CLR_GREEN }}, CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_WHITE ;
CIRCULAR INNERDIA 0.4 ;
UPDATE
@ nRow, 560 METER aMeter[ 3 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
COLOR APPLES, CLR_BLACK ;
BARCOLOR MANGOES, CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_WHITE ;
CIRCULAR INNERDIA { |n| 0.3 + ( n * 0.4 ) } ;
FILLCOLOR GRAPES ;
UPDATE
nRow += 350
@ nRow, 40 METER aMeter[ 4 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
COLOR 0x60ff0000, CLR_BLACK ;
BARCOLOR 0x6000ff00, CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_BLACK ;
CIRCULAR INNERDIA { |n| 0.2 + ( 0.6 * n ) } ;
FILLCOLOR { |n| NARGB( 210 - ( n * 200 ), CLR_BLACK ) } ;
UPDATE
@ nRow,300 METER aMeter[ 5 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
COLOR METRO_STEEL, CLR_BLACK ;
BARCOLOR METRO_AMBER, CLR_WHITE ;
TOTAL nTotal FONT oFont BORDER CLR_WHITE ;
CIRCULAR INNERDIA { |n| 0.3 + ( n * 0.4 ) } ;
FILLCOLOR {{ 1, CLR_HGREEN, 0X002000 }} ;
UPDATE
@ nRow,560 METER aMeter[ 6 ] VAR nActual SIZE 200,200 PIXEL OF oDlg ;
COLOR { |n| NARGB( n * 255, CLR_HRED ) }, CLR_BLACK ;
BARCOLOR { |n| NARGB( ( 1 - n ) * 255, CLR_GREEN ) }, CLR_WHITE ;
TOTAL nTotal FONT oSmal BORDER CLR_WHITE ;
PROMPT { |n| TRANSFORM( ( 1 - n ) * 15, "## SECONDS" ) + CRLF + "MORE" } ;
CIRCULAR INNERDIA 0.5 ;
FILLCOLOR { |n| NARGB( 210 - ( n * 200 ), CLR_BLACK ) } ;
UPDATE
@ 670,40 SLIDER nActual SIZE 720,20 PIXEL OF oDlg SLIMSTYLE ;
COLORS nil,nil,CLR_WHITE ;
RANGE 0,nTotal ON CHANGE oDlg:Update() ;
Code: Select all
@ <nRow>, <nCol> METER [ <oMeter> VAR ] <nActual> ;
[ TOTAL <nTotal> ] ;
[ SIZE <nWidth>, <nHeight> ];
[ OF <oWnd> ] ;
[ <update: UPDATE > ] ;
[ <lPixel: PIXEL > ] ;
[ FONT <oFont> ] ;
[ PROMPT <cPrompt> ] ;
[ <lNoPercentage: NOPERCENTAGE > ] ;
[ <color: COLOR, COLORS> <nClrPane>, <nClrText> ] ;
[ BARCOLOR <nClrBar>, <nClrBText> ] ;
[ <circ:CIRCULAR> [INNERDIA <nInnerDia> ] ] ;
[ FILLCOLOR <nClrFill> ] ;
[ BORDER <clrBorder> ] ;
[ <bmpArray:BMPARRAY> ] ;
[ <lDesign: DESIGN> ] ;
// nClrBar, nClrPane, nClrFill can be RGB or Alpha color, oBrush,
// hBitmap, aGradient or any Image source( file/resource/webaddress)
// Options CIRCULR and BMPARRAY or mutually exclusve.
It is also possible to draw circular meters, in any window, dialog or inside any other control, without actually creating a meter contol, by using this function:
Code: Select all
function PaintCircularMeter( oWnd, aRect, nInnerDia, nActual, nTotal, aColors, aPen )
Sample code:
Code: Select all
@ 20,20 XBROWSE oBrw SIZE -20,-20 PIXEL OF oDlg ;
DATASOURCE "STATES" AUTOCOLS CELL LINES ;
NOBORDER FONT oBrwFont
WITH OBJECT oBrw
:lTransparent := .t.
:nStretchCol := STRETCHCOL_WIDEST
:bPaintBack := <||
FillRect( oBrw:GetDC(), GetClientRect( oBrw:hWnd ), oBrush:hBrush )
PaintCircularMeter( oBrw, {130,30,430,330}, 0.5, oBrw:KeyNo, oBrw:nLen, ;
{ 0x6000ff00, 0x60FA6800 } )
oBrw:ReleaseDC()
return nil
>
:CreateFromCode()
END