Delphi TButton component styling - delphi

I just want to apologize in advanced if this question is already in another thread. I am also relatively new to Delphi.
Today I have seen an example Delphi program that has TButton components on it. The buttons have a pulsating blue effect that I assume is part of the Windows styling. There is absolutely no code written to make the button this way. I have searched for a possible setting, but to no avail.
Note: The buttons makes the effect at run-time and there is no custom components installed.
If someone could give me some information about how to do this without code, maybe just a setting would be great.
I am using Delphi 7 (2002).

Delphi Firemonkey (FMX) component framework has a TColorAnimation for which you can set properties like Duration, StartValue, StopValue, trigger etc. The FMX framework was introduced in Delphi XE2.
Blinking button demo
Now that you have clarified that you use Delphi 7 (please remember in future to indicate the version), here's an alternative that works in Delphi 7 (FMX is not compatible with Delphi 7)
var
b: boolean;
procedure TForm9.Timer1Timer(Sender: TObject);
begin
b := not b;
if b then
Button1.Perform(BM_SETSTATE, 0, 0)
else
Button1.Perform(BM_SETSTATE, 1, 0);
end;
Flashing is controlled by a TTimer, e.g 500 ms.
However, this doesn't fulfill your requirement of "There is absolutely no code written to make the button this way.", but I'm not aware of any way to achieve that.

Related

Troubles using the styles [duplicate]

Create a new VCL Forms application
On the main form add a Tbutton and a TSaveDialog
Set "ofOverwritePrompt" to True in properties for the SaveDialog1
Use:
procedure TForm1.Button1Click(Sender: TObject);
begin
SaveDialog1.Execute();
end;
Run the app. Press the button to execute the save dialog. Try to save to a file that already exists.
A message box appears if you want to replace the file. Press cancel. All fine so far. Close the app.
Go to Project/Options/Application/Appearance and select a Custom style (e.g. Amakrits). Set Amakrits as the default style.
Run the app as in #5 above. Only a small bit of the message box will be shown. You will have to press Enter to be able to continue.
(Using a TFileSaveDialog will give the same result)
If I compile and run the app using Delphi XE8 it will be ok since the save dialog window seems to use the default windows style even if another style is chosen.
Edit:
I have Windows 10 pro. Source compiled as win32 with Delphi 10.1 Berlin.
The replace message box is partly hidden. Only a small top left part is shown, see figure.
And here it is compiled with XE8 win32:
Ps. I am using the default 100% scale factor.
Compiling with win64 (Delphi 10.1 Berlin) seems to be ok:
So, compiling to win32 does not work for me, but 64-bit will. Any clues?
Edit: Trying with "GetSaveFileName(OFN)" will also not work for me in win32 (win 64 is ok):
You can avoid this issue using the dialog styling code of the VCL Styles Utils project.
Just Add these units to your project.
uses
Vcl.Styles.Utils.Menus, //Popup and Shell Menus (class #32768)
Vcl.Styles.Utils.Forms, //dialogs box (class #32770)
Vcl.Styles.Utils.StdCtrls, //buttons, static, and so on
Vcl.Styles.Utils.ComCtrls, //SysTreeView32, SysListView32
Vcl.Styles.Utils.ScreenTips, //tooltips_class32 class
Vcl.Styles.Utils.SysControls,
Vcl.Styles.Utils.SysStyleHook;
{$R *.dfm}
procedure TForm26.Button1Click(Sender: TObject);
begin
UseLatestCommonDialogs := false;
SaveDialog1.Execute();
end;
I cannot confirm the problem, and all looks well here, (32 bit executalbe, themed with Amakrits, compiled with 10.1 Berlin, on Windows 7, 100% scaling) but you could try this:
uses ... Winapi.CommDlg;
...
var
OFN: TOpenFileName;
begin
FillChar(OFN, SizeOf(OFN), 0);
OFN.lStructSize := SizeOf(OFN);
OFN.nMaxFile := MAX_PATH;
OFN.Flags := OFN_OVERWRITEPROMPT or OFN_HIDEREADONLY or OFN_ENABLESIZING or OFN_EXPLORER;
GetSaveFileName(OFN);
end;
The result is an Amakrits-themed, new Explorer-like save dialog, which works fine (for me). Only the two round, blue "back" and "forth" (<- and ->) buttons at the top left of the dialog look a little weird.
But I did not try this with custom scaling settings (e.g. Medium 125% in the Control Panel -> Display panel, etc.). I think this could influence such things.
Update
I just tried to use SaveDialog1 (commenting out the OFN code above) with custom Display scaling (125%). All looked fine, so that is not it. Also when I use the OFN code, all looks fine (actually, better, i.e. no XP style dialog, but a real Explorer-like dialog instead).
If I set "Enable High-DPI" to true in Project/Options/Application it will work (replace box properly displayed). Disabling it will cause the problem (both in win32 and win64).
For the record, I had exactly the same problem (Delphi 10.1 Berlin, compiling on Windows 10 64 bit, 100% screen settings, compiled for 32 bit target). Enabling or disabling High-DPMI awareness didn't help.
A workaround is to disable styles for dialog boxes before executing the TSaveDialog (or TOpenDialog) like this:
TStyleManager.SystemHooks := TStyleManager.SystemHooks - [shDialogs];
The file dialog itself will still be themed. You will get standard Windows-style message boxes in case an overwrite prompt (or create prompt) pops up, but they will be large enough for the user to read and click them. After the file dialog has finished, you can enable styled dialogs again by re-adding shDialogs to SystemHooks if needed.

Property "ofOverwritePrompt" for TSaveDialog does not work when VCL Styles are used in Delphi 10.1 Berlin

Create a new VCL Forms application
On the main form add a Tbutton and a TSaveDialog
Set "ofOverwritePrompt" to True in properties for the SaveDialog1
Use:
procedure TForm1.Button1Click(Sender: TObject);
begin
SaveDialog1.Execute();
end;
Run the app. Press the button to execute the save dialog. Try to save to a file that already exists.
A message box appears if you want to replace the file. Press cancel. All fine so far. Close the app.
Go to Project/Options/Application/Appearance and select a Custom style (e.g. Amakrits). Set Amakrits as the default style.
Run the app as in #5 above. Only a small bit of the message box will be shown. You will have to press Enter to be able to continue.
(Using a TFileSaveDialog will give the same result)
If I compile and run the app using Delphi XE8 it will be ok since the save dialog window seems to use the default windows style even if another style is chosen.
Edit:
I have Windows 10 pro. Source compiled as win32 with Delphi 10.1 Berlin.
The replace message box is partly hidden. Only a small top left part is shown, see figure.
And here it is compiled with XE8 win32:
Ps. I am using the default 100% scale factor.
Compiling with win64 (Delphi 10.1 Berlin) seems to be ok:
So, compiling to win32 does not work for me, but 64-bit will. Any clues?
Edit: Trying with "GetSaveFileName(OFN)" will also not work for me in win32 (win 64 is ok):
You can avoid this issue using the dialog styling code of the VCL Styles Utils project.
Just Add these units to your project.
uses
Vcl.Styles.Utils.Menus, //Popup and Shell Menus (class #32768)
Vcl.Styles.Utils.Forms, //dialogs box (class #32770)
Vcl.Styles.Utils.StdCtrls, //buttons, static, and so on
Vcl.Styles.Utils.ComCtrls, //SysTreeView32, SysListView32
Vcl.Styles.Utils.ScreenTips, //tooltips_class32 class
Vcl.Styles.Utils.SysControls,
Vcl.Styles.Utils.SysStyleHook;
{$R *.dfm}
procedure TForm26.Button1Click(Sender: TObject);
begin
UseLatestCommonDialogs := false;
SaveDialog1.Execute();
end;
I cannot confirm the problem, and all looks well here, (32 bit executalbe, themed with Amakrits, compiled with 10.1 Berlin, on Windows 7, 100% scaling) but you could try this:
uses ... Winapi.CommDlg;
...
var
OFN: TOpenFileName;
begin
FillChar(OFN, SizeOf(OFN), 0);
OFN.lStructSize := SizeOf(OFN);
OFN.nMaxFile := MAX_PATH;
OFN.Flags := OFN_OVERWRITEPROMPT or OFN_HIDEREADONLY or OFN_ENABLESIZING or OFN_EXPLORER;
GetSaveFileName(OFN);
end;
The result is an Amakrits-themed, new Explorer-like save dialog, which works fine (for me). Only the two round, blue "back" and "forth" (<- and ->) buttons at the top left of the dialog look a little weird.
But I did not try this with custom scaling settings (e.g. Medium 125% in the Control Panel -> Display panel, etc.). I think this could influence such things.
Update
I just tried to use SaveDialog1 (commenting out the OFN code above) with custom Display scaling (125%). All looked fine, so that is not it. Also when I use the OFN code, all looks fine (actually, better, i.e. no XP style dialog, but a real Explorer-like dialog instead).
If I set "Enable High-DPI" to true in Project/Options/Application it will work (replace box properly displayed). Disabling it will cause the problem (both in win32 and win64).
For the record, I had exactly the same problem (Delphi 10.1 Berlin, compiling on Windows 10 64 bit, 100% screen settings, compiled for 32 bit target). Enabling or disabling High-DPMI awareness didn't help.
A workaround is to disable styles for dialog boxes before executing the TSaveDialog (or TOpenDialog) like this:
TStyleManager.SystemHooks := TStyleManager.SystemHooks - [shDialogs];
The file dialog itself will still be themed. You will get standard Windows-style message boxes in case an overwrite prompt (or create prompt) pops up, but they will be large enough for the user to read and click them. After the file dialog has finished, you can enable styled dialogs again by re-adding shDialogs to SystemHooks if needed.

How should I fetch the ThemeServices instance in Delphi XE8

I have this code from a legacy Delphi 2010 application.
var InternalServices: TThemeServices;
function ThemeServices: TThemeServices;
begin
if InternalServices = nil then
InternalServices := ThemeServicesClass.Create;
Result := InternalServices;
end;
The compiler tells me that ThemeServicesClass.Create does not exist. How should I do this in Delphi XE8?
The code that you include in the question is lifted from the VCL's Themes unit. That code should not be compiled by you. It was probably always a mistake for your application to compile that code rather than using the code from the Themes unit.
In XE8 you should call the StyleServices method of Vcl.Themes. The name change (from ThemeServices to StyleServices) is to reflect that fact that the older XP theme support has now been augmented by VCL styles.
So far as I can ascertain, the code in your question should not be compiled by you. It should be removed. It may be part of a much greater piece of code that perhaps also performs dubious acts. Without full sight of that code it's not possible for us to give you definitive advice.

Use TStatusBar style and graphical effects within TTabSet control

OS: Windows XP Pro SP3
Issue:
As you see - in left side is located StatusBar
Control ; In right side - TabSet Control.
What approach you would suggest to "copy" StatusBar style ( dynamic darkening of Top and Button ) into TabSet Control? Colour manipulations like clNone or AlphaBlend do not work ... and TransparentColor prop is not available either ...
Again I am too puzzled because there is a lot of options ( imho ) to choose from, but I do not know possible side-effects and level of compatibility in various Windows versions.
Thank you very very very much for any help.
P.S. Sorry if it is hard to notice
issue I am experiencing in my little
image above, BUT if I would resize it, It
would lose quality and there might be
problems notice anything at all ..
Rephrasing the Question
StatusBar1 is Parent of TabSet1. Now it looks like this ( wrong ):
I must achieve this StatusBar1.Panels[0] and TabSet1 look ( correct ):
I also tried to use psOwnerDraw technique ( http://delphi.about.com/od/vclusing/a/statusbar_owner.htm ) for StatusBar1.Panels[0] and get this result:
I tried the following in Turbo Delphi:
Create a new VCL app.
Drop a TStatusBar and a TTabSet on the form.
Add the following OnCreate handler:
procedure TForm1.FormCreate(Sender: TObject);
begin
StatusBar1.SimplePanel := True;
StatusBar1.SimpleText := 'Hallo';
TabSet1.Tabs.Add('Code');
TabSet1.Tabs.Add('History');
TabSet1.SetBounds(30, 0, TabSet1.Width, StatusBar1.Height); // Replace the 204
TabSet1.ParentBackground := True;
TabSet1.SoftTop := True;
TabSet1.Style := tsSoftTabs;
TabSet1.Parent := StatusBar1;
end;
Add XPMan to Unit1's uses clause.
Run the app under XP. This gives me the following form:
Is this what you want?
You have two basic ways to accomplish this:
Do it the way that the control you're copying does it, which means, invoke the XP Theming engine. You should be aware if you do it this way, that this effect is conditional, and only shown on systems that (a) support and (b) have themes enabled, so any user who has chosen the Windows Classic Theme (Windows 2000 era look and feel) will not see it.
Write some code to do the effects yourself. In this case, a bitmap that is carefully painted into a region on top of an owner-drawn tab. This will give you a consistent application look, but will be ignoring the users perhaps-intentional-perhaps-unintentional preferences on how the application should look.
Obviously there are tradeoffs in both approaches.

Why can't I set fonts on TSpeedButtons in Delphi 7 with themes enabled?

Very strange thing happening:
I had a whole bunch of TFrame's (might have been TCustomFrame, don't remember because I made an intermediate class between the 40 odd frames and the parent) that I was inheriting to make up the configuration part of a 'really cool' HL7 formula editor. What was weird, but not to the point, was that the DFM on the frame kept on adding OldCreateOrder, PixelsPerInch and TextHeight to the DFM, even though I never implemented those properties in the base class.
Anyway, I had to put those properties in my subclass even though I didn't want to, or else it wouldn't let me compile, so fine. Then I added one of those Color Chooser controls to one of my frames, and that worked until last week when it started giving me the business about not being able to find the parent.
So... I got rid of all my DFM's I changed all the Frames to Panels and it works fine (on my computer, running XP in VM with no themes), but for my colleague to the left of me (running Windows 7 natively) it doesn't matter what I do with TSpeedButtons on these Panels, they always have the same Sans 10pt Bold font, which would work, but I've got some weird symbols for set operations which I'd like to retain and CalcTextWidth totally fails.
I've tried:
ParentFont := true and false;
Flat := true and false;
Parent.Font := Whatever;
Suffice it to say, I've tried all the old tricks. The only thing that works is just removing the XP Manifest (did I mention this is Delphi 7). And that's not an option because sometime this year we're going to port everything over to D2009 and that... won't be an option!
Edit
The really strange thing is that using TFrame and a DFM, it works (even with an ancient compiler). Using TPanel it doesn't work.
There must be some difference between themes on a TPanel (or TCustomPanel, neither worked) and themes on a TFrame.
Also, I've got a TGroupBox between the buttons and the TPanel. Maybe that's causing the problem. I could change that pretty easy.
Edit 2
uses buttons, extctrls, stdctrls
(for Delphi 7, put XPManifest on your form)
procedure TForm1.FormCreate(Sender: TObject);
var
Panel : TPanel;
Grp : TGroupBox;
Btn : TSpeedButton;
begin
Panel := TPanel.Create(Self);
Panel.Parent := self;
Panel.Align := alClient;
Grp := TGroupBox.Create(Panel);
Grp.Parent := Panel;
Grp.Align := alClient;
Btn := TSpeedButton.Create(Grp);
Btn.Parent := Grp;
Btn.Width := 117;
Btn.Font.Name := 'Symbol';
Btn.Caption := 'Here is some text';
end;
In windows XP fine, tried on 2008 Server R2 and just shows bold sans font.
I tried this without the Group Box in between and it seems to work though.
(doing it with the frame works, but is too much code to post)
Delphi 7 was released in August of 2002. Vista came out in 2007 and Windows 7 in 2009. I think to expect a compiler and dev system from 2002 to work with all the new stuff in Vista/7 is a bit much to expect. Upgrade and you will probably see things work.
Of course, upgrading a compiler, particularly for a large application, is never easy.
I do feel for you, but I would not call it a bug in the VCL.
I'll try to answer this question for you first:
What was weird, but not to the point,
was that the DFM on the frame kept on
adding OldCreateOrder, PixelsPerInch
and TextHeight to the DFM, even though
I never implemented those properties
in the base class.
This might have to do with either
Frame inheritance (your DFM file contains the wrong keyword: object in stead if inherited, see this blog posting)
Your .DPR file where the comment behind your Frame unit is wrong (the comment actually is not a comment, it is a hint to the Delphi IDE to tell it which frame, form or datamodule designer it needs to choose)
Let us know if that helps; then focus on the TSpeedButton problem.
--jeroen
OK, here's the answer that worked:
groupbox.ParentBackground := false
Not sure why the background of the group box changes the foreground of the speed button.
Well, I'll write an answer to my own question, because today's answer isn't upgrade.
Just override the Paint function in the TSpeedButton, you're not using it on the form anyway.
Then, when you finally do update all 12 million lines of code to D2009, if is problem occurs again, then you can keep that code as one of those fancy helper class functions if you don't want subclass TSpeedButton.

Resources