我对 TStatusBar 有疑问。
启用 VCL 样式后,即使 SizeGrip 属性设置为 false,sizegrip 也始终可见。
有没有办法解决它?
我对 TStatusBar 有疑问。
启用 VCL 样式后,即使 SizeGrip 属性设置为 false,sizegrip 也始终可见。
有没有办法解决它?
问题Paint
出在类的方法中TStatusBarStyleHook
,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, 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);