Tôi đã thực hiện giải pháp nhanh cho bạn. thêm các đơn vị này vào "Sử dụng" phần:
... ShlObj, ActiveX, ComObj
và đây là quy trình của bạn, tôi chỉ cần thêm mới tham số "HND" để thực hiện các xử lý của TWinControl mà bạn sẽ sử dụng để hiển thị Menu ngữ cảnh.
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;
sửa đổi/bổ sung khởi, phần hoàn thiện như thế này
initialization
OleInitialize(nil);
finalization
OleUninitialize;
và ở đây làm thế nào bạn có thể sử dụng thủ tục này:
procedure TForm2.Button1Click(Sender: TObject);
begin
ShowSysPopup(Edit1.Text,Edit1.Left,Edit1.Top, Handle);
end;
Tôi hy vọng điều này sẽ làm việc cho bạn.
Kính trọng,
Edit: nếu bạn muốn hiển thị menu ngữ cảnh để kiểm tra nhiều hơn một tập tin this article in my blog
Điều này có vẻ hơi không đầy đủ, các tin nhắn IContextMenu2 không được xử lý, tức là HandleMenuMsg không được gọi để trả lời các thông báo menu. Kết quả là một số menu phụ (như 'Open with') sẽ không được điền. [Ở đây] (http://stackoverflow.com/a/5287265) là một ví dụ về những gì tôi đang nói đến. –
Ngoài ra, nếu không có một lớp thực hiện giao diện IShellCommandVerb, tham số boolean 'Handled' của bạn và giao diện chính nó không phục vụ gì cả. Như bạn thấy trong mã của bạn, bạn đang truy vấn * nil * nếu nó hỗ trợ giao diện, tất nhiên bạn không bao giờ đưa ra giao diện, chỉ cần loại bỏ rất nhiều mã không cần thiết và khai báo kiểu không cần thiết. –
Tôi tự do làm điều đó. Câu lệnh này 'nếu Support (nil, IShellCommandVerb, SCV) thì' đã thực sự nổi bật. Xin vui lòng, cũng sửa mã trên blog của bạn .. Bình luận đầu tiên của tôi vẫn còn hợp lệ mặc dù. –