【问题标题】:Right-click doesn't update ItemIndex in TControlList右键单击不会更新 TControlList 中的 ItemIndex
【发布时间】:2021-06-26 00:54:55
【问题描述】:

我在TControlList 中添加了TPopupMenu,在右键单击时,ItemIndex 不会更新以反映所单击的项目。有没有办法让右键单击以类似于左键单击的方式响应?

如果用户右键单击特定项目,PopupMenu 与该项目相关联,而不是当前聚焦的项目,这将是很好的。

【问题讨论】:

  • 您可能需要引入类似于TTreeView.RightClickSelect 的新属性。要实现这一点,只需处理 WM_CONTEXTMENU 中的选择更改。

标签: delphi delphi-10.4-sydney


【解决方案1】:

您可以使用 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

【讨论】:

  • 我认为使用 HotItemIndex 属性是我所追求的
  • @Alister 那么请将我的回答标记为已接受。
【解决方案2】:

为了处理右键单击,您必须使用OnMouseDownOnMouseUp 事件而不是OnClick 事件。

与仅检测左键单击的OnClick 事件不同,OnMouseDownOnMouseUp 事件能够检测所有鼠标单击(左、右、中)。

procedure TForm1.ControlList1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbRight then
  begin
    //Do what needs to be done on right click
  end
  else if Button = mbMiddle then
  begin
    //Do what needs to be done on middle click
  end
end;

【讨论】:

    【解决方案3】:

    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;
    

    这主要是可行的,但如果您已经有一个可见的TPopupmenu,那么HotItemIndex 就是-1。这意味着连续的右键单击不会弹出正确的项目 - 但我可以忍受这一点。我认为需要MousePosToItemIndexItemIndexUnderMouse 方法才能正确解决此问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-04
      • 1970-01-01
      相关资源
      最近更新 更多