如何在TComboBox的OnDrawItem中判断滚动条及获取其宽度
TComboBox OnDrawItem中滚动条的判断与宽度获取
针对你在右对齐绘制内容时遇到的滚动条遮挡问题,以下是具体的解决方法:
一、判断下拉列表是否存在垂直滚动条
在OnDrawItem事件中,可以通过下拉列表窗口的属性或API来判断:
方法1:对比总项高度与客户区高度
var DropDownHandle: HWND; ClientRect: TRect; TotalHeight, ClientHeight: Integer; HasScrollBar: Boolean; begin DropDownHandle := (Control as TComboBox).DropDownListHandle; if DropDownHandle = 0 then Exit; GetClientRect(DropDownHandle, ClientRect); ClientHeight := ClientRect.Bottom - ClientRect.Top; TotalHeight := (Control as TComboBox).ItemHeight * (Control as TComboBox).Items.Count; HasScrollBar := TotalHeight > ClientHeight; end;
方法2:通过滚动条信息判断
var DropDownHandle: HWND; ScrollInfo: TScrollInfo; HasScrollBar: Boolean; begin DropDownHandle := (Control as TComboBox).DropDownListHandle; if DropDownHandle = 0 then Exit; ZeroMemory(@ScrollInfo, SizeOf(TScrollInfo)); ScrollInfo.cbSize := SizeOf(TScrollInfo); ScrollInfo.fMask := SIF_RANGE; GetScrollInfo(DropDownHandle, SB_VERT, ScrollInfo); HasScrollBar := ScrollInfo.nMax > ScrollInfo.nMin; end;
二、获取垂直滚动条宽度
直接调用系统API获取默认滚动条宽度,VCL组合框的滚动条使用系统默认样式,该值可靠:
ScrollBarWidth := GetSystemMetrics(SM_CXVSCROLL);
(需确保代码引用了Windows单元)
三、右对齐绘制的示例代码
结合滚动条判断,调整绘制区域避免遮挡:
procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var Cmb: TComboBox; DropDownHandle: HWND; ScrollInfo: TScrollInfo; HasScrollBar: Boolean; ScrollWidth: Integer; DrawRect: TRect; ItemText: string; begin Cmb := Control as TComboBox; ItemText := Cmb.Items[Index]; // 清空绘制背景 Cmb.Canvas.FillRect(Rect); // 判断滚动条是否存在 HasScrollBar := False; DropDownHandle := Cmb.DropDownListHandle; if DropDownHandle <> 0 then begin ZeroMemory(@ScrollInfo, SizeOf(TScrollInfo)); ScrollInfo.cbSize := SizeOf(TScrollInfo); ScrollInfo.fMask := SIF_RANGE; GetScrollInfo(DropDownHandle, SB_VERT, ScrollInfo); HasScrollBar := ScrollInfo.nMax > ScrollInfo.nMin; end; // 获取滚动条宽度 ScrollWidth := GetSystemMetrics(SM_CXVSCROLL); // 调整绘制矩形,避开滚动条区域 DrawRect := Rect; if HasScrollBar then DrawRect.Right := DrawRect.Right - ScrollWidth; // 右对齐绘制文本,距离右边缘10像素 DrawRect.Right := DrawRect.Right - 10; Cmb.Canvas.TextRect(DrawRect, ItemText, [tfRight, tfVerticalCenter]); end;
注意点
DropDownListHandle仅在下拉列表弹出后有效,而OnDrawItem事件正是在下拉列表显示时触发,所以无需担心句柄无效问题。- 如果使用自定义滚动条样式,可能需要通过其他方式获取宽度,但常规VCL场景下上述方法足够。
内容的提问来源于stack exchange,提问作者Matthias B
相关产品推荐
相关产品推荐

