ファイルのリストを含むリストボックスがあります。リストボックスの Windows の右クリック メニューにアクセスして、開く、プロパティ、削除、および名前の変更項目にアクセスできますか?
4 に答える
KermiaJclShell
は JEDI JCL ライブラリからユニットをチェックします。このユニット内には DisplayContextMenu
、ファイルに関連付けられたコンテキスト メニューを表示する関数が呼び出されます。この関数は、IContextMenu インターフェイスへの呼び出しをカプセル化し、作業をより簡単にします。
function DisplayContextMenu(const Handle: HWND; const FileName: string;
Pos: TPoint): Boolean;
IContextMenuインターフェイスを確認してください。ただし、Windows シェルはそのオブジェクトをファイル名で識別しないことに注意してください。実際にはファイルではない可能性があります。これは ID の連結を使用し、ファイルに対していくつかのシェル関数を呼び出す前に、ファイルが割り当てられている項目 ID リストを取得する必要がある場合があります。
これは、プロジェクトディレクトリ内のファイル名が入力されたリストボックスの「OnContextPopup」イベントを使用して、ファイルの名前を右クリックしたときにファイルのショートカットメニューを起動する実装例です。
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure ListBox1ContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
private
protected
procedure WndProc(var Msg: TMessage); override;
public
end;
var
Form1: TForm1;
implementation
uses
shlobj, comobj;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
SearchRec: TSearchRec;
begin
ListBox1.Clear;
// populate list box with files in the project folder
if FindFirst(ExtractFilePath(Application.ExeName) + '*.*',
0, SearchRec) = 0 then
repeat
ListBox1.Items.Add(SearchRec.Name);
until FindNext(SearchRec) <> 0;
FindClose(SearchRec);
end;
var
// Required to handle messages for owner drawn items, as in 'SendTo' menu.
// Also used as a flag in WndProc to know if we're tracking a shortcut menu.
ContextMenu2: IContextMenu2 = nil;
procedure TForm1.ListBox1ContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
var
Item: Integer;
DeskFolder, Folder: IShellFolder;
Eaten, Attributes: ULONG;
pIdl, FolderpIdl: PItemIDList;
ContextMenu: IContextMenu;
Menu: HMENU;
Pos: TPoint;
Cmd: DWORD;
CommandInfo: TCMInvokeCommandInfo;
begin
Item := (Sender as TListBox).ItemAtPos(MousePos, True);
Handled := Item <> -1;
if not Handled then
Exit;
TListBox(Sender).ItemIndex := Item;
// IShellFolder for Desktop folder (root)
OleCheck(SHGetDesktopFolder(DeskFolder));
// Item ID List for the folder that the file is in
Attributes := 0;
OleCheck(DeskFolder.ParseDisplayName(Handle, nil,
PWideChar(WideString(ExtractFilePath(Application.ExeName))),
Eaten, FolderpIdl, Attributes));
// IShellFolder for the folder the file is in
OleCheck(DeskFolder.BindToObject(FolderpIdl, nil, IID_IShellFolder, Folder));
CoTaskMemFree(FolderpIdl);
// Item ID List for the file, relative to the folder it is in
Attributes := 0;
OleCheck(Folder.ParseDisplayName(Handle, nil,
PWideChar(WideString(ExtractFileName(TListBox(Sender).Items[Item]))),
Eaten, pIdl, Attributes));
// IContextMenu for the relative Item ID List
OleCheck(Folder.GetUIObjectOf(Handle, 1, pIdl, IID_IContextMenu,
nil, ContextMenu));
CoTaskMemFree(pIdl);
Menu := CreatePopupMenu;
try
// Populate our menu with shortcut items
OleCheck(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE));
// ContextMenu2 used in WndProc
ContextMenu.QueryInterface(IID_IContextMenu2, ContextMenu2);
try
Pos := TWinControl(Sender).ClientToScreen(MousePos);
// launch the menu
Bool(Cmd) := TrackPopupMenu(Menu,
TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_RETURNCMD,
Pos.X, Pos.Y, 0, Handle, nil);
finally
// clear so that we don't intervene every owner drawn menu item message in
// WndProc
ContextMenu2 := nil;
end;
// Invoke command if we have one
if Bool(Cmd) then begin
FillChar(CommandInfo, SizeOf(CommandInfo), 0);
CommandInfo.cbSize := SizeOf(CommandInfo);
CommandInfo.hwnd := Handle;
CommandInfo.lpVerb := MakeIntResource(Cmd - 1);
CommandInfo.nShow := SW_SHOWNORMAL;
OleCheck(ContextMenu.InvokeCommand(CommandInfo));
end;
finally
DestroyMenu(Menu);
end;
end;
procedure TForm1.WndProc(var Msg: TMessage);
begin
if ((Msg.Msg = WM_INITMENUPOPUP) or (Msg.Msg = WM_DRAWITEM)
or (Msg.Msg = WM_MEASUREITEM)) and Assigned(ContextMenu2) then
ContextMenu2.HandleMenuMsg(Msg.Msg, Msg.WParam, Msg.LParam)
else
inherited;
end;
Delphi アプリでシェルのようなコントロールを表示したい場合は、 tpShellShockのようなものを見ることをお勧めします。エクスプローラー ウィンドウのように接続できるツリー ビュー、リスト ビューなどを提供します。ファイルの適切なアイコンが表示されます。おっしゃる通りの設備も整っていると思います。
最新の Unicode Delphi を使用している場合は、移植作業が必要になる場合がありますが、それを行ってみると、比較的簡単であることがわかりました。
シェル コントロールを提供する他のライブラリがあることは間違いありませんが、これは私がよく知っているものです。
それ以外の場合は、現在のソリューションに固執したい場合は、独自のメニュー アクションを実装するのが最も簡単です。Open と Properties は、適切な動詞を使用した単純な ShellExecute の呼び出しです。Delete は DeleteFile の呼び出しであり、Rename は MoveFile の呼び出しです。