Witam...
Chciałem zdobyć informacje na temat tego jak wywołać standardowe menu kontekstowe dla folderu czy pliku lub to, które pokazuje się, kiedy user kliknie na puste miejsce między plikami w explorerze...
Za jakąkolwiek pomoc z góry dziękuję...
Witam...
Chciałem zdobyć informacje na temat tego jak wywołać standardowe menu kontekstowe dla folderu czy pliku lub to, które pokazuje się, kiedy user kliknie na puste miejsce między plikami w explorerze...
Za jakąkolwiek pomoc z góry dziękuję...
Pewnie jest jaiś bezpośredni sposób, ale zawsze za pomoca SendInput możesz wysłać kod klawisza VK_APPS.
ale nie pokazać menu kontektowe w explorerze tylko klikając np na item w listboxie pokazać menu dla danego pliku jak z explorera (podobnie jak w total commanderze) - przynajmniej tak zrozumiałem, ale nawet jeśli nie o to chodzi to to jest moje pytanie w tym wątku bo mnie to interesuje ;P
z góry dzięki
Słowa klucze: IShellFolder,IShellFolder::GetUIObjectOf, IContextMenu, IContextMenu2
Dodatkowo handlery komunikatów WM_INITPOPUP, WM_DRAWITEM i WM_MEASUREITEM (to dla IContextMenu2::HandleMenuMsg)
Więcej informacji w MSDN'ie ;)
tak, właśnie o to mi chodzi :) tyle że trochę "przetrzepałem" internet i coś czuję że znalezienie tego nie będzie takie proste... :(
[dopisane]
OK :) [browar] w końcu znalazłem na jakimś niemieckim forum:
uses ShlObj, ComObj;
function SlashDirName(ADir: String): String;
var
S: String;
RootDir: Boolean;
begin
if ADir <> '' then
begin
S := ADir;
RootDir := ((Length(S) = 3) and (S[2] = ':')) or (S = '\');
if not RootDir then
if S[Length(S)] <> '\' then S := S + '\';
Result := S;
end;
end;
function SHGetIDListFromPath(Path: TFileName;
var ShellFolder: IShellFolder): PItemIDList;
var
TempPath, NextDir: TFileName;
SlashPos: Integer;
Folder, subFolder: IShellFolder;
PIDL, PIDLbase: PItemIDList;
ParseStruct: TStrRet;
ParseNAme: String;
EList: IEnumIDList;
DidGet: Cardinal;
ScanParam: Integer;
begin
SHGetDesktopFolder(Folder);
SHGetSpecialFolderLocation(0, CSIDL_DRIVES, PIDLbase);
OLECheck(Folder.BindToObject(PIDLbase,
nil, IID_IShellFolder, Pointer(SubFolder)));
TempPath := Path;
NextDir := '';
while Length(TempPath) > 0 do
begin
SlashPos := Pos('\', TempPath);
if SlashPos > 0 then
begin
if Pos(':', TempPath) > 0 then NextDir:=Copy(TempPath, 1, 3)
else NextDir := SlashDirName(NextDir) +
Copy(TempPath, 1, SlashPos - 1);
TempPath := Copy(TempPath, SlashPos + 1, Length(TempPath));
end else
begin
if NextDir = '' then NextDir := TempPath
else NextDir := SlashDirName(NextDir) + TempPath;
TempPath := '';
end;
PIDL := PidlBase;
ScanParam := SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN;
if (NextDir = Path) and (not DirectoryExists(Path)) then
ScanParam := ScanParam or SHCONTF_NONFOLDERS;
if S_OK = SubFolder.EnumObjects(0, ScanParam, EList) then
while S_OK = EList.Next(1, pidl, DidGet) do
begin
OLECheck(SubFolder.GetDisplayNameOf(PIDL,
SHGDN_FORPARSING, ParseStruct));
case ParseStruct.uType of
STRRET_CSTR: ParseName := ParseStruct.cStr;
STRRET_WSTR: ParseName := WideCharToString(ParseStruct.pOleStr);
STRRET_OFFSET: Parsename := PChar(DWORD(Pidl) + ParseStruct.uOffset);
end;
if UpperCase(Parsename) = UpperCase(NextDir) then Break;
end else
begin
Folder := nil;
Result := nil;
Exit;
end;
if DidGet = 0 then
begin
Folder := nil;
Result := nil;
Exit;
end;
PIDLBase := PIDL;
Folder := subFolder;
if not FileExists(NextDir) then
OLECheck(Folder.BindToObject(Pidl,
nil, IID_IShellFolder, Pointer(SubFolder)));
end;
ShellFolder := Folder;
if ShellFolder = nil then Result := nil else Result := PIDL;
end;
procedure ContextMenuForFile(FileName: TFileName;
X, Y: Integer; Handle: HWND);
var
aContextMenu: IContextMenu;
aPrgOut: Pointer;
aPopup: HMENU;
aCmd: Integer;
aCmdInfo: TCMInvokeCommandInfo;
PIDL: PItemIDList;
ShellFolder: IShellFolder;
begin
PIDL := SHGetIDListFromPath(FileName, ShellFolder);
if not Assigned(PIDL) then Exit;
aPrgOut := nil;
OLECheck(ShellFolder.GetUIObjectOf(0, 1, PIDL,
IID_IContextMenu, aPrgOut, Pointer(aContextMenu)));
aPopup := CreatePopUpMenu;
if aPopup = 0 then Exit;
try
OLECheck(aContextMenu.QueryContextMenu(aPopup, 0, 1, $7FFF, CMF_NORMAL));
aCmd := Integer(TrackPopupMenuEx(aPopup,
TPM_LEFTALIGN or TPM_RETURNCMD or TPM_RIGHTBUTTON or TPM_HORIZONTAL
or TPM_VERTICAL, X, Y, Handle, nil));
if aCmd <> 0 then
begin
FillChar(aCmdInfo, Sizeof(aCmdInfo), 0);
with aCmdInfo do
begin
cbSize := SizeOf(TCMInvokeCommandInfo);
lpVerb := MakeIntResource(aCmd - 1);
nShow := SW_SHOWNORMAL;
end;
try
aContextMenu.InvokeCommand(aCmdInfo);
except end;
end;
finally
DestroyMenu(aPopup);
end;
end;
//przykład użycia:
procedure TForm1.Button1Click(Sender: TObject);
var
P: TPoint;
begin
GetCursorPos(P);
ContextMenuForFile('C:\Windows\Notepad.exe', P.X, P.Y, Form1.Handle);
end;