Change TToolBar background color - delphi

I got a problem, that I can't normally change the background color (e.g. clwhite) of TToolBar with its property ToolBar.Color. I'm not very experienced in Delphi and I find out two possible solutions, but still I'd like to know, how to change it proper way or why it's not possible.
1) Change style to Gradient, but it also changes the basic animations for buttons.
ToolBar.DrawingStyle := dsGradient
ToolBar.GradientStartColor := clWhite
ToolBar.GradientEndColor := clWhite
2) Put TToolBar inside TPanel with the following settings.
Panel.Color := clwhite
ToolBar.Parent := Panel
ToolBar.Align := alClient
ToolBar.Transparent := True

By default a TToolbar ignores its Color property.
Also by default the Transparent property is true, therefore whatever the color of the Toolbar's parent is will shine through.
If you look at the VCL source code you'll see that TToolbar does not do its own drawing; it is a wrapper around the ToolbarWindow32 Win32 common control in ComCtl32.dll.
This is the code that does the drawing.
When Windows XP was introduced Microsoft added UI themes and Borland supported this via VCL.Themes.TStyleManager.
You can change the appearance of Common Controls through the style manager: Project -> Options -> Appearance -> Custom Styles, but its hard to know what effect this has, because the IDE does not display the result (you can see it at run time) and you can only choose from a limited list of rather odd themes; also the feature is buggy.
The same goes for TPageControl/TTabSheet which does not publish its Color propery.
All the controls imported via ComCtl32.dll and implemented by VCL.ComCtrls suffer from these inconsistencies.
In short
There is nothing you can do to make TToolbar respect its Color property.
You've already found the workarounds, either:
Set a gradient with identical GradientEndColor and GradientStartColor, or
Place the toolbar on another control (e.g. a TPanel) and change the color of that control, because the toolbar is transparent the parent color will shine through.
You'll need to set the panel's BevelInner/BevelOuter to bvNone, or
Enable VCL styles and suffer all the issues related with that corporate tickbox anti-pattern.

Related

Delphi VCL styles problem with TListview EditCaption and HideSelection

I'm using Delphi 10.3 in a VCL app with a Dark VCL style (default Windows10 Dark for example).
I have two problems with VCL styling in TListview
When editing an item in TListview, the listview's edit is not styled: it has a white background with black text. It there any way to apply the VCL style to that edit although it not a VCL control?
Also, with HideSelection = False and the listview not having focus, the selected item's background color is the default light gray color instead of a much darker color that would better fit in the VCL style. Is there any way to modify that other than custom drawing?
I checked this with several dark VCL styles, they all have these problems with TListView (and TTreeview too).
I was able to fix the listview's edit background and text color by overriding message handler WM_CTLCOLOREDIT in a TListView descendant (TListViewEx in my case) like below. If you check the VCL source for TCustomListView.WMCtlColorEdit you'll see this fix does not cover the case glassPaint case correct - but I'm not using that. It seems to me this is actually a VCL bug and the below code should have been included in TCustomListView.WMCtlColorEdit.
Note: the same type of fix also works for TTreeview (using a TTreeview descendant obviously)
I have not found a workaround for the unfocused selection color yet.
procedure TListViewEx.WMCtlColorEdit(var Message: TMessage);
var
DC: HDC;
begin
if StyleServices.IsSystemStyle then
inherited
else
begin
DC := Message.WParam;
SetTextColor(DC, StyleServices.GetSystemColor(clWindowText));
SetBkColor(DC, StyleServices.GetSystemColor(clWindow));
Message.Result := 1;
end;
end;

FMX progressbar color

Please be kind, I did my best with google, and found some guidance (also on StackOverflow), but none of it works for me.
FMX form with FMX Progressbar;
I only want to change the progressbar color from ugly yellow to cool skyBlue.
So far I've dropped a stylebook on the form;
I've added "progresscellstyle.htrack.hindicator" to the stylesheet designer;
It's the only one that even provides me with a color option (vs everything in "progressbarstyle treeitem") and that color does not influence my progressbar colour.
Please, a next step to decoding this problem if you could be so kind
Drop a TProgressBar on the form. Right click it and select Edit Custom Style. It should give you the style designer with a ProgressBar1Style1 object which contains htrack and vtrack.
htrack contains hindicator. Drop a TRectangle on the hindicator. Set the TRectangle to align Client. Change the Fill color as desired. Change the Stroke Kind to None.
vtrack contains vindicator. Drop a TRectangle on the vindicator. Set the TRectangle to align Client. Change the Fill color as desired. Change the Stroke Kind to None.
Close the style designer and save when it asks. This is one way to do it.
This may be a title old question, but the content about this is so rare that I think will be useful to future generations to have some info here.
To simply put, to change the color that will fill your bar you have to select a area in your BitmapLinks. To do that double click in the SourceLink property in the hindicator (a child of htrack in the tree view).
Then select a are that you will want to use as the filling, if none of the option pleases you, you may add a new BitMap to your StyleBook.
For the background color, just insert a rectangle inside htrack with a Client Alignment

TGraphicControl transparency on a TCustomControl

I created a control based on TGraphicControl that is transparent and mostly empty space. It actually implements a simple symbol in line art.
i.e. TLFMagicControl = class(TGraphicControl)
In the constructor which I have:
ControlStyle := ControlStyle + [csOpaque];
My "TLFMagicControl" is then placed on my own panel that is a TCustomControl.
i.e. TLFGridPanel = class(TCustomControl)
The transparency of the TLFMagicControl works perfectly interacting with each other but not with the parent panel they are on (TLFGridPanel).
The TLFGridPanel spends most of its time just black so its not an issue but I want to user to be able to turn on/off grid lines on the panel. When I override the paint handler TLFGridPanel and draw my grid the controls placed on top are not transparent and block the grid lines underneath.
Is there a way around this for a TCustomControl or have I chosen the wrong base for my panel?
csOpaque tells the VCL that you draw the control entirely by yourself, which supresses the automatic background drawing (or erasing). Remove that control style in order to let WM_ERASEBKGND do its work.

Draw an image instead of window caption

I need to do something which seems to be easy, but I'm searching for days with no success.
I have a window of fixed size (say 500*250) and need to replace the whole caption bar with a fixed size JPEG (or better PNG) image (say 500*25).
There are lots of samples talking about Glass, Aero, DWM, blah blah blah. But I just need to draw a fixed image!
I've already tried this, but it doesn't work:
procedure TForm1.Button1Click(Sender: TObject);
var
bmp:TBitmap;
DC:HDC;
begin
DC:=GetWindowDC(form1.Handle);
bmp:=tbitmap.Create;
bmp.SetSize(500, 25);
bmp.Canvas.TextOut(5,5,'Helloooooooooooooooooo');
BitBlt(dc,0,0,500,25,bmp.Canvas.Handle,0,0,SRCCOPY);
bmp.Free;
ReleaseDC(form1.Handle,DC);
end;
It should work both on XP and Vista/7. Please help.
P.S: I have Delphi XE.
You can do so by using VCL Styles.
You can change the appearance of the Windows caption bar like that by using the Delphi integrated Bitmap style designer to change a custom style and then use that Style in your application.
If you don't want to enforce the style to the whole application you can set the StyleElements property of the form to only include seBorder, this means that only the border aka caption of your application will be rendered using your custom style.
If you're working in Delphi XE2 then you won't be able to use the StyleElements property but that is just a minor obstacle, it just means that you will have to resort to using StyleHooks to implement the same behaviour and there is enough documentation on how to do that here.
Sadly, if your Delphi version is older then XE2 then you won't be able to use VCL Styles.
Another but rather unpleasant way would be to create a borderless form by changing the BorderStyle property to bsNone and then implementing your image in a way that it would act as a title bar, processing all actions made on the image and sending appropriate Messages to the application.
You can either:
Intercept the WM_NCPAINT message and custom-draw the caption bar manually.
Remove the caption bar altogether, by using SetWindowRgn() or overriding the CreateParams() method to remove the WS_CAPTION style, and then use the form's OnPaint event, or even a TImage, to display the graphic at the top of the form's remaining client area.
The simplest solution would be to use CreateParams() and TImage.

How to change caption font color on TCheckBox, TRadioButton, TGroupBox?

I don't know what my problem is, but I cannot set the font color in DEx2 for controls like TCheckBox, TRadioButton, TGroubBox, and TRadioGroup. It doesn't matter if I do it in the IDE or programmatically.
I have set my form color to clBlack and want my captions to be clWhite, but they won't render any color but clBlack. When I assign a color on a form's OnShow event and step through it in the debugger, it shows the value I assigned it, but on the screen it is still black.
I am not using styles or anything else. Any ideas?
Here is a sample form:
white on black example http://www.skippix.us/temp/Delphi-Font-Problem.bmp
When you uses the windows themes in an application, most of the custom settings like the font colors are ignored. As workaround and depending of the component you can ownerdraw the control (only when this feature is supported), override the paint method in order to use your own color in the font (TRadioGroup, TGroupBox), and for components like TCheckBox and TRadioButton (which are WinAPI controls wrappers) you must intercept the WM_PAINT windows message and implement your own code to draw the control.
Also starting with Delphi-xe2 you can use the vcl styles which allow you to change the appearance of the controls, from here (and when is possible) you can modify the style hooks to apply your own font colors and other customizations.
A simple and easier workaround is to create a checkbox without caption and add a label after it. You can easily change the label's color. You can also create a new component that binds a label to the checkbox itself. That's what worked for me on Delphi 2007.
It will work under the following setting:
Project Options > Application > Runtime Themes = none

Resources