Kısa cevap
JAM Software dan ShellBrowser Components deneyin. Bunlar, Explorer'in içerik menüsünü, TPopupMenu'dan karışık kendi komutlarınızla göstermenize izin verecek bir bileşene sahiptir.
Uzun cevap
, Tarayıcı menüsünden Alma tüm özellikleri sorgulama ve kendi menüde bunları barındırma
mümkündür, ama sen gerçekten rahat okuma/yazma düşük seviye Win32 kodu olmalıdır ve C'nin çalışma bilgisi yardımcı olacaktır. Ayrıca bazı tutacakları (aşağıda kapsanan) dikkat etmeniz gerekir. Birçok teknik ayrıntı için Raymond Chen'in
How to host an IContextMenu serisini okumanızı şiddetle tavsiye ediyorum.
kolay yaklaşım IContextMenu arabirimi için sorgu, sonra hMenu, ardından Windows menüsünü göstermek atalım TrackPopupMenu kullanın, ardından sonunda InvokeCommand diyoruz.
Aşağıdaki kodun bir kısmı test edilmediğinden veya kullandığımızdan değiştirildiğinden, kendi sorumluluğunuzda ilerleyin. İşte
bir taban klasör içindeki dosyaların bir grup için, IContextMenu olsun nasıl:
function GetExplorerMenu(AHandle: HWND; const APath: string;
AFilenames: TStrings): IContextMenu;
var
Desktop, Parent: IShellFolder;
FolderPidl: PItemIDList;
FilePidls: array of PItemIDList;
PathW: WideString;
i: Integer;
begin
// Retrieve the Desktop's IShellFolder interface
OleCheck(SHGetDesktopFolder(Desktop));
// Retrieve the parent folder's PItemIDList and then it's IShellFolder interface
PathW := WideString(IncludeTrailingPathDelimiter(APath));
OleCheck(Desktop.ParseDisplayName(AHandle, nil, PWideChar(PathW),
Cardinal(nil^), FolderPidl, Cardinal(nil^)));
try
OleCheck(Desktop.BindToObject(FolderPidl, nil, IID_IShellFolder, Parent));
finally
SHFree(FolderPidl);
end;
// Retrieve PIDLs for each file, relative the the parent folder
SetLength(FilePidls, AFilenames.Count);
try
FillChar(FilePidls[0], SizeOf(PItemIDList) * AFilenames.Count, 0);
for i := 0 to AFilenames.Count-1 do begin
PathW := WideString(AFilenames[i]);
OleCheck(Parent.ParseDisplayName(AHandle, nil, PWideChar(PathW),
Cardinal(nil^), FilePidls[i], Cardinal(nil^)));
end;
// Get the context menu for the files from the parent's IShellFolder
OleCheck(Parent.GetUIObjectOf(AHandle, AFilenames.Count, FilePidls[0],
IID_IContextMenu, nil, Result));
finally
for i := 0 to Length(FilePidls) - 1 do
SHFree(FilePidls[i]);
end;
end;
Eğer IContextMenu.QueryContextMenu çağırmanız gerekir fiili menü öğelerini almak için. DestroyMenu kullanarak iade edilen HMENU'yu yok edebilirsiniz.
procedure InvokeCommand(const AContextMenu: IContextMenu; AVerb: PChar);
const
CMIC_MASK_SHIFT_DOWN = $10000000;
CMIC_MASK_CONTROL_DOWN = $20000000;
var
CI: TCMInvokeCommandInfoEx;
begin
FillChar(CI, SizeOf(TCMInvokeCommandInfoEx), 0);
CI.cbSize := SizeOf(TCMInvokeCommandInfo);
CI.hwnd := GetOwnerHandle(Owner);
CI.lpVerb := AVerb;
CI.nShow := SW_SHOWNORMAL;
// Ignore return value for InvokeCommand. Some shell extensions return errors
// from it even if the command worked.
try
AContextMenu.InvokeCommand(PCMInvokeCommandInfo(@CI)^)
except on E: Exception do
MessageDlg(Owner, E.Message, mtError, [mbOk], 0);
end;
end;
procedure InvokeCommand(const AContextMenu: IContextMenu; ACommandID: UINT);
begin
InvokeCommand(AContextMenu, MakeIntResource(Word(ACommandID)));
end;
Şimdi başlığını almak için GetMenuItemInfo işlevini kullanabilirsiniz, bitmap, vs, ama çok daha kolay: İşte
function GetExplorerHMenu(const AContextMenu: IContextMenu): HMENU;
const
MENUID_FIRST = 1;
MENUID_LAST = $7FFF;
var
OldMode: UINT;
begin
OldMode := SetErrorMode(SEM_FAILCRITICALERRORS or SEM_NOOPENFILEERRORBOX);
try
Result := CreatePopupMenu;
AContextMenu.QueryContextMenu(Result, 0, MENUID_FIRST, MENUID_LAST, CMF_NORMAL);
finally
SetErrorMode(OldMode);
end;
end;
aslında kullanıcı menüsünden seçilen ettiğini komutu çağırır nasıl Yaklaşım TrackPopupMenu'u aramak ve Windows'un açılır menüyü göstermesine izin vermek. Aslında menü öğeleri/başlıkları ayıklamak ve (biz Çubuğu 2000 kullanmak ve tam olarak bunu) kendi açılan menüden eklemek isterseniz buraya,
procedure ShowExplorerMenu(AForm: TForm; AMousePos: TPoint;
const APath: string; AFilenames: TStrings;);
var
ShellMenu: IContextMenu;
Menu: HMENU;
MenuID: LongInt;
begin
ShellMenu := GetExplorerMenu(AForm.Handle, APath, AFilenames);
Menu := GetExplorerHMenu(ShellMenu);
try
MenuID := TrackPopupMenu(Menu, TPM_LEFTALIGN or TPM_TOPALIGN or TPM_RETURNCMD,
AMousePos.X, AMousePos.Y, 0, AForm.Handle, nil);
InvokeCommand(ShellMenu, MenuID - MENUID_FIRST);
finally
DestroyMenu(Menu);
end;
end;
diğer büyük sorunlar şunlardır: Yani böyle bir şey olmazdı çalıştıracağınız içine:
- menüsü "gönder" ve iletileri işlemek ve IContextMenu2/IContextMenu3 arayüzleri onları geçmek sürece on-demand inşa herhangi diğerleri çalışmaz.
- Menü bitmapler birkaç farklı formattadır. Delphi, coaxing olmadan yüksek renkteki Vista'ları işlemez ve eskileri bir XOR kullanarak arka plan rengine karışır.
- Bazı menü öğeleri sahiplenilmiştir, bu nedenle boya iletilerini yakalamanız ve bunları kendi tuvalinize boyamanız gerekir.
- El ile sorgulamadığınız sürece, ip dizeleri çalışmaz.
- IContextMenu ve HMENU'nun ömrünü yönetmeniz ve yalnızca açılır menü kapatıldıktan sonra bunları serbest bırakmanız gerekir.
kendi ortam menü öğelerini oluşturmak veya varolan menü öğelerini manipüle etmek istiyor musunuz? – Liton
@Liton, kendi kabuk içeriği menü öğelerini oluşturmama, ancak varolan menü yerleşik öğesinde veya 3. bölüm öğelerinde değişiklik yapmak. –