- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 Delphi 2007。我有一个 TListView
,其中 OwnerData
和 OwnerDraw
设置为 True。 ViewStyle
设置为 vsReport
。
我有一个记录
。
type TAList=record
Item:Integer;
SubItem1:String;
SubItem2:String;
end;
var
ModuleData: array of TAList;
procedure TForm1.ListView3Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := IntToStr(ModuleData[Item.Index].Item);
Item.SubItems.Add(ModuleData[Item.Index].SubItem1);
Item.SubItems.Add(ModuleData[Item.Index].SubItem2);
end;
procedure TForm1.ListView3DrawItem(Sender: TCustomListView; Item: TListItem; Rect: TRect; State: TOwnerDrawState);
var
LIndex : integer;
LRect: TRect;
LText: string;
TTListView: TListView;
begin
TTListView := TListView(Sender);
if (Item.SubItems[0] = '...') then
begin
TTListView.Canvas.Brush.Color := clHighlight;
TTListView.Canvas.Font.Color := clHighlightText;
end else
begin
TTListView.Canvas.Brush.Color := TTListView.Color;
TTListView.Canvas.Font.Color := TTListView.Font.Color;
end;
for LIndex := 0 to TTListView.Columns.Count - 1 do
begin
if (not(ListView_GetSubItemRect(TTListView.Handle, Item.Index, LIndex, LVIR_BOUNDS, @LRect))) then Continue;
TTListView.Canvas.FillRect(LRect);
if (LIndex = 0) then LText := Item.Caption else LText := Item.SubItems[LIndex - 1];
LRect.Left := LRect.Left + 6;
DrawText(TTListView.Canvas.Handle, PChar(LText), Length(LText), LRect, DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS);
end;
end;
我希望在 SubItem2 被截断时显示提示。在 Windows XP 上,根本不显示任何提示。在 Windows Vista 和 Windows 7 上,当我的鼠标悬停在某个项目上时,它会显示完全关闭的提示。
我没有特殊的代码来处理提示。 OwnerData
和 OwnerDraw
模式中应该有一个吗?
以下是我得到的图像:
(来源:noelshack.com)
(来源:noelshack.com)
编辑:David 问为什么将 OwnerDraw
设置为 True
。原因有二:
OwnerDraw
设置为 False
,则会遇到另一个问题。请参阅Why do I get white column separators on my custom-drawn listview? 编辑2:如果我按照 TLama 的建议处理 OnInfoTip
事件,我会得到一个无主题的气球提示以及来自 Windows Vista 和 7 的错误提示。
最佳答案
此处描述的行为我仅在 Windows 7 SP1 64 位 Home Premium 上进行过体验和测试,并安装了 Delphi 2009 内置应用程序的最新更新以及应用的最新更新。我没有在其他系统中尝试过这个。
您可以在屏幕截图中看到的默认项提示并非来自 VCL。在某些情况下,您刚刚点击的提示是否是系统以错误的方式(可能以某种方式缓存)显示的。您悬停的最后一个项目的文本将显示为您刚刚悬停的项目的提示。这是属性配置(只是重要的部分;其余部分我保留在默认组件值中):
ListView1.ShowHint := False;
ListView1.OwnerData := True;
ListView1.OwnerDraw := True;
ListView1.ViewStyle := vsReport;
处理以下事件:
OnData
OnDrawItem
实际上,您甚至不需要处理 OnDrawItem
来模拟问题。提示由 OnData
中的项目的文本显示。事件。我无法更深入地追踪它,因为似乎没有通知处理程序(甚至系统通知)可能与您在 VCL 中看到的提示相关,这就是我怀疑系统的原因。
我所尝试的一切都无法解决保持当前属性配置的问题。这是我尝试过的列表:
作为热门选项,实际上我检查的第一个内容是排除 LVS_EX_LABELTIP
从 ListView 的样式中希望项目提示显示将停止,您将能够通过 OnInfoTip
实现您自己的自定义提示事件。问题是,该样式没有在 ListView 控件中的任何地方实现,因此它不包含在 ListView 样式中。
设置 OwnerDraw
属性设置为 False 实际上解决了问题(然后通过实际悬停的项目显示正确的项目文本提示),但您已经说过您需要使用所有者绘图,因此它也不是您的解决方案。
删除 LVS_EX_INFOTIP
ListView 样式中的样式最终停止显示系统的项目提示,但也导致控件停止向父级发送工具提示通知。结果就是 OnInfoTip
其功能被切断的事件。在这种情况下,您需要完全自己实现提示处理。这就是我在下面的代码中尝试过的。
我决定通过排除 LVS_EX_INFOTIP
来禁用 ListView 的所有系统提示。样式并实现自己的工具提示处理。到目前为止我至少知道以下问题:
当您使用常规 Hint
时属性并从带有缩短标题的项目悬停到 ListView 的空白区域,Hint
显示,但它不会隐藏,除非您退出控件客户端矩形或提示显示时间间隔已过(即使您再次悬停带有缩短标题的项目)。问题是我不知道如何为 THintInfo
结构指定 CursorRect
,以便覆盖除项目之外的整个客户端矩形面积矩形。
您必须使用与您的所有者绘制事件方法中使用的相同的项目矩形范围,因为系统不知道您在何处渲染项目的文本。因此,另一个缺点是保持同步。
这是演示项目中的主体代码,您可以下载from here
如果你愿意:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, CommCtrl, StdCtrls;
type
TRecord = record
Item: Integer;
SubItem1: string;
SubItem2: string;
end;
type
TListView = class(ComCtrls.TListView)
private
procedure CMHintShow(var AMessage: TCMHintShow); message CM_HINTSHOW;
end;
type
TForm1 = class(TForm)
ListView1: TListView;
procedure FormCreate(Sender: TObject);
procedure ListView1DrawItem(Sender: TCustomListView; Item: TListItem;
Rect: TRect; State: TOwnerDrawState);
procedure ListView1Data(Sender: TObject; Item: TListItem);
private
ModuleData: array of TRecord;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
ListColumn: TListColumn;
begin
SetLength(ModuleData, 3);
ModuleData[0].Item := 0;
ModuleData[0].SubItem1 := '[0;0] Subitem caption';
ModuleData[0].SubItem2 := '[1;0] Subitem caption';
ModuleData[1].Item := 1;
ModuleData[1].SubItem1 := '[0;1] Subitem caption';
ModuleData[1].SubItem2 := '[1;1] Subitem caption';
ModuleData[2].Item := 2;
ModuleData[2].SubItem1 := '[0;2] This is a long subitem caption';
ModuleData[2].SubItem2 := '[0;2] This is even longer subitem caption';
ListView1.OwnerData := True;
ListView1.OwnerDraw := True;
ListView1.ViewStyle := vsReport;
ListView_SetExtendedListViewStyle(
ListView1.Handle,
ListView_GetExtendedListViewStyle(ListView1.Handle) and not LVS_EX_INFOTIP);
ListColumn := ListView1.Columns.Add;
ListColumn.Caption := 'Col. 1';
ListColumn.Width := 50;
ListColumn := ListView1.Columns.Add;
ListColumn.Caption := 'Col. 2';
ListColumn.Width := 50;
ListColumn := ListView1.Columns.Add;
ListColumn.Caption := 'Col. 3';
ListColumn.Width := 50;
ListView1.Items.Add;
ListView1.Items.Add;
ListView1.Items.Add;
end;
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := IntToStr(ModuleData[Item.Index].Item);
Item.SubItems.Add(ModuleData[Item.Index].SubItem1);
Item.SubItems.Add(ModuleData[Item.Index].SubItem2);
end;
procedure TForm1.ListView1DrawItem(Sender: TCustomListView; Item: TListItem;
Rect: TRect; State: TOwnerDrawState);
var
R: TRect;
S: string;
SubItem: Integer;
ListView: TListView;
begin
ListView := TListView(Sender);
if (Item.SubItems[0] = '...') then
begin
ListView.Canvas.Brush.Color := clHighlight;
ListView.Canvas.Font.Color := clHighlightText;
end
else
begin
ListView.Canvas.Brush.Color := ListView.Color;
ListView.Canvas.Font.Color := ListView.Font.Color;
end;
for SubItem := 0 to ListView.Columns.Count - 1 do
begin
if ListView_GetSubItemRect(ListView.Handle, Item.Index, SubItem,
LVIR_LABEL, @R) then
begin
ListView.Canvas.FillRect(R);
if (SubItem = 0) then
S := Item.Caption
else
begin
R.Left := R.Left + 6;
S := Item.SubItems[SubItem - 1];
end;
DrawText(ListView.Canvas.Handle, PChar(S), Length(S), R, DT_SINGLELINE or
DT_VCENTER or DT_NOPREFIX or DT_END_ELLIPSIS);
end;
end;
end;
{ TListView }
procedure TListView.CMHintShow(var AMessage: TCMHintShow);
var
R: TRect;
S: string;
Item: Integer;
SubItem: Integer;
HitTestInfo: TLVHitTestInfo;
begin
with AMessage do
begin
HitTestInfo.pt := Point(HintInfo.CursorPos.X, HintInfo.CursorPos.Y);
if ListView_SubItemHitTest(Handle, @HitTestInfo) <> -1 then
begin
Item := HitTestInfo.iItem;
SubItem := HitTestInfo.iSubItem;
if (Item <> -1) and (SubItem <> -1) and
ListView_GetSubItemRect(Handle, Item, SubItem, LVIR_LABEL, @R) then
begin
if (SubItem = 0) then
S := Items[Item].Caption
else
begin
R.Left := R.Left + 6;
S := Items[Item].SubItems[SubItem - 1];
end;
if ListView_GetStringWidth(Handle, PChar(S)) > R.Right - R.Left then
begin
MapWindowPoints(Handle, 0, R.TopLeft, 1);
MapWindowPoints(Handle, 0, R.BottomRight, 1);
HintInfo^.CursorRect := R;
HintInfo^.HintPos.X := R.Left;
HintInfo^.HintPos.Y := R.Top;
HintInfo^.HintMaxWidth := ClientWidth;
HintInfo^.HintStr := S;
AMessage.Result := 0;
end
else
AMessage.Result := 1;
end
else
AMessage.Result := 1;
end
else
inherited;
end;
end;
end.
关于delphi - 当 OwnerData 和 OwnerDraw 设置为 True 时,TListView 上显示错误提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13773435/
TDBLookupListBox(我正在使用Delphi Xe5)没有onDraw事件。我需要根据某些字段的值更改列表中显示的项目的文本颜色(或文本的背景颜色)。例如,如果显示要选择的员工列表,则以灰
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwner
我想将复选框添加到我的 CListCtrl 派生类中,该类具有 LVS_OWNERDRAWFIXED 样式,用于在任何子项中绘制它们。我可以在 DrawItem 成员函数中简单地绘制它们,但它看起来有
我有一个 ComboBox,我设置了 DrawMode = DrawMode.OwnerDrawFixed。然后我处理 OnDrawItem 事件,一切正常。但是,它看起来与标准 ComboBox 非
我有一个 ListView我希望调整项目的绘制(例如在 ListView 项目中突出显示某些字符串),但是我不想从根本上改变项目的显示方式。 我已经设置了 OwnerDraw到 true 并且可以了解
我想在 TVirtualStringTree 标题列上绘图,但我遇到了问题。我需要树列来使用它的“默认绘制”并在其上添加我自己的图形。 如果我将 hoOwnerDraw 与 Header.Option
我正在尝试使用 OnCustomDrawItem 在报告模式下绘制一个包含 4 列的 ListView 控件。 当我尝试更改 Canvas.font.color 时,这就是我所做的,没有任何问题。 如
使用标准按钮,如果我有 OK 和 Cancel,默认为 OK,我按下右箭头,Cancel 被选中,按下键盘上的 enter 键,Cancel 按钮函数被调用。 ownerdraw 按钮不会发生这种情况
我正在尝试实现所有者绘制的 ListView,因为基本控件占用了制表符,我需要用它来对齐列中的值。 使用 MSDN 中的示例作为基地,我能够接近。我仍然遇到的唯一问题是,当文本不适合列时使用的省略号句
我有一个带有 LargeIcon View 模式的所有者绘图 ListView,我想更改 ListViewItem 的边界属性。 This链接对我没有帮助,因为属性 SystemInformation
我用 DrawMode = OwnerDrawVariable 创建了一个自定义组合框。一切都很好,除了它在 DropDownList 模式下不再使用视觉样式,即它看起来像旧的组合框。如何使用视觉样式
这个问题可能被认为是 Flickering in listview with ownerdraw and virtualmode 的后续问题. 我在虚拟模式 中有一个ListView 控件,我尝试执行
我正在尝试为 slider 拇指制作一个带有自定义图形的轨迹栏。我从以下代码开始: namespace testapp { partial class MyTrackBar : System.
我为 TPopUpMenu 分配了一些图标,但看起来它已更改为ownerdraw(它设置为 false)...我也使用 XP Manifest,但它看起来仍然很旧(Win2000 风格)...是否可以
我正在为一个软件创建一个插件,该插件可以为我创建的表单设置皮肤。但是,按钮不是基于它们的皮肤,而是显示标准的灰色按钮。在软件论坛上询问指出 .NET 表单控件是所有者绘制的,因此我的按钮不会以正确的样
我遇到了 tabcontrol 的问题。当我将 DrawMode 更改为 ownderdrawfixed 时,tabcontrol 的 borderstyle 从“fixedsingle”更改为“3d
很难理解 ownerdraw TreeView ,这里是完整的故事: 一个 VS2013 WinForms 应用程序(在 Windows 8.1 上运行,如果重要的话启用了 TrueType ....
我正在绘制自定义 ListView,并将 OwnerDraw 属性设置为“true”。 listview 也有 AllowColumnReorder 'true' 属性。 private void l
我有一个静态控件,它在创建时具有 SS_OWNERDRAW 和 SS_NOTIFY 标志。它的父窗口有 WS_EX_COMPOSITED 标志。 在Windows XP下,绘制不正确,如下图(右上角的
我在我的 WinForms 应用程序中使用 OwnerDrawFixed 作为自定义 ListBox 控件的 DrawMode。 我想在用户将鼠标悬停在列表框项上时重新绘制 ListBoxItem 的
我是一名优秀的程序员,十分优秀!