Everything put together in one zipfile (bottom of post) with two UDFs: ShellContextMenu.au3 and ShellContextMenuCustom.au3. The zip contains several examples.
If you use ShellContextMenuCustom to add custom items to the context menu or modify existing items you must include five functions in your program to handle the custom/modified items: InsertCustomMenuItems(), InvokeCustomMenuItems(), HelpOnCustomMenuItems(), PrintMenuHelpMessage() and WM_INITMENUPOPUP(). See ListViewCustom.
To add bitmaps to custom menu items you need _GUICtrlMenu_CreateBitmap.au3 and/or GUICtrlMenuEx.au3. See update #2.
You also need APIConstants.au3 v3.8.
Examples
All examples are based on a ListView. Drag and drop some files or folders on the ListView.
ListView.au3: Small example with ShellContextMenu.au3.
ListViewCustom.au3: An example with ShellContextMenuCustom.au3. Shows how to add custom items to the context menu and how to add bitmaps to the custom items.
ExContextMenus.au3: Shows three different context menus. If you right click a file/folder it shows the usual menu. If you right click in the free area of the ListView it shows a context menu similar to the context menu in the free area of Windows Explorer. This menu contains the New-menu. If you right click a label in the bottom of the GUI it shows the desktop context menu.
ExModifyMenu.au3: Shows how to add custom items to the context menu and modify existing items. Also shows how to add bitmaps to custom items and to identify existing items with the language-independent verb. The picture is created from this example.
ExPrintMenu.au3: If you right click a file/folder to display the menu and then quit, info about the menu items will be printed with _ArrayDisplay(). For each item the index, command id, menu text and verb will be printed.
ExSubmenu.au3: Adds the context menu to an existing menu as a submenu.
Update #7 2012-10-08: Cut/Copy/Paste
asdf8 has pointed out that Cut/Copy/Paste commands aren't working. I've been doing some reading on this subject in the weekend. To make Cut/Copy/Paste work just use OleInitialize() to initialize COM in stead of CoInitialize(). Zipfile updated.
Update #6 2012-10-05: Multiple selections
asdf8 has pointed out that the menu commands aren't working if more than one file/folder is selected in the ListView.
If this line in ShellContextMenu.au3 and ShellContextMenuCustom.au3:
If $IShellFolder.GetUIObjectOf( $NULL, 1, $tArray, $tRIID_IContextMenu, 0, $pIContextMenu ) = $S_OK Then
is replaced with this line:
If $IShellFolder.GetUIObjectOf( $NULL, $cidl, $apidl, $tRIID_IContextMenu, 0, $pIContextMenu ) = $S_OK Then
where $cidl is the number of selected files/folders and $apidl is an array of PIDLs for the files/folders relative to the parent folder, then the menu commands are working for multiple selections.
Changed the styles of ListViews to allow multiple selections. Zipfile updated.
Update #5 2012-10-01
Not applicable after update #6: Changed the style of ListViewCustom.au3 to allow multiple selections and added an example to show the proper Properties dialog box when multiple files/folders are selected. This is done with the function SHMultiFileProperties and the helper function CIDLData_CreateFromIDArray. Both functions are implemented in shell32.dll. On XP CIDLData_CreateFromIDArray can only be called with the ordinal value which is 83.
Fixed an error in ListViewCustom.au3 which could lead to a crash on Windows 7. The function GetCommandVerb( $iCmd ) to get the language-independent verb must not be called if not $iCmd is in the valid range between $idCmdFirst (0x0001) and $idCmdLast (0x6FFF).
Update #4 2012-09-27: Language-independent verb
Added the CMF_EXTENDEDVERBS flag to the QueryContextMenu method to get extended items (Pin to Start menu) if holding the shift key while right clicking.
To modify existing menu items it's necessary to be able to identify the items. A convenient way to identify the items is to use the language-independent verb. The language-independent verb can be extracted with a function like this:
; Get the verb, the language-independent command name
; Canonical verbs: copy, cut, delete, open, paste, print, rename
Func GetCommandVerb( $iCmd )
Local $uFlags, $szName, $pszName, $tszName
$uFlags = $GCS_VERB
$tszName = DllStructCreate( "wchar[64]" )
$pszName = DllStructGetPtr( $tszName, 1 )
If $IContextMenu.GetCommandString( $iCmd - $idCmdFirst, $uFlags, $NULL, $pszName, 64 ) = $S_OK Then
If BitAND( $uFlags, $GCS_UNICODE ) Then
$szName = DllStructGetData( $tszName, 1 )
If StringLen( $szName ) > 0 Then Return $szName
EndIf
EndIf
Return ""
EndFuncGetCommandVerb() is called from WM_INITMENUPOPUP(). The WM_INITMENUPOPUP message is catched in the new window procedure.
Examples of these canonical verbs are: copy, cut, delete, open, paste, print and rename.
In ListViewCustom the Cut/Copy commands are renamed to Copy/Paste, the command identifiers are saved in two variables, and custom code is executed in stead of the default code.
Update #3 2012-09-23: Help messages
For Windows Explorer under XP help messages for the context menu are shown in the status bar. A help message is shown when an item is selected (hilited).
When an item is selected it generates a WM_MENUSELECT notification which can be catched in the new window procedure:
; New window procedure to be able to handle messages from the shell context menu
Func NewWindowProc( $hWnd, $iMsg, $iwParam, $ilParam )
If $pIContextMenu Then
If $iMsg = $WM_MENUSELECT Then WM_MENUSELECT( $hWnd, $iMsg, $iwParam, $ilParam )
...
EndFuncIn the WM_MENUSELECT() function help messages are printed with the GetCommandString method of the IContextMenu interface.
Update #2 2012-09-20: Bitmaps
To add bitmaps to system-drawn (not owner-drawn) menu items (Custom1 and Custom2) you can use the UDF _GUICtrlMenu_CreateBitmap.au3 by UEZ. You can get it in the German forum by following this link: http://www.autoit.de/index.php?page=Thread&threadID=21001. The UDF is not included in the zip.
To add bitmaps to owner-drawn menu items (Custom3, Custom4 and Custom5) you can use the UDF GUICtrlMenuEx.au3 by Ward. You can get it here: http://www.autoitscript.com/forum/index.php?showtopic=123223. The UDF is not included in the zip.
If you want slightly more space between the owner-drawn menu items you can modify a line in the __GUICtrlMenuEx_WM_MEASUREITEM() function like this:
DllStructSetData($MeasureItem, "itemHeight", $Size[1]) The original line
DllStructSetData($MeasureItem, "itemHeight", $Size[1]+4) Add 4 extra pixels of spaceThis is done in the picture.
Added a new zip at the bottom.
Update #1 2012-09-17: Custom menu items
When we have a handle to the context menu it's easy to add custom items. The zip at the bottom is updated.
2012-09-12
With ObjCreateInterface() it's possible to create a Shell Context Menu (Windows Explorer right click menu) for files and folders e.g. in a ListView or TreeView.
This can also be implemented with AutoItObject or with a C/C++ dll-file (there is an example of that in this forum). Here is used ObjCreateInterface() so this is pure AutoIt.
To create a Shell Context Menu you use the GetUIObjectOf method of the IShellFolder interface to get a pointer for the IContextMenu interface. With the QueryContextMenu method of this interface you add commands to the context menu and you execute the selected command with the InvokeCommand method.
With QueryInterface you can get pointers to the IContextMenu2 and IContextMenu3 interfaces. You need these interfaces to be able to handle owner-drawn menu items e.g. the "Open With" or "Send To" submenues. To handle the events of the owner-drawn menu items you also need a new window procedure and you must initialize COM.
This is the function in the UDF that shows the context menu:
; Show the Shell Context Menu
Func ShellContextMenu( $hWnd, $hWndContext, $tPOINT, $sFullPath )
Local $pidlFQ, $pidlRel, $pIShellFolder, $IShellFolder
Local $pIContextMenu, $IContextMenu, $tArray = DllStructCreate( "ptr" )
Local $hPopup, $iX, $iY, $iCmd, $fMask, $KeyState
; Get the fully qualified PIDL associated with the file
$pidlFQ = ILCreateFromPath( $sFullPath )
; Get an IShellFolder interface pointer ($pIShellFolder) for the parent folder
; and a PIDL ($pidlRel) associated with the file relative to the parent folder.
SHBindToParent( $pidlFQ, DllStructGetPtr( $tRIID_IShellFolder ), $pIShellFolder, $pidlRel )
; Create an IDispatch-Object for the IShellFolder Interface
$IShellFolder = ObjCreateInterface( $pIShellFolder, $sIID_IShellFolder, $dtagIShellFolder )
; Get a pointer to the IContextMenu Interface
DllStructSetData( $tArray, 1, $pidlRel )
If $IShellFolder.GetUIObjectOf( $NULL, 1, $tArray, $tRIID_IContextMenu, 0, $pIContextMenu ) = $S_OK Then
; Create an IDispatch-Object for the IContextMenu Interface
$IContextMenu = ObjCreateInterface( $pIContextMenu, $sIID_IContextMenu, $dtagIContextMenu )
; Create a Popup menu
$hPopup = CreatePopupMenu()
; Add commands to the Popup menu
$IContextMenu.QueryContextMenu( $hPopup, 0, $idCmdFirst, $idCmdLast, $CMF_NORMAL )
; Create an IDispatch-Object for the IContextMenu2 Interface
$IContextMenu.QueryInterface( DllStructGetPtr( $tRIID_IContextMenu2 ), $pIContextMenu2 )
$IContextMenu2 = ObjCreateInterface( $pIContextMenu2, $sIID_IContextMenu2, $dtagIContextMenu2 )
; Create an IDispatch-Object for the IContextMenu3 Interface
$IContextMenu.QueryInterface( DllStructGetPtr( $tRIID_IContextMenu3 ), $pIContextMenu3 )
$IContextMenu3 = ObjCreateInterface( $pIContextMenu3, $sIID_IContextMenu3, $dtagIContextMenu3 )
; Convert client coordinates to screen coordinates.
; This is among other things used to place the upper left corner
; of the Properties dialog box at the position of the mouse cursor.
_WinAPI_ClientToScreen( $hWndContext, $tPoint )
$iX = DllStructGetData( $tPoint, "X" )
$iY = DllStructGetData( $tPoint, "Y" )
; Show the Popup menu and track the selection
$iCmd = TrackPopupMenuEx( $hPopup, $TPM_RETURNCMD, $iX, $iY, $hWnd )
If $iCmd > 0 Then
; Create and fill a $tagCMINVOKECOMMANDINFOEX structure
Local $tCMINVOKECOMMANDINFOEX = DllStructCreate( $tagCMINVOKECOMMANDINFOEX )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "cbSize", DllStructGetSize( $tCMINVOKECOMMANDINFOEX ) )
$fMask = BitOr( $CMIC_MASK_UNICODE, $CMIC_MASK_PTINVOKE )
$KeyState = GetKeyState( $VK_CONTROL )
If $KeyState < 0 Or $KeyState > 32768 Then _
$fMask = BitOr( $fMask, $CMIC_MASK_CONTROL_DOWN )
$KeyState = GetKeyState( $VK_SHIFT )
If $KeyState < 0 Or $KeyState > 32768 Then _
$fMask = BitOr( $fMask, $CMIC_MASK_SHIFT_DOWN )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "fMask", $fMask )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "hWnd", $hWnd )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "lpVerb", $iCmd - $idCmdFirst )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "lpVerbW", $iCmd - $idCmdFirst )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "nShow", $SW_SHOWNORMAL )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "X", $iX )
DllStructSetData( $tCMINVOKECOMMANDINFOEX, "Y", $iY )
; Invoke the command
$IContextMenu.InvokeCommand( $tCMINVOKECOMMANDINFOEX )
EndIf
; Free memory allocated by the PIDL
CoTaskMemFree( $pidlFQ )
; Destroy menu and free memory
DestroyMenu( $hPopup )
$pIContextMenu3 = 0
$pIContextMenu2 = 0
$IContextMenu3 = 0
$IContextMenu2 = 0
$IContextMenu = 0
$IShellFolder = 0
EndIf
EndFunc
Double click To open a file or folder in Windows Explorer you double click it. It's the same as right click and select the default (bold) menu item. When you double click you use the CMF_DEFAULTONLY flag to tell the QueryContextMenu that you only want the default menu item.
This is the function in the UDF that executes the default menu item:
; Execute the default menu item
Func InvokeCommand( $hWnd, $sFullPath )
Local $pidlFQ, $pidlRel, $pIShellFolder, $IShellFolder
Local $pIContextMenu, $IContextMenu, $tArray = DllStructCreate( "ptr" )
Local $hPopup, $aRet, $idMenu
; Get the fully qualified PIDL associated with the file
$pidlFQ = ILCreateFromPath( $sFullPath )
; Get an IShellFolder interface pointer ($pIShellFolder) for the parent folder
; and a PIDL ($pidlRel) associated with the file relative to the parent folder.
SHBindToParent( $pidlFQ, DllStructGetPtr( $tRIID_IShellFolder ), $pIShellFolder, $pidlRel )
; Create an IDispatch-Object for the IShellFolder Interface
$IShellFolder = ObjCreateInterface( $pIShellFolder, $sIID_IShellFolder, $dtagIShellFolder )
; Get a pointer to the IContextMenu Interface
DllStructSetData( $tArray, 1, $pidlRel )
If $IShellFolder.GetUIObjectOf( $NULL, 1, $tArray, $tRIID_IContextMenu, 0, $pIContextMenu ) = $S_OK Then
; Create an IDispatch-Object for the IContextMenu Interface
$IContextMenu = ObjCreateInterface( $pIContextMenu, $sIID_IContextMenu, $dtagIContextMenu )
; Create a Popup menu
$hPopup = CreatePopupMenu()
; Add the default command to the Popup menu
$aRet = $IContextMenu.QueryContextMenu( $hPopup, 0, $idCmdFirst, $idCmdLast, $CMF_DEFAULTONLY )
If $aRet >= 0 Then
; Get the menu item identifier
Local $idMenu = GetMenuItemID( $hPopup, 0 )
; Create and fill a $tagCMINVOKECOMMANDINFO structure
Local $tCMINVOKECOMMANDINFO = DllStructCreate( $tagCMINVOKECOMMANDINFO )
DllStructSetData( $tCMINVOKECOMMANDINFO, "cbSize", DllStructGetSize( $tCMINVOKECOMMANDINFO ) )
DllStructSetData( $tCMINVOKECOMMANDINFO, "fMask", 0 )
DllStructSetData( $tCMINVOKECOMMANDINFO, "hWnd", $hWnd )
DllStructSetData( $tCMINVOKECOMMANDINFO, "lpVerb", $idMenu - $idCmdFirst )
DllStructSetData( $tCMINVOKECOMMANDINFO, "nShow", $SW_SHOWNORMAL )
; Invoke the command
$IContextMenu.InvokeCommand( $tCMINVOKECOMMANDINFO )
EndIf
; Free memory allocated by the PIDL
CoTaskMemFree( $pidlFQ )
; Destroy menu and free memory
DestroyMenu( $hPopup )
$IContextMenu = 0
$IShellFolder = 0
EndIf
EndFuncThis is a demonstration of how to use these functions to execute the default menu item when you double click. You can do exactly the same thing in one line with the builtin function ShellExecute().
Example This is a small example with a ListView. Drag and drop some files and folders on the ListView and right click to show the context menu or double click to open.
(If the window with the ListView is inactive then activate the window by clicking the titlebar or click in the ListView outside the items. If you click a LV item in an inactive window it generates a double click and opens the corresponding file or folder.)
#include <GuiListView.au3>
#include <GUIConstantsEx.au3>
#include "ShellContextMenu.au3"
Opt( "MustDeclareVars", 1 )
Global $hGui, $idLV, $hLV, $idLVdropFiles, $aLVfiles[1]
Global $idLVrightClick, $idLVdoubleClick, $tLVpoint, $iLVidx
MainScript()
Func MainScript()
$hGui = GUICreate( "The Shell Context Menu", 300, 200, 600, 300, -1, BitOR( $WS_EX_ACCEPTFILES, $WS_EX_TOPMOST ) )
$idLV = GUICtrlCreateListView( "", 0, 0, 300, 200 )
GUICtrlSetStyle( $idLV, BitOR( $LVS_LIST, $GUI_SS_DEFAULT_LISTVIEW ) )
GUICtrlSetState( $idLV, $GUI_DROPACCEPTED )
$hLV = ControlGetHandle( $hGui, "", $idLV )
$idLVdropFiles = GUICtrlCreateDummy()
$idLVrightClick = GUICtrlCreateDummy()
$idLVdoubleClick = GUICtrlCreateDummy()
; Window Procedures
$hNewWinProc = DllCallbackRegister( "NewWindowProc", "int", "hwnd;uint;wparam;lparam" ) ; New window procedure
$hOldWinProc = _WinAPI_SetWindowLong( $hGui, $GWL_WNDPROC, DllCallbackGetPtr( $hNewWinProc ) ) ; Old window procedure
GUIRegisterMsg( $WM_DROPFILES, "WM_DROPFILES" )
GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )
GUISetState( @SW_SHOW )
; Initialize COM
CoInitialize()
While 1
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
GUIDelete( $hGui )
; Cleanup
DllCallbackFree( $hNewWinProc )
CoUninitialize()
CloseDlls()
Exit
Case $idLVdropFiles
LVupdate()
Case $idLVrightClick
; Show the Shell Context Menu
ShellContextMenu( $hGui, $hLV, $tLVpoint, $aLVfiles[$iLVidx] )
Case $idLVdoubleClick
; Execute the default menu item
InvokeCommand( $hGui, $aLVfiles[$iLVidx] )
EndSwitch
WEnd
EndFunc
Func WM_DROPFILES( $hWnd, $iMsg, $iwParam, $ilParam )
#forceref $iMsg, $ilParam
Switch $hWnd
Case $hGui
Local $aRet, $nSize, $tFileName
$aRet = DllCall( $dllShell32, "int", "DragQueryFile", "hwnd", $iwParam, "int", -1, "ptr", 0, "int", 255 )
For $i = 0 To $aRet[0] - 1
$nSize = DllCall( $dllShell32, "int", "DragQueryFile", "hwnd", $iwParam, "int", $i, "ptr", 0, "int", 0 )
$nSize = $nSize[0] + 1
$tFileName = DllStructCreate( "char[" & $nSize & "]" )
DllCall( $dllShell32, "int", "DragQueryFile", "hwnd", $iwParam, "int", $i, "ptr", DllStructGetPtr( $tFileName ), "int", $nSize )
ReDim $aLVfiles[$i+1]
$aLVfiles[$i] = DllStructGetData( $tFileName, 1 )
$tFileName = 0
Next
GUICtrlSendToDummy( $idLVdropFiles )
Return 0
EndSwitch
EndFunc
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hLV
Switch $iCode
Case $NM_DBLCLK
$tLVpoint = _WinAPI_GetMousePos( True, $hLV )
Local $iX = DllStructGetData( $tLVpoint, "X" )
Local $iY = DllStructGetData( $tLVpoint, "Y" )
Local $aHit = _GUICtrlListView_HitTest( $hLV, $iX, $iY )
If $aHit[2] Or $aHit[3] Then
$iLVidx = $aHit[0]
GUICtrlSendToDummy( $idLVdoubleClick )
EndIf
Case $NM_RCLICK
$tLVpoint = _WinAPI_GetMousePos( True, $hLV )
Local $iX = DllStructGetData( $tLVpoint, "X" )
Local $iY = DllStructGetData( $tLVpoint, "Y" )
Local $aHit = _GUICtrlListView_HitTest( $hLV, $iX, $iY )
If $aHit[2] Or $aHit[3] Then
$iLVidx = $aHit[0]
GUICtrlSendToDummy( $idLVrightClick )
Return 0
EndIf
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc
Func LVupdate()
_GUICtrlListView_DeleteAllItems( $hLV )
For $file In $aLVfiles
GUICtrlCreateListViewItem( StringRight( $file, StringLen( $file ) - StringInStr( $file, "\", 0, -1 ) ), $idLV )
Next
EndFuncThe example is also contained in the zipfile.
Zipfile The zipfile contains the ShellContextMenu.au3 and ShellContextMenuCustom.au3 UDFs with the necessary globals, structures, interface definitions and functions. You need APIConstants.au3 v3.8 by Yashied. The zip contains several examples too.
Testet on XP and 7. It would be nice if someone would test the UDF on Vista.
The zipfile can be opened with 7-Zip.
ShellContextMenu.zip (You need _GUICtrlMenu_CreateBitmap.au3 and/or GUICtrlMenuEx.au3. See top of post.)
Now it's possible to display shell context menu in a control(treeview,listview,list...) just like you right click on a file/folder in windows explorer. Hope you will like it The idea and original code come from http://www.codeproject.com/KB/cs/shellContextMenu.aspx, And the dll file was compiled by sd007 ONE PROBLEM : the program works fine on XP, but several items won't show on win7-x64, such as unlocker, foobar2000...Anyone can fix this? Here is an simple apply based on Yashied‘’s TVExplorer UDF
#Include <GUIConstantsEx.au3>
#Include <GUITreeView.au3>
#Include <TVExplorer.au3>
#Include <TreeViewConstants.au3>
#Include <WindowsConstants.au3>
#Include <WinAPIEx.au3>
Opt('GUIOnEventMode', 1)
Global $hForm, $hTV, $Input, $hFocus = 0, $Dummy, $Style
Global $__RegAsmPath, $ShellContextMenu ;COM Handle
_NETFramework_Load(@ScriptDir & "ExplorerShellContextMenu.dll")
If Not @error Then
$ShellContextMenu = ObjCreate("ExplorerShellContextMenu.ShowContextMenu")
Else
MsgBox(0,'',"error=" & @error &@CRLF&@CRLF& _
"1=ExplorerShellContextMenu.dll has been registered"&@CRLF& _
"2=DLL file does not exist"&@CRLF& _
"3=.NET Framework 2.0 required!"&@CRLF& _
"4=can't register the .net DLL")
EndIf
If Not _WinAPI_DwmIsCompositionEnabled() Then
$Style = $WS_EX_COMPOSITED
Else
$Style = -1
EndIf
$hForm = GUICreate('TVExplorer UDF Example', 700, 406, -1, -1, -1, $Style)
GUISetOnEvent($GUI_EVENT_CLOSE, '_GUIEvent')
GUISetIcon(@WindowsDir & 'explorer.exe')
$Input = GUICtrlCreateInput('', 20, 20, 660, 19)
GUICtrlSetState(-1, $GUI_DISABLE)
$hTV = _GUICtrlTVExplorer_Create('', 20, 48, 660, 310, -1, $WS_EX_CLIENTEDGE, -1, '_TVEvent')
_TVSetPath($Input, _GUICtrlTVExplorer_GetSelected($hTV))
_GUICtrlTVExplorer_SetExplorerStyle($hTV)
$Dummy = GUICtrlCreateDummy()
GUICtrlSetOnEvent(-1, '_GUIEvent')
HotKeySet('{F5}', '_TVRefresh')
GUISetState()
While 1
Sleep(1000)
WEnd
Func _GUIEvent()
Local $Path
Switch @GUI_CtrlId
Case $GUI_EVENT_CLOSE
GUIDelete()
_GUICtrlTVExplorer_DestroyAll()
Exit
Case $Dummy
$Path = _GUICtrlTVExplorer_GetSelected($hFocus)
_GUICtrlTVExplorer_AttachFolder($hFocus)
_GUICtrlTVExplorer_Expand($hFocus, $Path, 0)
$hFocus = 0
EndSwitch
EndFunc ;==>_GUIEvent
Func _TVEvent($hWnd, $iMsg, $sPath, $hItem)
Switch $iMsg
Case $TV_NOTIFY_BEGINUPDATE
GUISetCursor(1, 1)
Case $TV_NOTIFY_ENDUPDATE
GUISetCursor(2)
Case $TV_NOTIFY_SELCHANGED
If $hTV = $hWnd Then
_TVSetPath($Input, $sPath)
EndIf
Case $TV_NOTIFY_DBLCLK
; Nothing
Case $TV_NOTIFY_RCLICK
Local $asCurInfo = GUIGetCursorInfo()
ClientToScreen($hForm, $asCurInfo[0], $asCurInfo[1])
$ShellContextMenu.Show($sPath,$asCurInfo[0],$asCurInfo[1])
Case $TV_NOTIFY_DELETINGITEM
; Nothing
Case $TV_NOTIFY_DISKMOUNTED
; Nothing
Case $TV_NOTIFY_DISKUNMOUNTED
; Nothing
EndSwitch
EndFunc ;==>_TVEvent
Func _TVSetPath($iInput, $sPath)
Local $Text = _WinAPI_PathCompactPath(GUICtrlGetHandle($iInput), $sPath, -2)
If GUICtrlRead($iInput) <> $Text Then
GUICtrlSetData($iInput, $Text)
EndIf
EndFunc ;==>_TVSetPath
Func _TVRefresh()
Local $hWnd = _WinAPI_GetFocus()
If $hTV = $hWnd Then
If Not $hFocus Then
$hFocus = $hWnd
GUICtrlSendToDummy($Dummy)
EndIf
Return
EndIf
HotKeySet('{F5}')
Send('{F5}')
HotKeySet('{F5}', '_TVRefresh')
EndFunc ;==>_TVRefresh
Func _NETFramework_Load($DLL_File)
$ShellContextMenu = ObjCreate("ExplorerShellContextMenu.ShowContextMenu")
If IsObj($ShellContextMenu) Then Return SetError(1,0,0) ; already registered
If Not FileExists($DLL_File) Then Return SetError(2,0,0) ; == file does not exist
Local $sRoot = RegRead("HKEY_LOCAL_MACHINESOFTWAREMicrosoft.NETFramework", "InstallRoot")
If @error Then Return SetError(3,0,0) ; == .NET Framework 2.0 required!
Local $aFolder = _FileListToArray($sRoot , "*", 2), $sNETFolder = ''
For $i = $aFolder[0] To 1 Step -1
If StringRegExp($aFolder[$i], "v2.0.d+", 0) Then
$sNETFolder = $aFolder[$i]
ExitLoop
EndIf
Next
If $sNETFolder = '' Then Return SetError(3,0,0) ; == NET Framework 2.0 required!
$__RegAsmPath = $sRoot & $sNETFolder & "RegAsm.exe"
If Not RunWait($__RegAsmPath & " /codebase " & $DLL_File, @ScriptDir, @SW_HIDE) Then Return SetError(4,0,0); can't register the .net DLL
Return 1
EndFunc ;==>_NETFramework_Load
Func __UnLoad_NET_Dll($DLL_File)
RunWait($__RegAsmPath & " /unregister " & $DLL_File, @ScriptDir, @SW_HIDE) ; unregister the .net DLL
EndFunc
Func ClientToScreen($hWnd, ByRef $x, ByRef $y)
Local $stPoint = DllStructCreate("int;int")
DllStructSetData($stPoint, 1, $x)
DllStructSetData($stPoint, 2, $y)
DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $hWnd, "ptr", DllStructGetPtr($stPoint))
$x = DllStructGetData($stPoint, 1)
$y = DllStructGetData($stPoint, 2)
; release Struct not really needed as it is a local
$stPoint = 0
EndFunc ;==>ClientToScreen ExplorerShellContextMenu.7z