Delphi 11.3中TToolButton运行时文本强制左对齐的实现方案
在Delphi 11.3中使用垂直排列的TToolBar(开启文本模式)时,会遇到一个问题:设计阶段按钮文本是左对齐的,但运行时自动变为居中显示。要实现文本左对齐并紧贴图标,关键是修改TToolBarStyleHook中计算文本区域的逻辑。
你找到的Vcl.ComCtrls单元中TToolBarStyleHook.Paint方法代码里,计算文本尺寸时用了DT_CENTER or DT_WORDBREAK or DT_CALCRECT,随后调用RectCenter(sRect, R)把文本区域居中,这就是运行时文本偏移的根源——即使后续绘制文本用了DT_LEFT,也因为区域已经被居中导致视觉上还是偏右。
要解决这个问题,需要重写TToolBarStyleHook的Paint方法,将计算文本尺寸时的DT_CENTER替换为DT_LEFT,同时去掉RectCenter(sRect, R)的调用(因为不需要再居中区域)。具体步骤如下:
实现自定义StyleHook
创建一个单元,编写自定义的TToolBarStyleHook子类:
unit CustomToolBarStyleHook; interface uses Vcl.ComCtrls, Vcl.Styles.Utils.SysStyleHooks, Winapi.Messages, Winapi.Windows, Vcl.Controls, Vcl.Graphics, System.Classes, Vcl.Themes; type TCustomToolBarStyleHook = class(TToolBarStyleHook) protected procedure Paint(Canvas: TCanvas); override; end; implementation uses Vcl.Styles.Utils.Graphics; procedure TCustomToolBarStyleHook.Paint(Canvas: TCanvas); var Details: TThemedElementDetails; ButtonState: TThemedToolBar; LStyle: TCustomStyleServices; R, sRect, iRect: TRect; Info: TToolButtonInfo; ImageDrawed: Boolean; DrawButtonFace: Boolean; WStyle: DWORD; begin inherited; LStyle := StyleServices; if not LStyle.Available then Exit; Details := LStyle.GetElementDetails(tbButtonNormal); ButtonState := ttbButtonNormal; GetClientRect(Control.Handle, R); DrawButtonFace := True; if GetToolBarInfo(Control.Handle, Info) then begin WStyle := GetWindowLongPtr(Control.Handle, GWL_STYLE); if (WStyle and TBSTYLE_LIST = TBSTYLE_LIST) then begin sRect := R; Canvas.Font := TControlClass(Control).Font; // 将DT_CENTER改为DT_LEFT,不居中计算文本区域 DrawText(Canvas.Handle, PChar(Info.pszText), Length(Info.pszText), sRect, DT_LEFT or DT_WORDBREAK or DT_CALCRECT); // 移除RectCenter调用,保持文本区域左对齐 // RectCenter(sRect, R); ImageDrawed := False; if (Info.iImage >= 0) and (FImages <> nil) then begin iRect := Rect(5, iRect.Top, FImages.Width + 5, iRect.Bottom); OffsetRect(iRect, R.Left, 0); ImageDrawed := True; sRect := Rect(iRect.Right + 3, sRect.Top, R.Right, sRect.Bottom); end; if DrawButtonFace then DrawControlText(Canvas, Details, Info.pszText, sRect, DT_LEFT or DT_WORDBREAK) else begin if ButtonState <> ttbButtonDisabled then Canvas.Font.Color := LStyle.GetSystemColor(clBtnText) else Canvas.Font.Color := LStyle.GetSystemColor(clGrayText); SetBkMode(Canvas.Handle, Transparent); DrawText(Canvas.Handle, Info.pszText, Length(Info.pszText), sRect, DT_LEFT or DT_WORDBREAK); end; end; end; end; initialization // 替换TToolBar的默认StyleHook TCustomStyleEngine.RegisterStyleHook(TToolBar, TCustomToolBarStyleHook); finalization // 注销自定义StyleHook TCustomStyleEngine.UnRegisterStyleHook(TToolBar, TCustomToolBarStyleHook); end.
使用说明
- 将上述单元添加到项目中
- 在主窗体的uses列表中引用
CustomToolBarStyleHook单元 - 运行程序后,垂直排列的TToolBar按钮文本会保持左对齐,紧贴图标
注意:代码中保留了原方法的核心逻辑,仅修改了文本区域计算的对齐方式和移除居中步骤,确保兼容性。
内容的提问来源于stack exchange,提问作者Bart Kindt
相关产品推荐
相关产品推荐

