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
相关产品推荐
相关产品推荐

