Delphi FMX, change TComboBox images at runtime - delphi

If I programmatically change TComboBox.Images to a new TImageList, only the selected icon in the TComboBox changes, all other icons in the TComboBox (drop-down list) remain the same.
I have two TImageLists, one with color icons and one with black and white icons and I want to change the black and white icons to colored icons and vice versa.
procedure TfrmMain.Button1Click(Sender: TObject);
begin
if ComboBox1.Images = ImageList1 then
ComboBox1.Images := ImageList2
else
ComboBox1.Images := ImageList1;
end;

As pointed in the question comments this is indeed a bug in Delphi as the internal drop down list is not refreshed when changing the Images property after showing the popup at least one time. This can be corrected by making a small change in the FMX.ListBox.pas source file at TCustomComboBox.SetImages procedure:
For Delphi 11:
procedure TCustomComboBox.SetImages(const Value: TCustomImageList);
begin
FImageLink.Images := Value;
FItemsChanged := True; // <- Add this
end;
For Delphi 10.4 CE:
procedure TCustomComboBox.SetImages(const Value: TCustomImageList);
begin
FImageLink.Images := Value;
TComboBoxHelper.SetItemsChanged(Self, True); // <- Add this
end;

Related

Firemonkey LiveBinding to TListbox to show images

I'm trying to use LiveBindings with TListbox. This works with TListview but not TListbox. I'm trying to display only images in a TListbox (no text) but added CustomerID just to show the LiveBindings works. Just that the image does not display from the CustomerPhoto blob field.
LinkFillControlToField1.Control := Listbox1;
with LinkFillControlToField1 do
begin
FillExpressions.Clear;
with FillExpressions.AddExpression do
begin
SourceMemberName := 'CustomerPhoto';
ControlMemberName := 'Bitmap'; // no error, means ControlMember exists
end;
with FillExpressions.AddExpression do
begin
SourceMemberName := 'CustomerID'; // just added this for testing
ControlMemberName := 'Text'; // displays correct
end;
end;
The Bitmap in TListview seems to be directly in it, whereas the 'Bitmap' of TListbox is in ItemData of the TListboxitem - could this be the issue?
Is there anything else to do to make the bitmap appear in TListbox, given that it's so automatic in TListview?

TChart with TKnobGauge creates shifted labels at runtime

Following code creates knob with labels shifted to the right:
procedure TForm1.FormShow(Sender: TObject);
begin
_chart := TChart.Create(Self);
_chart.Parent := Self;
_chart.Align := alClient;
_knob := TKnobGauge.Create(Self);
_knob.ParentChart := _chart;
_knob.RotateLabels := False;
_knob.RotationAngle := 180;
end;
The same code as DFM produces the right knob.
What could be wrong?
TeeChart Pro v2015.16.150901 32bit VCL
Delphi 10
There is a bug in TChart. When I set
_chart.Title.Text.Text := 'Some title';
labels are on their places.
When I do
_chart.Title.Text.Text := '';
or
_chart.Title.Visible := False;
they are shifted.
The reason why the same code in DFM produced the right knob is that the visual designer extends my minimal chart declaration by adding several properties automatically. Among these properties was a chart title too. It is automatically filled by "TChart" text.
Sounds as exactly what is described in the ticket #1547, initially reported here.
Please, give a try at the workaround described in the ticket:
I can only workaround by having a small title with only a blank in it.

Delphi DrawThemeBackground on timage causing white background

I want to use Windows's native look and I am trying to learn how to do it.
I am trying to paint timage.canvas with Windows toolbutton background but the background of timage seems White and it doesnt seem same as Windows,
how can i fix that?
here is my code;
procedure TForm1.Button1Click(Sender: TObject);
var
theme: HTHEME;
begin
theme := OpenThemeData(Handle, 'TOOLBAR');
// error checking omitted for brevity
try
DrawThemeBackground(
theme,
Image1.Canvas.Handle,
TP_BUTTON,
TS_HOT,
Image1.ClientRect,
nil
);
finally
CloseThemeData(theme);
end;
end;
here is the picture of result when i applied theme on timage:
You should ask for a 'BUTTON' theme, not 'TOOLBAR' if you want a button.
theme := OpenThemeData(Handle, 'BUTTON');
Also this line should come before the try.
For a list of theme parts and states see this
From the above list you will see that the iPartId and iStateId you used are not the right ones (although worked). I would suggest BP_PUSHBUTTON and PBS_HOT instead.
procedure TForm3.Button2Click(Sender: TObject);
var
theme: HTHEME;
begin
theme := OpenThemeData(Handle, 'BUTTON');
try
DrawThemeBackground(theme,
Image1.Canvas.Handle,
BP_PUSHBUTTON,
PBS_HOT,
Image1.ClientRect,
nil);
finally
CloseThemeData(theme);
end;
end;
Edit Here's an image just for comparison of a TToolButton on a TToolBar in Windows 7:
As you see the TToolbutton (on TToolbar at the top) when 'hot', doesn't have the bluish appearance as a TButton. Beneath the toolbar are your code on the left and my suggestion on the right. Is it the difference in lightgray / white or lightgray / bluish you ask about?

Add icons to TTabControl in Firemonkey

First of all I have to say that I've read this question of SO. But actually it wasn't helpful for me.
I want to add icons to TTabControl but it doesn't seems as easy as I can do it in VCL (TPageControl). As you know there is no something like Image Index in TTabControl.
So what's the easiest way to do this?
Thanks for your help.
I would suggest not going down the route of modifying the style given the inherent 'copy and paste "inheritance"' nature of the exercise, which becomes an issue if you're targeting more than one OS (even just Windows 7 and Windows 8.x). Instead, try this:
1) For each item you want an icon on, change its TextAlign property to taTrailing and pad its Text with four leading space characters.
2) Add one TImage to the form per tab, and load small bitmaps into them as desired.
3) Associate each tab item with its image by (for example) assigning its TagObject property to the image control in an OnCreate handler for the form:
procedure TForm1.FormCreate(Sender: TObject);
begin
TabItem1.TagObject := Image1;
//...
end;
4) Assign each tab item's OnPaint event the following shared event handler:
procedure TForm1.TabItemPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
var
B: TBitmap;
SrcR, DstR: TRectF;
TabItem: TTabItem;
begin
TabItem := (Sender as TTabItem);
B := (TabItem.TagObject as TImage).Bitmap;
SrcR := RectF(0, 0, B.Width, B.Height);
DstR := SrcR;
DstR.Fit(RectF(ARect.Left, ARect.Top, ARect.Left + ARect.Height, ARect.Bottom));
if not TabItem.IsSelected then DstR.Offset(0, 1);
Canvas.DrawBitmap(B, SrcR, DstR, 1);
end;

add TMenuItem bitmap

I want to add a bitmap to a TMenuItem created dynamically. With this code it doesn't work, I don't have the image on my menu. What's wrong?
procedure TForm3.FormCreate(Sender: TObject);
var
item : TmenuItem;
icon : TIcon;
begin
item := TMenuItem.Create(PopupMenu1);
item.Caption := 'coucou';
icon := TIcon.Create;
icon.LoadFromFile('d:\SmallIcon.ico');
icon.Height := 16;
icon.Width := 16;
item.Bitmap.Canvas.Draw(0,0,icon);
PopupMenu1.Items.Add(item);
end;
The Bitmap property on TMenuItem isn't the way to go here. You really should use image lists instead. This will allow you to share images between your UI elements in a manageable fashion.
Add the icon to a TImageList.
Set the Images property on the menu (i.e. PopupMenu1) to refer to the image list.
Set the image index of the menu item to the index of the icon in the list, i.e. 0 if it's the first image.
Of course, you really ought to be using actions too, in which case you simply need to set the ImageIndex for the action and the framework takes care of assigning it to the menu item.
As an aside, I would note that the Delphi implementation of Vista themed menus has a large number of subtle bugs, many related to drawing of images. However, these bugs are relatively minor in visual impact.
Add the line
item.Bitmap.SetSize(16,16);
as third one. Then it works.
So your code would look like this:
var
item : TmenuItem;
icon : TIcon;
begin
item := TMenuItem.Create(PopupMenu1);
item.Caption := 'coucou';
item.Bitmap.SetSize(16,16); // <--- set size of bitmap
icon := TIcon.Create;
icon.LoadFromFile('d:\SmallIcon.ico');
icon.Height := 16;
icon.Width := 16;
item.Bitmap.Canvas.Draw(0,0,icon);
PopupMenu1.Items.Add(item);
end;
Although I agree with David. Better use a TImageList.
a) You can't set TIcon dimensions once they have an image in them -- if your loaded icon isn't already 16x16 you'll get an exception, b) You don't indicate if your parent menu uses a TImageList (if so, you can't set individual images), c) by default, I don't think tmenuitem bitmaps have a particular size/color depth or anything else. You need to properly create a TBitmap to assign to the TMenuItem.Bitmap (assuming your parent menu doesn't use TImageLists).

Resources