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?
Related
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;
I have a TDBRadioGroup that I've added to my form.
I'd really like to have the caption to the left of it instead of on top (the form's a little busy and tall, and I'm trying to squeeze it in).
I can add my own label to the left of the Radio Group. But the control insists on reserving space of a Caption that does not exists. Is there a way I can turn it off completely?
The best we've come up with so far is sticking it on a TPanel and then hiding the top couple lines off-panel.
A TGroupBox (and it's descendant TDBGroupBox) are basically wrappers around the Windows GroupBox. The control is designed to sport a user-defined label across the upper-left corner, and doesn't have any style setting to remove it.
So, short of creating your own control to host a series of TRadioButton controls yourself and display them, there's no built-in way to disable the space reserved for the caption. You can suppress the text, of course, by setting the Caption := '', but the padding for the text descenders is not removed simply because the caption isn't displayed.
You can override the paint procedure for TRadioGroup so that the frame is drawn closer to the top of your item list. You could create a new component of type TNoCaptionRadioGroup. You might still have to use the panel trick that you have tried, but by lowering the top of the frame you can grab the space consumed by the non-existent caption. Something like this:
tNoCaptionRadioBox = class(TRadioGroup)
protected
procedure paint; override;
end;
procedure tNoCaptionRadioBox.paint;
var
H: Integer;
R: TRect;
begin
with Canvas do
begin
Font := Self.Font;
H := TextHeight('0');
R := Rect(0, H, Width, Height);
if Ctl3D then
begin
Inc(R.Left);
Inc(R.Top);
Brush.Color := clBtnHighlight;
FrameRect(R);
OffsetRect(R, -1, -1);
Brush.Color := clBtnShadow;
end else
Brush.Color := clWindowFrame;
FrameRect(R);
end;
end;
This is taken from the code for painting a TCustomGroupBox. I have removed the code for drawing the caption and have changed the top of the frame to the full height of the Font. Your actual captioned radio buttons will still be drawn where Windows wants them to be and with the default spacing.
Remember to register the new component by running the package installation tool.
procedure Register;
begin
RegisterComponents('myComponents', [tNoCaptionRadioBox]);
end;
Im trying to change the gradient color of TSpeedbutton at runtime using ApplyStyleLookup, but for some reason only the top twothird of the button changes color. When I change it at design time I see three points for the gradient. I'm using the buttonstyle in the TSpeedbuttons StyleLookup. Using Delphi XE6 Rad Studio.
Thanks.
Added 8/29/14 I found the way to change the gradient see below. But my problem is on the buttonstyle have three rectangles and the one I need to access is the rectangle2 under background. What do I need to access it.
procedure TForm1.SpeedButton1ApplyStyleLookup(Sender: TObject);
var
BckObject: TFmxObject;
begin
BckObject := SpeedButton1.FindStyleResource('background');
if Assigned(BckObject) and (BckObject is TRectAngle) then
begin
TRectAngle(BckObject).Fill.Gradient.Style := TGradientStyle.Linear;
TRectAngle(BckObject).Fill.Gradient.Points.Points[0].Color := $FF0097A5;
TRectAngle(BckObject).Fill.Gradient.Points.Points[0].Offset := 0.25;
TRectAngle(BckObject).Fill.Gradient.Points.Points[1].Color := $FF0097F5;
TRectAngle(BckObject).Fill.Gradient.Points.Points[1].Offset := 1.00;
end;
end;
The rectangle2 (TRectAngle) under background has the StyleName property blank, by enter a name in the StyleName and save it I can access the rectangle2 by using the same method:
BckObject := SpeedButton1.FindStyleResource('myname');
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;
I have a form with a background image (painted on the form in Form1.Repaint).
What I am a looking for: A transparent image control, that can smoothly resize (resample) the loaded image.
(I need it to be transparent because the forms background image should be visible through)
What I've tried:
Standard TImage: It's transparent, but it does not resample.
Graphics32 / Image32: Resamples beautifully, but it's not transparent.
I have googled for several hours now for fixes or work-arounds, but without much of a solution. This has nothing to do with the image loaded into Image32 being transparent, but instead the background color of the control still being white (white = the color-property of the Image32 control, and setting it to clNone does not work). This is apparently as designed
GR32ex (The GR32 Extension Components Pack), which supposedly adds a Transparent-property, however it has not been updated in many years, and I can not install it. It throws a gazillion errors on Delphi 2010 and Graphics32 v. 1.9.
Can anybody think of a solution or workaround? All I want is a control with transparency and resampling.
Thanks!
I'm surprised that TImage32 doesn't do transparency. Are you really sure that is the case?
Anyway, if that is so, I would combine the transparency support of TImage with the re-sampling ability of TBitmap32 to build a solution that way. Keep the original image in a TBitmap32 instance. Whenever you need to load it into the TImage component, for example when re-sizing, use TBitmap32 to perform an in-memory re-size and load that re-sized image.
In fact, if you are already painting the form's background yourself, why not paint the image yourself and simply do away with the image control?
Update 1: Websearch reveals a simple way to make TImage32 transparent: http://graphics32.org/news/newsgroups.php?art_group=graphics32.general&article_id=9505
Update 2: The link above is now dead, and the newsgroups can only be accessed via NNTP. I can't be 100% certain, but I think that the linked post was by Michael Haralabos and contained the following file:
unit GR32_ImageEx;
// Transparent TImage32 by Michael Haralabos
interface
uses
Windows, Messages, Classes, GR32_Image, GR32;
type
TImage32Ex = class(TImage32)
private
FTransparent: Boolean;
procedure SetTransparent(const Value: Boolean);
public
procedure ExecClearBackgnd(Dest: TBitmap32; StageNum: Integer); override;
published
property Enabled;
property Transparent: Boolean read FTransparent write SetTransparent;
end;
procedure Register;
implementation
procedure TImage32Ex.ExecClearBackgnd(Dest: TBitmap32; StageNum: Integer);
var
P: TPoint;
SaveIndex: Integer;
begin
if FTransparent and Assigned(Parent) and
not (Assigned(Bitmap) and (BitmapAlign = baTile)) then
begin
SaveIndex := SaveDC(Dest.Handle);
GetViewportOrgEx(Dest.Handle, P);
SetViewportOrgEx(Dest.Handle, P.X - Left, P.Y - Top, nil);
IntersectClipRect(Dest.Handle, 0, 0, Parent.ClientWidth, Parent.ClientHeight);
Parent.Perform(WM_ERASEBKGND, Dest.Handle, 0);
Parent.Perform(WM_PAINT, Dest.Handle, 0);
RestoreDC(Dest.Handle, SaveIndex);
end
else
inherited;
end;
procedure TImage32Ex.SetTransparent(const Value: Boolean);
begin
if FTransparent <> Value then
begin
FTransparent := Value;
Invalidate;
end;
end;
procedure Register;
begin
RegisterComponents('Graphics32', [TImage32Ex]);
end;
end.
Another topic here suggests that this may be what the now dead link referred to: Delphi TImage32 - how to make the component invisible if no picture is loaded?