我正在研究Delphi 10.2 Tokyo。
在SortArrow On ListView的帮助下,我可以为列表视图组件添加排序箭头(在colclick上添加了排序箭头逻辑),当我执行列调整大小排序箭头时消失。
如何在调整列大小时保持排序箭头(类似于Windows资源管理器)?
以下是我的组件代码:
unit uMyListView1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, Menus, DB, ExtCtrls, Buttons, ADODB,Commctrl;
const ARROW_SIZE = 10;
type
TMyListView = class(TListView)
private
FDataSet: TCustomADODataSet;
FPressedColumn: integer; //column index
FLastPressedColumn: integer; //last column to be pressed
FSortDir: integer; //-1 = desc, 1 = asc
FSortOrder: integer;
procedure SetListViewColumns;
protected
procedure ColClick(Column: TListColumn); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function BuildListView: boolean;
published
property DataSet: TCustomADODataSet read FDataSet write FDataSet;
end;
implementation
procedure TMyListView.ColClick(Column: TListColumn);
var DC: HDC;
Pos: TPoint;
Header: HWND;
Item: THDItem;
begin
inherited;
FLastPressedColumn := -1;
FPressedColumn := Column.Index;
FSortDir := 1;
//implement sorting
Header := ListView_GetHeader(Self.Handle);
ZeroMemory(@Item, SizeOf(Item));
Item.Mask := HDI_FORMAT;
//remove arrow old cloumn
if FLastPressedColumn <> -1 then
begin
Header_GetItem(Header, FLastPressedColumn, Item);
Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
Header_SetItem(Header, FLastPressedColumn, Item);
end;
Header_GetItem(Header, Column.Index, Item);
Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
if (FSortDir = 1) then
Item.fmt := Item.fmt or HDF_SORTUP//include the sort ascending flag
else if (FSortDir = -1) then
Item.fmt := Item.fmt or HDF_SORTDOWN;
Header_SetItem(Header, Column.Index, Item);
end;
constructor TMYListView.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPressedColumn := -1;
FLastPressedColumn := -1;
FSortOrder := 0;
end;
destructor TMYListView.Destroy;
begin
inherited Destroy;
end;
procedure TMYListView.SetListViewColumns;
var
NewColumn: TListColumn;
i: integer;
begin
if FDataSet <> nil then with FDataSet, Self.Columns do
begin
Clear; //clears any columns
for i := 0 to FieldCount - 1 do
if Fields[i].Visible then
begin
NewColumn := Add;
NewColumn.Caption := Fields[i].DisplayLabel;
NewColumn.Width := Fields[i].DisplayWidth * 10;
NewColumn.Alignment := Fields[i].Alignment;
end;
end;
end;
function TMYListView.BuildListView: boolean;
var NewListItem: TListItem;
i: integer;
begin
Result := FALSE;
FPressedColumn := -1;
FLastPressedColumn := -1;
Items.Clear;
if FDataSet = NIL then
begin
MessageDlg('The Dataset is NIL', mtError, [mbOK], 0);
Exit;
end;
try
FDataset.Open;
SetListViewColumns;
with FDataSet do
Begin
Items.BeginUpdate;
if not EOF then while not EOF do
begin
NewListItem := Items.Add;
for i := 0 to FieldCount - 1 do
begin
if Fields[i].Visible then
begin
if i = 0 then NewListItem.Caption := Fields[0].DisplayText
else if Fields[i].Visible then NewListItem.SubItems.Add(Fields[i].DisplayText);
end;
end;
Next;
Application.ProcessMessages;
end;
end;
Result := TRUE;
finally
FDataSet.Close;
Items.EndUpdate;
end;
end;
end.
答案 0 :(得分:1)
不确定为什么你的箭会消失。更糟糕的情况是,您可能需要从标题处获取ListView处理HDN_TRACK
通知以重置当前箭头(如果有)。
但是,您的代码中还存在与管理箭头有关的其他问题。
您的ColClick()
方法在之前将FLastPressedColumn
重置为-1 ,使用它来清除现有箭头:
begin
inherited;
//FLastPressedColumn := -1; // <-- REMOVE THIS!
...
//remove arrow old cloumn
if FLastPressedColumn <> -1 then
begin
...
FLastPressedColumn := -1; // <-- MOVED DOWN HERE INSTEAD!
end;
...
end;
事实上,您根本不需要FLastPressedColumn
,FPressedColumn
就足够了:
procedure TMyListView.ColClick(Column: TListColumn);
var
LNewColumn: Integer;
Item: THDItem;
begin
inherited;
if Column <> nil then
LNewColumn := Column.Index
else
LNewColumn := -1;
if FPressedColumn <> LNewColumn then
begin
FSortDir := 1;
//implement sorting
Header := ListView_GetHeader(Self.Handle);
ZeroMemory(@Item, SizeOf(Item));
Item.Mask := HDI_FORMAT;
//remove arrow old cloumn
if FPressedColumn <> -1 then
begin
Header_GetItem(Header, FPressedColumn, Item);
Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
Header_SetItem(Header, FPressedColumn, Item);
end;
FPressedColumn := LNewColumn;
if FPressedColumn <> -1 then
begin
Header_GetItem(Header, FPressedColumn, Item);
Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
if (FSortDir = 1) then
Item.fmt := Item.fmt or HDF_SORTUP//include the sort ascending flag
else if (FSortDir = -1) then
Item.fmt := Item.fmt or HDF_SORTDOWN;
Header_SetItem(Header, FPressedColumn, Item);
end;
end;
end;
此外,您的组件根本不处理窗口娱乐。如果重新创建ListView的HWND
(在此过程的生命周期中可以和 发生),则需要恢复当前的排序箭头(如果有)。如果CreateWnd()
不是-1,您可以覆盖虚拟CreateWindowHandle()
或Header_SetItem()
方法来调用FPressedColumn
:
type
TMyListView = class(TListView)
...
protected
...
procedure CreateWnd; override;
...
end;
...
procedure TMyListView.CreateWnd;
var
Header: HWND;
Item: THDItem;
begin
inherited;
if FPressedColumn <> -1 then
begin
Header := ListView_GetHeader(Self.Handle);
ZeroMemory(@Item, SizeOf(Item));
Item.Mask := HDI_FORMAT;
Header_GetItem(Header, FPressedColumn, Item);
Item.fmt := Item.fmt and not (HDF_SORTUP or HDF_SORTDOWN);//remove both flags
if (FSortDir = 1) then
Item.fmt := Item.fmt or HDF_SORTUP//include the sort ascending flag
else if (FSortDir = -1) then
Item.fmt := Item.fmt or HDF_SORTDOWN;
Header_SetItem(Header, FPressedColumn, Item);
end;
end;