Tuesday, 5 January 2010

Customizing QuantumGrid field display using the canvas

The components of the DevExpress Suite let you work with different components like QuantumGrid, PivotGrid, VerticalGrid, etc. All of them very useful and I've been working with this components for several years. With this components we can customize the way data is visualized and add our personal touch to them.

In this little post, I've made a customization of the displaying value of a deviation showing a rectangle inside the field, displaying the percent of the value into the bounds of it. Here is the example:


I have the main columns (Income and Expenses) and the deviation between them. To add emphasis to the view, I've changed the visualization inside the CustomDrawCell event using the boundaries of every field to show a rectangle. Here I have the result:

Hence, the code I've posted here can be used in any of the components, because more o less all of them work in the same way.

The following code is used to do all the explained:
  • Formatting the number:
The displayed number is formatted with a % char, and we need to convert this string to a float number.


function TForm1.GetNumber(DisplayValue : Variant) : Double;
var
Value : string;
number : double;
begin
number := 0;
if AnsiPos('%', DisplayValue) <> 0 then
begin
Value := AnsiLeftStr(DisplayValue, AnsiPos('%', DisplayValue) - 1);
Value := FormatFormattedNumber(Value);
Value := Trim(Value);
number := StrtoFloat(Value);
end;
Result := number;
end;

function TForm1.FormatFormattedNumber(num: string): string;
var
res: string;
i, j: Integer;
begin
res := StringOfChar(' ', Length(num));
j := 1;
for i := 1 to Length(num) do
begin
if num[i] <> '.' then
begin
res[j] := num[i];
j := j + 1;
end;
end;
result := res;
end;

  • Drawing the rectangle:
To calculate the rectangle boundaries, we need to use the following method:


function TForm1.GetRegionbyValue(import: string; ClipRect: TRect; var color: TColor): TRect;
var
newRect: TRect;
num: double;
begin
num := GetNumber(import);
if num <> 0.0 then
begin
newRect.Top := ClipRect.Top;
newRect.Bottom := ClipRect.Bottom;
if num > 0 then
begin
if num >= 100 then
begin
newRect.Left := ((ClipRect.Right - ClipRect.Left) div 2) + ClipRect.Left;
newRect.Right := ClipRect.Right;
end
else
begin
newRect.Left := ((ClipRect.Right - ClipRect.Left) div 2) + ClipRect.Left;
newRect.Right := newRect.Left + Round((num * (ClipRect.Right - newRect.Left)) / 100);
end;
color := clgreen;
end
else
begin
if num <= -100 then
begin
newRect.Left := ClipRect.Left;
newRect.Right := ClipRect.Right - ((ClipRect.Right - ClipRect.Left) div 2);
end
else
begin
newRect.Right := ClipRect.Right - ((ClipRect.Right - ClipRect.Left) div 2);
newRect.Left := newRect.Right + Round((num * (newRect.Right - ClipRect.Left)) / 100);
end;
color := clred;
end;

end;
result := newRect;
end;


For displaying the rectangle:


procedure TForm1.cxGrid1DBTableView1deviationCustomDrawCell(Sender: TcxCustomGridTableView;
ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);
var
recColor, beforeColor: TColor;
newClipRect: TRect;
number: double;
begin
//Draw the rectangles
with AViewInfo do
begin
number := GetNumber(DisplayValue);
ACanvas.FillRect(AViewInfo.Bounds);
beforeColor := ACanvas.Canvas.Brush.Color;
newClipRect := GetRegionbyValue(DisplayValue, Bounds, recColor);
ACanvas.Canvas.Brush.Color := recColor;
ACanvas.Canvas.Rectangle(newClipRect.Left, newClipRect.top, newClipRect.right, newClipRect.bottom);
ACanvas.Canvas.Brush.Color := beforeColor;
ACanvas.Canvas.Brush.Style := bsclear;
if number > 0 then
ACanvas.DrawTexT(DisplayValue, ClientBounds, cxAlignRight)
else
ACanvas.DrawTexT(DisplayValue, ClientBounds, cxAlignLeft);
end;
ADone := true;
end;


0 comments:

Post a Comment