1.環境
ここで説明する動作私はWindows7SP164ビットHomePremiumでのみ経験し、テストしました。最新の更新プログラムは、Delphi 2009で構築されたアプリケーションでインストールされ、最新の更新プログラムも適用されています。他のシステムでは、これを試したことはありません。
2.問題について
スクリーンショットに表示されるデフォルトのアイテムヒントは、VCLからのものではありません。ヒットしたばかりの特定の状況では、システムによって間違った、おそらく何らかの形でキャッシュされた方法で表示されるヒントがあります。最後にホバーしたアイテムのテキストは、ホバーしたばかりのアイテムのヒントとして表示されます。プロパティの構成は次のとおりです(重要な部分だけです。残りはデフォルトのコンポーネント値のままです)。
ListView1.ShowHint := False;
ListView1.OwnerData := True;
ListView1.OwnerDraw := True;
ListView1.ViewStyle := vsReport;
次のイベントが処理されます。
OnData
OnDrawItem
OnDrawItem
実際には、問題をシミュレートするためにを処理する必要はありません。OnData
ヒントは、イベントのアイテムに与えられたテキストによって示されます。VCLに表示されるヒントに関連する可能性のある通知ハンドラー(またはシステム通知)がないように思われるため、これ以上詳しく追跡することはできません。これが、システムを疑っている理由です。
3.解決する方法
私が試したことは、現在のプロパティ構成を維持する問題を修正しませんでした。これが私が試したことのリストです:
3.1。LVS_EX_LABELTIPスタイルを削除しますか?
一番のお気に入りで、実際に最初にチェックしたのは、アイテムのヒントの表示が停止し、イベントLVS_EX_LABELTIP
を通じて独自のカスタムヒントを実装できるようになることを期待して、リストビューのスタイルからを除外することでした。OnInfoTip
問題は、このスタイルがリストビューコントロールのどこにも実装されていないため、リストビュースタイルに含まれていないことです。
3.2。OwnerDrawプロパティを無効にしますか?
プロパティをFalseに設定すると、OwnerDraw
実際には問題が解決されます(ヒントは、実際のホバーされたアイテムによって正しいアイテムテキストで表示されます)が、所有者の描画を使用する必要があると言っているので、これも解決策ではありません。
3.3。LVS_EX_INFOTIPスタイルを削除しますか?
LVS_EX_INFOTIP
リストビューのスタイルからスタイルを削除すると、最終的にシステムによるアイテムヒントの表示が停止しましたが、コントロールが親にツールチップ通知を送信するのを停止しました。この結果として、OnInfoTip
その機能が遮断されたイベントが発生します。この場合、ヒント処理を完全に自分で実装する必要があります。そして、それは私が次のコードで試したことです。
4.回避策
LVS_EX_INFOTIP
スタイルを除外し、独自のツールチップ処理を実装することにより、リストビューのすべてのシステムヒントを無効にすることにしました。これまでのところ、少なくとも次の問題について知っています。
通常のHint
プロパティを使用して、キャプションが短縮されたアイテムからリストビューの空Hint
の領域にカーソルを合わせると、が表示されますが、コントロールクライアントの長方形を終了するか、ヒント表示の時間間隔が経過しない限り、非表示にはなりません(キャプションが短縮されたアイテムにもう一度カーソルを合わせます)。CursorRect
問題は、THintInfo
構造のを指定する方法がわからないため、アイテム領域の長方形を除くクライアントの長方形全体をカバーすることです。
システムはアイテムのテキストをどこにレンダリングしているかを認識しないため、所有者の描画イベントメソッドで使用するのと同じアイテムの長方形の範囲を使用する必要があります。したがって、もう1つの欠点は、これを同期させることです。
デモプロジェクトのメインユニットのコードは次のとおりです。必要に応じてダウンロードできます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.