显示默认的右键单击菜单-Delphi

显示默认的右键单击菜单-Delphi,delphi,properties,menu,right-click,Delphi,Properties,Menu,Right Click,我有一个包含文件列表的列表框。我可以访问列表框中的Windows右键单击菜单来访问打开、属性、删除和重命名项吗?我建议您在Delphi应用程序中查看类似shell的控件。它提供树视图、列表视图等,这些视图可以像浏览器窗口一样连接在一起。它将显示文件的相应图标。我相信它也提供了你所说的设施 如果您使用的是现代Unicode Delphi,那么可能需要进行一些移植工作,但当我完成了这项工作后,事实证明它相对简单 毫无疑问,还有其他库提供shell控件,这正是我熟悉的一个 否则,如果您想坚持使用当前的

我有一个包含文件列表的列表框。我可以访问列表框中的Windows右键单击菜单来访问打开、属性、删除和重命名项吗?

我建议您在Delphi应用程序中查看类似shell的控件。它提供树视图、列表视图等,这些视图可以像浏览器窗口一样连接在一起。它将显示文件的相应图标。我相信它也提供了你所说的设施

如果您使用的是现代Unicode Delphi,那么可能需要进行一些移植工作,但当我完成了这项工作后,事实证明它相对简单

毫无疑问,还有其他库提供shell控件,这正是我熟悉的一个

否则,如果您想坚持使用当前的解决方案,则最容易实现自己的菜单操作。Open和Properties只是使用适当的动词对ShellExecute的简单调用。Delete是对DeleteFile的调用,Rename是对MoveFile的调用。

检查界面。但请注意,Windows shell不会通过文件名来标识其对象,实际上它们不可能是文件。它使用id的串联,在调用某个文件上的某些shell函数之前,您可能需要获得该文件所要协助的项目id列表。

Kermia从绝地JCL库检查该单元,该单元内部存在一个名为
DisplayContextMenu
的函数,该函数显示与文件关联的上下文菜单。此函数封装了对IContextMenu界面的调用,使您的工作更加轻松

function DisplayContextMenu(const Handle: HWND; const FileName: string;
  Pos: TPoint): Boolean;

下面是一个实现示例,使用列表框的“OnContextPopup”事件(该事件填充了项目目录中的文件名)在右键单击文件名时启动文件的快捷菜单:

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure ListBox1ContextPopup(Sender: TObject; MousePos: TPoint;
      var Handled: Boolean);
  private
  protected
    procedure WndProc(var Msg: TMessage); override;
  public
  end;

var
  Form1: TForm1;

implementation

uses
  shlobj, comobj;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  SearchRec: TSearchRec;
begin
  ListBox1.Clear;

  // populate list box with files in the project folder
  if FindFirst(ExtractFilePath(Application.ExeName) + '*.*',
               0, SearchRec) = 0 then
    repeat
      ListBox1.Items.Add(SearchRec.Name);
    until FindNext(SearchRec) <> 0;
  FindClose(SearchRec);
end;

var
  // Required to handle messages for owner drawn items, as in 'SendTo' menu.
  // Also used as a flag in WndProc to know if we're tracking a shortcut menu.
  ContextMenu2: IContextMenu2 = nil;

procedure TForm1.ListBox1ContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
var
  Item: Integer;
  DeskFolder, Folder: IShellFolder;
  Eaten, Attributes: ULONG;
  pIdl, FolderpIdl: PItemIDList;
  ContextMenu: IContextMenu;
  Menu: HMENU;
  Pos: TPoint;
  Cmd: DWORD;
  CommandInfo: TCMInvokeCommandInfo;
begin
  Item := (Sender as TListBox).ItemAtPos(MousePos, True);
  Handled := Item <> -1;
  if not Handled then
    Exit;
  TListBox(Sender).ItemIndex := Item;

  // IShellFolder for Desktop folder (root)
  OleCheck(SHGetDesktopFolder(DeskFolder));

  // Item ID List for the folder that the file is in
  Attributes := 0;
  OleCheck(DeskFolder.ParseDisplayName(Handle, nil,
                    PWideChar(WideString(ExtractFilePath(Application.ExeName))),
                    Eaten, FolderpIdl, Attributes));

  // IShellFolder for the folder the file is in
  OleCheck(DeskFolder.BindToObject(FolderpIdl, nil, IID_IShellFolder, Folder));
  CoTaskMemFree(FolderpIdl);

  // Item ID List for the file, relative to the folder it is in
  Attributes := 0;
  OleCheck(Folder.ParseDisplayName(Handle, nil,
           PWideChar(WideString(ExtractFileName(TListBox(Sender).Items[Item]))),
           Eaten, pIdl, Attributes));

  // IContextMenu for the relative Item ID List
  OleCheck(Folder.GetUIObjectOf(Handle, 1, pIdl, IID_IContextMenu,
                                  nil, ContextMenu));
  CoTaskMemFree(pIdl);

  Menu := CreatePopupMenu;
  try
    // Populate our menu with shortcut items
    OleCheck(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE));

    // ContextMenu2 used in WndProc
    ContextMenu.QueryInterface(IID_IContextMenu2, ContextMenu2);
    try
      Pos := TWinControl(Sender).ClientToScreen(MousePos);
      // launch the menu
      Bool(Cmd) := TrackPopupMenu(Menu,
                            TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_RETURNCMD,
                            Pos.X, Pos.Y, 0, Handle, nil);
    finally
      // clear so that we don't intervene every owner drawn menu item message in
      // WndProc
      ContextMenu2 := nil;
    end;

    // Invoke command if we have one
    if Bool(Cmd) then begin
      FillChar(CommandInfo, SizeOf(CommandInfo), 0);
      CommandInfo.cbSize := SizeOf(CommandInfo);
      CommandInfo.hwnd := Handle;
      CommandInfo.lpVerb := MakeIntResource(Cmd - 1);
      CommandInfo.nShow := SW_SHOWNORMAL;

      OleCheck(ContextMenu.InvokeCommand(CommandInfo));
    end;

  finally
    DestroyMenu(Menu);
  end;
end;

procedure TForm1.WndProc(var Msg: TMessage);
begin
  if ((Msg.Msg = WM_INITMENUPOPUP) or (Msg.Msg = WM_DRAWITEM)
              or (Msg.Msg = WM_MEASUREITEM)) and Assigned(ContextMenu2) then
    ContextMenu2.HandleMenuMsg(Msg.Msg, Msg.WParam, Msg.LParam)
  else
    inherited;
end;
类型
TForm1=类(TForm)
ListBox1:TListBox;
过程表单创建(发送方:ToObject);
过程ListBox1ContextPopup(发送者:ToObject;鼠标点:TPoint;
变量:布尔值);
私有的
受保护的
程序WndProc(var Msg:TMessage);推翻
公众的
结束;
变量
表1:TForm1;
实施
使用
科摩比省什洛布吉;
{$R*.dfm}
过程TForm1.FormCreate(发送方:TObject);
变量
SearchRec:TSearchRec;
开始
列表框1。清除;
//用项目文件夹中的文件填充列表框
如果FindFirst(ExtractFilePath(Application.ExeName)+'*.*',
0,SearchRec)=0,然后
重复
ListBox1.Items.Add(SearchRec.Name);
直到FindNext(SearchRec)0;
FindClose(SearchRec);
结束;
变量
//需要处理所有者绘制项目的消息,如“发送到”菜单中所示。
//也用作WndProc中的标志,以了解我们是否正在跟踪快捷菜单。
ContextMenu2:IContextMenu2=nil;
过程TForm1.ListBox1ContextPopup(发送方:ToObject;鼠标点:TPoint;
变量:布尔值);
变量
项目:整数;
桌面文件夹,文件夹:IShellFolder;
食用,属性:乌龙;
pIdl,FolderpIdl:PItemIDList;
ContextMenu:IContextMenu;
菜单:华浓;
位置:TPoint;
Cmd:DWORD;
CommandInfo:TCMInvokeCommandInfo;
开始
Item:=(发送者作为TListBox)。ItemAtPos(鼠标点,True);
已处理:=项目-1;
如果不处理的话
出口
TListBox(发送者)。ItemIndex:=项;
//IShellFolder用于桌面文件夹(根目录)
OleCheck(SHGetDesktopFolder(DeskFolder));
//文件所在文件夹的项目ID列表
属性:=0;
OleCheck(DeskFolder.ParseDisplayName)(句柄,无,
PWideChar(宽字符串(ExtractFilePath(Application.ExeName)),
吃过、吃过、吃过);
//文件所在文件夹的IShellFolder
olcheck(DeskFolder.BindToObject(FolderpIdl,nil,IID_-IShellFolder,Folder));
CoTaskMemFree(FolderpIdl);
//相对于文件所在文件夹的文件项ID列表
属性:=0;
olcheck(Folder.ParseDisplayName)(句柄,nil,
PWideChar(宽字符串(提取文件名(TListBox(Sender).Items[项目])),
吃的,皮德尔,属性);
//相对项目ID列表的IContextMenu
OleCheck(Folder.GetUIObjectOf)(句柄,1,pIdl,IID_IContextMenu,
无,上下文菜单);
CoTaskMemFree(pIdl);
菜单:=CreatePopupMenu;
尝试
//用快捷方式项填充菜单
olcheck(ContextMenu.QueryContextMenu(Menu,0,1,$7FFF,CMF_EXPLORE));
//WndProc中使用的ContextMenu2
QueryInterface(IID_IContextMenu2,ContextMenu2);
尝试
Pos:=TWinControl(发送方)。客户端到屏幕(鼠标点);
//启动菜单
Bool(Cmd):=TrackPopupMenu(菜单,
TPM_LEFTBUTTON或TPM_RIGHTBUTTON或TPM_RETURNCMD,
位置X,位置Y,0,手柄,无);
最后
//清除,这样我们就不会干预每个所有者绘制的菜单项消息
//WndProc
ContextMenu2:=nil;
结束;
//调用命令,如果我们有一个
如果Bool(Cmd),则开始
FillChar(CommandInfo,SizeOf(CommandInfo),0);
CommandInfo.cbSize:=SizeOf(CommandInfo);
CommandInfo.hwnd:=句柄;
CommandInfo.lpVerb:=MakeIntResource(Cmd-1);
CommandInfo.nShow:=SW_SHOWNORMAL;
ocheck(ContextMenu.InvokeCommand(CommandInfo));
结束;
最后
菜单(菜单);
结束;
结束;
程序TForm1.WndProc(var Msg:TMessage);
开始
如果((Msg.Msg=WM_INITMENUPOPUP)或(Msg.Msg=WM_DRAWITEM)
或(Msg.Msg=WM_MEASUREITEM))并赋值(ContextMenu2),然后
ContextMenu2.HandleMenuMsg(Msg.Msg,Msg.WParam,Msg.LParam)
其他的
继承;
结束;

这看起来像是允许您在上下文菜单中枚举shell所认为的内容。正如我所读到的,您仍然需要自己填充菜单,然后通过此接口调用命令以响应Delphi OnClick事件。这是正确的吗?+1看起来确实是实现OnClick处理程序的好方法。是的,您必须创建菜单(至少它允许您使用任何您喜欢的菜单),无论如何它会给您命令e