You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:08:23