如何使用Delphi弹出给定文件的Windows上下文菜单? [英] How to pop-up the Windows context menu for a given file using Delphi?

查看:255
本文介绍了如何使用Delphi弹出给定文件的Windows上下文菜单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写下面的过程/函数:

  procedure ShowSysPopup(aFile:string; x,y:integer) ; 

哪个将构建和显示(在坐标x和y)右键单击shell菜单哪一个在Windows资源管理器中查看给定的文件。我不太喜欢显示部分,但更多的是如何构建这样的菜单。

解决方案

ve为你做了一个快速的解决方案。
将这些单位添加到使用部分:

  ... ShlObj,ActiveX,ComObj 

这里是您的程序,我只需添加新参数HND即可携带您将要使用的TWinControl的句柄显示上下文菜单。

  procedure ShowSysPopup(aFile:string; x,y:integer; HND:HWND); 
var
根:IShellFolder;
ShellParentFolder:IShellFolder;
chEaten,dwAttributes:ULONG;
FilePIDL,ParentFolderPIDL:PItemIDList;
CM:IContextMenu;
菜单:HMenu;
命令:LongBool;
ICM2:IContextMenu2;

ICI:TCMInvokeCommandInfo;
ICmd:integer;
P:TPoint;
开始
OleCheck(SHGetDesktopFolder(Root)); //获取桌面IShellFolder接口

OleCheck(Root.ParseDisplayName(HND,nil,
PWideChar(WideString ExtractFilePath(aFile))),
chEaten,ParentFolderPIDL,dwAttributes)); //获取父文件夹的PItemIDList

OleCheck(Root.BindToObject(ParentFolderPIDL,nil,IShellFolder,
ShellParentFolder)); //获取父文件夹的IShellFolder接口

OleCheck(ShellParentFolder.ParseDisplayName(HND,nil,
PWideChar(WideString(ExtractFileName(aFile))),
chEaten,FilePIDL ,dwAttributes)); //获取文件的相对PItemIDList

ShellParentFolder.GetUIObjectOf(HND,1,FilePIDL,IID_IContextMenu,nil,CM); //获取文件的IContextMenu Interace

如果CM = nil然后退出;
P.X:= X;
P.Y:= Y;

Windows.ClientToScreen(HND,P);

菜单:= CreatePopupMenu;

尝试
CM.QueryContextMenu(菜单,0,1,$ 7FFF,CMF_EXPLORE或CMF_CANRENAME);
CM.QueryInterface(IID_IContextMenu2,ICM2); //处理子菜单
try
命令:= TrackPopupMenu(菜单,TPM_LEFTALIGN或TPM_LEFTBUTTON或TPM_RIGHTBUTTON或
TPM_RETURNCMD,p.X,p.Y,0,HND,nil);
finally
ICM2:= nil;
结束

如果命令然后
begin
ICmd:= LongInt(Command) - 1;
FillChar(ICI,SizeOf(ICI),#0);
与ICI do
begin
cbSize:= SizeOf(ICI);
hWND:= 0;
lpVerb:= MakeIntResourceA(ICmd);
nShow:= SW_SHOWNORMAL;
结束
CM.InvokeCommand(ICI);
结束
finally
DestroyMenu(Menu)
end;
结束;

修改/添加初始化,这样的定稿部分

 初始化
OleInitialize(nil);
finalization
OleUninitialize;

此处如何使用此过程:

  procedure TForm2.Button1Click(Sender:TObject); 
begin
ShowSysPopup(Edit1.Text,Edit1.Left,Edit1.Top,Handle);
结束

我希望这将适合你。



<如果要显示多个文件检查的上下文菜单,则 b

编辑:
我的博客中的这篇文章


I want to write the following procedure / function:

procedure ShowSysPopup(aFile: string; x, y: integer);

Which will build and show (at the coordinates x and y) the right-click shell menu which one sees in the Windows Explorer for the given file. I'm not so interested in the 'showing' part but more in how one can build such a menu.

解决方案

I've made a quick solution for you. add these units to the "Uses" section:

... ShlObj, ActiveX, ComObj

and here is your procedure, I just add new parameter "HND" to carry the handle of the TWinControl that you will use to display the context Menu.

procedure ShowSysPopup(aFile: string; x, y: integer; HND: HWND);
var
  Root: IShellFolder;
  ShellParentFolder: IShellFolder;
  chEaten,dwAttributes: ULONG;
  FilePIDL,ParentFolderPIDL: PItemIDList;
  CM: IContextMenu;
  Menu: HMenu;
  Command: LongBool;
  ICM2: IContextMenu2;

  ICI: TCMInvokeCommandInfo;
  ICmd: integer;
  P: TPoint;
Begin
  OleCheck(SHGetDesktopFolder(Root));//Get the Desktop IShellFolder interface

  OleCheck(Root.ParseDisplayName(HND, nil,
    PWideChar(WideString(ExtractFilePath(aFile))),
    chEaten, ParentFolderPIDL, dwAttributes)); // Get the PItemIDList of the parent folder

  OleCheck(Root.BindToObject(ParentFolderPIDL, nil, IShellFolder,
  ShellParentFolder)); // Get the IShellFolder Interface  of the Parent Folder

  OleCheck(ShellParentFolder.ParseDisplayName(HND, nil,
    PWideChar(WideString(ExtractFileName(aFile))),
    chEaten, FilePIDL, dwAttributes)); // Get the relative  PItemIDList of the File

  ShellParentFolder.GetUIObjectOf(HND, 1, FilePIDL, IID_IContextMenu, nil, CM); // get the IContextMenu Interace for the file

  if CM = nil then Exit;
  P.X := X;
  P.Y := Y;

  Windows.ClientToScreen(HND, P);

  Menu := CreatePopupMenu;

  try
    CM.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE or CMF_CANRENAME);
    CM.QueryInterface(IID_IContextMenu2, ICM2); //To handle submenus.
    try
      Command := TrackPopupMenu(Menu, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RIGHTBUTTON or
        TPM_RETURNCMD, p.X, p.Y, 0, HND, nil);
    finally
      ICM2 := nil;
    end;

    if Command then
    begin
      ICmd := LongInt(Command) - 1;
      FillChar(ICI, SizeOf(ICI), #0);
      with ICI do
      begin
        cbSize := SizeOf(ICI);
        hWND := 0;
        lpVerb := MakeIntResourceA(ICmd);
        nShow := SW_SHOWNORMAL;
      end;
      CM.InvokeCommand(ICI);
    end;
  finally
     DestroyMenu(Menu)
  end;
End;

modify/add the initialization, finalization section like this

initialization
  OleInitialize(nil);
finalization
  OleUninitialize;

and here how you can use this procedure:

procedure TForm2.Button1Click(Sender: TObject);
begin
  ShowSysPopup(Edit1.Text,Edit1.Left,Edit1.Top, Handle);
end;

I hope this will work for you.

Regards,

Edit: if you want to show context menu for more than one file check this article in my blog

这篇关于如何使用Delphi弹出给定文件的Windows上下文菜单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆