Delphi TStatusBar SizeGrip和VCL样式

我有TStatusBar的问题.

启用VCL样式后,即使SizeGrip属性设置为false,sizegrip也始终可见.

有办法解决吗?

解决方法

该问题位于TStatusBarStyleHook类的Paint方法中,VCl代码不检查SizeGrip属性的值并始终绘制控件.解决方法是创建一个从TStatusBarStyleHook类派生的新样式钩子并覆盖paint方法.

试试这个样本

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

 type
 TStatusBarStyleHookFix=class(TStatusBarStyleHook)
 protected
    procedure Paint(Canvas: TCanvas); override;
 end;

 TCustomStatusBarHelper= class helper for TCustomStatusBar
  private
    function GetCanvas: TCanvas;
    procedure SetCanvas(const Value: TCanvas);
  public
    property  CanvasRW : TCanvas read GetCanvas write SetCanvas;
 end;



{ TCustomStatusBarHelper }

function TCustomStatusBarHelper.GetCanvas: TCanvas;
begin
   Result:=Canvas;
end;

procedure TCustomStatusBarHelper.SetCanvas(const Value: TCanvas);
begin
  Self.FCanVas:=Value;
end;


{ TStatusBarStyleHookFix }

procedure TStatusBarStyleHookFix.Paint(Canvas: TCanvas);
const
  AlignStyles: array [TAlignment] of Integer = (DT_LEFT,DT_RIGHT,DT_CENTER);
var
  LServices : TCustomStyleServices;
  LGripRect: TRect;
  LDetails: TThemedElementDetails;
  LText: string;
  LCanvas: TCanvas;
  Res,Count,I: Integer;
  Idx,Flags: Cardinal;
  Borders: array [0..2] of Integer;
  LRect : TRect;
begin
  LServices:=StyleServices;
  if not LServices.Available then
    Exit;

  LDetails := LServices.GetElementDetails(tsStatusRoot);
  LServices.DrawElement(Canvas.Handle,LDetails,Rect(0,Control.Width,Control.Height));

  if SendMessage(Handle,SB_ISSIMPLE,0) > 0 then
  begin
    LRect := Control.ClientRect;
    FillChar(Borders,SizeOf(Borders),0);
    SendMessage(Handle,SB_GETBORDERS,IntPtr(@Borders));
    LRect.Left := Borders[0] + Borders[2];
    LRect.Top := Borders[1];
    LRect.Bottom := LRect.Bottom - Borders[1];
    LRect.Right := LRect.Right - Borders[2];

    LDetails := LServices.GetElementDetails(tsPane);
    LServices.DrawElement(Canvas.Handle,LRect);

    //draw the grip only if the  SizeGrip property is true
    if TCustomStatusBar(Control).SizeGrip then
    begin
      LGripRect := Control.ClientRect;
      LGripRect.Left := LGripRect.Right - LRect.Height;
      LDetails := LServices.GetElementDetails(tsGripper);
      LServices.DrawElement(Canvas.Handle,LGripRect);
    end;

    LDetails := LServices.GetElementDetails(tsPane);
    SetLength(LText,Word(SendMessage(Handle,SB_GETTEXTLENGTH,0)));
    if Length(LText) > 0 then
    begin
     SendMessage(Handle,SB_GETTEXT,IntPtr(@LText[1]));
     Flags := Control.DrawTextBiDiModeFlags(DT_LEFT);
     DrawControlText(Canvas,LText,LRect,Flags);
    end;
  end
  else
  begin
    if Control is TStatusBar then
      Count := TStatusBar(Control).Panels.Count
    else
      Count := SendMessage(Handle,SB_GETPARTS,0);
    for I := 0 to Count - 1 do
    begin
      LRect := Rect(0,0);
      SendMessage(Handle,SB_GETRECT,I,IntPtr(@LRect));
      if IsRectEmpty(LRect) then
        Continue;
      LDetails := LServices.GetElementDetails(tsPane);
      LServices.DrawElement(Canvas.Handle,LRect);
      //draw the grip only if the  SizeGrip property is true
      if TCustomStatusBar(Control).SizeGrip and (I = Count - 1) then
      begin
        LGripRect := Control.ClientRect;
        LGripRect.Left := LGripRect.Right - LRect.Height;
        LDetails := LServices.GetElementDetails(tsGripper);
        LServices.DrawElement(Canvas.Handle,LGripRect);
      end;
      LDetails := LServices.GetElementDetails(tsPane);
      InflateRect(LRect,-1,-1);
      if Control is TCustomStatusBar then
        Flags := Control.DrawTextBiDiModeFlags(AlignStyles[TCustomStatusBar(Control).Panels[I].Alignment])
      else
        Flags := Control.DrawTextBiDiModeFlags(DT_LEFT);
      Idx := I;
      SetLength(LText,Idx,0)));
      if Length(LText) > 0 then
      begin
        Res := SendMessage(Handle,IntPtr(@LText[1]));
        if (Res and SBT_OWNERDRAW = 0) then
          DrawControlText(Canvas,Flags)
        else
        if (Control is TCustomStatusBar) and Assigned(TCustomStatusBar(Control).OnDrawPanel) then
        begin
          LCanvas := TCustomStatusBar(Control).Canvas;
          TCustomStatusBar(Control).CanvasRW := Canvas;
          try
            TCustomStatusBar(Control).OnDrawPanel(TCustomStatusBar(Control),TCustomStatusBar(Control).Panels[I],LRect);
          finally
            TCustomStatusBar(Control).CanvasRW := LCanvas;
          end;
        end;
      end
      else if (Control is TCustomStatusBar) then
       if (TCustomStatusBar(Control).Panels[I].Style <> psOwnerDraw) then
         DrawControlText(Canvas,TCustomStatusBar(Control).Panels[I].Text,Flags)
       else
         if Assigned(TCustomStatusBar(Control).OnDrawPanel) then
         begin
           LCanvas := TCustomStatusBar(Control).Canvas;
           TCustomStatusBar(Control).CanvasRW := Canvas;
           try
             TCustomStatusBar(Control).OnDrawPanel(TCustomStatusBar(Control),LRect);
           finally
             TCustomStatusBar(Control).CanvasRW := LCanvas;
           end;
         end;
    end;
  end;

end;

别忘了像这样注册新式钩子

TStyleManager.Engine.RegisterStyleHook(TCustomStatusBar,TStatusBarStyleHookFix);
TStyleManager.Engine.RegisterStyleHook(TStatusBar,TStatusBarStyleHookFix);

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...