Explorer - Menu kontekstowe

0

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ę...

0

Pewnie jest jaiś bezpośredni sposób, ale zawsze za pomoca SendInput możesz wysłać kod klawisza VK_APPS.

0

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

0

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 ;)

0

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;

1 użytkowników online, w tym zalogowanych: 0, gości: 1