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

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.

Related

Greyed TWebBrowser control

When TWebBrowser control is too small it becomes greyed.
If TWebBrowser control is aligned to alClient and there are no other controls on the form I can make it really small (50x10 for example). However, when I add other controls like panels, toolbar, main menu and so on which all float on top (alTop) - the more controls I add it seems, the smaller window of TWebBrowser I can get without greying itself. When window is resized to become larger, then it becomes ungreyed again.
In this example I placed TToolBar with 2 buttons aligned to alTop, and TWebBrowser aligned to alClient. If I make toolbar invisible, I can make web browser really small. However, with toolbar visible it greys itself. The more controls I add it seems to have less and less usable space before greying itself.
As you can see in last example web browser is even smaller than in second example but still visible and everything is the same except there is no toolbar on top. Same applies if used on Windows 7 or 8 or with Internet Explorer 10 or 11.
The examples here are just examples. I don't have a problem with having 100x100 control as minimum size. The problem is that when I place quite a bit of controls then it doesn't allow me to have smaller control than 550x250, which is quite large.
Can anyone enlighten me why other controls have an effect on web browser not being able to use smaller size when it can do this perfectly normally when there are no other controls on form?
Many thanks to bummi in the comments up there for finding a following workaround:
It appears that the problem with greyed control doesn't appear in XE3 and later but can be reproduced in earlier versions like XE2, XE, 2010 and 2009.
For these earlier versions the workaround is to place TWebBrowser on another control such as TPanel and then align both controls to alClient (so that the TWebBrowser fills entire TPanel and TPanel fills entire area previously filled by TWebBrowser). Of course, alignment here is not an issue but the workaround is just to place one control on another.
The same works for TEmbeddedWB and probably other controls that host Internet Explorer ActiveX control.
When placed on container control like TPanel, web browser can be resized to any size without the problem described above.

TToolbar incompatible with TForm.DoubleBuffered?

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.

Scrolling like Google Chrome with a click of the mouse wheel button

In Google Chrome when you click the mouse wheel button you get this cursor:
And then you are able to scroll to all possible directions, when you move around with your mouse...
IE also has this, but only moves up and down:
Is there any component for Delphi that can do this? (for a TScrollBox for example)
TMemo, for example, can do that for you, provided you set its ScrollBars property to something else than ssNone. It will even adjust according to which scroll bars are enabled. Problem with TScrollBar component is that on its own it doesn't have any focusable parts and won't receive OnMouseWheel(/Up/Down) events, but its included windowed controls might. You could write a workaround for that on main form events, though. Check solutions at http://www.delphipages.com/forum/showthread.php?t=197309
EDIT: OnMouseWheel(/Up/Down) should be OnMouse(/Up/Down), thanks to #Sertac Akyuz for pointing this out ;)
Seems like this feature is available in RAD studio 2009 (but not in D7).
You need to use Imouse (imouse.pas unit) and the control must have ControlStyle of csPannable.
quote:
Imouse (imouse.pas unit) is a standard implementation of scrolling
with middle button (called also "mouse panning"). It's also used in
RAD Studio. Imouse functionality relays on standard window scrollbars
and sends WM_HSCROLL/WM_VSCROLL to the window to make it scroll. It
works on every window, that have a scrollbar (e.g. TListView,
TTreeView, even TForm/TFrame if AutoScroll is True and at least one
scrollbar is visible).
Oh, I've forgotten one thing. Control must have csPannable in
ControlStyle, but RichView hasn't by default. So, after adding Code:
RichViewEdit1.ControlStyle := RichViewEdit1.ControlStyle +
[csPannable];
I didn't test it though.
All that is left for me is to look into the source code (When I can get my hands on copy of D2009) and maybe impliment this with D7...

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.

Delphi buttons show white border on Aero glass

I have been trying to find a good-looking design using Aero in Delphi 2010. One of the obvious uses one sees, is where the glass frame is extended to include the OK/Cancel buttons at the bottom of the screen. I notice though that this doesn't look quite right in Delphi 2010 - there is a white border all around each button.
This image shows the problem: the top 3 buttons are from my app, the bottom two were taken from Paint.NET's Layer Properties dialog.
I tried various combinations of DoubleBuffered and a few combinations of placing the controls on other controls first, but the problem remains. Any ideas?
If no one has a clean solution, as a workaround use TBitBtn with DoubleBuffered = false.
It appears that the only workaround is owner-draw, or a third-party button control Check out the Glass Button by Roy Klever or, as stated in the QC entry linked below, TBitBtn with DoubleBuffered=false, which was the accepted answer above to this question.
This is a bug in Windows Aero DWM or else a bug in the windows common controls, or a bug in the way the VCL class hierachy handles common control window messages and painting when painting on glass. In short, windows common controls do not paint themselves properly on glass, or rather DWM composition (Aero) is broken. Surprise surprise.
The standard VCL button component uses the Window Class BUTTON from Windows Common Controls.
Note that TSpeedButton does not use the windows common control, and does not have this problem. however, it also does not accept focus.
It appears Embarcadero knows about this issue, it is QC # 75246, which is closed because it is really a bug in the common controls library, as Won't Fix, with the suggestion to use TBitBtn. Buttons are not alone, this is part of a group of QC reports including panels, and other common controls.
However I have a commercial TcxButton (part of developer express components) which accepts keyboard focus, and does not draw this glitch. Any code that uses the Win32 common control button control appears to have this problem. It may be possible that a low level Win32 API hacker might find a workaround for this. I am looking into it. This answer will be updated if I figure it out.
One interesting detail: TcxButton has three drawing styles, cxButton.LookAndFeel.Kind = {lfOffice11,lfFlat,lfStandard}. Selecting lfOffice11 adds this glitch back in. It looks like a strange interaction between the glass feature in aero in Vista/Win7 and the common control/xptheme button drawing code.
It may be that the only workaround is to use a completely app-drawn button control and to not use Windows common controls buttons, or any button control that relies upon the XP theme engine to draw buttons, on an aero glass pane.
Edit: July 28, someone at Embarcadero has closed the above QC Entry, which was a mistake. I am urging them to reopen it, if only to clarify if this is indeed a Windows bug in the common controls dll.
If you wish to play around, make a copy of the VCL source code for the TButton and TCustomButton classes from StdCtrls, as I have done here, modify CNCtlColorBtn, so that you force one of three things to happen - PerformEraseBackground, DrawParentBackground or inherited, and see the results. Interesting stuff.
procedure TCustomGlassButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
begin
PerformEraseBackground(Self, Message.ChildDC);
Message.Result := GetStockObject(NULL_BRUSH);
(*
with ThemeServices do
if ThemesEnabled then
begin
if (Parent <> nil) and Parent.DoubleBuffered then
PerformEraseBackground(Self, Message.ChildDC)
else
DrawParentBackground(Handle, Message.ChildDC, nil, False);
{ Return an empty brush to prevent Windows from overpainting we just have created. }
Message.Result := GetStockObject(NULL_BRUSH);
end
else
inherited;
*)
end;
Some interesting reading on Vista era glass/DWM/aero APIs (C++ developers blog)
Here I'm providing some code that makes TButton look right on Glass. Unfortunately it makes the form "click-throw", so I don't think it's a good idea. But maybe you can find a way to fix the form's "click-throw".
if you are able to use win32 api, try exploiting NM_CUSTOMDRAW notification (not ownerdraw), as i do (yes, buttons DO send it, including radio and checkboxes. For these it is best to use WM_CTLCOLORSTATIC though.). This is how it is done in C++, but the idea is the same. While my idea is good, it so happens that my buttons do DISAPPEAR once per program execution from the window, when they are customdrawn and i need to hover mouse over them so they are visible again. That's why i'm still looking for comments for this. Note that it is really difficult to reproduce disappearing buttons in one-form applications. I hovewer am experiencing this behaviour in every project.
case WM_NOTIFY:
switch(((LPNMHDR)lParam)->code){
case NM_CUSTOMDRAW:
{
NMHDR *nmh=(NMHDR*)lParam;
//these 6000 through 6004 are button identifiers assigned by me
if(nmh->idFrom >= 6000 && nmh->idFrom <= 6004){
switch(((LPNMCUSTOMDRAW)nmh)->dwDrawStage){
case CDDS_PREERASE:
//BackgroundBrush is a HBRUSH used also as window background
FillRect(((LPNMCUSTOMDRAW)nmh)->hdc, &((LPNMCUSTOMDRAW)nmh)->rc, BackgroundBrush);
break;
}
}
break;
}
break;

Resources