Delphi 10.2.3:如何计算TSpeedButton的精确边框宽度?
在Delphi 10.2.3里要精准算出TSpeedButton的边框宽度,核心得看它的Flat和Down属性组合,这俩直接决定了控件的绘制逻辑,甚至连文本的起始像素位置都会跟着变(尤其是你提到的Margin≠-1且没设置Glyph的场景)。我给你拆解成具体场景来说:
1. 当Flat属性为False时
这是TSpeedButton的默认状态,不管Down属性是True还是False,边框宽度固定为1像素。
此时文本的起始位置是:控件ClientRect的边缘 + 1像素边框宽度 + Margin值——标准按钮的边框是凸起样式,视觉上有立体感,但实际物理宽度就是1像素。
2. 当Flat属性为True时
这种扁平化状态下,边框的显示会根据按钮的交互状态变化:
- Down=False(未按下)、未获得焦点、鼠标未悬停:此时控件没有可见边框,边框宽度为0。文本的起始位置就是控件ClientRect的边缘 + Margin值,完全紧贴控件边缘(受Margin控制间距)。
- Down=True(按下)、获得焦点、或鼠标悬停:这时候会显示1像素的边框,同时文本会向内偏移1像素(因为按下状态下按钮是凹陷绘制的,文本跟着位移)。此时边框宽度为1像素,文本起始位置是:控件ClientRect边缘 +1像素边框 + Margin值 +1像素偏移。
3. 精确计算的代码实现
如果要在运行时动态获取边框宽度,可以结合控件属性直接判断,或者通过绘制逻辑反推。这里给你一个实用的函数(注意MouseInControl是保护属性,外部调用需要用RTTI或者继承控件来访问,或者在事件中记录鼠标状态):
function GetSpeedButtonBorderWidth(ASpeedBtn: TSpeedButton): Integer; var HasHoverOrFocus: Boolean; begin if not ASpeedBtn.Flat then Result := 1 else begin // 判断是否处于悬停/聚焦状态 HasHoverOrFocus := ASpeedBtn.Down or ASpeedBtn.Focused; // 如果需要判断鼠标悬停,可通过继承控件暴露MouseInControl属性,或者在OnMouseMove/OnMouseLeave中记录 // 这里暂时简化,只考虑Down和Focused if HasHoverOrFocus then Result := 1 else Result := 0; end; end;
要是你想更精准地验证文本位置,可以通过DrawText计算文本的绘制矩形,对比控件的ClientRect来反推边框宽度,这种方式能覆盖所有绘制细节。
内容的提问来源于stack exchange,提问作者Jens
相关产品推荐
相关产品推荐

