如何设置ListView标题栏的弹出菜单以及项目弹出菜单?

时间:2012-06-29 09:15:41

标签: delphi listview popupmenu

我有一个带ViewStyle = vsReport的ListView和两个弹出菜单:

  1. 列弹出菜单,我想在用户右键单击标题栏时打开
  2. 项目弹出菜单,必须在用户右键单击任何列表项/子项或项目下方的空白时打开。
  3. 显示菜单的最正确方法是什么?我应该处理哪些事件?

    问题是当我设置ListView.PopupMenu属性时,右键单击ListView的客户端矩形中的任何点后出现弹出菜单。

    当我处理ListView.OnColumnRightClick事件时,如果仅在单击列标题后触发,则排除标题栏的可用空间(在列的右侧)。

    事件LisView.OnMouseUp只有在右键点击项目下方的空格后才会触发。

3 个答案:

答案 0 :(得分:8)

您不必使用列表视图的PopupMenu属性,不设置它,您可以将处理程序附加到OnContextPopup事件并根据位置启动您想要的任何弹出菜单。例如:

procedure TForm1.ListViewContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
var
  HeaderRect: TRect;
  Pos: TPoint;
begin
  GetWindowRect(ListView_GetHeader(ListView.Handle), HeaderRect);
  Pos := ListView.ClientToScreen(MousePos);
  if PtInRect(HeaderRect, Pos) then
    PopupMenuColumns.Popup(Pos.X, Pos.Y)
  else
    PopupMenuItems.Popup(Pos.X, Pos.Y);
end;

答案 1 :(得分:3)

您可以大大简化它。创建两个弹出菜单(标题行和列各一个。在IDE中分配TListView.PopupMenu列弹出菜单。

将此用于ListView的事件处理程序:

procedure TForm1.ListView1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
var
  HeaderRect: TRect;
  HeaderHeight: Integer;
  Header: HWnd;
begin
  ListView1.PopupMenu := ColumnMenu;   // Default to ColumnMenu
  Header := ListView_GetHeader(ListView1.Handle);
  GetWindowRect(Header, HeaderRect);
  HeaderHeight := HeaderRect.Bottom - HeaderRect.Top;
  if MousePos.Y < HeaderHeight then
    ListView1.PopupMenu := HeaderMenu;
end;

与@ Sertac的方法略有不同,在不调用ClientToScreenPtInRect时 - 因为我们知道该点在ListView的范围内,所以对点击高度的简单测试就足够了知道我们是否在标题或列区域。它还确保始终至少有一个弹出菜单分配给ListView

答案 2 :(得分:0)

这就是我解决它的方法,但我不喜欢这个解决方案。如果你有一个更好的,请写下来,我会接受它是正确的。

uses
  CommCtrl;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListView.PopupMenu := TPopupMenu.Create(Self);
  ListView.PopupMenu.OnPopup := ListViewPopup;
end;

procedure TForm1.ListViewPopup(Sender: TObject);
var
  Pos: TPoint;
  SrcMenu: TPopupMenu;
  I: Integer;
  MenuItem: TMenuItem;
  Header: HWND;
  HeaderRect: TRect;
  HeaderHeight: Integer;
begin
  // Re-filling ListView's popup menu
  ListView.PopupMenu.Items.Clear();

  // Getting header height
  Header := ListView_GetHeader(ListView.Handle);
  GetWindowRect(Header, HeaderRect);
  HeaderHeight := HeaderRect.Bottom - HeaderRect.Top;
  Pos := ListView.ScreenToClient(ListView.PopupMenu.PopupPoint);

  // Clicked on header?
  if Pos.Y < HeaderHeight then
    SrcMenu := PopupMenuColumns
  else
    SrcMenu := PopupMenuItems;

  // Copying destired menu to ListView.PopupMenu
  for I := 0 to SrcMenu.Items.Count - 1 do
  begin
    MenuItem := TMenuItem.Create(FListViewPopupMenu);

    with SrcMenu.Items[I] do
    begin
      MenuItem.Action := Action;
      MenuItem.Caption := Caption;
      MenuItem.ShortCut := ShortCut;
      MenuItem.Checked := Checked;
      MenuItem.Enabled := Enabled;
      MenuItem.OnClick := OnClick;
      MenuItem.HelpContext := HelpContext;
      MenuItem.Name := Name;
      MenuItem.ImageIndex := ImageIndex;
    end;

    ListView.PopupMenu.Items.Add(MenuItem);
  end;

  ListView.PopupMenu.Images := SrcMenu.Images;
end;