TToolbar incompatible with TForm.DoubleBuffered? - delphi

I am using Delphi XE3.
When I create a new VCL project and drop a TToolbar on it, everything works fine - except when I activate Form1.DoubleBuffered.
From that moment on, drawing of the toolbar is broken - in designtime, it's either black, transparent, or parts of the IDE (statusbar, toolbar, etc.) are copied into it. It changes between these options when I click on it and when I change to source code (F12) and back.
In runtime, it's always black.
With DrawingStyle=dsGradient, everything works as expected. Switching back to dsNormal breaks it again.
Deactivating Form1.DoubleBuffered repairs it.
Any hints how to work around that issue?

In my opinion the solution is to set TForm.DoubleBuffered to False. Using a value of True causes all sorts of other problems. This property worked reasonably well before XP themes, but since their arrival, using TForm.DoubleBuffered has not been viable, in my view.
In addition to the problems you have encountered, I've come across lots of painting flaws when using the Windows Basic theme. I know that's not mainstream, but I happen to see that a lot with remote access. And there's more. When you double buffer a form you stop the theme animation from working. For example, a default button pulses to indicate that it is the default button.
If you get resize flickering without double buffering the form, use the ideas from my answer to another question. From the comments it seems that the flickering you wish to combat is in a paint box. I obviously don't know the details, but my experience and instincts say that you should be able to deal quite easily with that flickering at a local level. There surely should be no need for the global form wide double buffering.

As reported in this article, When not to use DoubleBuffered, some controls like TToolBar and TRichEdit don't work well with the DoubleBuffered property set to true.
The reason be be found in documentation, TWinControl.DoubleBuffered, where some WinControls can't draw themselves on a temporary bitmap (as happens when DoubleBuffered is true).
One workaround can be to put the TToolBar on a TPanel.

Related

Delphi - Changing active page's tab color and having it reset after clicking on another tab

So in the program I'm writing, I'm using a TPageControl component with multiple tab sheets. I want to change the color of the tab of the sheet that is currently the active page on the PageControl and then have the color be reset after clicking on another page (then that tab will change due to it being the active page and so on...), to make navigating the page control a bit easier. But I'm not sure how to do it? I did try using the OnChange procedure of the page control and some code like this (I know it's horribly wrong but I ran out of ideas and google searches. It didn't work anyway.):
with pgcTabs.ActivePage do
begin
brush.color:=clBlue;
font.color:=clWhite;
end;
Thanks in advance for the help!
Kind Regards
PrimeBeat
You can't. Apart from using TTabSheet.Highlighted you have no control over how the tabs are displayed.
Or you have to fully draw it yourself, as usual as for most other controls: set TPageControl.OwnerDraw to true, then use the OnDrawTab event to paint whatever you want to. It should be identical to TTabControl.OnDrawTab (see answer). The drawbacks (pun intended) of painting everything yourself is usually all the extra work to do: checking dimensions, interpreting accelerator keys, respecting system colors and settings (i.e. LTR)...
In my opinion "just adding a color" has little to no value compared to how the control by default paints already with all its advantages and features. Consider color blindness: those people might rather have problems.

Firemonkey - updating visual components

We are working with Firemonkey since version 1, and still find difficulties updating components that are currently visible on the screen. There are many 'ways' to request a repaint in Firemonkey, perhaps too many:
Applying a style (ApplyStyle event) - mostly when it becomes visible on screen
Requesting ".repaint" - some components have this
Requesting ".realign" - sometime works, current versions of FMX seem to drop / hide it
Requesting ".invalidate" - some components, mostly forms, have this
Requesting ".invalidateRect" - most components have this
Calling the ApplyStyle event manually - not guaranteed to work and design-wise is incorrect...
Given the lacking documentation for the platform, is there a "well defined" way to change the visual appearance (internal values of a style) when a component is already displayed? I.e. a listboxItem that is already present and visible on screen, a TGrid cell, and so on. Would appreciate your thoughts...
I don't think there's a single unified 'correct way' to refresh the visual of components in Firemonkey.
However, as a recommendation from personal experience, I'd take the .repaint route - this method is at the TControl level, and so it precedes primitives and styled controls (which are generally made up of primitives) and so applies to all visual controls. It also doesn't require parameters, so it's a good all-round solution.
I have noted that Firemonkey has always had an issue correctly repainting controls of it's own accord. Often I'm left with a 'shadow' of the previous visual of a control/primitive, and must call .repaint manually to update it. This got noticeably worse with FM2 and FM3 (presumably due to optimizations made for mobile platforms), and so doing a manual .repaint -- especially where effects such as TGlow and moving or rotating controls/primitives are concerned, has become a standard practice for me.

How to make my Deskband's (Taskbar Toolbar) Form transparent

I'm working on a Windows Deskband in Delphi XE2 for Windows XP, Vista and 7 (Win32 and Win64)...
I've implemented all the necessary interfaces (ITrayDeskBand, IDeskBandInfo, IDeskBand2, IDeskBand) in my code, and that all works exactly as it should (there are no warnings on Vista/7 complaining about compatibility as others have experienced).
The problem I have is that my Deskband Form appears with a non-transparent band. Also, only certain Controls are displaying (in this case TBitBtn and TImage containing a PNG). I need it to display TEdit and TComboBox objects properly too, but they won't appear at all.
I've tried enabling GlassFrame and SheetOfGlass properties on my Form, but this doesn't help one bit.
Furthermore, the Form itself is exceeding the top boundary of the Taskbar, meaning you cannot (for example) resize the Taskbar if the cursor is in-line with the top of the Taskbar immediately above my Deskband.
I believe there is something Delphi's VCL TForm type is doing behind the scenes which renders the TForm type incompatible as a Deskband container... but this is just a suspicion.
Here's a screenshot illustrating the various problems:
As you can see (above), the Deskband's Form is pale (instead of Transparent), it overlaps the top of the Taskbar (preventing resizing and Autohide triggering when the Taskbar is "hidden")
Any ideas?
UPDATE 1
Okay, I have been playing around and noticed that a totally different behaviour is observed when creating a TToolBar control to be used for the Deskband, rather than a form:
Notice there are three TToolButton controls (with their text virtually invisible due to the Glass theme)? There should also be a TEdit and TComboBox between two separators, but these refuse to display at all.
Also notice the artefacting (the repetition of actual Taskbar Icons)?
I'm not sure if this is a step in the right direction or not, but it might help you (or others) to deduce a solution!
Okay... I've finally figured this out, and it is the most absurd thing I've ever come across.
I'm posting my findings here for the benefit of others (to save you going through the nuisance I've just been through).
To get all of the controls on your Deskband Form to display and function properly, simply set the Visible property of your Form (in the IDE designer) to True.
Ridiculous, I know, but it works and is easily repeatable.

TToolBar paints incorrectly on non-themed Windows

It was recently brought to my attention that one of our applications paints incorrectly on non-themed Windows.
Toolbar is built from TSpeedButtons nested in TToolbar which in turn lives inside a page control.
On themed Windows everything looks nice. Well, not nice, but ok.
On non-themed Windows, however, weird vertical lines appear inside buttons.
I've searched around but cannot find any report of such a problem. (Most probably just my search kung fu sucks.) Does anybody know of a description of this problem or, even better, a fix?
TToolbar isn't designed to hold TSpeedButtons. It's designed to hold TToolButtons, which are made to not only sit on a TToolBar, but are specially written to behave correctly on the bar.
The issue you're having (particularly with the separators being drawn the way they are) is because you're using the incompatible TSpeedButton and separating them with TToolButton separatorss. TSpeedButton works well on a TPanel, and IIRC were designed for just that prior to MS providing the TToolBar/TToolButton pair in ComCtl.
A quick test app with both a TToolBar with TToolButtons and a TPanel with TSpeedButtons should see if this solves the problem.
EDIT: Your comment isn't quite correct. :)
Set the TToolBar.AllowTextButtons to True, and then set the button's you want wider to style tbsTextButton. As you can see, I've used a plain button, a separator, a text button (with text and image), a separator, and another plain button.
As TOndrej said in comments, this happens when TSpeedButton.Flat and .Transparent are both set to True. As David found out, TToolbar must also have .Flat set to True for the problem to occur.
A workaround that doesn't require changing the VCL source code is to set .Transparent to False.

Seeking a way to have a "Hover button" to expand a section

i have a flow panel that i'm adding extra items to it at runtime based on whether they have chosen to show all the items. that's all works fine; the expansion is controlled by a toolbar button.
the trouble is we'd like the user to be able to move his mouse over the "+" sign to expand the section.
initially i looked at TSpeedButton (OnMouseEnter) but even when it's "Flat", the focus rectangle still shows and so the glyph isn't centered. the main problem with this solution is it's appearance.
then i looked at making a descendant of TImage. that's a bit "unconventional" but it'd work. in OnMouseEnter or OnClick, it'd toggle an internal boolean "Expanded" flag and then load the appropriate picture from a resource. i have a dislike for unconventional solutions like that.
i need to add it to a few different screens so it's probably prudent for me to have/build a component for this. i have JVCL but i don't see anything suitable offhand.
thank you for your comments/help!
I always liked the approach used by the ModelMaker Code Explorer.
For example, when you're adding a new method, some rarely-used stuff is displayed collapsed ('Options and Directives' in the image below).
(source: 17slon.com)
When you hover over the text, you notice that it's actually a flat button. (Except that it's not - I believe Gerrit does some custom painting magic here).
(source: 17slon.com)
When you click this button, a panel appears. Button is still there, but with a new image. You can click it to close the panel.
(source: 17slon.com)
The state of this toggle button is preserved between sessions. IOW, even if you restart the Delphi, next tima you invoke 'Add Method', the 'Options and Directives' panel will appear exactly as you left it the last time.
i have a dislike for unconventional solutions like that.
Over the past few years, I have grown a bit suspicious of unconventional UI solutions — which is what you seem to be creating here. Why not just use a button that the user actually has to click? That seems to be much more common in the software I use, be it MS Office or programming utilities. Also, I'd make the button somewhat larger: in the screenshot, it really seems like a tiny little thing you have to target with your mouse cursor. Oh well, and if I'm bugging you with advise you haven't asked for anyway, why not give it ">>" as a caption instead of "+"? And if you'd give it a textual caption with a mnemonic as well, it'd actually be keyboard accessible. All this should make your UI better and more intuitive. I guess.
I do apologize for not answering your question, but I hope you'll spend 2 minutes thinking whether your users would actually prefer this solution :-)
Good luck!
Actually, I think that using a TImage in this situation is pretty conventional. I have seen many people suggest using the TImage, when either the TButton, or any of its associates did not have the right amount of control for whatever the developer was trying to do.
Have you tried a TBitBtn? I think when you get rid of the text it centers whatever image you have associated with it. I just checked in Delphi 6, all I have installed on this machine, and it had the MouseMove event.

Resources