我有一个带ViewStyle = vsReport
的ListView和两个弹出菜单:
显示菜单的最正确方法是什么?我应该处理哪些事件?
问题是当我设置ListView.PopupMenu
属性时,右键单击ListView的客户端矩形中的任何点后出现弹出菜单。
当我处理ListView.OnColumnRightClick
事件时,如果仅在单击列标题后触发,则排除标题栏的可用空间(在列的右侧)。
事件LisView.OnMouseUp
只有在右键点击项目下方的空格后才会触发。
答案 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的方法略有不同,在不调用ClientToScreen
和PtInRect
时 - 因为我们知道该点在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;