Delphi 右键单击';t更新TControlList中的ItemIndex

Delphi 右键单击';t更新TControlList中的ItemIndex,delphi,delphi-10.4-sydney,Delphi,Delphi 10.4 Sydney,我已将TPopupMenu添加到t控制列表,右键单击时,项目索引不会更新以反映单击的项目。有没有一种方法可以使右键单击做出与左键单击类似的响应 如果用户右键单击某个特定项目,PopupMenu将与该项目关联,而不是与当前关注的项目关联,这将非常好。您可以使用OnPopupMenu事件中的HotItemIndex属性,并将其保存到变量中。然后,对于弹出菜单项事件,您可以使用它 示例代码: unit Unit1; interface uses Winapi.Windows, Winapi.M

我已将
TPopupMenu
添加到
t控制列表
,右键单击时,项目索引不会更新以反映单击的项目。有没有一种方法可以使右键单击做出与左键单击类似的响应


如果用户右键单击某个特定项目,PopupMenu将与该项目关联,而不是与当前关注的项目关联,这将非常好。

您可以使用OnPopupMenu事件中的HotItemIndex属性,并将其保存到变量中。然后,对于弹出菜单项事件,您可以使用它

示例代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.ControlList, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    ControlList1: TControlList;
    PopupMenu1: TPopupMenu;
    TestPopupMnu: TMenuItem;
    Label1: TLabel;
    Memo1: TMemo;
    procedure ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas; ARect:
        TRect; AState: TOwnerDrawState);
    procedure ControlList1Click(Sender: TObject);
    procedure TestPopupMnuClick(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
  private
    FPopupItemIndex : Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas;
    ARect: TRect; AState: TOwnerDrawState);
begin
    Label1.Caption := AIndex.ToString;
end;

procedure TForm1.ControlList1Click(Sender: TObject);
begin
    Memo1.Lines.Add('Clicked item ' + ControlList1.ItemIndex.ToString);
end;

procedure TForm1.TestPopupMnuClick(Sender: TObject);
begin
    Memo1.Lines.Add('Test PopupMenu item ' + FPopupItemIndex.ToString);
end;

procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
    FPopupItemIndex := ControlList1.HotItemIndex;
end;

end.
表格本身:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object ControlList1: TControlList
    Left = 24
    Top = 20
    Width = 317
    Height = 200
    ItemCount = 5
    ItemMargins.Left = 0
    ItemMargins.Top = 0
    ItemMargins.Right = 0
    ItemMargins.Bottom = 0
    ParentColor = False
    PopupMenu = PopupMenu1
    TabOrder = 0
    OnBeforeDrawItem = ControlList1BeforeDrawItem
    OnClick = ControlList1Click
    object Label1: TLabel
      Left = 92
      Top = 20
      Width = 31
      Height = 13
      Caption = 'Label1'
    end
  end
  object Memo1: TMemo
    Left = 368
    Top = 24
    Width = 241
    Height = 201
    Lines.Strings = (
      'Memo1')
    TabOrder = 1
  end
  object PopupMenu1: TPopupMenu
    OnPopup = PopupMenu1Popup
    Left = 436
    Top = 128
    object TestPopupMnu: TMenuItem
      Caption = 'Test'
      OnClick = TestPopupMnuClick
    end
  end
end

您可以使用OnPopupMenu事件中的HotItemIndex属性并将其保存到变量中。然后,对于弹出菜单项事件,您可以使用它

示例代码:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.ControlList, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    ControlList1: TControlList;
    PopupMenu1: TPopupMenu;
    TestPopupMnu: TMenuItem;
    Label1: TLabel;
    Memo1: TMemo;
    procedure ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas; ARect:
        TRect; AState: TOwnerDrawState);
    procedure ControlList1Click(Sender: TObject);
    procedure TestPopupMnuClick(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
  private
    FPopupItemIndex : Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ControlList1BeforeDrawItem(AIndex: Integer; ACanvas: TCanvas;
    ARect: TRect; AState: TOwnerDrawState);
begin
    Label1.Caption := AIndex.ToString;
end;

procedure TForm1.ControlList1Click(Sender: TObject);
begin
    Memo1.Lines.Add('Clicked item ' + ControlList1.ItemIndex.ToString);
end;

procedure TForm1.TestPopupMnuClick(Sender: TObject);
begin
    Memo1.Lines.Add('Test PopupMenu item ' + FPopupItemIndex.ToString);
end;

procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
    FPopupItemIndex := ControlList1.HotItemIndex;
end;

end.
表格本身:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 299
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object ControlList1: TControlList
    Left = 24
    Top = 20
    Width = 317
    Height = 200
    ItemCount = 5
    ItemMargins.Left = 0
    ItemMargins.Top = 0
    ItemMargins.Right = 0
    ItemMargins.Bottom = 0
    ParentColor = False
    PopupMenu = PopupMenu1
    TabOrder = 0
    OnBeforeDrawItem = ControlList1BeforeDrawItem
    OnClick = ControlList1Click
    object Label1: TLabel
      Left = 92
      Top = 20
      Width = 31
      Height = 13
      Caption = 'Label1'
    end
  end
  object Memo1: TMemo
    Left = 368
    Top = 24
    Width = 241
    Height = 201
    Lines.Strings = (
      'Memo1')
    TabOrder = 1
  end
  object PopupMenu1: TPopupMenu
    OnPopup = PopupMenu1Popup
    Left = 436
    Top = 128
    object TestPopupMnu: TMenuItem
      Caption = 'Test'
      OnClick = TestPopupMnuClick
    end
  end
end

要处理右键单击,您必须使用
OnMouseDown
OnMouseUp
事件,而不是
OnClick
事件

与只检测鼠标左键点击的
OnClick
事件不同,
OnMouseDown
onmousedup
事件能够检测所有鼠标点击(左键、右键、中键)


要处理右键单击,您必须使用
OnMouseDown
OnMouseUp
事件,而不是
OnClick
事件

与只检测鼠标左键点击的
OnClick
事件不同,
OnMouseDown
onmousedup
事件能够检测所有鼠标点击(左键、右键、中键)


HotItemIndex
属性可用于通过使用以下命令检测右键单击了哪个项目

procedure TListingList.clListingsMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  inherited;
  if Button <> mbRight then
    Exit;

  if clListings.HotItemIndex <> -1 then
    clListings.ItemIndex := clListings.HotItemIndex;
end;
procedure TListingList.clListingsMouseDown(发送方:TObject;按钮:TMouseButton;Shift:TShiftState;X,Y:整数);
开始
继承;
如果按钮亮了那么
出口
如果clListings.HotItemIndex为-1,则
clListings.ItemIndex:=clListings.HotItemIndex;
终止

这基本上是可行的,但是如果您已经有了一个可见的
tpopumenu
,那么
HotItemIndex
就是
-1
。这意味着连续的右键点击不会弹出正确的项目-但我可以接受这一点。我认为需要使用
MousePosToItemIndex
ItemIndexUnderMouse
方法来正确修复此问题。

可以使用
HotItemIndex
属性通过使用以下命令来检测右键单击了哪个项目

procedure TListingList.clListingsMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  inherited;
  if Button <> mbRight then
    Exit;

  if clListings.HotItemIndex <> -1 then
    clListings.ItemIndex := clListings.HotItemIndex;
end;
procedure TListingList.clListingsMouseDown(发送方:TObject;按钮:TMouseButton;Shift:TShiftState;X,Y:整数);
开始
继承;
如果按钮亮了那么
出口
如果clListings.HotItemIndex为-1,则
clListings.ItemIndex:=clListings.HotItemIndex;
终止

这基本上是可行的,但是如果您已经有了一个可见的
tpopumenu
,那么
HotItemIndex
就是
-1
。这意味着连续的右键点击不会弹出正确的项目-但我可以接受这一点。我认为需要使用
MousePosToItemIndex
ItemIndexUnderMouse
方法来正确修复此问题。

您可能需要引入类似的新属性。要实现这一点,只需处理
WM_CONTEXTMENU
中的选择更改。您可能需要引入类似的新属性。要实现这一点,只需处理
WM_CONTEXTMENU
中的选择更改即可。我认为使用HotItemIndex属性就是我想要的after@Alister那么请将我的答案标记为已接受。我认为使用HotItemIndex属性就是我想要的after@Alister那么请把我的回答标记为已接受。