tags:

views:

523

answers:

4

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.

White borders around Delphi controls

I tried various combinations of DoubleBuffered and a few combinations of placing the controls on other controls first, but the problem remains. Any ideas?

A: 

http://www.installationexcellence.com/articles/VistaWithDelphi/Original/Index.html - here are some workarounds. i remember the problems with xp manifest. have you tried that too?

best regards,

Radu Barbu
I don't believe that this (good) article is applied to *Delphi 2010*.
Alexander
except the -1, your solution is????
Radu Barbu
Great article, but it makes no mention of my problem or a possible solution.
Cobus Kruger
this is not applicable to this question. nice link. answering a question that he did not ask.
Warren P
+2  A: 

If no one has a clean solution, as a workaround use TBitBtn with DoubleBuffered = false.

Uwe Raabe
+1 for out-of the box thinking. But of course it's never that simple :-(BitBtn looks fine without double-buffering when the form has no double buffering. But switch it on for the form, and BitBtn looks just the same. Switch it off for the form, and your labels disappear. Aaargh!
Cobus Kruger
TSpeedButton looks fine when I try it here. However it doesn't accept keyboard focus.
Warren P
+1  A: 

It appears that the only workaround is owner-draw, or a third-party button control. Check out the Glass Button by Roy Klever.

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. 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)

Warren P
+1  A: 

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".

Cosmin Prund