Jump to content

Recommended Posts

Posted

Hi my friends, 

just to ask how to Drag Out element inside a listview to windows explorer

I need to select inside of a listview item and drag and copy to windows explorer

i atached the imagen 

 

best regards

 

 

 

 

 

 

image.png

Posted

Hi Netol,

I've had a bit of a read, and it looks a bit involved 

Basically I think we need to do a "dodragdrop". https://learn.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-dodragdrop.
Part of this process requires us to craft an object that supports both the IDropSource and IDropSourceNotify interfaces. This is more than writing tags for ObjCreateInterface -  we'll actually need to write the methods etc to handle callbacks. 

The idea is we get feedback as we're dragging -  so our app can determine if you're over a valid "drop" location amongst other things. 

I've made a start on it, but need to get some rest - so I'll get back to you tomorrow :)

Posted

For the fun of it.  Here a strongly hacked way :

; From Nine
#include <GUIConstants.au3>
#include <File.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Opt("MustDeclareVars", True)

Global Enum $NONE, $DRAG, $DROP
Global $hMSHook, $sFile, $iState = $NONE

Example()

Func Example()
  GUICreate("Listview items", 600, 450)
  Local $idListview = GUICtrlCreateListView("File Name", 10, 10, 520, 400)
  _GUICtrlListView_SetColumnWidth($idListview, 0, 480)
  Local $aList = _FileListToArray(@ScriptDir, "*.au3", Default, True)
  For $i = 1 To $aList[0]
    GUICtrlCreateListViewItem($aList[$i], $idListview)
  Next
  GUISetState()

  Local $hWnd, $hCtrl

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)

  Local $hMSProc = DllCallbackRegister(WH_MOUSE_LL, "long", "int;wparam;lparam")
  $hMSHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hMSProc), _WinAPI_GetModuleHandle(0))

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
    If $iState = $DROP Then
      $hWnd = WinGetHandle("[CLASS:CabinetWClass]")
      $hCtrl = _WinAPI_WindowFromPoint(_WinAPI_GetMousePos())
      If _WinAPI_GetClassName($hCtrl) = "DirectUIHWND" And _WinAPI_GetAncestor($hCtrl, $GA_ROOT) = $hWnd Then
        SetMute(1)
        FileCopy($sFile, GetExplorerPath($hWnd) & "/*", $FC_OVERWRITE)
        Sleep(1200)
        SetMute(0)
      EndIf
      $iState = $NONE
    EndIf
  WEnd

  _WinAPI_UnhookWindowsHookEx($hMSHook)
  DllCallbackFree($hMSProc)
EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
  Local $tList = DllStructCreate($tagNMLISTVIEW, $lParam)
  If $tList.Code = $LVN_BEGINDRAG Then
    $iState = $DRAG
    $sFile = _GUICtrlListView_GetItemTextString($tList.hWndFrom, $tList.Item)
  EndIf
EndFunc   ;==>WM_NOTIFY

Func GetExplorerPath($hExplorer)
  Local $oShell = ObjCreate("Shell.Application")
  For $oWindow In $oShell.Windows()
    If $oWindow.HWND = $hExplorer Then ExitLoop
  Next
  Return StringReplace($oWindow.LocationURL, "file:///", "")
EndFunc   ;==>GetExplorerPath

Func WH_MOUSE_LL($nCode, $wParam, $lParam)
  If $nCode >= 0 And $iState = $DRAG And $wParam = $WM_LBUTTONUP Then $iState = $DROP
  Return _WinAPI_CallNextHookEx($hMSHook, $nCode, $wParam, $lParam)
EndFunc   ;==>WH_MOUSE_LL

Func SetMute($iMute)
  Local Const $RENDER = 0
  Local Const $CLSCTX_INPROC_SERVER = 1
  Local Const $CONSOLE = 0

  Local Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
  Local Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
  Local Const $sTagIMMDeviceEnumerator = _
      "EnumAudioEndpoints hresult(int;dword;ptr*);" & _
      "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _
      "GetDevice hresult(wstr;ptr*);" & _
      "RegisterEndpointNotificationCallback hresult(ptr);" & _
      "UnregisterEndpointNotificationCallback hresult(ptr)"

  Local Const $sIID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
  Local Const $sTagIMMDevice = _
      "Activate hresult(struct*;dword;ptr;ptr*);" & _
      "OpenPropertyStore hresult(dword;ptr*);" & _
      "GetId hresult(wstr*);" & _
      "GetState hresult(dword*)"

  Local Const $sIID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
  Local Const $sTagIAudioEndpointVolume = _
      "RegisterControlChangeNotify hresult(ptr);" & _
      "UnregisterControlChangeNotify hresult(ptr);" & _
      "GetChannelCount hresult(uint*);" & _
      "SetMasterVolumeLevel hresult(float;ptr);" & _
      "SetMasterVolumeLevelScalar hresult(float;ptr);" & _
      "GetMasterVolumeLevel hresult(float*);" & _
      "GetMasterVolumeLevelScalar hresult(float*);" & _
      "SetChannelVolumeLevel hresult(uint;float;ptr);" & _
      "SetChannelVolumeLevelScalar hresult(uint;float;ptr);" & _
      "GetChannelVolumeLevel hresult(uint;float*);" & _
      "GetChannelVolumeLevelScalar hresult(uint;float*);" & _
      "SetMute hresult(int;ptr);" & _
      "GetMute hresult(int*);" & _
      "GetVolumeStepInfo hresult(uint*;uint*);" & _
      "VolumeStepUp hresult(ptr);" & _
      "VolumeStepDown hresult(ptr);" & _
      "QueryHardwareSupport hresult(dword*);" & _
      "GetVolumeRange hresult(float*;float*;float*)"

  Local $pIMMDevice, $pIAudioEndpointVolume
  Local $oMMDeviceEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $sTagIMMDeviceEnumerator)
  $oMMDeviceEnumerator.GetDefaultAudioEndpoint($RENDER, $CONSOLE, $pIMMDevice)
  Local $oMMDevice = ObjCreateInterface($pIMMDevice, $sIID_IMMDevice, $sTagIMMDevice)

  $oMMDevice.Activate(_WinAPI_GUIDFromString($sIID_IAudioEndpointVolume), $CLSCTX_INPROC_SERVER, 0, $pIAudioEndpointVolume)
  Local $oIAudioEndpointVolume = ObjCreateInterface($pIAudioEndpointVolume, $sIID_IAudioEndpointVolume, $sTagIAudioEndpointVolume)
  $oIAudioEndpointVolume.SetMute($iMute, 0)
EndFunc   ;==>SetMute

:D

Posted (edited)
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $gaDropFiles[1]

__Example()
Func __Example()
    GUICreate("listview items", 220, 250, 100, 200, -1, $WS_EX_ACCEPTFILES)
    GUISetBkColor(0x00E0FFFF) ; will change background color

    Local $idListview = GUICtrlCreateListView("col1", 10, 10, 200, 150)
    GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; to allow drag and dropping
    GUISetState(@SW_SHOW)
    GUIRegisterMsg ($WM_DROPFILES, "WM_DROPFILES_FUNC")

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $GUI_EVENT_DROPPED
                 For $i = 0 To UBound($gaDropFiles) - 1
                    GUICtrlCreateListViewItem($gaDropFiles[$i], $idListview)
                 Next
        EndSwitch
    WEnd
EndFunc

Func WM_DROPFILES_FUNC($hWnd, $msgID, $wParam, $lParam)
    ;~ https://www.autoitscript.com/forum/topic/28062-drop-multiple-files-on-any-control/       <by @Lazycat>
    Local $nSize, $pFileName
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $gaDropFiles[$i+1]
        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)
        $pFileName = 0
    Next
EndFunc

 

Edited by jugador
Posted
On 1/21/2026 at 6:21 PM, Nine said:

For the fun of it.  Here a strongly hacked way :

; From Nine
#include <GUIConstants.au3>
#include <File.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Opt("MustDeclareVars", True)

Global Enum $NONE, $DRAG, $DROP
Global $hMSHook, $sFile, $iState = $NONE

Example()

Func Example()
  GUICreate("Listview items", 600, 450)
  Local $idListview = GUICtrlCreateListView("File Name", 10, 10, 520, 400)
  _GUICtrlListView_SetColumnWidth($idListview, 0, 480)
  Local $aList = _FileListToArray(@ScriptDir, "*.au3", Default, True)
  For $i = 1 To $aList[0]
    GUICtrlCreateListViewItem($aList[$i], $idListview)
  Next
  GUISetState()

  Local $hWnd, $hCtrl

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)

  Local $hMSProc = DllCallbackRegister(WH_MOUSE_LL, "long", "int;wparam;lparam")
  $hMSHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hMSProc), _WinAPI_GetModuleHandle(0))

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
    If $iState = $DROP Then
      $hWnd = WinGetHandle("[CLASS:CabinetWClass]")
      $hCtrl = _WinAPI_WindowFromPoint(_WinAPI_GetMousePos())
      If _WinAPI_GetClassName($hCtrl) = "DirectUIHWND" And _WinAPI_GetAncestor($hCtrl, $GA_ROOT) = $hWnd Then
        SetMute(1)
        FileCopy($sFile, GetExplorerPath($hWnd) & "/*", $FC_OVERWRITE)
        Sleep(1200)
        SetMute(0)
      EndIf
      $iState = $NONE
    EndIf
  WEnd

  _WinAPI_UnhookWindowsHookEx($hMSHook)
  DllCallbackFree($hMSProc)
EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
  Local $tList = DllStructCreate($tagNMLISTVIEW, $lParam)
  If $tList.Code = $LVN_BEGINDRAG Then
    $iState = $DRAG
    $sFile = _GUICtrlListView_GetItemTextString($tList.hWndFrom, $tList.Item)
  EndIf
EndFunc   ;==>WM_NOTIFY

Func GetExplorerPath($hExplorer)
  Local $oShell = ObjCreate("Shell.Application")
  For $oWindow In $oShell.Windows()
    If $oWindow.HWND = $hExplorer Then ExitLoop
  Next
  Return StringReplace($oWindow.LocationURL, "file:///", "")
EndFunc   ;==>GetExplorerPath

Func WH_MOUSE_LL($nCode, $wParam, $lParam)
  If $nCode >= 0 And $iState = $DRAG And $wParam = $WM_LBUTTONUP Then $iState = $DROP
  Return _WinAPI_CallNextHookEx($hMSHook, $nCode, $wParam, $lParam)
EndFunc   ;==>WH_MOUSE_LL

Func SetMute($iMute)
  Local Const $RENDER = 0
  Local Const $CLSCTX_INPROC_SERVER = 1
  Local Const $CONSOLE = 0

  Local Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
  Local Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
  Local Const $sTagIMMDeviceEnumerator = _
      "EnumAudioEndpoints hresult(int;dword;ptr*);" & _
      "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _
      "GetDevice hresult(wstr;ptr*);" & _
      "RegisterEndpointNotificationCallback hresult(ptr);" & _
      "UnregisterEndpointNotificationCallback hresult(ptr)"

  Local Const $sIID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
  Local Const $sTagIMMDevice = _
      "Activate hresult(struct*;dword;ptr;ptr*);" & _
      "OpenPropertyStore hresult(dword;ptr*);" & _
      "GetId hresult(wstr*);" & _
      "GetState hresult(dword*)"

  Local Const $sIID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
  Local Const $sTagIAudioEndpointVolume = _
      "RegisterControlChangeNotify hresult(ptr);" & _
      "UnregisterControlChangeNotify hresult(ptr);" & _
      "GetChannelCount hresult(uint*);" & _
      "SetMasterVolumeLevel hresult(float;ptr);" & _
      "SetMasterVolumeLevelScalar hresult(float;ptr);" & _
      "GetMasterVolumeLevel hresult(float*);" & _
      "GetMasterVolumeLevelScalar hresult(float*);" & _
      "SetChannelVolumeLevel hresult(uint;float;ptr);" & _
      "SetChannelVolumeLevelScalar hresult(uint;float;ptr);" & _
      "GetChannelVolumeLevel hresult(uint;float*);" & _
      "GetChannelVolumeLevelScalar hresult(uint;float*);" & _
      "SetMute hresult(int;ptr);" & _
      "GetMute hresult(int*);" & _
      "GetVolumeStepInfo hresult(uint*;uint*);" & _
      "VolumeStepUp hresult(ptr);" & _
      "VolumeStepDown hresult(ptr);" & _
      "QueryHardwareSupport hresult(dword*);" & _
      "GetVolumeRange hresult(float*;float*;float*)"

  Local $pIMMDevice, $pIAudioEndpointVolume
  Local $oMMDeviceEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $sTagIMMDeviceEnumerator)
  $oMMDeviceEnumerator.GetDefaultAudioEndpoint($RENDER, $CONSOLE, $pIMMDevice)
  Local $oMMDevice = ObjCreateInterface($pIMMDevice, $sIID_IMMDevice, $sTagIMMDevice)

  $oMMDevice.Activate(_WinAPI_GUIDFromString($sIID_IAudioEndpointVolume), $CLSCTX_INPROC_SERVER, 0, $pIAudioEndpointVolume)
  Local $oIAudioEndpointVolume = ObjCreateInterface($pIAudioEndpointVolume, $sIID_IAudioEndpointVolume, $sTagIAudioEndpointVolume)
  $oIAudioEndpointVolume.SetMute($iMute, 0)
EndFunc   ;==>SetMute

:D

Thanks a lot for your responce.
I tryed to drag out to windows explorer and not working

Posted
15 hours ago, jugador said:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $gaDropFiles[1]

__Example()
Func __Example()
    GUICreate("listview items", 220, 250, 100, 200, -1, $WS_EX_ACCEPTFILES)
    GUISetBkColor(0x00E0FFFF) ; will change background color

    Local $idListview = GUICtrlCreateListView("col1", 10, 10, 200, 150)
    GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; to allow drag and dropping
    GUISetState(@SW_SHOW)
    GUIRegisterMsg ($WM_DROPFILES, "WM_DROPFILES_FUNC")

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

            Case $GUI_EVENT_DROPPED
                 For $i = 0 To UBound($gaDropFiles) - 1
                    GUICtrlCreateListViewItem($gaDropFiles[$i], $idListview)
                 Next
        EndSwitch
    WEnd
EndFunc

Func WM_DROPFILES_FUNC($hWnd, $msgID, $wParam, $lParam)
    ;~ https://www.autoitscript.com/forum/topic/28062-drop-multiple-files-on-any-control/       <by @Lazycat>
    Local $nSize, $pFileName
    Local $nAmt = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", 0xFFFFFFFF, "ptr", 0, "int", 255)
    For $i = 0 To $nAmt[0] - 1
        $nSize = DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", 0, "int", 0)
        $nSize = $nSize[0] + 1
        $pFileName = DllStructCreate("char[" & $nSize & "]")
        DllCall("shell32.dll", "int", "DragQueryFile", "hwnd", $wParam, "int", $i, "ptr", DllStructGetPtr($pFileName), "int", $nSize)
        ReDim $gaDropFiles[$i+1]
        $gaDropFiles[$i] = DllStructGetData($pFileName, 1)
        $pFileName = 0
    Next
EndFunc

 

Thanks a lot for your responce.
I copied a file inside of this coda and after 
I tryed to drag out to windows explorer and not working

Posted
8 hours ago, Netol said:

I tryed to drag out to windows explorer and not working

Wrong.  It is working good.  You need to understand why it is not working for you.  Maybe you are on an old OS ?  This was tested with Win11. 

Posted
1 hour ago, MattyD said:

But its kinda working

Yep it does, beside minor issues.  For example the cursor stays on drag mode after completion, and sound after attempting a drag over an invalid region is only heard later. But overall, it is a way better approach than my hacked endeavor :D

Posted

Thanks Nine,

Yep there's plenty left to work on. I had a couple of false starts with the DataObject, so there's some superfluous stuff in there - and there's also some questionable error checking in patches!

I'll probably do a cleanup and post a heavily commented version, just to make things a bit more intelligible. But that's probably where my energies end for this one. I'll leave the artifacts  undocumented features for others to tackle  enjoy. :P

Posted

OK curiosity got the better of me -

There seems to be a drag-drop mechanism baked into AutoIt's message handling which is causing the incessant "dinging".  I've sub-classed the GUI and done a blanket _WinAPI_DefWindowProcW() for now rather than looking for the exact cause. Bit heavy-handed but it does the trick.

Stay tuned for an example..

Posted
6 hours ago, MattyD said:

OK take 2, :)

This is quite incredible, Matty. It seems to work really well in both directions.

I'm not sure if any older reference code would be beneficial, but there is something similar from @ProgAndy over here. That one seems to drag into the GUI fine but crashes when dragging out of the GUI. It probably worked back in the day but a lot has likely changed with the OS since that time. But I figured I'd share it with you just in case some of it may be helpful.

Posted

Yeah thanks for that. It seems like Andy's created the DataObject from scratch too, which might be worth a closer look for interest's sake.

5 hours ago, WildByDesign said:

crashes when dragging out of the GUI

x64 didn't work for me, but x86 seemed to go OK? (apart from a blinging noise in one direction!). 

Posted
On 1/21/2026 at 4:21 PM, Nine said:

For the fun of it.  Here a strongly hacked way :

This is pretty neat too. Works well. I had tried it initially and I assumed that it wasn't working. That was my fault though because I was trying to drag it onto the desktop. Once I dragged to Windows Explorer, that worked great.

Speaking of Desktop. I wonder if it would be easy enough to add the ability to drop on SysListView32 class of the desktop.

I really like the technique that you use to get the currently opened directory in File Explorer with your GetExplorerPath() function.

Posted
2 hours ago, WildByDesign said:

I wonder if it would be easy enough to add the ability to drop on SysListView32 class of the desktop.

Yes it is quite easy.  Once you have identified a drop, you just need to check for desktop.  See below :

Spoiler
; From Nine
#include <GUIConstants.au3>
#include <File.au3>
#include <GuiListView.au3>
#include <WinAPI.au3>

Opt("MustDeclareVars", True)

Global Enum $NONE, $DRAG, $DROP
Global $hMSHook, $sFile, $iState = $NONE

Example()

Func Example()
  GUICreate("Listview items", 600, 450)
  Local $idListview = GUICtrlCreateListView("File Name", 10, 10, 520, 400)
  _GUICtrlListView_SetColumnWidth($idListview, 0, 480)
  Local $aList = _FileListToArray(@ScriptDir, "*.au3", Default, True)
  For $i = 1 To $aList[0]
    GUICtrlCreateListViewItem($aList[$i], $idListview)
  Next
  GUISetState()

  Local $sDir

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)

  Local $hMSProc = DllCallbackRegister(WH_MOUSE_LL, "long", "int;wparam;lparam")
  $hMSHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hMSProc), _WinAPI_GetModuleHandle(0))

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
    If $iState = $DROP Then
      $sDir = GetPathFromPoint()
      If $sDir Then
        SetMute(1)
        FileCopy($sFile, $sDir, $FC_OVERWRITE)
        Sleep(1200)
        SetMute(0)
      EndIf
      $iState = $NONE
    EndIf
  WEnd

  _WinAPI_UnhookWindowsHookEx($hMSHook)
  DllCallbackFree($hMSProc)
EndFunc   ;==>Example

Func GetPathFromPoint()
  Local $hCtrl = _WinAPI_WindowFromPoint(_WinAPI_GetMousePos())
  Local $hParent = _WinAPI_GetAncestor($hCtrl, $GA_ROOT)
  Switch _WinAPI_GetClassName($hCtrl)
    Case "DirectUIHWND"
      Local $hWnd = WinGetHandle("[CLASS:CabinetWClass]")
      If  $hParent = $hWnd Then Return GetExplorerPath($hWnd)
    Case "SysListView32"
      If $hParent = WinGetHandle("[CLASS:Progman]") Then Return @DesktopDir
  EndSwitch
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
  Local $tList = DllStructCreate($tagNMLISTVIEW, $lParam)
  If $tList.Code = $LVN_BEGINDRAG Then
    $iState = $DRAG
    $sFile = _GUICtrlListView_GetItemTextString($tList.hWndFrom, $tList.Item)
  EndIf
EndFunc   ;==>WM_NOTIFY

Func GetExplorerPath($hExplorer)
  Local $oShell = ObjCreate("Shell.Application")
  For $oWindow In $oShell.Windows()
    If $oWindow.HWND = $hExplorer Then ExitLoop
  Next
  Return StringReplace($oWindow.LocationURL, "file:///", "")
EndFunc   ;==>GetExplorerPath

Func WH_MOUSE_LL($nCode, $wParam, $lParam)
  If $nCode >= 0 And $iState = $DRAG And $wParam = $WM_LBUTTONUP Then $iState = $DROP
  Return _WinAPI_CallNextHookEx($hMSHook, $nCode, $wParam, $lParam)
EndFunc   ;==>WH_MOUSE_LL

Func SetMute($iMute)
  Local Const $RENDER = 0
  Local Const $CLSCTX_INPROC_SERVER = 1
  Local Const $CONSOLE = 0

  Local Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
  Local Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
  Local Const $sTagIMMDeviceEnumerator = _
      "EnumAudioEndpoints hresult(int;dword;ptr*);" & _
      "GetDefaultAudioEndpoint hresult(int;int;ptr*);" & _
      "GetDevice hresult(wstr;ptr*);" & _
      "RegisterEndpointNotificationCallback hresult(ptr);" & _
      "UnregisterEndpointNotificationCallback hresult(ptr)"

  Local Const $sIID_IMMDevice = "{D666063F-1587-4E43-81F1-B948E807363F}"
  Local Const $sTagIMMDevice = _
      "Activate hresult(struct*;dword;ptr;ptr*);" & _
      "OpenPropertyStore hresult(dword;ptr*);" & _
      "GetId hresult(wstr*);" & _
      "GetState hresult(dword*)"

  Local Const $sIID_IAudioEndpointVolume = "{5CDF2C82-841E-4546-9722-0CF74078229A}"
  Local Const $sTagIAudioEndpointVolume = _
      "RegisterControlChangeNotify hresult(ptr);" & _
      "UnregisterControlChangeNotify hresult(ptr);" & _
      "GetChannelCount hresult(uint*);" & _
      "SetMasterVolumeLevel hresult(float;ptr);" & _
      "SetMasterVolumeLevelScalar hresult(float;ptr);" & _
      "GetMasterVolumeLevel hresult(float*);" & _
      "GetMasterVolumeLevelScalar hresult(float*);" & _
      "SetChannelVolumeLevel hresult(uint;float;ptr);" & _
      "SetChannelVolumeLevelScalar hresult(uint;float;ptr);" & _
      "GetChannelVolumeLevel hresult(uint;float*);" & _
      "GetChannelVolumeLevelScalar hresult(uint;float*);" & _
      "SetMute hresult(int;ptr);" & _
      "GetMute hresult(int*);" & _
      "GetVolumeStepInfo hresult(uint*;uint*);" & _
      "VolumeStepUp hresult(ptr);" & _
      "VolumeStepDown hresult(ptr);" & _
      "QueryHardwareSupport hresult(dword*);" & _
      "GetVolumeRange hresult(float*;float*;float*)"

  Local $pIMMDevice, $pIAudioEndpointVolume
  Local $oMMDeviceEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $sTagIMMDeviceEnumerator)
  $oMMDeviceEnumerator.GetDefaultAudioEndpoint($RENDER, $CONSOLE, $pIMMDevice)
  Local $oMMDevice = ObjCreateInterface($pIMMDevice, $sIID_IMMDevice, $sTagIMMDevice)

  $oMMDevice.Activate(_WinAPI_GUIDFromString($sIID_IAudioEndpointVolume), $CLSCTX_INPROC_SERVER, 0, $pIAudioEndpointVolume)
  Local $oIAudioEndpointVolume = ObjCreateInterface($pIAudioEndpointVolume, $sIID_IAudioEndpointVolume, $sTagIAudioEndpointVolume)
  $oIAudioEndpointVolume.SetMute($iMute, 0)
EndFunc   ;==>SetMute

 

You can add targets easily that way.

Posted
On 1/24/2026 at 3:00 AM, MattyD said:

OK take 2, :)

let me know if anything needs more explanation, and I'll do my best.

_Demo.zip

Matty, may I please have your permission to use this code in the Files Au3 file manager project?

For curiosity sake, I tested it out there briefly. It allowed me to drag and drop nicely from the ListView but also the TreeView as well once I modified the code slightly.

Posted

I was digging into the code for Explorer++ since it uses the same drag and drop as File Explorer uses. I came across Commit 06ae949 which the developer switch from using the older DoDragDrop function to using the newer SHDoDragDrop function. For what it's worth, he leaves fantastic comments on the majority of his commits.

- The IDataObject instance is now created by the shell, which should be
  more reliable. Previously, the IDataObject instance was being
  constructed manually.
- The previous implementation wasn't working correctly. For example,
  dropping the item in a folder wasn't working.
- SHDoDragDrop() is used to perform the drag, so drag images are managed
  automatically.
- Previously, the only allowed effect set during the drag was
  DROPEFFECT_LINK. Now, DROPEFFECT_COPY and DROPEFFECT_MOVE will also be
  set, if the item can be copied/moved. The preferred drop effect is set
  to DROPEFFECT_LINK. This matches the behaviour of Windows Explorer.

Since I was researching this earlier this morning, I figured that I would put it out there just in case I forget later.

Posted
2 hours ago, WildByDesign said:

may I please have your permission

sure thing :) 

31 minutes ago, WildByDesign said:

switch from using the older DoDragDrop function to using the newer SHDoDragDrop function

Fair enough - it's quite easy to swap out.

It looks like if you don't specify a DropSource object, SHDoDragDrop will create one for you - so that significantly simplifies things...  We lose some control over QueryContinueDrag etc, but TBH how much customization do we really want to do there anyway?

Supposedly it's meant to make working with drag images easier too. (if we want more than that cursor with the little plus-in-a-box). But to be fair I haven't really explored that side of things.  I think the next thing for me is probably getting a multi-file drop from our app working. 

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...