时间:2010-07-26 11:00:42

标签: delphi aero-glass

4 个答案:

答案 0 :(得分:5)

答案 1 :(得分:2)

似乎唯一的解决方法是所有者绘制,或第三方按钮控件Check out the Glass Button by Roy Klever,或者如下面链接的QC条目中所述,TBitBtn和DoubleBuffered = false,这是上面接受的答案这个问题。

这是Windows Aero DWM中的一个错误,或者是Windows常用控件中的错误,或者是VCL类层次在玻璃上绘制时处理常见控件窗口消息和绘画的错误。简而言之,Windows常用控件不会在玻璃上正确绘制,或者DWM成分(Aero)被破坏。惊喜。

标准VCL按钮组件使用Windows Common Controls中的Window Class BUTTON。

请注意,TSpeedButton不使用Windows公共控件,并且没有此问题。但是,它也不接受焦点。

似乎Embarcadero知道这个问题,它是QC # 75246,它是关闭的,因为它确实是公共控件库中的一个bug,因为Will Not Fix,建议使用TBitBtn。按钮并不是唯一的,这是一组质量控制报告的一部分,包括面板和其他常见控件。

但是我有一个商业TcxButton(开发人员快速组件的一部分),它接受键盘焦点,并没有画出这个小故障。任何使用Win32公共控件按钮控件的代码似乎都有此问题。有可能低级别的Win32 API黑客可能会找到解决方法。我正在研究它。如果我弄明白,这个答案将会更新。

一个有趣的细节:TcxButton有三种绘图样式,cxButton.LookAndFeel.Kind = {lfOffice11,lfFlat,lfStandard}。选择lfOffice11会重新添加这个故障。它看起来像是Vista / Win7中aero中的玻璃功能与常用控件/ xptheme按钮绘图代码之间的奇怪交互。

可能唯一的解决方法是使用完全应用程序绘制的按钮控件,并且不使用Windows常用控件按钮,或依赖于XP主题引擎在航空玻璃窗格上绘制按钮的任何按钮控件。

编辑:7月28日,Embarcadero的某人关闭了上述QC Entry,这是一个错误。我敦促他们重新打开它,如果只是为了澄清这是否确实是常见控件dll中的Windows错误。

如果您想玩游戏,请从StdCtrls中复制TButton和TCustomButton类的VCL源代码,正如我在此处所做的那样,修改CNCtlColorBtn,以便强制执行以下三种操作之一 - PerformEraseBackground,DrawParentBackground或继承,并看到结果。有趣的东西。

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)

答案 2 :(得分:1)

Here我提供了一些使TButton在Glass上正确的代码。不幸的是它使表单“点击”,所以我认为这不是一个好主意。但也许你可以找到一种方法来修复表单的“点击”。

答案 3 :(得分:0)

如果你能够使用win32 api,尝试利用NM_CUSTOMDRAW通知(不是ownerdraw),就像我一样(是的,按钮DO发送它,包括无线电和复选框。对于这些,最好使用WM_CTLCOLORSTATIC。)。这就是用C ++完成的,但想法是一样的。虽然我的想法很好,但是当我们从窗口执行每个程序时,我的按钮会执行DISAPPEAR一次,当它们被自定义并且我需要将鼠标悬停在它们之上以便它们再次可见时。这就是为什么我还在为此寻找评论。请注意,在单一形式的应用程序中重现消失的按钮确实很困难。我希望每个项目都能遇到这种情况。

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;