Hello COM people :)
My first post here, and I have no idea about how to use COM but I realised that it is very powerfull feature of Win32
Anyway I wanted to add menu to my program that will show explorer context menu for some file/folder, but due to my ignorance in this area I am not exacly sure how to do this.
I saw ernie's file manager source and found this code, but still I could not make it to work in my program.



ContextMenu proc public uses ebx edx hWnd:DWORD, pshfParent:LPSHELLFOLDER, pidl:LPITEMIDLIST, ppoint:DWORD
LOCAL pcm:LPCONTEXTMENU
LOCAL hMenu:DWORD
LOCAL iCmd:DWORD
LOCAL cmi:CMINVOKECOMMANDINFO

mov ebx, pshfParent
mov ebx,[ebx]
invoke (IShellFolder ptr [ebx]).GetUIObjectOf, pshfParent,
hWnd,
1,
addr pidl,
addr IID_IContextMenu,
0,
addr pcm
test eax,eax
js ret_error

invoke CreatePopupMenu
test eax,eax
jz ret_error
mov hMenu, eax

mov ebx, pcm
mov ebx, [ebx]
invoke (IContextMenu ptr [ebx]).QueryContextMenu, pcm,
hMenu,
0,
1,
7FFFh,
CMF_EXPLORE
test eax,eax
js ret_error

mov edx, ppoint
invoke TrackPopupMenu,
hMenu,
TPM_LEFTALIGN or TPM_RIGHTBUTTON or 0100h, ;TPM_RETURNCMD
(POINT ptr [edx]).x,
(POINT ptr [edx]).y,
0,
hWnd,
0
test eax,eax
jz ret_error
mov iCmd, eax

mov cmi.cbSize, sizeof CMINVOKECOMMANDINFO
mov cmi.fMask, 0
mov eax, hWnd
mov cmi.hwnd, eax

mov eax, iCmd
dec eax
and eax, 0000FFFFh
mov cmi.lpVerb, eax

mov cmi.lpParameters, 0
mov cmi.lpDirectory, 0
mov cmi.nShow, SW_SHOWNORMAL
mov cmi.dwHotKey, 0
mov cmi.hIcon, 0

mov ebx, pcm
mov ebx, [ebx]
invoke (IContextMenu ptr [ebx]).InvokeCommand, pcm, addr cmi
.IF eax < 0 ; failed
;int 3
.ENDIF
invoke DestroyMenu, hMenu
invoke (IContextMenu ptr [ebx]).Release, pcm

ret_ok:
mov eax,1
ret

ret_error:
xor eax,eax
ret
ContextMenu endp


I dont understand much this code, and also looks like I dont have all includes needed to compile COM stuff properly. Does someone maybe already has standalone example on how to show context menu from his own app?
Posted on 2004-03-28 10:41:35 by Mikky
I have no experience with this area as well, but i can help by explaining this function to you:

	mov		ebx, pshfParent

mov ebx,[ebx]
invoke (IShellFolder ptr [ebx]).GetUIObjectOf, pshfParent,
hWnd,
1,
addr pidl,
addr IID_IContextMenu,
0,
addr pcm
test eax,eax
js ret_error

This uses a provided COM object instance. In this case its pshfParent (IShellFolder instance). This is only generated via COM function calls, or specific API. My guess is if its failing, it would be here as your probably not getting the right Object instance to satisfy this parameter. If it does work, it will return in 'pcm' (pointer to context menu instance) a context menu.

	invoke	CreatePopupMenu

test eax,eax
jz ret_error
mov hMenu, eax

This simply makes a Popup menu. Nothing new.

	mov		ebx, pcm

mov ebx, [ebx]
invoke (IContextMenu ptr [ebx]).QueryContextMenu, pcm,
hMenu,
0,
1,
7FFFh,
CMF_EXPLORE
test eax,eax
js ret_error

This uses the returned context menu pointer (another COM object instance) to query it and popuplate hMenu (the popup menu you just created). This is my best guess from the parameters provided.

	mov		edx, ppoint

invoke TrackPopupMenu,
hMenu,
TPM_LEFTALIGN or TPM_RIGHTBUTTON or 0100h, ;TPM_RETURNCMD
(POINT ptr [edx]).x,
(POINT ptr [edx]).y,
0,
hWnd,
0
test eax,eax
jz ret_error

This simply displays the popup menu. Again, nothing to new here.

	mov		iCmd, eax	


mov cmi.cbSize, sizeof CMINVOKECOMMANDINFO
mov cmi.fMask, 0
mov eax, hWnd
mov cmi.hwnd, eax

mov eax, iCmd
dec eax
and eax, 0000FFFFh
mov cmi.lpVerb, eax

mov cmi.lpParameters, 0
mov cmi.lpDirectory, 0
mov cmi.nShow, SW_SHOWNORMAL
mov cmi.dwHotKey, 0
mov cmi.hIcon, 0

mov ebx, pcm
mov ebx, [ebx]
invoke (IContextMenu ptr [ebx]).InvokeCommand, pcm, addr cmi
.IF eax < 0 ; failed
;int 3
.ENDIF

This section of code takes the chosen item from the popup menu and packs it into a CMINVOKECOMMANDINFO structure, so it can be passed back to the context menu object. Once the context menu object has been notified of the selection chosen from the user, it is told to 'invoke' the desired action associated with the item number.

	invoke	DestroyMenu, hMenu

invoke (IContextMenu ptr [ebx]).Release, pcm

This is clean up. Free the menu resource used as well as Release the COM instance created, which was the returned Context Menu object.


I hope this helps. Again from reviewing this, my guess is its not working because your probably do not have the right Object instance to get the entire train rolling. Everything else in this function is tightly written by appearances.

Best of luck.
:NaN:
Posted on 2004-03-29 20:52:11 by NaN
Posted on 2004-03-29 20:55:16 by NaN
This link talks about ways of getting the IShellFolder interface (what you need for this function to work).

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_programming/folder_info.asp

My guess is a simple test would be using the API: SHGetDesktopFolder

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shgetdesktopfolder.asp

Using this interface you should *probably* be presented with the context menu that you would see when you goto "my computer" and right click. (My guess only here)

Regards,
:NaN:
Posted on 2004-03-29 21:02:23 by NaN