2013-06-29 3 views
3

TStatusBar에 문제가 있습니다.Delphi TStatusBar SizeGrip 및 VCL 스타일

VCL 스타일을 사용하면 SizeGrip 속성을 false로 설정해도 크기 그립이 항상 표시됩니다.

해결 방법이 있습니까?

+0

델파이의 어떤 버전과 같은 새로운 스타일의 후크를 등록 잊지 마세요 ? – lurker

+0

XE3, 죄송 합니다만 지정하지 않았습니다. – Xenon

답변

7

TStatusBarStyleHook 클래스의 Paint 메서드에 문제가 있으며 VCL 코드가 SizeGrip 속성의 값을 확인하지 않고 항상 그립을 그립니다. 해결 방법은 TStatusBarStyleHook 클래스에서 파생 된 새 스타일 후크를 만들고 페인트 메서드를 재정의하는 것입니다.

이 샘플을 시도

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, 0, Control.Width, Control.Height)); 

    if SendMessage(Handle, SB_ISSIMPLE, 0, 0) > 0 then 
    begin 
    LRect := Control.ClientRect; 
    FillChar(Borders, SizeOf(Borders), 0); 
    SendMessage(Handle, SB_GETBORDERS, 0, 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, LDetails, 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, LDetails, LGripRect); 
    end; 

    LDetails := LServices.GetElementDetails(tsPane); 
    SetLength(LText, Word(SendMessage(Handle, SB_GETTEXTLENGTH, 0, 0))); 
    if Length(LText) > 0 then 
    begin 
    SendMessage(Handle, SB_GETTEXT, 0, IntPtr(@LText[1])); 
    Flags := Control.DrawTextBiDiModeFlags(DT_LEFT); 
    DrawControlText(Canvas, LDetails, LText, LRect, Flags); 
    end; 
    end 
    else 
    begin 
    if Control is TStatusBar then 
     Count := TStatusBar(Control).Panels.Count 
    else 
     Count := SendMessage(Handle, SB_GETPARTS, 0, 0); 
    for I := 0 to Count - 1 do 
    begin 
     LRect := Rect(0, 0, 0, 0); 
     SendMessage(Handle, SB_GETRECT, I, IntPtr(@LRect)); 
     if IsRectEmpty(LRect) then 
     Continue; 
     LDetails := LServices.GetElementDetails(tsPane); 
     LServices.DrawElement(Canvas.Handle, LDetails, 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, LDetails, 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, Word(SendMessage(Handle, SB_GETTEXTLENGTH, Idx, 0))); 
     if Length(LText) > 0 then 
     begin 
     Res := SendMessage(Handle, SB_GETTEXT, Idx, IntPtr(@LText[1])); 
     if (Res and SBT_OWNERDRAW = 0) then 
      DrawControlText(Canvas, LDetails, LText, LRect, 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, LDetails, TCustomStatusBar(Control).Panels[I].Text, LRect, Flags) 
     else 
     if 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; 
    end; 

end; 

그래서 당신이 사용하는

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

enter image description here

+0

@RRUZ 덕분에 그것은 매력처럼 작동했습니다. 그리고 VCL Styles Utils에 감사드립니다. – Xenon