【问题标题】:Delphi buttons show white border on Aero glassDelphi 按钮在 Aero 玻璃上显示白色边框
【发布时间】:2011-03-21 00:53:02
【问题描述】:

我一直试图在 Delphi 2010 中使用 Aero 找到一个好看的设计。人们看到的一个明显的用途是玻璃框架被扩展以包括屏幕底部的 OK/Cancel 按钮。我注意到这在 Delphi 2010 中看起来不太正确 - 每个按钮周围都有一个白色边框。

这张图片显示了问题:前 3 个按钮来自我的应用程序,底部两个来自 Paint.NET 的图层属性对话框。

我尝试了 DoubleBuffered 的各种组合以及一些先将控件放在其他控件上的组合,但问题仍然存在。有什么想法吗?

【问题讨论】:

  • 您是否有显示此行为的最小应用程序的来源? (简单形式的 .dfm 和 .pas 就可以了)
  • @Jeroen:我可以使用包含 TButton 并设置 glassframe 以使按钮位于玻璃上的简单表单来重现该行为。我现在无法连接到 QC,所以我无法确定是否已经提交了类似的错误。
  • 有趣的行为 - 当 button.doublebuffered 为真,但 form doublebuffered 为假时,我在按钮周围得到一种颜色(黑色),当两者都为真时,我得到不同的颜色(如上,灰色或 clBtnFace),当按钮没有双缓冲时,文本看起来是灰色的。所以在delphi 2010中使用玻璃上的按钮而不看起来像废话是不可能的?
  • 相关问题:WinForms 的人对玻璃也没有任何乐趣:stackoverflow.com/questions/1870139/…

标签: delphi aero-glass


【解决方案1】:

如果没有人有一个干净的解决方案,作为一种解决方法,使用 TBitBtnDoubleBuffered = false

【讨论】:

  • +1 开箱即用。但是当然它从来没有那么简单:-(当表单没有双缓冲时,如果没有双缓冲,BitBtn 看起来很好。但是为表单打开它,BitBtn 看起来一样。为表​​单和你的标签关闭它消失。啊!
  • TSpeedButton 在这里尝试时看起来不错。但是它不接受键盘焦点。
  • 在 Delphi XE 中,TBitBtn 完美运行 - 无论 TBitBtn 或表单上的 DoubleBuffered 设置如何。这是我目前首选的解决方案。
  • DoubleBuffered 设置为False 可以解决无数问题!
【解决方案2】:

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

这是 Windows Aero DWM 中的一个错误,或者是 Windows 公共控件中的一个错误,或者是 VCL 类层次结构处理公共控件窗口消息和在玻璃上绘画时的绘画方式中的一个错误。简而言之,windows 常用控件无法在玻璃上正确绘制自己,或者更确切地说,DWM 组合 (Aero) 已损坏。惊喜惊喜。

标准 VCL 按钮组件使用 Windows 通用控件中的 Window 类 BUTTON。

注意TSpeedButton不使用windows常用控件,不存在这个问题。但是,它也不接受焦点。

Embarcadero 似乎知道这个问题,它是QC # 75246,它已被关闭,因为它确实是公共控件库中的一个错误,因为它不会修复,建议使用 TBitBtn。按钮并不孤单,它是一组 QC 报告的一部分,包括面板和其他常用控件。

但是,我有一个商业 TcxButton(开发人员快递组件的一部分),它接受键盘焦点,并且不会出现此故障。任何使用 Win32 通用控件按钮控件的代码似乎都存在此问题。低级别的 Win32 API 黑客可能会找到解决此问题的方法。我正在调查它。如果我弄清楚了,这个答案将被更新。

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

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

编辑:7 月 28 日,Embarcadero 有人关闭了上述 QC 入口,这是一个错误。我敦促他们重新打开它,只是为了澄清这是否确实是公共控件 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)

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      如果您能够使用 win32 api,请尝试利用 NM_CUSTOMDRAW 通知(不是 ownerdraw),就像我一样(是的,按钮会发送它,包括单选框和复选框。不过,最好使用 WM_CTLCOLORSTATIC。)。这就是它在 C++ 中的完成方式,但想法是一样的。虽然我的想法很好,但碰巧我的按钮在每个程序执行时都会从窗口中消失一次,当它们是自定义绘制时,我需要将鼠标悬停在它们上方以便它们再次可见。这就是为什么我仍在为此寻找 cmets。请注意,在单一表单应用程序中重现消失的按钮确实很困难。但是我在每个项目中都遇到了这种行为。

      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;
      

      【讨论】:

        猜你喜欢
        • 2013-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-22
        • 2011-05-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多