Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Ein Windows ShellMenu für eine Datei erscheinen lassen (https://www.delphipraxis.net/119387-ein-windows-shellmenu-fuer-eine-datei-erscheinen-lassen.html)

blackdrake 25. Aug 2008 19:22


Ein Windows ShellMenu für eine Datei erscheinen lassen
 
Hallo.

Ich habe eine Listbox, die Dateinamen in den Captions besitzt. (Dateinamen ohne Pfadangaben)

Wenn der Benutzer einen Eintrag doppelklickt, wird die Datei geöffnet (über ShellExecute im OnDblClick)

Was ich jetzt noch realisieren möchte, ist ein Windows Kontextmenü (Öffnen, Umbenennen, Löschen, Eigenschaften etc.) für die jeweils angewählte Datei, wenn der Benutzer mit der rechten Maustaste auf eine Zeile klickt.

Wie realisiert man das?

Delphi-Quellcode:
procedure TMainForm.database_list_mousedown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  tmp: string;
begin
  if (Button = mbRight) and (database_list.SelCount > 0) then
  begin
    tmp := GetDownloadDirectory + database_list.Selected.Caption;
    if FileExists(tmp) then
    begin
      // ToDo: KontextMenue
      // KontextMenue(tmp);
      showmessage(tmp);
    end;
  end;
end;
Vielen Dank.

Gruß
blackdrake

Luckie 25. Aug 2008 19:25

Re: Ein ShellMenu für eine Datei erscheinen lassen
 
Wenn ich mich nicht irre, kannst du der Listbox ein Popupmenü als Kontextmenü zuweisen.

blackdrake 25. Aug 2008 19:26

Re: Ein ShellMenu für eine Datei erscheinen lassen
 
Ich möchte jedoch exakt das Kontextmenü von Windows (so wie man es bei WinZip WinRAR sieht)

Luckie 25. Aug 2008 19:53

Re: Ein Windows ShellMenu für eine Datei erscheinen lassen
 
Ach so, sag das doch auch:
Delphi-Quellcode:
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;
Ich weiß jetzt allerdings nicht, welche Units du noch eibinden muss. Probier es mal mit diesen hier: ActiveX, ShlObj, ComObj.

blackdrake 25. Aug 2008 21:02

Re: Ein Windows ShellMenu für eine Datei erscheinen lassen
 
Hallo Luckie.

Vielen Dank für deine Hilfe! Bei diesen API-Funktionen habe ich das große Problem, dass ich die Schlagwörter (ContextMenuHandler, ShellMenu, etc.) nicht weiß bzw. diese in anderen Problematiken quasi identisch sind (Beispiel: ShellMenu).

Die benötigte Funktion SHGetIDListFromPath() ist übrigens hier zu finden: http://www.delphipraxis.net/internal...=121338#121338 .

Hier mein Code:

Delphi-Quellcode:
procedure TMainForm.database_list_mousedown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  tmp: string;
begin
  if (Button = mbRight) and (database_list.SelCount > 0) then
  begin
    tmp := GetDownloadDirectory + database_list.Selected.Caption;
    if FileExists(tmp) then
    begin
      // The left border as well as the title line of the ListView is not included
      // in the X and Y parameter, so we have to add X+6 and Y+32... :-/

      ContextMenuForFile(tmp, MainForm.Left + database_list.Left + X + 6,
                              MainForm.Top + database_list.Top + Y + 32,
                              Application.Handle);
    end;
  end;
end;
Ich hab nur noch so ein seltsames Problem: Die X und Y Angaben sind abzüglich der Titelzeile und abzüglich des linken Randes der TSortListView (TListView), weswegen ich hier die Zahlen 6 und 32 "hard-coden" musste :? (Lösung?)

Ich bin erstaunt darüber, dass sich sofort auch mein sekundäres Problem von selbst gelöst hat - ich wollte nämlich die "Umbenennen"-Funktion deaktivieren bzw. zumindestens behandeln (Datenbankeintrag, der zu der Datei gehört, mit umbenennen). Das Shell-Menu hat den "Umbenennen"-Eintrag nicht :thumb: Naja, man kann trotzdem die Datei löschen oder über den Eigenschafts-Dialog die Datei umbenennen. Ich muss mich da noch um ein Shell-Notify (?) für Änderungsereignisse des Zielordners beschäftigen.

Gruß
blackdrake

Luckie 25. Aug 2008 21:11

Re: Ein Windows ShellMenu für eine Datei erscheinen lassen
 
Zitat:

Zitat von blackdrake
Die benötigte Funktion SHGetIDListFromPath() ist übrigens hier zu finden: http://www.delphipraxis.net/internal...=121338#121338 .

Ah. Das ist code aus einem älteren Projekt ich wusste nicht mehr, was da noch alles zugehört und was nicht.

blackdrake 26. Aug 2008 12:11

Re: Ein Windows ShellMenu für eine Datei erscheinen lassen
 
Hallo.

Ich habe eine zusätzliche Frage, die sich auf die selbe Problematik bezieht:

Ich dachte mir, da jetzt ein ShellMenu existiert, kann man in der ListView auch ein MultiSelect erlauben. Somit kann der Nutzer z.B. mehrere Dokumente auf einmal über das Windows-Kontextmenü öffnen oder drucken. Wie müsste ich bei mehreren Dateien vorgehen?

Gruß
blackdrake


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz