如何在自己的ListView中弹出系统的右键菜单,并执行相应功能。(300分)

  • 主题发起人 主题发起人 zw84611
  • 开始时间 开始时间
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
ListView中的每个item代表一个文件。
1.如何在自己的ListView中弹出系统的右键菜单,并执行相应功能。
2.如何把系统的右键菜单添加到自己的popup menu中去。

我知道第一个问题可以参考syslistview等控件的源码,但我没有太多时间,请给出完整
的实现代码,谢谢。
 
得到它的HMENU ---Menu Handle。
使用WINDOW API的函数InsertMenu, InsertMenuItem加入到你的菜单中。
或者在Menu事件中把它加入。
 
HMENU GetSystemMenu(

HWND hWnd, // handle of window to own window menu
BOOL bRevert // reset flag
);
 
我指的是资源管理器中的那种右键菜单。应该要用到IContextMenu。
 
每一个问题我曾看到过一个类似控件有些功能。
第二个关注!
 
确实,第一个问题SellListView及其它类似控件的源码中有,只是太复杂了,我想照着做,
没做出来。[:(]
 
你可以看看gxexplorer是怎么做的:
http://www.gxexplorer.org
 
http://www.gxexplorer.org
上不去
 
我有一个独立的Pas文件,只提供了一个函数就是实现弹出Context Menu的功能,
但是太长了,1000多行,我不想贴,如果需要的话说一声,是DFSSysView控件包
里面的。

PS:这个问题前两天好像有人问过,不是你吧?
 
在Delphi6.0的安装目录下Delphi6/Demos/ShellControls/ShellCtrls.pas有现成的例子,
即函数procedure InvokeContextMenu(Owner: TWinControl;
AFolder: TShellFolder; X, Y: Integer);
依样可以实现之。需要指出的是例子中只能处理单个对象。由于处理上下文菜单如'Rename'
,'Paste','Delete'等时要在LV中实时更新,因此用接口来调用LV的相关函数。
 
请给出完整的实现代码,谢谢。
 
UP,
你给我的回答还不是太完美,
因为他们的鼠标拖动只能对两个ITEM交换位置
而不能象BORLAND那样真正上移下移,
你应该好好看看DEPHI的控件面板属性,感受一下, 谢谢!
希望你能帮我找到更好的原代码
 
谢谢你,不够还是用你后来那段最好,
有简单,有能达到目的!
 
怎么做的,把代码贴出来,我这里有一个ShellTree的控件,只是代码太长,看得太累也看不懂。
呵呵
 
我也不懂,不过很感谢你教我如何
鼠标拖动上移下移,
不过我的LISTBOX上移下移还是搞不定
,真不好意思,又得麻烦你贴代码给我了
谢谢!
你去CSDN上问过了吗?
小弟我现在还没有你钻研的这么深呢?
还望你多多指教!
 
请参照LsFileExplore2.87,是个免费的控件,实现了你要的功能,有源码。
www.vclxx.org,
torry上都有
 
从JCLShell得到的代码:
unit ShenShell;

interface

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

implementation

uses
ShlObj,
Active;

type
TUnicodePath = array[0..MAX_PATH - 1] of WideChar;

const
ShenPathSeparator = '/';

function PidlFree(var IdList: PItemIdList): Boolean;
var
Malloc: IMalloc;
begin
Result := False;
if IdList = nil then
Result := True
else
begin
if Succeeded(SHGetMalloc(Malloc)) and (Malloc.DidAlloc(IdList) > 0) then
begin
Malloc.Free(IdList);
IdList := nil;
Result := True;
end;
end;
end;

function MenuCallback(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM):
LRESULT; stdcall;
var
ContextMenu2: IContextMenu2;
begin
case Msg of
WM_CREATE:
begin
ContextMenu2 := IContextMenu2(PCreateStruct(lParam).lpCreateParams);
SetWindowLong(Wnd, GWL_USERDATA, Longint(ContextMenu2));
Result := DefWindowProc(Wnd, Msg, wParam, lParam);
end;
WM_INITMENUPOPUP:
begin
ContextMenu2 := IContextMenu2(GetWindowLong(Wnd, GWL_USERDATA));
ContextMenu2.HandleMenuMsg(Msg, wParam, lParam);
Result := 0;
end;
WM_DRAWITEM, WM_MEASUREITEM:
begin
ContextMenu2 := IContextMenu2(GetWindowLong(Wnd, GWL_USERDATA));
ContextMenu2.HandleMenuMsg(Msg, wParam, lParam);
Result := 1;
end;
else
Result := DefWindowProc(Wnd, Msg, wParam, lParam);
end;
end;

function CreateMenuCallbackWnd(const ContextMenu: IContextMenu2): HWND;
const
IcmCallbackWnd = 'ICMCALLBACKWND';
var
WndClass: TWndClass;
begin
FillChar(WndClass, SizeOf(WndClass), #0);
WndClass.lpszClassName := PChar(IcmCallbackWnd);
WndClass.lpfnWndProc := @MenuCallback;
WndClass.hInstance := HInstance;
Windows.RegisterClass(WndClass);
Result := CreateWindow(IcmCallbackWnd, IcmCallbackWnd, WS_POPUPWINDOW, 0,
0, 0, 0, 0, 0, HInstance, Pointer(ContextMenu));
end;

function DisplayContextMenuPidl(const Handle: HWND; const Folder: IShellFolder;
Item: PItemIdList; Pos: TPoint): Boolean;
var
Cmd: Cardinal;
ContextMenu: IContextMenu;
ContextMenu2: IContextMenu2;
Menu: HMENU;
CommandInfo: TCMInvokeCommandInfo;
CallbackWindow: HWND;
begin
Result := False;
if (Item = nil) or (Folder = nil) then
Exit;
Folder.GetUIObjectOf(Handle, 1, Item, IID_IContextMenu, nil,
Pointer(ContextMenu));
if ContextMenu <> nil then
begin
Menu := CreatePopupMenu;
if Menu <> 0 then
begin
if Succeeded(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE))
then
begin
CallbackWindow := 0;
if Succeeded(ContextMenu.QueryInterface(IContextMenu2, ContextMenu2))
then
begin
CallbackWindow := CreateMenuCallbackWnd(ContextMenu2);
end;
ClientToScreen(Handle, Pos);
Cmd := Cardinal(TrackPopupMenu(Menu, TPM_LEFTALIGN or TPM_LEFTBUTTON or
TPM_RIGHTBUTTON or TPM_RETURNCMD, Pos.X, Pos.Y, 0, CallbackWindow,
nil));
if Cmd <> 0 then
begin
FillChar(CommandInfo, SizeOf(CommandInfo), #0);
CommandInfo.cbSize := SizeOf(TCMInvokeCommandInfo);
CommandInfo.hwnd := Handle;
CommandInfo.lpVerb := MakeIntResource(Cmd - 1);
CommandInfo.nShow := SW_SHOWNORMAL;
Result := Succeeded(ContextMenu.InvokeCommand(CommandInfo));
end;
if CallbackWindow <> 0 then
DestroyWindow(CallbackWindow);
end;
DestroyMenu(Menu);
end;
end;
end;

function PathAddSeparator(const Path: string): string;
begin
Result := Path;
if (Length(Path) = 0) or (AnsiLastChar(Path) <> ShenPathSeparator) then
Result := Path + ShenPathSeparator;
end;

function DriveToPidlBind(const DriveName: string; out Folder: IShellFolder):
PItemIdList;
var
Attr: ULONG;
Eaten: ULONG;
DesktopFolder: IShellFolder;
Drives: PItemIdList;
Path: TUnicodePath;
begin
Result := nil;
if Succeeded(SHGetDesktopFolder(DesktopFolder)) then
begin
if Succeeded(SHGetSpecialFolderLocation(0, CSIDL_DRIVES, Drives)) then
begin
if Succeeded(DesktopFolder.BindToObject(Drives, nil, IID_IShellFolder,
Pointer(Folder))) then
begin
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
PChar(PathAddSeparator(DriveName)), -1, Path, MAX_PATH);
if FAILED(Folder.ParseDisplayName(0, nil, Path, Eaten, Result,
Attr)) then
begin
Folder := nil;
end;
end;
end;
PidlFree(Drives);
end;
end;

function PathToPidlBind(const FileName: string; out Folder: IShellFolder):
PItemIdList;
var
Attr, Eaten: ULONG;
PathIdList: PItemIdList;
DesktopFolder: IShellFolder;
Path, ItemName: TUnicodePath;
begin
Result := nil;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(ExtractFilePath(FileName)),
-1, Path, MAX_PATH);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(ExtractFileName(FileName)),
-1, ItemName, MAX_PATH);
if Succeeded(SHGetDesktopFolder(DesktopFolder)) then
begin
if Succeeded(DesktopFolder.ParseDisplayName(0, nil, Path, Eaten, PathIdList,
Attr)) then
begin
if Succeeded(DesktopFolder.BindToObject(PathIdList, nil, IID_IShellFolder,
Pointer(Folder))) then
begin
if FAILED(Folder.ParseDisplayName(0, nil, ItemName, Eaten, Result,
Attr)) then
begin
Folder := nil;
Result := DriveToPidlBind(FileName, Folder);
end;
end;
PidlFree(PathIdList);
end
else
Result := DriveToPidlBind(FileName, Folder);
end;
end;

function DisplayContextMenu(const Handle: HWND; const FileName: string;
Pos: TPoint): Boolean;
var
ItemIdList: PItemIdList;
Folder: IShellFolder;
begin
Result := False;
ItemIdList := PathToPidlBind(FileName, Folder);
if ItemIdList <> nil then
begin
Result := DisplayContextMenuPidl(Handle, Folder, ItemIdList, Pos);
PidlFree(ItemIdList);
end;
end;

end.
 
1)"金山快译“那样的导航条,他是如何控制
mouseout mouseenter的消息映射?
2)如何象WINRAR那样编写RarExt.dll中的内容,
可以拥有我们自己, 文件右键菜单?
 
接受答案了.
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
930
DelphiTeacher的专栏
D
D
回复
0
查看
871
DelphiTeacher的专栏
D
后退
顶部