Introduction
CPercentageCtrl
is an easy control to display the ratio between many entities, as the used space and the free space, or the composition of a cocktail :)
Obviously user can modify ratios dragging the blocks' edges.
Using the control
Add an instance of the control as member data in your dialog;
class CMyDialog : public CDialog
{
...
CPercentageCtrl m_percentage;
...
}
Then initialize the control in OnInitDialog()
using the Create(...)
function
BOOL CMyDialog::OnInitDialog()
{
...
CRect r(10,10, 200, 50);
m_percentage.Create(NULL, NULL, WS_VISIBLE | WS_BORDER, r,
this, ID_PERCENTAGE);
...
}
To add a block is really easy, you must only specify its weight:
m_percentage.AddBlock(250);
In any block you can select the color and a text to be displayed: the text can be formatted using CString::Format(...) (or printf) style,
the color is the usual RGB value
m_percentage.AddBlock(250, "%0.1f%%", RGB(200,255,255));
Blocks' dimension must be an integer value, but you can set a double
multiplier that is used to display the text.
For example, if you want to show the value as "25.1" you should insert a 251 dimension and set the multiplier to 0.1
m_percentage.AddBlock(251);
m_percentage.SetMultiplier(0.1);
Some options are available:
PC_HORIZONTAL
(default) or PC_VERTICAL
PC_VERTICALTEXT
(default) or PC_HORIZONTALTEXT
PC_READONLY
PC_ALWAYSSHOWTEXT
: the control will show the text even if it is not completely contained in the block; otherwise the control display text only if it is completely contained in his block.
PC_TEXTELLIPSIS
: if it's needed, the control does a text ellipsis to shorten the text as it could be contained in the block.
You can set these options using the command
SetOptions(int)
:
m_percentage.SetOptions(PC_HORIZONTAL | PC_ALWAYSSHOWTEXT);
Any time that the user modifies the dimension of a
block, the control sends a message. You can intercept this message
inserting in the messages map the macro:
<code>ON_REGISTERED_MESSAGE(PERCENTAGE_CHANGED,FunctionName)
For example:
BEGIN_MESSAGE_MAP(CPercentageCtrlDemoDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_REGISTERED_MESSAGE(PERCENTAGE_CHANGED,OnPercentageChanged)
END_MESSAGE_MAP()
In this case remember to declare the message
PERCENTAGE_CHANGED
in this way:
extern const UINT PERCENTAGE_CHANGED;
The called function will receive in WPARAM the handle of the calling
control, and in LPARAM the index of the first modified block (when a
user modifies a block, he modifies also that one at its
right).
The
OnPercentageChanged
function could be:
LRESULT MyDialog::OnPercentageChanged(WPARAM WParam, LPARAM LParam)
{
if ((HWND)WParam == m_percentage.m_hWnd)
{
int data1 = m_percentage.GetData((int)LParam);
int data2 = m_percentage.GetData((int)LParam+1);
....
}
}
Developing notes
I chose to allow the insertion of entire values with a
multiplier in order to avoid errors of approximation in the
visualization of the text
(e.g. 99 = 24 + 24 + 24 + 27 = 24.4 + 24.4 + 24.4 + 26.8 = 100 = 24.6 + 24.6 + 24.6 + 26.2 = 25 + 25 + 25 + 26 = 101)
I used Keith Rule's CMemDC to avoid flickering. You can find his class and an article here at codeproject :)
Obviously the code compiles cleanly under the warning level 4 :)
History
21 Mar 2002 - serious GDI resources leaks fixed.