Context menu for integrated housings in your application
Author: _foo (2004.5.11)
Keywords: shell, namespace, icontextmenu, shell, namespace, context menu
Article difficulty: primary
Introduction (What is the shell contextmenu)
With more and more software extensions, resource manager becomes more powerful and easy to use, before compressed one or more files, you have to find a shortcut to compression software and open him. Then, a series of selection operations, this is absolutely annoying to me, and there is a housing menu extension mechanism, you only need to select the file you want to operate in the Explorer. Then popup the right-click menu to select the appropriate item to get it, more convenient.
Oh, hit, this article is not to introduce how to add a menu extension to the resource manager (Note 1), but introduce how to call the context menu with rich features in your own program. For example, the local file window on the left of FlashFXP (Figure 1):
(Figure 1: Assuming that you open the FTP software to discover some files to discover these files yet, what should I do? Switch to the resource manager to pack them and return to FlashFXP? No no no, don't do so inefficiency Things, in the left window of Flashfxp, then press and hold the SHIFT button and pop up the right button. Take a look, it is too wonderful. In the future, you can use your favorite to enjoy it directly in the FTP. )
(Note 1: Basically, write a context menu extension is easier to implement, with a large number of articles and sample code available from http://www.codeproject.com/shell)
HOW TO IMPLEMENT
We know that in Win32 is in the form of a housing name space (Note 2), each folder in the housing name space implements an ISHELLFOLDER interface, we can query or indirectly through this interface. Get other related interfaces.
The interface with the context menu of the object (Note 3) is IconTextMenu, which interface can be obtained by the ISHELLFOLDER :: GetuiObjectof method through the parent folder of the object. After getting this interface, you can use the iconTextMenu :: queryContextMenu method to generate a menu item of the context menu, call the corresponding command with IconTextMenu :: InvokeCommand. It looks very simple? Here's a specific implementation, including how to get an object's parent folder iShellfolder interface, how to get icontextMenu, and how to call all methods of IconTextMenu.
(Note 2: The concept of the namespace of the shell, I recommend everyone to see Jiang Weihua's Windows House Name Space Browse, more information can be obtained from MSDN)
(Note 3: The object here refers to a node in the enclosure name space, the object may be a folder, it is possible to be a file, it is also possible to be a virtual folder, for example: my computer, online neighbor, control Panel, etc.)
Specific implementation and examples
For the sake of simplicity, this example is based on the dialog engineering based on the MFC. List the subfolders and files under the C dote in a listbox control. Right-click each of the listbox to pop up the corresponding enclosure context menu. .
(1) Enumerate the folders and files under the C drive and added to listbox: Steps are as follows:
a) Get the ISHELLFOLDER interface pointer of the desktop with ShgetDesktopFolder, which is a way we have achieved other objects ISHELLFOLDER. b) Get the PIDL of the drive C with ishellfolder :: parsedisplayName, then pass the resulting PIDL as a parameter to ISHELLFOLDER :: BindToObject to get the Drive C's ISHELLFOLDER interface pointer.
c) You can get an enumerator with the iShellfolder :: Enumjects method you just get the C drive, and you can enumerate the PIDL of the subfolders and files under the C disc. You can get the display name of the object represented by PIDL through GetDisplayNameO, so we add this name to listbox, and save the corresponding PIDL with CListbox: Setitemdata, use J
Sample code:
...
LPMalloc PMalloc;
LPITEMIDLIST PIDLC = NULL;
LPITEMIDLIST PIDLITEMS = NULL;
ISHELLFOLDER * psfdesktop = NULL;
IShellfolder * psffolderc = null;
LPENUMIDLIST PPENUM = NULL;
Ulong celtfetched;
HRESULT HR;
Strret strdispname;
Tchar pszdisplayName [max_path];
Ulong Uattr;
HR = SHGETMALLOC (& PMalloc);
HR = SHGETDESKTOPFOLDER (& PsfDesktop);
HR = psfdesktop-> pasedisplayName (GetsafehWnd (), NULL, L "C: ///", NULL, & PIDLC, NULL)
HR = psfdesktop-> bindtoobject (PIDLC, NULL, IID_ID_IDFOLDER, (Void **) & psffolderc);
Psfdesktop-> release ();
HR = psffolderc-> enumobjects (GetSafehWnd (), Shcontf_folders | Shcontf_nonfolders, & Ppenum
While (hr = ppenum-> next (1, & pidlitems, & celtfetched) == s_ok && (celtfetched) == 1)
{
Psffolderc-> getDisplayNameOf (Pidlitems, SHGDN_INFOLDER, & STRDISPNAME);
Uattr = sfgao_folder;
Psffolderc-> GetAttributesof (1, (lpcitemidlist *) & pidlitems, & uattr);
StrretTobuf (& Strdispname, Pidlitems, PszdisPlayName, Max_Path);
CString strdisplayName;
IF (uattr & sfgao_folder)
{
STRDISPLAYNAME.FORMAT ("% s% s% s", "[", pszdisplayname, "]");
}
Else
{
STRDISPLAYNAME = pszdisplayname;
}
M_ListBox.SetItemData (m_listbox.insertstring (-1, strdisplayname), (dword) pidlitems;
Ppenum-> Release ();
Pmalloc-> free (PIDLC);
PMalloc-> Release ();
m_psffolderc = psffolderc;
...
FAINT, beyond 64K, to be renewed ...
The context menu of the integrated housing in the application (below)