LarsJ Posted October 30, 2012 Share Posted October 30, 2012 (edited) (The title of this example was originally "The Shell/Custom Favorites/Programs Menus".)This is an implementation of the Shell Favorites and Programs menus with the IShellMenu interface.The purpose of this menu system is to create a popup menu from a directory structure consisting of subfolders and internet or program links. The menu will look like the Favorites menu in Internet or Windows Explorer (as it looked when XP SP2 was released in August 2004).The IShellMenu interface can generally be used to create a menu from a directory structure. The menu items will be supplied with the same icons as the link files and they will be supplied with tooltips too. When you click a menu item the command associated with the internet or program link will be executed.The Favorites and Programs menus will create popup menus from the directory structures given by $CSIDL_FAVORITES, $CSIDL_PROGRAMS, $CSIDL_STARTMENU, $CSIDL_COMMON_PROGRAMS, $CSIDL_COMMON_STARTMENU.The Custom Favorites and Custom Programs menus can be used to create custom popup menus from custom directory structures.Note that the context (right click) menu is working in the Favorites menu.Update #4 2014-05-03: AutoIt 3.3.10This example was created under 3.3.8 and based on APIConstants.au3 and WinAPIEx.au3 by Yashied.The original example runs under 3.3.10 without any changes at all. But a lot of unused constants and functions are included.In 3.3.10 the two UDFs are divided into several smaller UDFs. This makes it much easier to just include, what is needed. This update only includes the necessary UDFs. You find the new and old zip in bottom of the post.Update #3 2012-11-06: Programs menusAdded the Programs menus from the directory structures given by $CSIDL_PROGRAMS, $CSIDL_STARTMENU, $CSIDL_COMMON_PROGRAMS, $CSIDL_COMMON_STARTMENU.To create a menu like the "All Programs" menu copy the two "Start Menu" folders (your own + "All Users") to the "Custom Programs 1" folder and overwrite the existing "Start Menu" folder. Then select the menu item "Custom Programs | Custom Programs 1".Update #2 2012-11-03: Custom Favorites menusIf you are creating an AutoIt program and want to add a custom Favorites menu with relevant internet links all you have to do is to create a directory structure, add the subfolders (optional) and links and call the ShowFavsProgsMenu() function with a path to the directory. And you will get a menu that looks like and works like the Favorites menu in Internet Explorer.You can see two custom Favorites menus in the examples.Added two small directory structures to the zip to be used for the custom Favorites menus.Fixed an error: OleInitialize() is used to initialize COM in stead of CoInitialize() (necessary to make the Copy command in the context menu work).Update #1 2012-11-01: Window procedureBecause a popup menu like the Favorites menu is modal, it's necessary to use some kind of a window procedure to catch the menu messages. When it's a popup menu it should be enough to have the window procedure running while the popup menu is displayed.In the original scripts the window procedure was created with these commands:$hNewWinProc = DllCallbackRegister( "NewWindowProc", "int", "hwnd;uint;wparam;lparam" ) ; New window procedure $hOldWinProc = _WinAPI_SetWindowLong( $hGui, $GWL_WNDPROC, DllCallbackGetPtr( $hNewWinProc ) ) ; Old window procedureThe procedure was started in the main script in the example and was running as long as the script was running.In this update the menu messages is catched with a hook procedure:$hFavMenuMsg = DllCallbackRegister( "FavMenuMsg", "long", "int;wparam;lparam" ) $hFavMenuMsgHook = _WinAPI_SetWindowsHookEx( $WH_MSGFILTER, DllCallbackGetPtr( $hFavMenuMsg ), 0, _WinAPI_GetCurrentThreadId() ) ; $WH_MSGFILTER installs a hook procedure that monitors messages generated as a ; result of an input event in a dialog box, message box, menu, or scroll bar.The procedure is started in the bottom of the ShowFavoritesMenu() function immediately after the Favorites menu is displayed on the screen, and the procedure is stopped when the menu disappears from the screen. Either because the menu is cancelled or a selection is made.(If you comment out these commands in ShellFavoritesMenu.au3 the Favorites menu will still show up. But the submenus will not be expanded if you keep the mouse steady over a submenu or use the arrow keys.)This hook procedure is much better than the original window procedure. It's much easier to integrate the Favorites menu in other programs when it isn't depending on a "global" window procedure.A "global" window procedure can also have some influence on the GUI (at least on XP, I think it's better on 7). In the original example you saw it clearly when the GUI lost focus. When the GUI got focus back the upper line of the edit box could be behind the toolbar. This is not a problem with a hook procedure only running when the Favorites menu is displayed.Added an example with a menu. Zip updated.First post 2012-10-30This is an implementation of the Favorites menu primary with the IShellMenu interface but several other interfaces are used as well.The main function:expandcollapse popupFunc ShowFavoritesMenu( $hWnd, $hMenu, $xCoord, $yCoord ) ; --- Create a menu band object and the IShellMenu interface --- Local $oIShellMenu, $pIShellMenu ; Create a menu band object and get a pointer to the IShellMenu interface CoCreateInstance( $tCLSID_MenuBand, $NULL, $CLSCTX_INPROC_SERVER, $tRIID_IShellMenu, $pIShellMenu ) $oIShellMenu = ObjCreateInterface( $pIShellMenu, $sIID_IShellMenu, $dtag_IShellMenu ) If Not IsObj( $oIShellMenu ) Then Return SetError(1,0,0) ; --- Initialize the interface --- If $oIShellMenu.Initialize( $NULL, -1, $ANCESTORDEFAULT, BitOR( $SMINIT_TOPLEVEL, $SMINIT_VERTICAL ) ) <> $S_OK Then Return SetError(2,0,0) ; --- Specify the folder for the menu band to browse --- ; Get a pointer to the IShellFolder interface for the desktop Local $pIShellFolder = $NULL, $oIShellFolderDesktop, $pIShellFolderDesktop, $pidlRel SHGetDesktopFolder( $pIShellFolderDesktop ) SHGetSpecialFolderLocation( $NULL, $CSIDL_FAVORITES, $pidlRel ) $oIShellFolderDesktop = ObjCreateInterface( $pIShellFolderDesktop, $sIID_IShellFolder, $dtag_IShellFolder ) $oIShellFolderDesktop.BindToObject( $pidlRel, $NULL, $tRIID_IShellFolder, $pIShellFolder ) If $pIShellFolder = $NULL Then Return SetError(3,0,0) ; Get the registry key with the "Order" value of the Favorites folder Local $hRegOrder = _WinAPI_RegOpenKey( $HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites", $KEY_READ ) If $hRegOrder = 0 Then Return SetError(4,0,0) ; Specify the folder for the menu band to browse If $oIShellMenu.SetShellFolder( $pIShellFolder, $pidlRel, $hRegOrder, BitOR( $SMSET_BOTTOM, $SMSET_USEBKICONEXTRACTION ) ) <> $S_OK Then Return SetError(5,0,0) _WinAPI_CoTaskMemFree( $pidlRel ) _WinAPI_RegCloseKey( $hRegOrder ) ; --- Append a static menu to the menu band --- If $oIShellMenu.SetMenu( $hMenu, $hWnd, $SMSET_TOP ) <> $S_OK Then Return SetError(6,0,0) ; --- Get access to IMenuPopup, IDeskBar and IDeskBand interfaces --- Local $pIMenuPopup, $pIDeskBar, $pIDeskBand ; The IMenuPopup interface If $pIShellMenu Then If $oIShellMenu.QueryInterface( $tRIID_IMenuPopup, $pIMenuPopup ) <> $S_OK Then Return SetError(7,0,0) EndIf ; The IDeskBar interface If $pIMenuPopup Then Local $oIMenuPopup = ObjCreateInterface( $pIMenuPopup, $sIID_IMenuPopup, $dtag_IMenuPopup ) If $oIMenuPopup.QueryInterface( $tRIID_IDeskBar, $pIDeskBar ) <> $S_OK Then Return SetError(8,0,0) EndIf ; The IDeskBand interface If $pIDeskBar Then Local $oIDeskBar = ObjCreateInterface( $pIDeskBar, $sIID_IDeskBar, $dtag_IDeskBar ) If $oIDeskBar.QueryInterface( $tRIID_IDeskBand, $pIDeskBand ) <> $S_OK Then Return SetError(9,0,0) EndIf ; --- Create a menu desk bar object and the IMenuPopup interface --- Local $oIUnknown, $pIUnknown, $oIMenuPopup, $pIMenuPopup ; Create a menu desk bar object and get a pointer to the IUnknown interface CoCreateInstance( $tCLSID_MenuDeskBar, $NULL, $CLSCTX_INPROC_SERVER, $tRIID_IUnknown, $pIUnknown ) $oIUnknown = ObjCreateInterface( $pIUnknown, $sIID_IUnknown, $dtag_IUnknown ) ; Create the IMenuPopup interface $oIUnknown.QueryInterface( $tRIID_IMenuPopup, $pIMenuPopup ) $oIMenuPopup = ObjCreateInterface( $pIMenuPopup, $sIID_IMenuPopup, $dtag_IMenuPopup ) If Not IsObj( $oIMenuPopup ) Then Return SetError(10,0,0) ; --- Create a menu band site object and the IBandSite interface --- Local $oIBandSite, $pIBandSite ; Create a menu band site object and get a pointer to the IBandSite interface CoCreateInstance( $tCLSID_MenuBandSite, $NULL, $CLSCTX_INPROC_SERVER, $tRIID_IBandSite, $pIBandSite ) $oIBandSite = ObjCreateInterface( $pIBandSite, $sIID_IBandSite, $dtag_IBandSite ) If Not IsObj( $oIBandSite ) Then Return SetError(11,0,0) ; --- Set the band site object as client for the desk bar object --- If $oIMenuPopup.SetClient( $pIBandSite ) <> $S_OK Then Return SetError(12,0,0) ; --- Add the desk band object to the band site object --- If $oIBandSite.AddBand( $pIDeskBand ) <> $S_OK Then Return SetError(13,0,0) ; --- Show the Favorites menu --- Local $tPOINT = DllStructCreate( $tagPOINT ) DllStructSetData( $tPOINT, "X", $xCoord ) DllStructSetData( $tPOINT, "Y", $yCoord ) Local $tRECT = DllStructCreate( $tagRECT ) DllStructSetData( $tRECT, "Left", $xCoord ) DllStructSetData( $tRECT, "Top", $yCoord+1 ) DllStructSetData( $tRECT, "Right", $xCoord ) DllStructSetData( $tRECT, "Bottom", $yCoord+1 ) $oIMenuPopup.Popup( $tPOINT, $tRECT, $MPPF_ALIGN_RIGHT ) ; --- Create the IMenuBand interface --- Local $oIDeskBand $oIDeskBand = ObjCreateInterface( $pIDeskBand, $sIID_IDeskBand, $dtag_IDeskBand ) $oIDeskBand.QueryInterface( $tRIID_IMenuBand, $pIMenuBand ) $oIMenuBand = ObjCreateInterface( $pIMenuBand, $sIID_IMenuBand, $dtag_IMenuBand ) If Not IsObj( $oIMenuBand ) Then Return SetError(14,0,0) ; $oIMenuBand and $pIMenuBand are global variables ; $oIMenuBand is used to handle the messages from the Favorites menu in the function below ; $pIMenuBand is used to test if the Favorites menu is open ($pIMenuBand <> $NULL) Return 0 EndFuncExampleThe zip contains the example as you can see in the picture. There are two versions of the example: A version based on a toolbar (ExShellFavsProgsMenus.au3), and a version based on a menu bar (ExShellFavsProgsMenus2.au3). The purpose of the text box is just to have something to put in the window.The zip contains also the ShellFavsProgsMenus.au3 UDF.This zip contains the original scripts for 3.3.8. You need APIConstants.au3 and WinAPIEx.au3 by Yashied. The UDFs are not included in the zip. The zip can be opened with 7-Zip.ShellFavsProgsMenus.zipThis zip contains the updated scripts for 3.3.10. Only a matter of UDFs. These scripts will not run under 3.3.8.TheFavoritesMenu.7zTestet on XP 32 bit and Win 7 32/64 bit. Edited May 3, 2014 by LarsJ SouzaRM, JScript, mesale0077 and 1 other 3 1 Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
JScript Posted October 30, 2012 Share Posted October 30, 2012 (edited) Very nice, thanks! But why use toolbar instead of menu? Edit: 5 * from me!!! JS Edited October 30, 2012 by JScript http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!) Somewhere Out ThereJames Ingram Download Dropbox - Simplify your life!Your virtual HD wherever you go, anywhere! Link to comment Share on other sites More sharing options...
LarsJ Posted November 1, 2012 Author Share Posted November 1, 2012 (edited) JScript, Added an example with a menu. Thank you for the stars. The "global" window procedure that runs all the time is replaced with a hook procedure that only runs when the Favorites menu is displayed. Lars. Edited November 1, 2012 by LarsJ Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
JScript Posted November 1, 2012 Share Posted November 1, 2012 Now it's much better, thanks! JS http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!) Somewhere Out ThereJames Ingram Download Dropbox - Simplify your life!Your virtual HD wherever you go, anywhere! Link to comment Share on other sites More sharing options...
LarsJ Posted November 3, 2012 Author Share Posted November 3, 2012 Added support for custom Favorites menus. Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted November 6, 2012 Author Share Posted November 6, 2012 Added support for Programs menus. Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
Bluesmaster Posted November 21, 2013 Share Posted November 21, 2013 This is fantastic , I searched for such a menu for years and and always planned to programm my own I have some questions for a bit more of control: - Is it possible to better control the menu, like selecting items programmaticly and determine the current path ( especially when entering submenus... ) - It it possible to add own entrys directly in such a menu ( for example a recent folders entry or favourites ) Â Thanks in advance Bluesmaster My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
LarsJ Posted November 22, 2013 Author Share Posted November 22, 2013 Bluesmaster, The purpose of this menu system is to create a popup menu from a directory structure consisting of subfolders and internet or program links. The menu will look like the Favorites menu in Internet or Windows Explorer (as they looked when XP SP2 was released in August 2004).To control the menu you need menu handles. But menu handles are generated internally and you get new handles every time the menu is shown. So there is no easy way to control the menu.If you add new links and subfolders to the directory structure they will be shown as new menu items and submenus. Because the entire directory structure is read each time the menu is shown you can do it dynamically.This menu cannot replace an entire menu system. But it can be used as a part of a menu system to create a menu similar to the Favorites menu or Programs menu.I'm using the code in this OpenGL example to create a Links menu with links to information.Lars. Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
Bluesmaster Posted November 22, 2013 Share Posted November 22, 2013 Hello Lars, I am glad you care for this after one year has passed. I am planning to transform this into a more general menu for moving and browsing files fast and efficent. Just started, and its quite promising. Main hurdle is to know, the path corresponding to the object currently selected by the user. Figured out, that the menu is represented by a "toolbar32" but I failed to get the handles . And even if I could get them, the other task is to get the full path of the item and not just its name in one of the submenus. Here some attempts to get infos from the menu ( all failed ) local $hPopupWin $oIMenuPopup.GetWindow( $hPopupWin ) or $oIShellMenu.GetShellFolder( $hMenu, $hWnd, $SMSET_TOP ) or $hToolbar = ControlGetHandle( WinGetHandle( "[CLASS:BaseBar" ) , "" , "[CLASS:ToolbarWindow32; INSTANCE:1]" ) Can you please give me some small tips I really got stuck for a day now.  Here is a first snippet showing the direction of my attempt ( please ignore the missing error-handling for now )ContextBrowser.au3 My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
LarsJ Posted November 22, 2013 Author Share Posted November 22, 2013 Bluesmaster, I'm pretty sure you can get the path of the selected item if you implement the IShellMenuCallback interface and look for SMC_SFSELECTITEM notifications. From the documentation of SMC_SFSELECTITEM notifications: "The user has selected the item specified by the accompanying SMDATA structure." From this SMDATA structure you can get all the information you need.I have not looked at your code yet, but the project seems to be quite interesting.Regards Lars. Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
Bluesmaster Posted November 23, 2013 Share Posted November 23, 2013 Thanks for your answer. I will try. But I really struggle with those IInterfaces... I never really understood the difference to the "objectCreate"-method and it seems nobody can really explain it to me. I can get the "$IID_IShellMenuCallback =Â "{4CA300A1-9B8D-11d1-8B22-00C04FD918D0}"Â but how to get those mysterious vTables. For me it seems like google fortune and I had no in this case. There seem to be professional solutions like TypeLibInspector ( '?do=embed' frameborder='0' data-embedContent> title=""> ) but I never get that to run, and my question was never answerd. Where do you get your vTables and clsids from? Â regards Blues My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
trancexx Posted November 23, 2013 Share Posted November 23, 2013 (edited) Microsoft provides info. It's documented on MSDN. If web page lacks info about v-table order or identifiers it wouldn't miss to tell you in which file those definitions are. The files are part of Microsoft SDKs. In case you don't program for Windows and don't use Visual Studio and don't have SDK then you can allways google, for example IShellMenuCallback ReactOS or maybe IShellMenuCallback Wine and get definition from there. Former will very quickly lead you to http://doxygen.reactos.org/d4/d3f/shobjidl_8idl_source.html where you can see definition for your interface and list of functions in, of course, v-table order together with parameters definitions. Edited November 23, 2013 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
LarsJ Posted November 24, 2013 Author Share Posted November 24, 2013 (edited) Bluesmaster, Here is an implementation of IShellMenuCallback. It's not completely trivial. It'll write the paths in Scite console.Download IShellMenuCallback.au3 below.Edit ShellFavsProgsMenus.au3 from the the zip in the first post.Include IShellMenuCallback.au3:; Dynamic Link Libraries Global Const $dllOle32 = DllOpen( "ole32.dll" ) Global Const $dllShell32 = DllOpen( "shell32.dll" ) Global Const $dllUser32 = DllOpen( "user32.dll" ) #include "IShellMenuCallback.au3" ; <<<<<<<<<<<<<<<<Comment out this line:;Global Const $NULL = 0x0000Comment out this section:#cs ; IShellFolder Interface Global Const $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" Global Const $tRIID_IShellFolder = CLSIDFromString( $sIID_IShellFolder ) Global Const $dtag_IShellFolder = _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;struct*;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;struct*;ptr*);" & _ "GetAttributesOf hresult(uint;struct*;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;struct*;struct*;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;struct*);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" #ceComment out a line and add a line:;If $oIShellMenu.Initialize( $NULL, -1, $ANCESTORDEFAULT, BitOR( $SMINIT_TOPLEVEL, $SMINIT_VERTICAL ) ) <> $S_OK Then Return SetError(2,0,0) If $oIShellMenu.Initialize( $pIShellMenuCallback, -1, $ANCESTORDEFAULT, BitOR( $SMINIT_TOPLEVEL, $SMINIT_VERTICAL ) ) <> $S_OK Then Return SetError(2,0,0)Open and run one of the examples in Scite and you'll see the paths in the console.V-table: I get the information from the same sources as trancexx.Regards Lars.IShellMenuCallback.au3Edit: See next post. Edited November 25, 2013 by LarsJ Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted November 25, 2013 Author Share Posted November 25, 2013 You can replace oIShellMenuCallback_CallbackSM in IShellMenuCallback.au3 with this:Func oIShellMenuCallback_CallbackSM( $pSelf, $psmd, $uMsg, $wParam, $lParam ) ;ConsoleWrite( "oIShellMenuCallback_CallbackSM" & @CRLF ) Switch $uMsg Case $SMC_SFSELECTITEM Local $tSMDATA = DllStructCreate( $tagSMDATA, $psmd ), $sPath Local $pPidl = ILClone( DllStructGetData( $tSMDATA, "pidlFolder" ) ) $pPidl = ILCombine( $pPidl, DllStructGetData( $tSMDATA, "pidlItem" ) ) SHGetPathFromIDList( $pPidl, $sPath ) _WinAPI_CoTaskMemFree( $pPidl ) ConsoleWrite( $sPath & @CRLF ) Return $S_FALSE Case Else Return $S_FALSE EndSwitch EndFuncAdd these two functions to the bottom of the file:Func ILClone( $pidl ) Local $aRet = DllCall( $dllShell32, "ptr", "ILClone", "ptr", $pidl ) If @error Then Return SetError(1, 0, 0) Return $aRet[0] EndFunc Func ILCombine( $pidlAbs, $pidlRel ) Local $aRet = DllCall( $dllShell32, "ptr", "ILCombine", "ptr", $pidlAbs, "ptr", $pidlRel ) If @error Then Return SetError(1, 0, 0) Return $aRet[0] EndFuncThen you can delete the following:Global Const $dllShlwapi = DllOpen( "shlwapi.dll" ) Global $iIShellFolder = 0, $apIShellFolder[1], $aoIShellFolder[1] Func StrRetToBuf( $pSTRRET, $pidl, ByRef $sBuf, $iBuf = 512 ) Local $aRet = DllCall( $dllShlwapi, "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sBuf, "uint", $iBuf ) If @error Then Return SetError(1, 0, 0) $sBuf = $aRet[3] Return $aRet[0] EndFunc Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
Bluesmaster Posted November 30, 2013 Share Posted November 30, 2013 (edited) Hello Lars, Sorry for my late respose. Its very hard to find time at the moment. Your code is amazing. And it works Honestly I would never had been able to implement this. I will need some time to develop the full context-menu-explorer. I will post the result here. And again: Thank you so much Bluesmaster Edited November 30, 2013 by Bluesmaster My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
Bluesmaster Posted December 8, 2013 Share Posted December 8, 2013 (edited) Hi Lars, I found some time to continue working on the "context-menu-explorer" based on your "ShowFavsProgsMenu". And...I am desperate. My purpose is to merge 2 of those menus in 1 menu to augment the first menu with some "most recent folders" ... and so on. I build an example that should merge "c:" and "c:users" but they popup separatly, or alone or do not even popup whatever I try. The code is extra unreadable  because I condensed it a lot for overview reasons. But its more a question of basic understanding. In Point 1 ( line 90 ) I create a menu. In Point 2 ( line 120 ) I create a second one...I could write a thousand words, I think you know what I mean. Can you please give me some small advice again? expandcollapse popup#include-once #include <GuiMenu.au3> #include "APIConstants.au3" #include "WinAPIEx.au3" HotKeySet( "{ESC}" , "_exit" ) Func _exit() Exit EndFunc ShowFavsProgsMenu( "C:\" ) While 1 Sleep( 1000 ) WEnd Func ShowFavsProgsMenu( $targetFolder , $xCoord = "" , $yCoord = "" , $pasteAndLeaveMode = 0 , $nFavouritesToShow = 1 ) ; 0 - PREPARE - ( define constants and vTables ) #region PREPARE Global $NULL = 0x0000, $S_FALSE = 0x00000001, $MAX_PATH = 260, $iIShellFolder = 0, $apIShellFolder[1], $aoIShellFolder[1] Global $hFavsProgsMenu , $oIMenuBand, $pIMenuBand = 0x0000, $S_OK = 0, $hFavsProgsMenuMsg = 0x0000, $tFavsProgsMenuMsg, $hFavsProgsMenuMsgHook, $idFavsProgsMenuMsgUnHook = 0 Global Const $dllOle32 = DllOpen( "ole32.dll" ) DllCall( $dllOle32 , "long", "OleInitialize", "ptr", 0) Global $tagMSG = "hwnd hwnd;uint message;wparam wParam;lparam lParam;dword time;int X;int Y" $IID_IShellMenuCallback = "{4CA300A1-9B8D-11d1-8B22-00C04FD918D0}" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; CLSID_MenuBand Global Const $tCLSID_MenuBand = $tCLSID Global Const $sCLSID_MenuBand = "{5B4DAE26-B807-11D0-9815-00C04FD91972}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sCLSID_MenuBand, "ptr", DllStructGetPtr($tCLSID)) $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; CLSID_MenuDeskBar Global Const $sCLSID_MenuDeskBar = "{ECD4FC4F-521C-11D0-B792-00A0C90312E1}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sCLSID_MenuDeskBar, "ptr", DllStructGetPtr($tCLSID)) Global Const $tCLSID_MenuDeskBar = $tCLSID $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; CLSID_MenuBandSite Global Const $sCLSID_MenuBandSite = "{E13EF4E4-D2F2-11D0-9816-00C04FD91972}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sCLSID_MenuBandSite, "ptr", DllStructGetPtr($tCLSID)) Global Const $tCLSID_MenuBandSite = $tCLSID $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IShellMenu Global Const $sIID_IShellMenu = "{EE1F7637-E138-11d1-8379-00C04FD918D0}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IShellMenu, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IShellMenu = $tCLSID Global Const $dtag_IShellMenu = "Initialize hresult(ptr;uint;uint;dword);GetMenuInfo hresult(ptr*;uint*;uint*;dword*);SetShellFolder hresult(ptr;ptr;handle;dword);GetShellFolder hresult(ptr*;ptr*;struct*;ptr*);" & _ "Setmenu hresult(handle;hwnd;dword);GetMenu hresult(handle*;hwnd*;dword*);InvalidateItem hresult(ptr;dword);GetState hresult(ptr);SetMenuToolbar hresult(ptr*;dword);" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IShellFolder Global Const $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IShellFolder, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IShellFolder = $tCLSID Global Const $dtag_IShellFolder = "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);EnumObjects hresult(hwnd;dword;ptr*);BindToObject hresult(ptr;ptr;struct*;ptr*);BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);CreateViewObject hresult(hwnd;struct*;ptr*);GetAttributesOf hresult(uint;struct*;ulong*);GetUIObjectOf hresult(hwnd;uint;struct*;struct*;uint*;ptr*);GetDisplayNameOf hresult(ptr;uint;struct*);SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IMenuPopup Global Const $sIID_IMenuPopup = "{D1E7AFEB-6A2E-11d0-8C78-00C04FD918B4}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IMenuPopup, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IMenuPopup = $tCLSID Global Const $dtag_IMenuPopup = "GetWindow hresult(hwnd);ContextSensitiveHelp hresult(bool);SetClient hresult(ptr);GetClient hresult(ptr*);OnPosRectChangeDB hresult(struct*);Popup hresult(struct*;struct*;dword);OnSelect hresult(dword);SetSubMenu hresult(ptr;bool);" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IDeskBar Global Const $sIID_IDeskBar = "{EB0FE173-1A3A-11D0-89B3-00A0C90A90AC}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IDeskBar, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IDeskBar = $tCLSID Global Const $dtag_IDeskBar = "SetClient hresult(ptr);GetClient hresult(ptr*);OnPosRectChangeDB hresult(struct*);" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IDeskBand Global Const $sIID_IDeskBand = "{EB0FE172-1A3A-11D0-89B3-00A0C90A90AC}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IDeskBand, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IDeskBand = $tCLSID Global Const $dtag_IDeskBand ="GetBandInfo hresult(dword;dword;struct*);" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IUnknown Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IUnknown, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IUnknown = $tCLSID Global Const $dtag_IUnknown = "QueryInterface hresult(struct*;ptr*);AddRef ulong();Release ulong();" $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IBandSite Global Const $sIID_IBandSite = "{4CF504B0-DE96-11D0-8B3F-00A0C911E8E5}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IBandSite, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IBandSite = $tCLSID Global Const $dtag_IBandSite = "AddBand hresult(ptr);EnumBands hresult(uint;dword*);QueryBand hresult(dword;ptr*;dword*;wstr;int);SetBandState hresult(dword;dword;dword);RemoveBand hresult(dword);GetBandObject hresult(dword;struct*;ptr*);SetBandSiteInfo hresult(ptr);GetBandSiteInfo hresult(ptr*);" ; BANDSITEINFO* pbsinfo $tCLSID = DllStructCreate("dword;word;word;byte[8]") ; IMenuBand Global Const $sIID_IMenuBand = "{568804CD-CBD7-11d0-9816-00C04FD91972}" DllCall( $dllOle32 , "long", "CLSIDFromString", "wstr", $sIID_IMenuBand, "ptr", DllStructGetPtr($tCLSID)) Global Const $tRIID_IMenuBand = $tCLSID Global Const $dtag_IMenuBand = "IsMenuMessage hresult(struct*);TranslateMenuMessage hresult(struct*;lresult*);" #endregion PREPARE ; 1 - MENU 1 ( "c:\" ) Local $oMainFolderMenu, $pIShellMenu , $CLSCTX_INPROC_SERVER = 0x1 $pIShellMenu = DllCall( $dllOle32, "long_ptr", "CoCreateInstance", "ptr", DllStructGetPtr($tCLSID_MenuBand), "ptr", $NULL, "dword", $CLSCTX_INPROC_SERVER, "ptr", DllStructGetPtr($tRIID_IShellMenu), "ptr*", 0 ) $oMainFolderMenu = ObjCreateInterface( $pIShellMenu[5] , $sIID_IShellMenu, $dtag_IShellMenu ) ;~ $SMINIT_RESTRICT_DRAGDROP = 0x00000002 ; Don't allow Drag and Drop | $SMINIT_TOPLEVEL = 0x00000004 ; This is the top band. | $SMSET_DONTOWN = 0x00000001 ; The Menuband doesn't own the non-ref counted object Local $SMINIT_VERTICAL = 0x10000000, $ANCESTORDEFAULT = 0xFFFFFFFF, $SMSET_USEBKICONEXTRACTION = 0x00000008 , $SMSET_TOP = 0x10000000 ,$SMINIT_TOPLEVEL = 0x00000004 ,$SMSET_BOTTOM = 0x20000000 ; Bias this namespace to the bottom of the menu $oMainFolderMenu.Initialize( ObjCreateInterfaceEx( "oIShellMenuCallback_", "CallbackSM hresult(ptr;uint;wparam;lparam);", True ) , -1, $ANCESTORDEFAULT, BitOR( $SMINIT_TOPLEVEL, $SMINIT_VERTICAL ) ) ; Callback installieren $r = DllCall( "shell32.dll" , "uint", "SHILCreateFromPath", "wstr", $targetFolder , "ptr*", 0, "dword*", 0 ) ; set Folder $oMainFolderMenu.SetShellFolder( $NULL , $r[2] , $NULL , BitOR( $SMSET_BOTTOM, $SMSET_USEBKICONEXTRACTION ) ) ; IMenuPopup >> IDeskBar >> IDeskBand >> IShellMenu ) Local $pIMenuPopup, $pIDeskBar, $pIDeskBand $oMainFolderMenu.QueryInterface( $tRIID_IMenuPopup, $pIMenuPopup ) ; IShellMenu >> ... >> IMenuPopup ??? $oIMenuPopup = ObjCreateInterface( $pIMenuPopup, $sIID_IMenuPopup, $dtag_IMenuPopup ) $oIMenuPopup.QueryInterface( $tRIID_IDeskBar, $pIDeskBar ) $oIDeskBar = ObjCreateInterface( $pIDeskBar, $sIID_IDeskBar, $dtag_IDeskBar ) $oIDeskBar.QueryInterface( $tRIID_IDeskBand, $pIDeskBand ) ; IBandSite >> IDeskbar $pIUnknown = DllCall( $dllOle32, "long_ptr", "CoCreateInstance", "ptr", DllStructGetPtr($tCLSID_MenuDeskBar), "ptr", $NULL, "dword", $CLSCTX_INPROC_SERVER, "ptr", DllStructGetPtr($tRIID_IUnknown), "ptr*", 0 ) $oIUnknown = ObjCreateInterface( $pIUnknown[5] , $sIID_IUnknown, $dtag_IUnknown ) $oIUnknown.QueryInterface( $tRIID_IMenuPopup, $pIMenuPopup ) $oIMenuPopup = ObjCreateInterface( $pIMenuPopup, $sIID_IMenuPopup, $dtag_IMenuPopup ) $pIBandSite = DllCall( $dllOle32, "long_ptr", "CoCreateInstance", "ptr", DllStructGetPtr($tCLSID_MenuBandSite), "ptr", $NULL, "dword", $CLSCTX_INPROC_SERVER, "ptr", DllStructGetPtr($tRIID_IBandSite), "ptr*", 0 ) $oIBandSite = ObjCreateInterface( $pIBandSite[5] , $sIID_IBandSite, $dtag_IBandSite ) $oIMenuPopup.SetClient( $pIBandSite[5] ) ; IBandSite >> IMenuPopup $oIBandSite.AddBand( $pIDeskBand ) ; IDeskBand >> IBandSite ; 2 - MENU 2 ( "C:\Users" ) Local $oAppendixMenu, $pIShellMenu2 , $CLSCTX_INPROC_SERVER = 0x1 $pIShellMenu2 = DllCall( $dllOle32, "long_ptr", "CoCreateInstance", "ptr", DllStructGetPtr($tCLSID_MenuBand), "ptr", $NULL, "dword", $CLSCTX_INPROC_SERVER, "ptr", DllStructGetPtr($tRIID_IShellMenu), "ptr*", 0 ) $oAppendixMenu = ObjCreateInterface( $pIShellMenu2[5] , $sIID_IShellMenu, $dtag_IShellMenu ) ;~ $SMINIT_RESTRICT_DRAGDROP = 0x00000002 ; Don't allow Drag and Drop | $SMINIT_TOPLEVEL = 0x00000004 ; This is the top band. | $SMSET_DONTOWN = 0x00000001 ; The Menuband doesn't own the non-ref counted object Local $SMINIT_VERTICAL = 0x10000000, $ANCESTORDEFAULT = 0xFFFFFFFF, $SMSET_USEBKICONEXTRACTION = 0x00000008 , $SMSET_TOP = 0x10000000 ,$SMINIT_TOPLEVEL = 0x00000004 ,$SMSET_BOTTOM = 0x20000000 ; Bias this namespace to the bottom of the menu $oAppendixMenu.Initialize( ObjCreateInterfaceEx( "oIShellMenuCallback2_", "CallbackSM hresult(ptr;uint;wparam;lparam);", True ) , -1, $ANCESTORDEFAULT, BitOR( $SMINIT_TOPLEVEL, $SMINIT_VERTICAL ) ) ; Callback installieren $r = DllCall( "shell32.dll" , "uint", "SHILCreateFromPath", "wstr", "C:\Users" , "ptr*", 0, "dword*", 0 ) ; set Folder $oAppendixMenu.SetShellFolder( $NULL , $r[2] , $NULL , BitOR( $SMSET_BOTTOM, $SMSET_USEBKICONEXTRACTION ) ) ; IMenuPopup >> IDeskBar >> IDeskBand >> IShellMenu ) Local $pIMenuPopup2, $pIDeskBar2, $pIDeskBand2 $oAppendixMenu.QueryInterface( $tRIID_IMenuPopup, $pIMenuPopup2 ) $oIMenuPopup2 = ObjCreateInterface( $pIMenuPopup2, $sIID_IMenuPopup, $dtag_IMenuPopup ) $oIMenuPopup2.QueryInterface( $tRIID_IDeskBar, $pIDeskBar2 ) $oIDeskBar2 = ObjCreateInterface( $pIDeskBar2, $sIID_IDeskBar, $dtag_IDeskBar ) $oIDeskBar2.QueryInterface( $tRIID_IDeskBand, $pIDeskBand2 ) $pIUnknown2 = DllCall( $dllOle32, "long_ptr", "CoCreateInstance", "ptr", DllStructGetPtr($tCLSID_MenuDeskBar), "ptr", $NULL, "dword", $CLSCTX_INPROC_SERVER, "ptr", DllStructGetPtr($tRIID_IUnknown), "ptr*", 0 ) $oIUnknown2 = ObjCreateInterface( $pIUnknown2[5] , $sIID_IUnknown, $dtag_IUnknown ) $oIUnknown2.QueryInterface( $tRIID_IMenuPopup, $pIMenuPopup2 ) $oIMenuPopup2 = ObjCreateInterface( $pIMenuPopup2, $sIID_IMenuPopup, $dtag_IMenuPopup ) $pIBandSite2 = DllCall( $dllOle32, "long_ptr", "CoCreateInstance", "ptr", DllStructGetPtr($tCLSID_MenuBandSite), "ptr", $NULL, "dword", $CLSCTX_INPROC_SERVER, "ptr", DllStructGetPtr($tRIID_IBandSite), "ptr*", 0 ) $oIBandSite2 = ObjCreateInterface( $pIBandSite2[5] , $sIID_IBandSite, $dtag_IBandSite ) $oIMenuPopup2.SetClient( $pIBandSite2[5] ) ; IBandSite >> IMenuPopup $oIBandSite2.AddBand( $pIDeskBand2 ) ; IDeskBand >> IBandSite ;~ $oIBandSite.AddBand( $pIDeskBand2 ) ; IDeskBand >> IBandSite ; 3 - APPEND - ( ...to exsiting menu = optional ) $hWnd = GUICreate( "" ) $hMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem( $hMenu , 0 , "&custom command 2" , 55 ) _GUICtrlMenu_InsertMenuItem( $hMenu , 0 , "&custom command 1" , 55 ) _GUICtrlMenu_AddMenuItem( $hMenu , "" ) ; Separator _GUICtrlMenu_AddMenuItem( $hMenu , "" ) $oMainFolderMenu.SetMenu( $hMenu, $hWnd, $SMSET_TOP ) $oAppendixMenu.SetMenu( $hMenu, $hWnd, $SMSET_TOP ) ; 4 - SHOW - ( position ) ; Flags > IMenuPopup::Popup method Global Enum _ $MPPF_SETFOCUS = 0x1, _ ; The menu should have focus when it appears. $MPPF_INITIALSELECT = 0x2, _ ; The first item in the menu should be selected. $MPPF_NOANIMATE = 0x4, _ ; Do not animate this show. $MPPF_KEYBOARD = 0x10, _ ; The menu is activated by the keyboard. $MPPF_REPOSITION = 0x20, _ ; Reposition the displayed bar. $MPPF_FORCEZORDER = 0x40, _ ; The menu bar should ignore submenu positions. $MPPF_FINALSELECT = 0x80, _ ; The last item in the menu should be selected. $MPPF_TOP = 0x20000000, _ ; Display the pop-up menu above the point specified in ppt. $MPPF_LEFT = 0x40000000, _ ; Display the pop-up menu to the left of the point specified in ppt. $MPPF_RIGHT = 0x60000000, _ ; Display the pop-up menu to the right of the point specified in ppt. $MPPF_BOTTOM = 0x80000000, _ ; Display the pop-up menu below the point specified in ppt. $MPPF_POS_MASK = 0xE0000000, _ ; Mask for position values MPPF_TOP, MPPF_LEFT, and MPPF_RIGHT. $MPPF_ALIGN_LEFT = 0x2000000, _ ; Default alignment. $MPPF_ALIGN_RIGHT = 0x4000000 ; The pop-up menu should be aligned to the right of the excluded rectangle specified by prcExclude. if $xCoord = "" Then ; falls keine Position gegeben > am Mauszeiger erstellen $xCoord = MouseGetPos( 0 ) $yCoord = MouseGetPos( 1 ) EndIf Local $tPOINT = DllStructCreate( $tagPOINT ) DllStructSetData( $tPOINT, "X", $xCoord ) DllStructSetData( $tPOINT, "Y", $yCoord ) Local $tRECT = DllStructCreate( $tagRECT ) DllStructSetData( $tRECT, "Left", $xCoord ) DllStructSetData( $tRECT, "Top", $yCoord+1 ) DllStructSetData( $tRECT, "Right", $xCoord ) DllStructSetData( $tRECT, "Bottom", $yCoord+1 ) $oIMenuPopup.Popup( $tPOINT, $tRECT, $MPPF_ALIGN_RIGHT ) $oIMenuPopup2.Popup( $tPOINT, $tRECT, $MPPF_ALIGN_RIGHT ) ;~ $oIMenuPopup2.SetSubMenu( $oIMenuPopup , 1 ) ; 5 - MESSAGE HOOK - ( messages to expand the submenus and other user interaction ) Local $oIDeskBand $oIDeskBand = ObjCreateInterface( $pIDeskBand, $sIID_IDeskBand, $dtag_IDeskBand ) $oIDeskBand.QueryInterface( $tRIID_IMenuBand, $pIMenuBand ) $oIMenuBand = ObjCreateInterface( $pIMenuBand, $sIID_IMenuBand, $dtag_IMenuBand ) If $idFavsProgsMenuMsgUnHook = 0 Then $idFavsProgsMenuMsgUnHook = GUICtrlCreateDummy() $hFavsProgsMenuMsg = DllCallbackRegister( "FavsProgsMenuMsg", "long", "int;wparam;lparam" ) $hFavsProgsMenuMsgHook = _WinAPI_SetWindowsHookEx( $WH_MSGFILTER, DllCallbackGetPtr( $hFavsProgsMenuMsg ), 0, _WinAPI_GetCurrentThreadId() ) Return 0 EndFunc Func FavsProgsMenuMsg( $nCode, $wParam, $lParam ) ;~ If $nCode <= 0 Then Return ;~ ConsoleWrite( $nCode & @CRLF ) If $pIMenuBand Then ; Falls das Menü noch existiert > Windowmessages auswerten $tFavsProgsMenuMsg = DllStructCreate( $tagMSG, $lParam ) $msg = DllStructGetData( $tFavsProgsMenuMsg, "message" ) if $msg = $WM_NULL OR $msg = $WM_PAINT OR $msg = $WM_TIMER OR $msg = 0x0118 OR ( $msg > $WM_MOUSEFIRST AND $msg < $WM_XBUTTONDBLCLK ) Then Return False ; 0x0118 ~ WM_SYSTIMER ; TRANSLATE MESSAGE ( menü auffordern, die Nachricht auszuwerten ) $i = $oIMenuBand.IsMenuMessage( $tFavsProgsMenuMsg ) If $i >= 0 Then $tLRESULT = DllStructCreate( "lresult" ) If $oIMenuBand.TranslateMenuMessage( $tFavsProgsMenuMsg, $tLRESULT ) = $S_OK Then Return True ElseIf $i = $E_FAIL Then ; The menu has exited the menu mode and can be destroyed $pIMenuBand = $NULL Return False EndIf Return False Else; Falls das Menü nicht mehr existiert If $hFavsProgsMenuMsg <> $NULL Then _GUICtrlMenu_DestroyMenu( $hFavsProgsMenu ) _WinAPI_UnhookWindowsHookEx( $hFavsProgsMenuMsgHook ) ;~ DllCallbackFree( $hFavsProgsMenuMsg ) ; Aufhänger, grund unbekannt EndIf Return False EndIf EndFunc Func ObjCreateInterfaceEx( $sFunctionPrefix, $dtag_Interface, $fNoUnknown = False ) ; ObjCreateInterfaceEx creates custom object defined with "dtag" interface description string. ; Main purpose of this function is to create custom objects that serve as event handlers for other objects. ; Registered callback functions (defined methods) are left for AutoIt to free at its convenience on exit. ; Original is _AutoItObject_ObjectFromDtag in AutoItObject.au3 by the AutoItObject-Team ; (http://www.autoitscript.com/forum/index.php?showtopic=110379, v1.2.8.3 in post 302) ; Modified by Ward (http://www.autoitscript.com/forum/index.php?showtopic=138372) If $fNoUnknown Then $dtag_Interface = "QueryInterface hresult(ptr;ptr*);AddRef ulong();Release ulong();" & $dtag_Interface ; Inherits from IUnknown Local $sMethods = StringTrimRight(StringReplace(StringRegExpReplace($dtag_Interface, "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF), 1) If $sMethods = $dtag_Interface Then $sMethods = StringTrimRight(StringReplace(StringRegExpReplace($dtag_Interface, "\h*(\w+)\h*(;|;*\z)", "$1\|" & @LF), ";" & @LF, @LF), 1) $sMethods = StringReplace(StringReplace(StringReplace(StringReplace($sMethods, "object", "idispatch", 0, 1), "variant*", "ptr"), "hresult", "long"), "bstr", "ptr") Local $aMethods = StringSplit($sMethods, @LF, 3) Local $iUbound = UBound($aMethods) Local $sMethod, $aSplit, $sNamePart, $aTagPart, $sTagPart, $sRet, $sParams, $hCallback Local $PtrSize = DllStructGetSize(DllStructCreate("ptr", 1)) Local $AllocSize = $PtrSize * ($iUbound + 1) Local $AllocPtr = _WinAPI_CoTaskMemAlloc( $AllocSize ) If @error Or $AllocPtr = 0 Then Return SetError(1, 0, 0) Local $tInterface = DllStructCreate("ptr[" & $iUbound + 1 & "]", $AllocPtr) If @error Then Return SetError(1, 0, 0) For $i = 0 To $iUbound - 1 $aSplit = StringSplit($aMethods[$i], "|", 2) If UBound($aSplit) <> 2 Then ReDim $aSplit[2] $sNamePart = $aSplit[0] $sTagPart = $aSplit[1] $sMethod = $sFunctionPrefix & $sNamePart $aTagPart = StringSplit($sTagPart, ";", 2) $sRet = $aTagPart[0] $sParams = StringReplace($sTagPart, $sRet, "", 1) $sParams = "ptr" & $sParams $hCallback = Eval(":Callback:" & $sMethod) If Not $hCallback Then $hCallback = DllCallbackRegister($sMethod, $sRet, $sParams) Assign(":Callback:" & $sMethod, $hCallback, 2) EndIf DllStructSetData($tInterface, 1, DllCallbackGetPtr($hCallback), $i + 2) Next DllStructSetData($tInterface, 1, $AllocPtr + $PtrSize) ; Interface method pointers are actually pointer size away Return $AllocPtr EndFunc Func SHGetPathFromIDList( $pidl, ByRef $sPath ) Local $stPath = DllStructCreate( "wchar[" & $MAX_PATH & "]" ) Local $aRet = DllCall( "shell32.dll", "int", "SHGetPathFromIDListW", "ptr", $pidl, "ptr", DllStructGetPtr( $stPath ) ) If @error Then Return SetError(1, 0, 0) $sPath = DllStructGetData( $stPath, 1 ) Return $aRet[0] EndFunc Func StrRetToBuf( $pSTRRET, $pidl, ByRef $sBuf, $iBuf = 512 ) Local $aRet = DllCall( "shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sBuf, "uint", $iBuf ) If @error Then Return SetError(1, 0, 0) $sBuf = $aRet[3] Return $aRet[0] EndFunc #region CALLBACK Func oIShellMenuCallback_CallbackSM( $pSelf, $psmd, $uMsg, $wParam, $lParam ) ;ConsoleWrite( "oIShellMenuCallback_CallbackSM" & @CRLF ) Local $pIShellFolder, $oIShellFolder ; SMC_XXX messages and notifications ;~ $SMC_INITMENU = 0x00000001 ;~ $SMC_CREATE = 0x00000002 ;~ $SMC_EXITMENU = 0x00000003 ;~ $SMC_GETINFO = 0x00000005 ;~ $SMC_GETSFINFO = 0x00000006 ;~ $SMC_GETOBJECT = 0x00000007 ;~ $SMC_GETSFOBJECT = 0x00000008 ;~ $SMC_SFEXEC = 0x00000009 $SMC_SFSELECTITEM = 0x0000000A ;~ $SMC_REFRESH = 0x00000010 ;~ $SMC_DEMOTE = 0x00000011 ;~ $SMC_PROMOTE = 0x00000012 ;~ $SMC_DEFAULTICON = 0x00000016 ;~ $SMC_NEWITEM = 0x00000017 ;~ $SMC_CHEVRONEXPAND = 0x00000019 ;~ $SMC_DISPLAYCHEVRONTIP = 0x0000002A ;~ $SMC_SETSFOBJECT = 0x0000002D ;~ $SMC_SHCHANGENOTIFY = 0x0000002E ;~ $SMC_CHEVRONGETTIP = 0x0000002F ;~ $SMC_SFDDRESTRICTED = 0x00000030 ;~ $SMC_SFEXEC_MIDDLE = 0x00000031 ;~ $SMC_GETAUTOEXPANDSTATE = 0x00000041 ;~ $SMC_AUTOEXPANDCHANGE = 0x00000042 ;~ $SMC_GETCONTEXTMENUMODIFIER = 0x00000043 ;~ $SMC_GETBKCONTEXTMENU = 0x00000044 ;~ $SMC_OPEN = 0x00000045 $SHGDN_NORMAL = 0x0000 ;~ $SHGDN_INFOLDER = 0x0001 ;~ $SHGDN_FOREDITING = 0x1000 ;~ $SHGDN_FORADDRESSBAR = 0x4000 ;~ $SHGDN_FORPARSING = 0x8000 Switch $uMsg Case $SMC_SFSELECTITEM ;SESESESESESESESESESESESESESESESESESE SELECTED SESESESESESESESESESESESESESESESESESESESESESE $tagSMDATA = "dword dwMask;dword dwFlags;handle hmenu;hwnd hwnd;uint uId;uint UIDParent;uint uIdAncestor;ptr punk;ptr pidlFolder;ptr pidlItem;ptr psf;ptr pvUserData" ; SMDATA struct Local $tSMDATA = DllStructCreate( $tagSMDATA, $psmd ) ; New IShellFolder interface? $pIShellFolder = DllStructGetData( $tSMDATA, "psf" ) For $i = 0 To $iIShellFolder - 1 If $pIShellFolder = $apIShellFolder[$i] Then ExitLoop Next If $i < $iIShellFolder Then $oIShellFolder = $aoIShellFolder[$i] Else If Mod( $iIShellFolder, 10 ) = 0 Then ReDim $apIShellFolder[$iIShellFolder+10] ReDim $aoIShellFolder[$iIShellFolder+10] EndIf $apIShellFolder[$iIShellFolder] = $pIShellFolder $oIShellFolder = ObjCreateInterface( $pIShellFolder, $sIID_IShellFolder, $dtag_IShellFolder ) $aoIShellFolder[$iIShellFolder] = $oIShellFolder $iIShellFolder += 1 EndIf ; Parent folder Local $pParentFolder = DllStructGetData( $tSMDATA, "pidlFolder" ), $sPath SHGetPathFromIDList( $pParentFolder, $sPath ) ; Current file or folder Local $tSTRRET = DllStructCreate( "uint uType;ptr data;" ), $sName $oIShellFolder.GetDisplayNameOf( DllStructGetData( $tSMDATA, "pidlItem" ), $SHGDN_NORMAL, $tSTRRET ) StrRetToBuf( DllStructGetPtr( $tSTRRET ), $NULL, $sName ) ; Full path $fullPath = StringReplace( $sPath & "\" & $sName , "\\" , "\" ) ConsoleWrite( $fullPath & @CRLF ) Return $S_FALSE Case Else Return $S_FALSE EndSwitch EndFunc Func oIShellMenuCallback_QueryInterface( $pSelf, $pRIID, $pObj ) Return $E_NOTIMPL EndFunc Func oIShellMenuCallback_AddRef( $pSelf ) ; neues Untermenü erstellen ConsoleWrite( "oIShellMenuCallback_AddRef" & @CRLF ) $iIShellMenuCallback_Ref = 0 $iIShellMenuCallback_Ref += 1 Return $iIShellMenuCallback_Ref EndFunc Func oIShellMenuCallback_Release( $pSelf ) ConsoleWrite( "oIShellMenuCallback_Release" & @CRLF ) $iIShellMenuCallback_Ref = 0 $iIShellMenuCallback_Ref -= 1 Return $iIShellMenuCallback_Ref EndFunc #endregion CALLBACK #region CALLBACK 2 Func oIShellMenuCallback2_CallbackSM( $pSelf, $psmd, $uMsg, $wParam, $lParam ) ;ConsoleWrite( "oIShellMenuCallback_CallbackSM" & @CRLF ) Local $pIShellFolder, $oIShellFolder ; SMC_XXX messages and notifications ;~ $SMC_INITMENU = 0x00000001 ;~ $SMC_CREATE = 0x00000002 ;~ $SMC_EXITMENU = 0x00000003 ;~ $SMC_GETINFO = 0x00000005 ;~ $SMC_GETSFINFO = 0x00000006 ;~ $SMC_GETOBJECT = 0x00000007 ;~ $SMC_GETSFOBJECT = 0x00000008 ;~ $SMC_SFEXEC = 0x00000009 $SMC_SFSELECTITEM = 0x0000000A ;~ $SMC_REFRESH = 0x00000010 ;~ $SMC_DEMOTE = 0x00000011 ;~ $SMC_PROMOTE = 0x00000012 ;~ $SMC_DEFAULTICON = 0x00000016 ;~ $SMC_NEWITEM = 0x00000017 ;~ $SMC_CHEVRONEXPAND = 0x00000019 ;~ $SMC_DISPLAYCHEVRONTIP = 0x0000002A ;~ $SMC_SETSFOBJECT = 0x0000002D ;~ $SMC_SHCHANGENOTIFY = 0x0000002E ;~ $SMC_CHEVRONGETTIP = 0x0000002F ;~ $SMC_SFDDRESTRICTED = 0x00000030 ;~ $SMC_SFEXEC_MIDDLE = 0x00000031 ;~ $SMC_GETAUTOEXPANDSTATE = 0x00000041 ;~ $SMC_AUTOEXPANDCHANGE = 0x00000042 ;~ $SMC_GETCONTEXTMENUMODIFIER = 0x00000043 ;~ $SMC_GETBKCONTEXTMENU = 0x00000044 ;~ $SMC_OPEN = 0x00000045 $SHGDN_NORMAL = 0x0000 ;~ $SHGDN_INFOLDER = 0x0001 ;~ $SHGDN_FOREDITING = 0x1000 ;~ $SHGDN_FORADDRESSBAR = 0x4000 ;~ $SHGDN_FORPARSING = 0x8000 Switch $uMsg Case $SMC_SFSELECTITEM ;SESESESESESESESESESESESESESESESESESE SELECTED SESESESESESESESESESESESESESESESESESESESESESE $tagSMDATA = "dword dwMask;dword dwFlags;handle hmenu;hwnd hwnd;uint uId;uint UIDParent;uint uIdAncestor;ptr punk;ptr pidlFolder;ptr pidlItem;ptr psf;ptr pvUserData" ; SMDATA struct Local $tSMDATA = DllStructCreate( $tagSMDATA, $psmd ) ; New IShellFolder interface? $pIShellFolder = DllStructGetData( $tSMDATA, "psf" ) For $i = 0 To $iIShellFolder - 1 If $pIShellFolder = $apIShellFolder[$i] Then ExitLoop Next If $i < $iIShellFolder Then $oIShellFolder = $aoIShellFolder[$i] Else If Mod( $iIShellFolder, 10 ) = 0 Then ReDim $apIShellFolder[$iIShellFolder+10] ReDim $aoIShellFolder[$iIShellFolder+10] EndIf $apIShellFolder[$iIShellFolder] = $pIShellFolder $oIShellFolder = ObjCreateInterface( $pIShellFolder, $sIID_IShellFolder, $dtag_IShellFolder ) $aoIShellFolder[$iIShellFolder] = $oIShellFolder $iIShellFolder += 1 EndIf ; Parent folder Local $pParentFolder = DllStructGetData( $tSMDATA, "pidlFolder" ), $sPath SHGetPathFromIDList( $pParentFolder, $sPath ) ; Current file or folder Local $tSTRRET = DllStructCreate( "uint uType;ptr data;" ), $sName $oIShellFolder.GetDisplayNameOf( DllStructGetData( $tSMDATA, "pidlItem" ), $SHGDN_NORMAL, $tSTRRET ) StrRetToBuf( DllStructGetPtr( $tSTRRET ), $NULL, $sName ) ; Full path $fullPath = StringReplace( $sPath & "\" & $sName , "\\" , "\" ) ConsoleWrite( $fullPath & @CRLF ) Return $S_FALSE Case Else Return $S_FALSE EndSwitch EndFunc Func oIShellMenuCallback2_QueryInterface( $pSelf, $pRIID, $pObj ) Return $E_NOTIMPL EndFunc Func oIShellMenuCallback2_AddRef( $pSelf ) ; neues Untermenü erstellen ConsoleWrite( "oIShellMenuCallback2_AddRef" & @CRLF ) $iIShellMenuCallback_Ref = 0 $iIShellMenuCallback_Ref += 1 Return $iIShellMenuCallback_Ref EndFunc Func oIShellMenuCallback2_Release( $pSelf ) ConsoleWrite( "oIShellMenuCallback2_Release" & @CRLF ) $iIShellMenuCallback_Ref = 0 $iIShellMenuCallback_Ref -= 1 Return $iIShellMenuCallback_Ref EndFunc #endregion CALLBACK 2 ContexMenuBrowser.au3 Edited December 8, 2013 by Bluesmaster My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
LarsJ Posted December 8, 2013 Author Share Posted December 8, 2013 Why on earth do you think you can put menus together in that way? What you can do is to add a Recent Folders menu to the static part of the menu. The menu you are using in SetMenu. You can do this with the usual functions in GuiMenu.au3. Add the folders to the static menu before you call SetMenu. Controls,  File Explorer,  ROT objects,  UI Automation,  Windows Message MonitorCompiled code: Accessing AutoIt variables,  DotNet.au3 UDF,  Using C# and VB codeShell menus: The Context menu,  The Favorites menu. Shell related: Control Panel,  System Image ListsGraphics related: Rubik's Cube,  OpenGL without external libraries,  Navigating in an image,  Non-rectangular selectionsListView controls: Colors and fonts,  Multi-line header,  Multi-line items,  Checkboxes and icons,  Incremental searchListView controls: Virtual ListViews,  Editing cells,  Data display functions Link to comment Share on other sites More sharing options...
Bluesmaster Posted December 8, 2013 Share Posted December 8, 2013 Sorry that was just a guess. I thought if one can append it to another menu, then the purpose of this must be to append multiple menus. Are you absolutly sure this is not possible? If so I would have to find a workaround with the static part of the menu of course, but I see some disadvantages. However you are the expert and I trust your word and start implementing the static solution. Thanks. Blues My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
Bluesmaster Posted January 21, 2014 Share Posted January 21, 2014 (edited) Hello LarsJ, Do you think those menus will work for virtual folder too? ( like the control panel = ) I cannot try because I dunno how to get the PIDL of such a folder as: $r = DllCall( "shell32.dll" , "uint", "SHILCreateFromPath", "wstr", $targetFolder , "ptr*", 0, "dword*", 0 ) only works with paths. And virtual folders only got CLSIDS as far as I know. Do you know a CLSID > PIDL method? Or any other suggestion? Thank you PS: CLSID for control panel: ShellExecute( "explorer" , "shell:::{7be9d83c-a729-4d97-b5a7-1b7313c39e0a}" ) Edited January 21, 2014 by Bluesmaster My UDF: [topic='156155']_shellExecuteHidden[/topic] Link to comment Share on other sites More sharing options...
BrewManNH Posted January 21, 2014 Share Posted January 21, 2014 _WinAPI_ShellGetKnownFolderIDList will get the PIDL.http://msdn.microsoft.com/en-us/library/windows/desktop/bb762187(v=vs.85).aspx If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now