TListView:如果添加列,VCL 会丢失列的顺序

2023-11-25

我正在尝试在 TListView 中的现有列之间添加一列。因此,我在末尾添加新列,并通过将其索引设置为指定值来移动它。这是有效的,直到添加另一个新列。

我做了什么: 在最后一个位置添加列 (Columns.Add),并在最后一个位置添加子项 (Subitems.Add)。然后,我通过将列的索引设置到正确的位置来移动该列。 只要添加一列,这种方法就可以正常工作。当添加第二个新列时,子项会搞砸。第一列的新子项移动到最后一个位置,例如像这样:

0        |  1          |  new A       |  new B      | 3
Caption  |  old sub 1  |  old sub 3   |  new Sub B  | new sub A

如果有人能提供帮助,我会很高兴!

例如,是否有可能我可以发送到 ListView 的命令或消息,以便它刷新或保存它的列 --> 子项映射,我可以在添加第一个新列及其子项后使用它,以便我可以处理第二个新列与第一个方法相同。

或者这只是 TListViews 列-->子项处理或 TListColumns... 的错误?

vcl 表单应用程序的示例代码(分配 Form1.OnCreate 事件):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    listview: TListView;
    initButton: TButton;
    addColumn: TButton;
    editColumn: TEdit;
    subItemCount: Integer;
    procedure OnInitClick(Sender: TObject);
    procedure OnAddClick(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  listview := TListView.Create(self);
  with listview do
  begin
    Left := 8;
    Top := 8;
    Width := self.Width - 30;
    Height := self.Height - 100;
    Anchors := [akLeft, akTop, akRight, akBottom];
    TabOrder := 0;
    ViewStyle := vsReport;
    Parent := self;
  end;

initButton := TButton.Create(self);
with initButton do
  begin
    left := 8;
    top := listview.Top + listview.Height + 20;
    Width := 75;
    Height := 25;
    TabOrder := 1;
    Caption := 'init';
    OnClick := OnInitClick;
    Parent := self;
  end;

  editColumn := TEdit.Create(self);
  with editColumn do
  begin
    left := initButton.Left + initButton.Width + 30;
    top := listview.Top + listview.Height + 20;
    Width := 120;
    Height := 25;
    TabOrder := 2;
    Parent := self;
    Caption := '';
  end;

  addColumn := TButton.Create(self);
  with addColumn do
  begin
    left := editColumn.Left + editColumn.Width + 10;
    top := listview.Top + listview.Height + 20;
    Width := 75;
    Height := 25;
    TabOrder := 1;
    Enabled := true;
    Caption := 'add';
    OnClick := OnAddClick;
    Parent := self;
  end;

end;

procedure TForm1.OnInitClick(Sender: TObject);
var col: TListColumn;
i, j: integer;
item: TListItem;
begin
  listview.Items.Clear;
  listview.Columns.Clear;

  // add items
  for I := 0 to 2 do
  begin
    col := ListView.Columns.Add;
    col.Caption := 'column ' + IntToStr(i);
    col.Width := 80;
  end;

  // add columns
  for I := 0 to 3 do
  begin
    item := ListView.Items.Add;
    item.Caption := 'ItemCaption';

    // add subitems for each column
    for j := 0 to 1 do
    begin
      item.SubItems.Add('subitem ' + IntToStr(j+1));
    end;
  end;

  subItemCount := 5;
end;

procedure TForm1.OnAddClick(Sender: TObject);
var number: integer;
col: TListColumn;
i: Integer;
ascii: char;
begin
  listview.Columns.BeginUpdate;

  number := StrToInt(editColumn.Text);
  ascii :=  Chr(65 + number);

  // create the new column
  col := TListColumn(ListView.Columns.add());
  col.Width := 80;
  col.Caption := ascii;

  // add the new subitems
  for I := 0 to ListView.Items.Count-1 do
  begin
    ListView.Items[i].SubItems.Add('subitem ' + ascii);
  end;

  // move it to the designated position
  col.Index := number;

  listview.Columns.EndUpdate;

  Inc(subItemCount);
end;

end.

谢谢你!


Edit:Sertac Akyuz 建议的修复工作正常,但我无法使用它,因为更改 Delphi 源代码对于我的项目来说不是解决方案。已报告错误。

Edit:删除了第一篇文章中无意包含的第二个问题并提出了新问题(请参阅链接问题和问题修订版)。

Update: The 报告的错误现已关闭,从 Delphi XE2 开始已修复Update 4.


致电UpdateItems排列列后的方法。例如。:

..
col.Index := number;
listview.UpdateItems(0, MAXINT);
..



Update:

在我的测试中,在某些情况下我似乎仍然需要上述调用。但真正的问题是“Delphi 列表视图控件中存在错误”.

用一个简单的项目复制问题:

  • Place a TListViewVCL 窗体上的控件,设置其ViewStyle到“vsReport”并设置FullDrag到“真实”。
  • 将以下代码放入OnCreate表单的处理程序:
    ListView1.Columns.Add.Caption := 'col 1';
    ListView1.Columns.Add.Caption := 'col 2';
    ListView1.Columns.Add.Caption := 'col 3';
    ListView1.AddItem('cell 1', nil);
    ListView1.Items[0].SubItems.Add('cell 2');
    ListView1.Items[0].SubItems.Add('cell 3');
    
  • Place a TButton在表单上,​​并将以下代码放入其OnClick处理程序:
    ListView1.Columns.Add.Caption := 'col 4';
  • Run the project and drag the column header of 'col 3' to in-between 'col 1' and 'col 2'. The below picture is what you'll see at this moment (everything is fine):

    list view after column drag

  • Click the button to add a new column, now the list view becomes:

    list view after adding column

    Notice that 'cell 2' has reclaimed its original position.

Bug:

a 的列TListView (TListColumn)将其订购信息保存在其FOrderTag场地。每当您更改列的顺序(通过设置Index属性或通过拖动标题),这FOrderTag得到相应更新。

现在,当您向TListColumns集合,集合首先添加新的TListColumn然后调用UpdateCols方法。下面是代码UpdateCols的方法TListColumns在 D2007 VCL 中:

procedure TListColumns.UpdateCols;
var
  I: Integer;
  LVColumn: TLVColumn;
begin
  if not Owner.HandleAllocated then Exit;
  BeginUpdate;
  try
    for I := Count - 1 downto 0 do
      ListView_DeleteColumn(Owner.Handle, I);

    for I := 0 to Count - 1 do
    begin
      with LVColumn do
      begin
        mask := LVCF_FMT or LVCF_WIDTH;
        fmt := LVCFMT_LEFT;
        cx := Items[I].FWidth;
      end;
      ListView_InsertColumn(Owner.Handle, I, LVColumn);
      Items[I].FOrderTag := I;
    end;
    Owner.UpdateColumns;
  finally
    EndUpdate;
  end;
end;


上面的代码从底层 API 列表视图控件中删除所有列,然后重新插入它们。请注意代码如何分配每个插入列的FOrderTag索引计数器:

      Items[I].FOrderTag := I;

这是该时间点从左到右的列顺序。如果每当列的排序与创建时不同时调用该方法,则该排序将丢失。由于物品不会相应地改变它们的位置,所以一切都会变得混乱。

Fix:

根据我的测试,以下对该方法的修改似乎有效,您需要进行更多测试(显然这个修复并没有涵盖所有可能的情况,请参阅下面的“torno”评论以了解详细信息):

procedure TListColumns.UpdateCols;
var
  I: Integer;
  LVColumn: TLVColumn;
  ColumnOrder: array of Integer;
begin
  if not Owner.HandleAllocated then Exit;
  BeginUpdate;
  try
    SetLength(ColumnOrder, Count);
    for I := Count - 1 downto 0 do begin
      ColumnOrder[I] := Items[I].FOrderTag;
      ListView_DeleteColumn(Owner.Handle, I);
    end;

    for I := 0 to Count - 1 do
    begin
      with LVColumn do
      begin
        mask := LVCF_FMT or LVCF_WIDTH;
        fmt := LVCFMT_LEFT;
        cx := Items[I].FWidth;
      end;
      ListView_InsertColumn(Owner.Handle, I, LVColumn);
    end;
    ListView_SetColumnOrderArray(Owner.Handle, Count, PInteger(ColumnOrder));

    Owner.UpdateColumns;
  finally
    EndUpdate;
  end;
end;

如果您不使用包,您可以将“comctrls.pas”的修改副本放入您的项目文件夹中。否则,您可能会寻求运行时代码修补,或提交错误报告并等待修复。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TListView:如果添加列,VCL 会丢失列的顺序 的相关文章

  • 可以解析Delphi XMLDoc格式并构建在线帮助的工具

    API 文档的 XMLDoc 工具解释如下 http edn embarcadero com article 32770 http edn embarcadero com article 32770 是否有任何免费或商业工具可用于创建基于
  • Windows EventLog:它的操作速度有多快?

    我有一个服务应用程序 它通过 TCP 处理客户端请求并将任何事件写入 Windows EventLog 由于该应用程序预计会在短时间内为许多客户端和每个客户端的大量请求提供服务 假设每秒 1 到 50 个请求 因此我很想知道密集程度 CPU
  • 如何在Delphi 7中监听麦克风并检测声音响度

    我需要一个程序来捕获麦克风输入声音超过特定阈值时的事件 那么我可能需要不断地听麦克风 并以某种方式测量声音幅度 Delphi 7 中可以这样做吗 我建议您使用低音音频库 http www un4seen com bass html http
  • NvCplGetThermalSettings 返回 false

    问题 您好 我正在尝试使用 Delphi 获取 nividia gtx 980 的 GPU 温度 我看过C 问题 他的解决方案是不使用nvcpl dll 我认为这不是正确的解决方案 因为 nivida 有完整的文档说明如何处理 API 见下
  • Delphi 2009之前如何处理UTF-8和ANSI转换?

    在 Delphi 2009 中 我们有 RichEdit1 Lines LoadFromFile OpenDialog1 FileName TEncoding UTF8 RichEdit1 Lines SaveToFile OpenDial
  • Delphi XE2 中的 TDataModule.ClassGroup 伪属性到底有什么作用?

    我尝试将一个组件从一个数据模块复制并粘贴到 Delphi XE2 中的另一个数据模块中 该组件是一个 Fast Report 数据源链接组件 数据模块是全新的 刚刚在 XE2 中创建 其他人也遇到了同样的问题并报告了质量中心为106369
  • 在 Pascal 中将文本文件中的字符串读入数组

    使用这个程序 我试图读取一个文件并将其随机打印到控制台 我想知道是否必须使用数组 例如 我可以将字符串分配到一个数组中 然后从数组中随机打印 但是 我不确定如何解决这个问题 另一个问题是 我当前的程序没有从我的文件中读取第一行 我有一个文本
  • ClientDataset 索引更改时不计算 TAggregateField

    我正在使用连接到 DBGrid 的 TClientDataset 和几个聚合字段 用于计算其他几个浮点字段的总和 所有字段均已在设计时创建 一切都按预期工作 直到 ClientDataset 的 IndexName 使用自定义索引更改 以便
  • 桌面 Delphi 应用程序是否可以通过 Windows 8 认证(使用 Windows 应用程序认证套件)?

    显然 Delphi 任何版本 不支持安全异常处理程序 https forums embarcadero com thread jspa messageID 473469 Visual Studio 中的 SAFESEH 开关 在 Windo
  • Firemonkey - 更新视觉组件

    我们从版本 1 开始就使用 Firemonkey 但仍然发现更新当前在屏幕上可见的组件很困难 在 Firemonkey 中请求重画的 方式 有很多 也许太多了 应用样式 ApplyStyle 事件 主要是当它在屏幕上可见时 请求 repai
  • 如何仅在某些列中设置带有复选框的 TListView?

    我正在使用 Delphi 2010 并且我试图允许用户在 TListView 中的每行 2 个选项之间进行选择 使用 TListView 我可以将样式设置为 vsReport 并启用复选框 但这只会让我每行有 1 个复选框 我需要的是每行
  • 为什么Delphi打开时间越长编译速度就越慢,我该怎么办?

    我的公司十多年来一直在德尔福上运行一个大型项目 我们的代码库多年来一直在增长 目前代码数量约为 400 万行 编译速度正在成为一个问题 我们花了时间清除单元循环引用 编译缓慢的已知原因 并检查了设置的各个方面 已经到了我们无法通过我们所能控
  • 在 Delphi 7 中使用 TScreen

    我的 Delphi 7 应用程序显示 Screen DesktopWidth Screen DesktopHeight Screen Monitors 0 Width Screen Monitors 0 Height 并且 如果选择了第二台
  • 在主表单之前显示登录表单

    我在表单之间导航时遇到问题 我使用 Delphi XE5 创建了一个 Android Firemonkey 移动应用程序 我目前有一个登录表单和主表单 现在我想要有关如何处理登录表单以显示在主表单之前的建议 在 项目选项 中的表单下 选择要
  • 如何使用 Delphi Sydney 10.4.2 和 Edge Webbrowser 组件获取 HTML SOURCE

    I have TEdgeBrowser在德尔福 10 4 2 中 我想从 HTML 代码中提取基于 RegEx 的字符串 在过去 这是可能的TWebBrowser 仅适用于 IE 11 或更低版本 作为 selectedEngine 但我的
  • 条件表达式在包内是否被破坏?

    考虑以下片段 requires designide rtl vcl IF RTLVersion lt 19 0 E2026 Constant expression expected IF CompilerVersion 22 0 same
  • Indy FTP 传输类型

    我正在使用 IdFTP Indy 10 组件从远程位置下载一些文件 zip 和 txt 在获取每个文件之前 我将 TransferType 设置为二进制 IdFTP TransferType ftBinary IdFTP Get ASour
  • 在 Outlook 中创建带有附件的邮件并显示它

    我想在 Outlook 中创建一封带有附件的邮件并在发送之前显示它 但我想我已经尝试了几乎在网上找到的所有示例 但没有任何运气 我可以使用 Indy 但我非常想使用 Outlook 来确保邮件正确 因为它是用于商业用途 函数的任何输入 该函
  • 能否从 Vista Shell 获取 48x48 或 64x64 图标?

    如果 Vista Shell 中存在 48x48 或 64x64 图标 如何使用 SHGetFileInfo 获取在 TImage 中显示图标的句柄 我想从图像列表中选择一个代表文件夹路径的图标 并在 Timage 中显示 48x48 或
  • 使用 StretchDIBits 使用 Delphi 6 处理条形码图像 - 输出中缺少条形线

    我的应用程序是在 Delphi 6 中开发的 由于后台处理和大量数据 它消耗大约 60MB 120MB 物理内存 这是一个资源密集型应用程序 该应用程序的功能之一是在进行某些处理后创建条形码图像 如果用户继续生成条形码 那么至少十分之一的条

随机推荐

  • Websocket 在 localhost 上工作但不能在 Heroku 上工作

    我有一个使用 websockets STOMP over SockJs 的应用程序 后端使用 Spring 应用程序在 Tomcat 上的本地主机上运行良好 websockets 但是当我部署到 Heroku 或 AWS Web Socke
  • 如何查找Android蓝牙版本?

    我需要以编程方式在手机上查找 Android 蓝牙版本 有人可以提示我如何做到这一点吗 据我所知 我做了很多研究 无法查明您的 Android 蓝牙设备的硬件版本 4 0 4 2 5 0 有些人声称他们有一个可以做到这一点的应用程序 但我从
  • 如何查看预处理后包含文件的实际顺序?

    我有一个 cpp 文件 其中包含一些头文件 这些头文件也可能包含其他头文件 包含防护已就位 以防止包含同一文件两次 知道每个文件只包含一次 有没有办法确定包含所有标头的最终顺序 I tried gcc E获取预处理器输出 但生成的代码似乎无
  • Spring 带有 Query Dsl 自定义绑定和或操作不起作用

    我有以下要求查询 文章 category 厨房 category sports 此查询无需自定义绑定即可工作 它会给我所有厨房和体育文章作为响应 它正在以某种方式进行 或 运算 但我需要自定义绑定 因为我需要忽略大小写 现在我正在使用这个自
  • foreach循环php中的总和值[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 foreach group as key gt val
  • Python创建条形图比较2组数据

    我有一个带有 2 条形图的笔记本 一个是冬季数据 一个是夏季数据 我计算了所有犯罪的总数 并使用代码将它们绘制在条形图中 ax summer crime type value counts plot kind bar plt show 其中
  • pre-commit.com:.pre-commit-config.yaml 和requirements.txt 中的版本相同

    我想在中使用完全相同版本的 flake8requirements txt and in pre commit config yaml 为了避免冗余 我想在我的存储库中保留 flake8 的版本号一次 pre commit com可以从中读取
  • 为 Python 项目添加 .gitignore 文件的最佳实践? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我正在尝试收集一些默认设置 我意识到我没有标准的一件事是 gitignore 文件 有一个很棒的线程显示了适用于 Visual Studio 项目的良好 gitignore 但我没有看到很
  • 使用 git 在文件的特定行上查找令牌的第一个引入

    假设我有一个文件 A cpp 我注意到该文件的第 15 行有一个错误 假设错误是函数上的 const 该函数返回指向成员变量的指针 这意味着在函数上使用 const 在技术上是正确的 但在语义上是错误的 我想与进行更改的作者讨论语义 使用
  • ng-repeat 完成后调用函数

    我想要实现的基本上是一个 on ng 重复完成渲染 处理程序 我能够检测到它何时完成 但我不知道如何从中触发函数 检查小提琴 http jsfiddle net paulocoelho BsMqq 3 JS var module angul
  • 在代码隐藏中模拟用户

    我想在代码中模拟特定用户以在远程计算机上执行一些文件操作 我遇到的问题是我无法让模拟工作 我正在使用此处找到的 Microsoft 文章中的代码 如何在 ASP NET 应用程序中实现模拟 我想要有关如何 在哪里开始调试过程的指导 这是我的
  • OWIN Cookie 与 FormsAuthentication

    与 Forms Authentication 基于 cookie 的身份验证相比 使用基于 OWIN cookie 的身份验证来开发 MVC Web 应用程序有什么主要优势吗 我问的原因是我不会使用任何基于实体框架的挂钩进行 OWIN 身份
  • Windows 服务和桌面应用程序之间的通信

    我想在 Windows 7 上的 Windows 服务和桌面应用程序之间创建通信 我读到命名管道是两个进程之间通信的一种方式 我可以将它们用于我的目的吗 确保您可以使用命名管道 WCF 许多其他 IPC 方法 有关堆栈溢出问题中的命名管道示
  • 在 Three.js 着色器中使用灯光

    我正在尝试从 Three js 中的着色器访问场景的灯光 这个问题几乎是重复的Three js ShaderMaterial 灯光问题但对该问题的评论并不能帮助我解决问题 这是顶点着色器 if NUM DIR LIGHTS gt 0 str
  • ASPxComboBox - 如何设置所选项目?

    我在用着 ASPx组合框 问题是如何从后面的代码设置 selectedValue 如果我的html是这样的
  • LogisticRegression:未知标签类型:在 python 中使用 sklearn 的“连续”

    我有以下代码来测试 sklearn python 库的一些最流行的 ML 算法 import numpy as np from sklearn import metrics svm from sklearn linear model imp
  • pandas DataFrame to_html 中的粗体列

    我试图用一个粗体列返回 df to html 我只尝试过 df pd DataFrame important column 1 2 3 4 dummy column 5 6 7 8 def some function df apply la
  • 将项目添加到任务栏应用程序菜单

    我有一个申请 我想通过 C 将我的特定项目添加到右键单击应用程序的任务栏菜单中 我想添加永久项目和临时项目 如果我没有让你明白 这就是我正在谈论的菜单 此功能称为 JumpList 适用于 Windows 7 它是 Microsoft AP
  • Android Studio - 如何使用 ARM 而不是 HAXM 制作 AVD?

    我是 Android Studio 的新手 我的计算机不支持 HAXM 因此不允许我安装它来用于虚拟化 在该网站上的一些类似问题中 人们提到使用 ARM 而不是 HAXM 设置虚拟设备 我怎样才能做到这一点 在 AVD 管理器中 所有预制硬
  • TListView:如果添加列,VCL 会丢失列的顺序

    我正在尝试在 TListView 中的现有列之间添加一列 因此 我在末尾添加新列 并通过将其索引设置为指定值来移动它 这是有效的 直到添加另一个新列 我做了什么 在最后一个位置添加列 Columns Add 并在最后一个位置添加子项 Sub