Change color in tcxgrid column in delphi? - delphi

I have two grids:
in one form and compare between two value I need to change the color of the column in the grid when the two values are not equal
TotalYear:=0 ;
while not (mTblDetail.eof) do
begin
TotalYear:=TotalMonth +mTblDetail.FieldByName('Target_').AsFloat;
mTblDetail.Next;
end;
TotalMonth:=0;
while not(DataSet.Eof) do
begin
TotalMonth:=TotalMonth+DataSet.FieldByName('Target_').AsFloat;
DataSet.Next;
end;
I need to compare the two values and change the color
if(TotalYear<>TotalMonth) then
I tried to use this :
DataSet.Columns[8].Color:= clRed
but is displays an error "Not Accepted". How Can change the color of a column of a Tcxgrid?

Coloring in cxGrids is best done via cxStyles. Drop a TcxStyleRepository on the form and add some styles. You can assign them to the View.Styles.* properties or via events like OnGetContentStyle. I'm sure the online help contains an overview with screenshots and examples.

Related

Style individual Labels on Gantt-Rows in a VCL TeeChart

I am using TeeChart (Build 2020.30.200525) in a Delphi XE3 VCL-Application.
In that application I am setting up a Gantt series and I would like to style an individual row label on the left axis to set it apart from the others.
Something like changing the color or font-style of the label or highlighting it by using a background.
How could I achieve this?
I have found the OnGetAxisLabel event which I ca use to change the text of the labels.
And I have also tried Axes.Left.Items, but that only has a single element even after I have added several Values to the Gantt-Series.
You need to force a chart repaint to populate the axis items. Ie:
uses VclTee.GanttCh;
procedure TForm1.FormCreate(Sender: TObject);
begin
Chart1.AddSeries(TGanttSeries).FillSampleValues;
Chart1.Draw; // Force a repaint to populate Axis Items
Chart1.Axes.Left.Items.Automatic:=False;
Chart1.Axes.Left.Items[2].Format.Font.Color:=clRed;
end;

Setting the glyph image in a FireMonkey TListView

I have a FireMonkey TListView in a project. It's using a DynamicAppearance, each item features a couple of text entries and a glyph button. What I cannot seem to figure out is how to set the glyph image for that button when I build the list.
For example, when building the list items, I can do this for a text field:
lviAmount := lvi.Objects.FindObjectT<TListItemText>('Amount');
lviAmount.Text := FloatToStrF( tx.amount, ffNumber, 7, 2);
But I cannot see how to do the same thing with a TListItemGlyphButton:
lviDelete := lvi.Objects.FindObjectT<TListItemGlyphButton>('DeleteButton');
//then??
How can I set/assign the glyph image on a TListItemGlyphButton in a FireMonkey TListView? Any help would be greatly appreciated.
You cannot do that with a TListViewGlyphButton. It's only for Add, Delete or CheckBox button types. If you want to have an image of your own, use TListItemImage, and use the Bitmap property, e.g:
lviDelete := lvi.Objects.FindObjectT<TListItemImage>('DeleteButton');
lviDelete.Bitmap := SomeBitmap;
You'll also need to use the OnListViewItemClickEx event to determine whether or not it was the image that was clicked

Prevent delphi from redrawing columns

I have a string grid where user can change colors of columns. I'm storing a color in a string it looks likethis : columnToColor:= '1;233,233,233' 1 is the column 233;233;233 is a rgb color; I change this string everytime i have to change colors. It never contains more than one column and one color
In my drawcellevent i'm doing this:
color := Explode(';',columnToColor); //this will return an array
if (length(color)-1 >= 0) then
begin
if TryStrToInt(color[0], val) then
begin
if aCol = StrToInt(color[0]) then
begin
cellText := grid.Cells[aCol,aRow];
grid.Canvas.Brush.Color := TColor(RGB(StrToInt(color[1]),StrToInt(color[2]),StrToInt(color[3])));
rec := grid.CellRect(aCol,aRow);
grid.Canvas.FillRect(rec);
grid.Canvas.TextOut(rec.Left,rec.top,cellText);
end;
end;
end;
I'm calling invalidateCol from another procedure using a hacked StringGrid class:
With TCustomStringGrid(grid) do
InvalidateCol(grid.col)
This works when i change only one column color. I can scroll freely trought the grid and it will still be there with the good column color. But when i change the color of another column the colors are shown when their are still visibile. Once i scroll horizontally and get back to the columns only the last colored column is colored and other are set to default color. The color only stays on the last colored column. So if i color 2 columns and i click on the first one, the cell's color is set to default. And i scroll horizontally the whole column 1 is set to default color. Only the second column keep its color what ever i do.
How can i fix this pls?
This is perhaps becoming a little more clear to me. The problem is that you want the grid control to paint each column in separate colors. Although your columnToColor string specifies the color for only a single column, you want each column to have, potentially, a different color. When you scroll the grid, and columns are re-painted, only the column specified in columnToColor has the desired color.
All this is happening because Windows controls need to be able to re-paint themselves completely at any time. Once you have painted a control, the control does not remember its state. If it becomes invalid (control dragged over, scrolled, etc.) then the control must be able to re-paint itself in its entirety.
Your code fails to do that. Since it only remembers the color for the most recently modified column, when it needs to paint other columns, they get the default color. Your approach cannot succeed since the control only keeps track of one single column color.
The solution is simple enough. You need to remember the color for each column. An obvious way to do so would be to hold the colors in an array:
FColumnColor: array of TColor;
or
FColumnColor: TArray<TColor>;
in a more modern Delphi. Or perhaps even TList<TColor>.
When you need to change a column's color do so by modifying FColumnColor[ColIndex]. Likewise, whenever you need to paint, read the color out of FColumnColor[ColIndex].

Print fields alignment misaligned on report

I have the following PrintValue code that prints a line to the report (tbasedxreportlink). It prints two fields on one line in the header, the caption and m. The problem is that m is never aligned straight for multiple lines. It always prints all over the place.
How do I get it to align to the right or even print decimal aligned.
Printed Data
Caption One 4,685.33
Caption 2 4.99
Caption three 74,586.88
Caption 4 58.66
Code
procedure PrintValue(Caption, Value: string);
var
m: string;
s: string;
begin
m := FormatFloat(',0.00 ;(,0.00);0.00 ', StrToFloat(Value));
s := Format('%-24s %15s', [Caption, m]);
AReportLink.PrinterPage.PageHeader.LeftTitle.Add(s);
end;
The font used on the report is Segoe UI if it matters.
Thanks
The simplest way is using monospace (fixed-width) font, for example, Courier New or Lucida Console
I found no easy way to format the strings to get the desired effect. The main reason for that is the simplicity of using the LeftTitle, CenterTitle or RightTitle 'boxes' - they only allow simple string text to be inserted. Nothing fancy allowed not to mention the True Type Font issue.
In order to solve the problem I added a tPanel to the screen and dropped the all screen fields I needed to show up on the grid print to it. I added a tdxCustomContainerReportLink to link to that panel. I then used a tdxCompositionReportLink to print both the grid and the tdxCustomContainerReportLink (panel) as individual items when the print button was pressed by overwriting the current link code:
procedure TFrmViewAcct.dxBarBtnPrintClick(Sender: TObject);
begin
dxCmpntPrtrDetail.CurrentLink := dxCmpntPrtrDetailLink2;
inherited;
end;
Thus it prints the grid info then prints what ever is on the panel. Problem solved and you can see how this solution can be flexible.
Yes I could have easily changed to a True Type font but that is an ugly workaround as far as I am concerned especially where standardized fonts need to be observed.

How to change the color of a FM TSpeedButton

My Application has several TSpeedButtons with which to choose a color and I want each choice to be shown by the color of the TSpeedButton.
I found this answer on Stackoverflow on how to change the color of a TButton. The second answer (change colors dynamically) appears to be the solution I am looking for. It reads as follows:
var r: TRectangle;
begin
// Find the background TRectangle style element for the button
r := (Button1.FindStyleResource('background') as TRectangle);
if Assigned(r) then
begin
r.Fill.Color := claBlue;
end;
end;
This does not work anymore (i use XE5, this is XE2?). It generates an exception at the r := ... statement with:
"illegal cast".
The FindStyleResource returns a FMXObject.
TRectangle is a TShape->TControl->TFMXObject.
I can cast to TControl but not to TShape. In case you wonder, Button1 is a TButton.
Does anyone know how I do change the color of a TSpeedButton?
As an aside: is there a way to determine which type of object exactly is beging returned? I couldn't find out in the debugger.
The answer to the question you linked to relates to vector styles, where the style constructed entirely from shapes etc (such as the TRectangle).
In newer versions of FireMonkey the 'system' styles (which mimic the OS look) and some other styles use bitmaps.
If you want to edit a bitmap style, you'll need to find the bitmap image in the style, edit it, and then redo/edit the button's style to use the new image. (If you're on mobile this will probably be hard enough that you shouldn't even try it).
Another route would be be to change to one of the bitmap styles supplied with Delphi. You will find them under the redist/styles/fmx folder of your Delphi installation.
As for the class of the object, and as per other comments, examine the ClassName property of the object returned.
But bear in mind that not every style will have an object called 'background'. Both the name of the object and it's class can easily vary between styles. You really ought to look at the style you want to pluck objects from to see what's there. (Note that the objects name ('background') will be in the StyleName property).
It would be much easier to use a TColorButton instead, which directly exposes the Color property. You can find it on the Colors page of the component palette. Here are two on a new FMX form in the IDE's form designer:
As far as "which type of object is being returned", you can use the debugger or a ShowMessage for the TFMXObject.ClassName of the return value:
var
Obj: TFmxObject;
begin
Obj := Button1.FindResource('background');
if Assigned(Obj) then
ShowMessage(Obj.ClassName);
end;

Resources