Delphi 10.3样式下TPageControl RTL布局标签页标题镜像翻转问题求解
Delphi 10.3 VCL样式下TPageControl RTL标签页绘制解决方案
问题原因
VCL样式启用后,TPageControl的绘制逻辑被VCL样式引擎接管,不再调用原生Windows控件的绘制流程。你通过SetWindowLong添加的WS_EX_LAYOUTRTL扩展样式只会让样式引擎输出的整个绘制缓存镜像翻转,所以才会出现标签文字反向的问题,该样式仅在无样式的原生控件绘制场景下生效。
可行解决方案
方案:开启自绘+适配样式的自定义绘制逻辑
该方案完全使用RAD自带的VCL样式接口,不需要引入第三方组件,也不会破坏现有样式效果:
- 先移除你之前实现的
SetPageControlRightToLeft方法调用,不要给TPageControl及子控件添加WS_EX_LAYOUTRTL扩展样式 - 设置
TPageControl的两个基础属性:OwnerDraw:设为True,启用控件自绘BiDiMode:设为bdRightToLeft,自动实现标签从右往左排列的布局
- 实现
TPageControl的OnDrawTab事件,代码如下:
procedure TMasterOfAllFrm.PageControl1DrawTab(Control: TCustomTabControl; TabIndex: Integer; const Rect: TRect; Active: Boolean); var LPageControl: TPageControl; LTabSheet: TTabSheet; LText: string; LDrawRect: TRect; LStyleServices: TCustomStyleServices; begin LPageControl := TPageControl(Control); LTabSheet := LPageControl.Pages[TabIndex]; LText := LTabSheet.Caption; LStyleServices := StyleServices; // 按当前启用的VCL样式绘制标签背景 if Active then LStyleServices.DrawElement(LPageControl.Canvas.Handle, LStyleServices.GetElementDetails(ttTabItemSelected), Rect) else LStyleServices.DrawElement(LPageControl.Canvas.Handle, LStyleServices.GetElementDetails(ttTabItemNormal), Rect); // 计算文字绘制边距 LDrawRect := Rect; InflateRect(LDrawRect, -4, -2); // 右对齐绘制文字,适配RTL规则,无镜像问题 LStyleServices.DrawText(LPageControl.Canvas.Handle, LStyleServices.GetElementDetails(ttTabItemNormal), LText, LDrawRect, DT_RIGHT or DT_VCENTER or DT_SINGLELINE or DT_NOCLIP); end;
效果验证
该方案绘制的标签会完全适配当前启用的VCL自带样式的配色、字体、圆角等效果,标签从右往左排列,文字不会出现镜像翻转,完全符合RTL桌面应用的要求。
内容的提问来源于stack exchange,提问作者mazluta
相关产品推荐
相关产品推荐

