加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 在VCL风格的表单上禁用TButton问题

发布时间:2020-12-15 10:08:40 所属栏目:大数据 来源:网络整理
导读:当我尝试禁用一个风格的VCL上的按钮使用下面的代码行 TButton(Sender).enabled:= False; 我得到这个结果(在运行时禁用了按钮) 而不是这个! (设计时按钮禁用) 让两个或更多个具有相同颜色的按钮彼此相互混淆确实令人困惑,一个被禁用,另一个被启用 解决方法
当我尝试禁用一个风格的VCL上的按钮使用下面的代码行
TButton(Sender).enabled:= False;

我得到这个结果(在运行时禁用了按钮)

而不是这个! (设计时按钮禁用)

让两个或更多个具有相同颜色的按钮彼此相互混淆确实令人困惑,一个被禁用,另一个被启用

解决方法

此问题的原因位于 TButtonStyleHook(在Vcl.StdCtrls单元)样式hook类的Paint方法中.

在方法中找到此代码

if FPressed then
  Details := StyleServices.GetElementDetails(tbPushButtonPressed)
else if MouseInControl  then //this condition is triggered even if the button is disabled
  Details := StyleServices.GetElementDetails(tbPushButtonHot)
else if Focused then //this condition is triggered even if the button is disabled
  Details := StyleServices.GetElementDetails(tbPushButtonDefaulted)
else if Control.Enabled then
  Details := StyleServices.GetElementDetails(tbPushButtonNormal)
else
  Details := StyleServices.GetElementDetails(tbPushButtonDisabled);

并替换此代码

if FPressed then
  Details := StyleServices.GetElementDetails(tbPushButtonPressed)
else if MouseInControl and Control.Enabled then
  Details := StyleServices.GetElementDetails(tbPushButtonHot)
else if Focused and Control.Enabled then
  Details := StyleServices.GetElementDetails(tbPushButtonDefaulted)
else if Control.Enabled then
  Details := StyleServices.GetElementDetails(tbPushButtonNormal)
else
  Details := StyleServices.GetElementDetails(tbPushButtonDisabled);

另一个选项是重写TButton的Style钩子:

检查这个代码在这篇文章Fixing a VCL Style bug in the TButton component.这个代码的优点是你正在修复两个问题103708和103962.

Uses
 Winapi.CommCtrl,Vcl.Themes,Vcl.Styles;

type
  TCustomButtonH=class(TCustomButton);

  //we need this helper to access some strict private fields
  TButtonStyleHookHelper = class Helper for TButtonStyleHook
  protected
   function Pressed : Boolean;
   function DropDown: Boolean;
  end;

  //to avoid writting a lot of extra code we are to use TButtonStyleHook class and override the paint method
  TButtonStyleHookFix = class(TButtonStyleHook)
  protected
    procedure Paint(Canvas: TCanvas); override;
  end;


{ TButtonStyleHookFix }

procedure TButtonStyleHookFix.Paint(Canvas: TCanvas);
var
  LDetails          : TThemedElementDetails;
  DrawRect          : TRect;
  pbuttonImagelist  : BUTTON_IMAGELIST;
  IW,IH,IY        : Integer;
  LTextFormatFlags  : TTextFormatFlags;
  ThemeTextColor    : TColor;
  Buffer            : string;
  BufferLength      : Integer;
  SaveIndex         : Integer;
  X,Y,I           : Integer;
  BCaption          : String;
begin

  if StyleServices.Available then
  begin
    BCaption := Text;

    if Pressed then
      LDetails := StyleServices.GetElementDetails(tbPushButtonPressed)
    else
    if MouseInControl and Control.Enabled then
      LDetails := StyleServices.GetElementDetails(tbPushButtonHot)
    else
    if Focused and Control.Enabled  then
      LDetails := StyleServices.GetElementDetails(tbPushButtonDefaulted)
    else
    if Control.Enabled then
      LDetails := StyleServices.GetElementDetails(tbPushButtonNormal)
    else
      LDetails := StyleServices.GetElementDetails(tbPushButtonDisabled);

    DrawRect := Control.ClientRect;
    StyleServices.DrawElement(Canvas.Handle,LDetails,DrawRect);

    if Button_GetImageList(handle,pbuttonImagelist) and (pbuttonImagelist.himl <> 0) and ImageList_GetIconSize(pbuttonImagelist.himl,IW,IH) then
    begin
      if (GetWindowLong(Handle,GWL_STYLE) and BS_COMMANDLINK) = BS_COMMANDLINK then
        IY := DrawRect.Top + 15
      else
        IY := DrawRect.Top + (DrawRect.Height - IH) div 2;

      //here the image is drawn properly according to the ImageAlignment value
      case TCustomButton(Control).ImageAlignment of
        iaLeft  :
                  begin
                    ImageList_Draw(pbuttonImagelist.himl,Canvas.Handle,DrawRect.Left + 3,IY,ILD_NORMAL);
                    Inc(DrawRect.Left,IW + 3);
                  end;
        iaRight :
                  begin
                    ImageList_Draw(pbuttonImagelist.himl,DrawRect.Right - IW -3,ILD_NORMAL);
                    Dec(DrawRect.Right,IW - 3);
                  end;

        iaCenter:
                  begin
                   ImageList_Draw(pbuttonImagelist.himl,(DrawRect.Right - IW) div 2,ILD_NORMAL);
                  end;


        iaTop   :
                  begin
                   ImageList_Draw(pbuttonImagelist.himl,3,ILD_NORMAL);
                  end;


        iaBottom:
                  begin
                   ImageList_Draw(pbuttonImagelist.himl,(DrawRect.Height - IH) - 3,ILD_NORMAL);
                  end;

      end;


    end;

    if (GetWindowLong(Handle,GWL_STYLE) and BS_COMMANDLINK) = BS_COMMANDLINK then
    begin
      if pbuttonImagelist.himl = 0 then
        Inc(DrawRect.Left,35);

      Inc(DrawRect.Top,15);
      Inc(DrawRect.Left,5);
      Canvas.Font := TCustomButtonH(Control).Font;
      Canvas.Font.Style := [];
      Canvas.Font.Size := 12;
      LTextFormatFlags := TTextFormatFlags(DT_LEFT);
      if StyleServices.GetElementColor(LDetails,ecTextColor,ThemeTextColor) then
         Canvas.Font.Color := ThemeTextColor;
      StyleServices.DrawText(Canvas.Handle,BCaption,DrawRect,LTextFormatFlags,Canvas.Font.Color);
      SetLength(Buffer,Button_GetNoteLength(Handle) + 1);
      if Length(Buffer) <> 0 then
      begin
        BufferLength := Length(Buffer);
        if Button_GetNote(Handle,PChar(Buffer),BufferLength) then
        begin
          LTextFormatFlags := TTextFormatFlags(DT_LEFT or DT_WORDBREAK);
          Inc(DrawRect.Top,Canvas.TextHeight('Wq') + 2);
          Canvas.Font.Size := 8;
          StyleServices.DrawText(Canvas.Handle,Buffer,Canvas.Font.Color);
        end;
      end;

      if pbuttonImagelist.himl = 0 then
      begin
        if Pressed then
          LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphPressed)
        else if MouseInControl then
          LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphHot)
        else if Control.Enabled then
          LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphNormal)
        else
          LDetails := StyleServices.GetElementDetails(tbCommandLinkGlyphDisabled);
        DrawRect.Right := 35;
        DrawRect.Left := 3;
        DrawRect.Top := 10;
        DrawRect.Bottom := DrawRect.Top + 32;
        StyleServices.DrawElement(Canvas.Handle,DrawRect);
      end;

    end
    else
    if (GetWindowLong(Handle,GWL_STYLE) and BS_SPLITBUTTON) = BS_SPLITBUTTON then
    begin
      Dec(DrawRect.Right,15);
      DrawControlText(Canvas,Text,DT_VCENTER or DT_CENTER);
      if DropDown then
      begin
        LDetails := StyleServices.GetElementDetails(tbPushButtonPressed);
        SaveIndex := SaveDC(Canvas.Handle);
        try
          IntersectClipRect(Canvas.Handle,Control.Width - 15,Control.Width,Control.Height);
          DrawRect := Rect(Control.Width - 30,Control.Height);
          StyleServices.DrawElement(Canvas.Handle,DrawRect);
        finally
          RestoreDC(Canvas.Handle,SaveIndex);
        end;
      end;

      with Canvas do
      begin
        Pen.Color := StyleServices.GetSystemColor(clBtnShadow);
        MoveTo(Control.Width - 15,3);
        LineTo(Control.Width - 15,Control.Height - 3);
        if Control.Enabled then
          Pen.Color := StyleServices.GetSystemColor(clBtnHighLight)
        else
          Pen.Color := Font.Color;
        MoveTo(Control.Width - 14,3);
        LineTo(Control.Width - 14,Control.Height - 3);
        Pen.Color := Font.Color;
        X := Control.Width - 8;
        Y := Control.Height div 2 + 1;
        for i := 3 downto 0 do
        begin
          MoveTo(X - I,Y - I);
          LineTo(X + I + 1,Y - I);
        end;
      end;

    end
    else
    begin
      //finally the text is aligned and drawn depending of the value of the ImageAlignment property
      case TCustomButton(Control).ImageAlignment of
        iaLeft,iaRight,iaCenter : DrawControlText(Canvas,DT_VCENTER or DT_CENTER);
        iaBottom : DrawControlText(Canvas,DT_TOP or DT_CENTER);
        iaTop    : DrawControlText(Canvas,DT_BOTTOM or DT_CENTER);
      end;
    end;
  end;
end;

{ TButtonStyleHookHelper }

function TButtonStyleHookHelper.DropDown: Boolean;
begin
  Result:=Self.FDropDown;
end;

function TButtonStyleHookHelper.Pressed: Boolean;
begin
  Result:=Self.FPressed;
end;


initialization
 TStyleManager.Engine.RegisterStyleHook(TButton,TButtonStyleHookFix);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读