Delphi 如何设置ListView标题栏的弹出菜单以及项目弹出菜单?
我有一个带有Delphi 如何设置ListView标题栏的弹出菜单以及项目弹出菜单?,delphi,listview,popupmenu,Delphi,Listview,Popupmenu,我有一个带有ViewStyle=vsReport的列表视图和两个弹出菜单: 列弹出菜单,我想在用户右键单击标题栏时打开该菜单 项目弹出菜单必须在用户右键单击任何列表项目/子项目或项目下方的空白时打开 显示该菜单的最正确方式是什么?我应该处理哪些事件 问题是当我设置ListView.PopupMenu属性时,右键单击ListView客户端矩形中的任意点后会出现弹出菜单 当我处理ListView.OnColumnRightClick事件时,如果仅在单击列标题后激发,则不包括标题栏(列右侧)的可用空间
ViewStyle=vsReport
的列表视图和两个弹出菜单:
ListView.PopupMenu
属性时,右键单击ListView客户端矩形中的任意点后会出现弹出菜单
当我处理ListView.OnColumnRightClick事件时,如果仅在单击列标题后激发,则不包括标题栏(列右侧)的可用空间
事件
LisView.OnMouseUp
仅在右键单击项目下方的空格后激发。我就是这样解决的,但我不喜欢这个解决方案。如果你有更好的,请写下来,我会认为它是正确的
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;
使用
CommCtrl;
过程TForm1.FormCreate(发送方:TObject);
开始
ListView.PopupMenu:=TPopupMenu.Create(Self);
ListView.PopupMenu.OnPopup:=ListViewPopup;
结束;
程序TForm1.ListViewPopup(发送方:ToObject);
变量
位置:TPoint;
SrcMenu:TPopupMenu;
I:整数;
菜单项:TMenuItem;
标题:HWND;
头颅ct:TRect;
HeaderHeight:整数;
开始
//重新填充ListView的弹出菜单
ListView.PopupMenu.Items.Clear();
//获取收割台高度
Header:=ListView\u GetHeader(ListView.Handle);
GetWindowRect(标题、标题等);
HeaderHeight:=HeaderRect.Bottom-HeaderRect.Top;
Pos:=ListView.ScreenToClient(ListView.PopupMenu.PopupPoint);
//点击标题?
如果位置Y<车头高度,则
SrcMenu:=PopupMenuColumns
其他的
srcmenue:=popupmenuiems;
//正在将目标菜单复制到ListView.PopupMenu
对于I:=0到srcmunu.Items.Count-1 do
开始
MenuItem:=TMenuItem.Create(FListViewPopupMenu);
使用SrcMenu.Items[I]do
开始
MenuItem.Action:=操作;
MenuItem.Caption:=标题;
MenuItem.ShortCut:=快捷方式;
MenuItem.Checked:=已检查;
MenuItem.Enabled:=已启用;
MenuItem.OnClick:=OnClick;
MenuItem.HelpContext:=HelpContext;
MenuItem.Name:=名称;
MenuItem.ImageIndex:=ImageIndex;
结束;
ListView.PopupMenu.Items.Add(菜单项);
结束;
ListView.PopupMenu.Images:=SrcMenu.Images;
结束;
您不必使用listview的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;
你可以大大简化它。创建两个弹出菜单(标题行和列各一个。在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;
procedure TForm1.ListView1ContextPopup(发送方:TObject;鼠标点:TPoint;变量处理:Boolean);
变量
头颅ct:TRect;
HeaderHeight:整数;
标题:HWnd;
开始
ListView1.PopupMenu:=ColumnMenu;//默认为ColumnMenu
Header:=ListView\u GetHeader(ListView1.Handle);
GetWindowRect(标题、标题等);
HeaderHeight:=HeaderRect.Bottom-HeaderRect.Top;
如果MousePos.Y
它与@Sertac的方法稍有不同,不调用
ClientToScreen
和PtInRect
——因为我们知道点在ListView的范围内,所以简单的点击高度测试就足以知道我们是否在标题或列区域。它还确保始终至少有一个弹出窗口始终分配给列表视图的菜单。您不喜欢这个解决方案的哪些方面?@NGLN当您需要复制菜单项时,感觉有点奇怪。我认为可以滑到WinAPI级别并在那里执行一些操作。您是否希望仅当您在某个项目上,甚至在您正在运行时,才弹出弹出菜单项er子项?@TLama是的,有多个子项比我强。:-)当“新答案发布”横幅出现时,我正在从IDE复制我的测试代码粘贴到我的答案中,说了同样的话+1.@Ken-我觉得在几个小时前的问题上出现这种情况很奇怪,对不起。。谢谢。)@塞塔克,这很奇怪。我把这归咎于我今天的网络连接滞后。:-)+一对二@安德鲁,我给你留下了关于OnContextPopup
的评论,但几分钟后就删除了。但是无论如何,Handled
参数呢?您不应该将其设置为True吗?@TLama-仅当控件的“PopupMenu”指定了一个弹出窗口,并且您不想启动它时才可以。