禁用 TListView 控件中的取消选择

发布于 2024-12-23 04:08:39 字数 747 浏览 2 评论 0原文

我想使用 TListView (vsIcon) 作为一种选项卡 - 这样只能像选项卡一样选择一个项目。仅选择一项没有问题(禁用 Multiselect 属性)。问题是单击列表视图中图标和文本之间的空白点时取消选择项目。

这是我到目前为止所尝试的:

void __fastcall TForm::ListViewChanging(TObject *Sender, TListItem *Item, TItemChange Change, bool &AllowChange)
{
if (Change == ctState)
    {
    TPoint CursorRel = ListView->ScreenToClient(Mouse->CursorPos);
    AllowChange = (ListView->GetItemAt(CursorRel.x, CursorRel.y) != NULL);
    StatusBar->SimpleText = (AllowChange)? "YES" : "NO";
    }
}

上面的方法有效,但有一个问题。当鼠标单击空白区域时,它会取消选择该项目,并且键盘上/下箭头不再起作用,尽管该项目看起来仍然被选中。如果我忽略键盘,则对于鼠标选择,它可以正常工作,并且会忽略对空白区域的点击,并在状态栏中显示消息“否”。

任何想法如何解决这个问题,以便它适用于所有可能的选择方法(键盘、鼠标(任何其他?))。

I would like to use TListView (vsIcon) as a kind of tabs - so that only one item can be selected just like tabs. Selecting only one item is no problem (disabling Multiselect property). Problem is deselecting items when clicking on blank spots between icons and text in the listview.

Here is what I tried so far:

void __fastcall TForm::ListViewChanging(TObject *Sender, TListItem *Item, TItemChange Change, bool &AllowChange)
{
if (Change == ctState)
    {
    TPoint CursorRel = ListView->ScreenToClient(Mouse->CursorPos);
    AllowChange = (ListView->GetItemAt(CursorRel.x, CursorRel.y) != NULL);
    StatusBar->SimpleText = (AllowChange)? "YES" : "NO";
    }
}

The above works but there is a problem. When mouse is clicked on blank area it deselects the item and keyboard up/down arrow no longer work although the item still looks selected. If I ignore keyboard, for mouse selection it works fine and it ignores clicks on blank areas with the message "NO" in the statusbar.

Any ideas how to fix this so it works with all possible selection methods (keyboard, mouse (any other?)).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

櫻之舞 2024-12-30 04:08:39

如果点击不在某个项目上,则拦截发送到控件的 WM_LBUTTONDOWN 并停止默认处理。子类化控件,或使用 ApplicationEvents 组件等。带有插入器类的 Delphi 代码示例:

type
  TListView = class(comctrls.TListView)
  protected
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  end;

  TForm1 = class(TForm)
    ListView1: TListView;
  private
    ..

procedure TListView.WMLButtonDown(var Message: TWMLButtonDown);
begin
  if GetItemAt(Message.XPos, Message.YPos) <> nil then
    inherited;
end;

Intercept WM_LBUTTONDOWN posted to the control and halt default processing if the click is not on an item. Subclass the control, or use an ApplicationEvents component, etc.. Delphi code sample with an interposer class:

type
  TListView = class(comctrls.TListView)
  protected
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  end;

  TForm1 = class(TForm)
    ListView1: TListView;
  private
    ..

procedure TListView.WMLButtonDown(var Message: TWMLButtonDown);
begin
  if GetItemAt(Message.XPos, Message.YPos) <> nil then
    inherited;
end;
请帮我爱他 2024-12-30 04:08:39

这是您问题的另一个可能的答案:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListView1: TListView;
    ImageList1: TImageList;
    StatusBar1: TStatusBar;
    procedure ListView1Changing(Sender: TObject; Item: TListItem;
      Change: TItemChange; var AllowChange: Boolean);
    procedure ListView1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ListView1Enter(Sender: TObject);
  private
    FListItem: TListItem;
    procedure SelectedListItemStateSave;
    procedure SelectedListItemStateRestore;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SelectedListItemStateRestore;
begin
  ListView1.Selected := FListItem;
  ListView1.Selected.Focused := True; // Always focused
end;

procedure TForm1.SelectedListItemStateSave;
begin
  FListItem := ListView1.Selected;
end;

procedure TForm1.ListView1Changing(Sender: TObject; Item: TListItem;
  Change: TItemChange; var AllowChange: Boolean);
begin
  if (Change=ctState) then
    SelectedListItemStateSave;
end;

procedure TForm1.ListView1Enter(Sender: TObject);
begin
  if ListView1.Selected = nil then
  begin
    FListItem :=ListView1.Items[0]; // Initialization
    SelectedListItemStateRestore;
  end;
end;

procedure TForm1.ListView1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ListView1.GetItemAt(X,Y) = nil then
  begin
    SelectedListItemStateRestore;
  end;
end;

end.

Here is another possible answer to your question :

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListView1: TListView;
    ImageList1: TImageList;
    StatusBar1: TStatusBar;
    procedure ListView1Changing(Sender: TObject; Item: TListItem;
      Change: TItemChange; var AllowChange: Boolean);
    procedure ListView1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ListView1Enter(Sender: TObject);
  private
    FListItem: TListItem;
    procedure SelectedListItemStateSave;
    procedure SelectedListItemStateRestore;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SelectedListItemStateRestore;
begin
  ListView1.Selected := FListItem;
  ListView1.Selected.Focused := True; // Always focused
end;

procedure TForm1.SelectedListItemStateSave;
begin
  FListItem := ListView1.Selected;
end;

procedure TForm1.ListView1Changing(Sender: TObject; Item: TListItem;
  Change: TItemChange; var AllowChange: Boolean);
begin
  if (Change=ctState) then
    SelectedListItemStateSave;
end;

procedure TForm1.ListView1Enter(Sender: TObject);
begin
  if ListView1.Selected = nil then
  begin
    FListItem :=ListView1.Items[0]; // Initialization
    SelectedListItemStateRestore;
  end;
end;

procedure TForm1.ListView1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ListView1.GetItemAt(X,Y) = nil then
  begin
    SelectedListItemStateRestore;
  end;
end;

end.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文