2010-09-23 17 views
11

विंडोज एक्सप्लोरर में, आप एक फ़ाइल पर राइट क्लिक करते हैं, एक संदर्भ मेनू दिखाता है जिसमें अंतर्निहित आइटम जैसे 'भेजें ...' और/या तृतीय पक्ष क्रियाएं जैसे कि 'विनज़िप के साथ ज़िप फ़ाइल' शामिल हैं। मेरा सवाल है:विंडोज शैल संदर्भ मेनू आइटम तक कैसे पहुंचे?

  • किसी विशिष्ट फ़ाइल के लिए उपलब्ध मेनू आइटम की पूरी सूची कैसे प्राप्त करें?
  • प्रत्येक मेनू आइटम के लिए, कैप्शन कैसे प्राप्त करें?
  • किसी विशिष्ट डिस्क फ़ाइल के लिए विशिष्ट मेनू आइटम कार्रवाई कैसे करें?

अग्रिम धन्यवाद!

[संपादित करें]: जबकि अन्य जानकारी बिल्कुल उपयोगी है, डेल्फी समाधान की बहुत सराहना की जाएगी!

+0

आप स्वयं के संदर्भ मेनू आइटम बनाने के लिए या मौजूदा मेनू आइटम हेरफेर करने के लिए करना चाहते हैं? – Liton

+0

@ लिटन, अपना खुद का खोल संदर्भ मेनू आइटम नहीं बना रहा है, लेकिन मौजूदा मेनू में निर्मित या तृतीय भाग आइटमों में हेरफेर करने के लिए। –

उत्तर

9

शैल संदर्भ मेनू प्राप्त करने की कुंजी IContextMenu इंटरफ़ेस का उपयोग करती है।

अधिक जानकारी के लिए इस महान लेख Shell context menu support देखें।

अद्यतन

डेल्फी उदाहरण के लिए आप JEDI JCL से JclShell इकाई (जाँच DisplayContextMenu समारोह) और ShellCtrls इकाई डेल्फी के नमूने फ़ोल्डर में शामिल देख सकते हैं।

+0

लिंक के लिए धन्यवाद, मैं इसे देख लूंगा! –

+0

हाय आरआरयूजेड, जेसीएल पैकेज से DisplayContextMenu funciton वही करता है जो मैं चाहता हूं! धन्यवाद! –

7

लघु जवाब

JAM सॉफ्टवेयर से ShellBrowser Components की कोशिश करो। उनके पास एक घटक है जो आपको एक्सप्लोरर के संदर्भ मेनू को आपके स्वयं के आदेशों के साथ एक TPopupMenu में मिश्रित करने देगा।


लांग जवाब

, एक्सप्लोरर मीनू हो रही है उसके गुण के सभी क्वेरी करने, और उन्हें अपने खुद मेनू में होस्टिंग संभव है, लेकिन क्या तुम सच में आराम से पढ़ने/निम्न स्तर के लेखन Win32 कोड होना चाहिए और सी का एक कामकाजी ज्ञान मदद करेगा। आपको कुछ गॉथ (नीचे कवर) के लिए भी देखना होगा। मैं बहुत सारे तकनीकी विवरणों के लिए रेमंड चेन की How to host an IContextMenu श्रृंखला पढ़ने की दृढ़ता से अनुशंसा करता हूं।

आसान दृष्टिकोण IContextMenu इंटरफेस के लिए क्वेरी करने के लिए है, तो HMENU, तो TrackPopupMenu का उपयोग करने देने के लिए Windows मेनू दिखाने है, तो अंत में InvokeCommand कहते हैं।

नीचे दिए गए कुछ कोड को अनचाहे किया गया है या हम जो भी उपयोग कर रहे हैं उससे संशोधित किया गया है, इसलिए अपने जोखिम पर आगे बढ़ें।

यहाँ कैसे आप एक आधार फ़ोल्डर के भीतर फ़ाइलों के एक समूह के लिए IContextMenu मिलता है, है:

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; 

वास्तविक मेनू आइटम आप IContextMenu.QueryContextMenu कॉल करने की आवश्यकता प्राप्त करने के लिए। आप DestroyMenu का उपयोग कर लौटे हुए एचएमईएनयू को नष्ट कर सकते हैं।

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; 

अब आप शीर्षक प्राप्त करने के लिए GetMenuItemInfo समारोह का उपयोग कर सकते, बिटमैप, आदि, लेकिन एक बहुत आसान:

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; 

यहाँ कैसे आप वास्तव में आदेश फोन उपयोगकर्ता मेनू से चयन किया है कि दृष्टिकोण TrackPopupMenu पर कॉल करना है और विंडोज़ को पॉपअप मेनू दिखाएं। यहाँ

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; 

आप वास्तव में मेनू आइटम/कैप्शन निकालने और उन्हें अपने खुद के पॉपअप मेनू में जोड़ने के लिए (हम टूलबार 2000 उपयोग और बिल्कुल ऐसा) चाहते हैं, अन्य बड़े मुद्दे हैं: यही कारण है कि कुछ इस तरह दिखेगा आप चलाएंगे में:

  • "भेजें" मेनू में, और किसी भी अन्य लोगों कि मांग पर निर्माण कर रहे हैं काम नहीं करेगा जब तक कि आप संदेशों को संभालने और उन्हें IContextMenu2/IContextMenu3 इंटरफेस के गुजरती हैं।
  • मेनू बिटमैप्स कुछ अलग प्रारूपों में हैं। डेल्फी विस्टा के बिना विस्टा उच्च-रंग वाले लोगों को संभाल नहीं पाता है, और पुराने लोगों को एक्सओआर का उपयोग करके पृष्ठभूमि रंग पर मिश्रित किया जाता है।
  • कुछ मेनू आइटम मालिक-तैयार हैं, इसलिए आपको पेंट संदेशों को कैप्चर करना होगा और उन्हें अपने कैनवास पर पेंट करना होगा।
  • संकेत तार तब तक काम नहीं करेंगे जब तक कि आप उनके लिए मैन्युअल रूप से क्वेरी नहीं करते।
  • आपको आईसीएन्टेक्स्टमेनू और एचएमईएनयू के जीवनकाल को प्रबंधित करने की आवश्यकता होगी और पॉपअप मेनू बंद होने के बाद ही उन्हें रिलीज़ करना होगा।
+0

हाय क्रेग, विस्तृत तकनीकी जानकारी के लिए धन्यवाद, वे बहुत उपयोगी हैं! लेकिन मुझे आरआरयूजेड के जवाब को स्वीकार करना है क्योंकि उसने मुझे जेसीएल से डिस्प्ले कॉन्टेक्स्टमेनू फ़ंक्शन पर इंगित किया है जो वही करता है जो मैं एक पंक्ति के साथ चाहता हूं ... –

0

यहाँ एक exmple है कैसे पीछे ऑपरेटिंग सिस्टम तर्क "भेजें ... करने के लिए | मेल प्राप्तकर्ता" मेनू आइटम डिफ़ॉल्ट मेल क्लाइंट को खोलने के लिए एक डेल्फी आवेदन से इस्तेमाल किया जा सकता, के साथ एक नया मेल प्रदर्शित पारित कर दिया (चयनित) फ़ाइलें संलग्न:

How can I simulate ‘Send To…’ with Delphi?

संबंधित मुद्दे