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

Delphi 11.3下OwnerDraw TListBox切换选中项后旧项样式未更新问题

Delphi 11.3 TListBox OwnerDraw选中项切换后旧样式未恢复的解决办法

你的问题核心是没有先填充每个项的完整背景区域,直接绘制文本会导致旧的选中样式(蓝底)残留,切换选中项后之前的项无法被覆盖还原。

修正后的代码如下:

procedure TForm1.ListBoxColoringStyleDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  LListBox: TListBox;
  LItemText: string;
begin
  LListBox := Control as TListBox;
  with LListBox.Canvas do
  begin
    // 根据选中状态设置画笔和字体颜色
    if Index = LListBox.ItemIndex then
    begin
      Brush.Color := clBlue;
      Font.Color := clWhite;
    end
    else
    begin
      Brush.Color := clWindow;
      Font.Color := clBlack;
    end;

    // 填充整个Item的矩形区域,彻底覆盖旧绘制内容
    FillRect(Rect);

    // 获取项文本,用DrawText绘制,自动适配位置
    LItemText := LListBox.Items[Index];
    DrawText(Handle, PChar(LItemText), Length(LItemText), Rect, DT_LEFT or DT_VCENTER or DT_SINGLELINE);

    // 你的红框绘制代码可以放在这里,注意基于Rect坐标绘制
    // 示例:Pen.Color := clRed; Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
  end;
end;

关键修改点说明:

  • 用Control参数转换为TListBox,代替直接引用控件变量,代码更通用
  • 增加FillRect(Rect):强制用当前背景色填充整个项的区域,彻底清除之前的绘制痕迹
  • 替换TextOut为DrawText:自动实现文本垂直居中,并且基于项的Rect边界绘制,避免文本偏移或超出区域
  • 把clWindow改为clWhite(如果你的窗口背景是白色的话,clWindow可能受系统主题影响,也可以保留原设置)

另外要确保ListBox的Style属性设为lbOwnerDrawFixed(若为可变高度则设为lbOwnerDrawVariable),切换选中项时ListBox会自动触发OnDrawItem重绘需要更新的项。

内容的提问来源于stack exchange,提问作者stevenvh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 20:12:10