Jump to content
Ward

DragDropEvent UDF - Handle OLE DragDrop Event

Recommended Posts

Ward

To deal with OLE drag-and-drop event is painful in autoit. is an exmaple from ProgAndy (thanks). But since we have AutoItObject UDF, it should go easy. However, there are still a lot of works to do. So I wrote the UDF to convert OLE drag-and-drop event to "Windows Message" event that can be easily handled by GUIRegisterMsg() in AutoIt.

 

This UDF provides 4 kinds of message: $WM_DRAGENTER, $WM_DRAGOVER, $WM_DRAGLEAVE, and $WM_DROP. To use is easy, just register a GUI window or control as the drop target, then handle message by GUIRegisterMsg(). See example:

 

 

#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>
#Include "DragDropEvent.au3"

Opt("MustDeclareVars", 1)

DragDropEvent_Startup()
Main()
Exit

Func Main()
    Local $MainWin = GUICreate("DragDropEvent Example", 380, 130, -1, -1, -1, $WS_EX_TOPMOST)
    GUISetFont(12, 900)
    GUICtrlCreateLabel("(Drop text or files on me)", 40, 40)

    DragDropEvent_Register($MainWin)

    GUIRegisterMsg($WM_DRAGENTER, "OnDragDrop")
    GUIRegisterMsg($WM_DRAGOVER, "OnDragDrop")
    GUIRegisterMsg($WM_DRAGLEAVE, "OnDragDrop")
    GUIRegisterMsg($WM_DROP, "OnDragDrop")

    GUISetState(@SW_SHOW)
    While GUIGetMsg() <> $GUI_EVENT_CLOSE
    WEnd
    GUIDelete()
EndFunc

Func OnDragDrop($hWnd, $Msg, $wParam, $lParam)
    Static $DropAccept

    Switch $Msg
        Case $WM_DRAGENTER, $WM_DROP
            ToolTip("")
            Select
                Case DragDropEvent_IsFile($wParam)
                    If $Msg = $WM_DROP Then
                        Local $FileList = DragDropEvent_GetFile($wParam)
                        MsgBox(262144, "DragDropEvent", StringReplace($FileList, "|", @LF))
                    EndIf
                    $DropAccept = $DROPEFFECT_COPY

                Case DragDropEvent_IsText($wParam)
                    If $Msg = $WM_DROP Then
                        MsgBox(262144, "DragDropEvent", DragDropEvent_GetText($wParam))
                    EndIf
                    $DropAccept = $DROPEFFECT_COPY

                Case Else
                    $DropAccept = $DROPEFFECT_NONE

            EndSelect
            Return $DropAccept

        Case $WM_DRAGOVER
            Local $X = DragDropEvent_GetX($wParam)
            Local $Y = DragDropEvent_GetY($wParam)
            ToolTip("(" & $X & "," & $Y & ")")
            Return $DropAccept

        Case $WM_DRAGLEAVE
            ToolTip("")

    EndSwitch
EndFunc

 

== Public Functions List ==

 

DragDropEvent_Startup()
; DragDropEvent UDF startup.
;
DragDropEvent_Register($hWnd, $hWndToReceiveMsg = $hWnd)
;   Register a window or control that can be the target. $hWndToReceiveMsg is needed only when $hWnd is a control.
;
DragDropEvent_Revoke($hWnd)
;   Revokes the registration of the specified window or control.
;
DragDropEvent_GetHWnd($wParam)
;   Can invoke by all message handler, to get what window or control is the target.
;
DragDropEvent_GetX($wParam)
DragDropEvent_GetY($wParam)
DragDropEvent_GetKeyState($wParam)
;   Can invoke by all message handler except $WM_DRAGLEAVE, to get the modifier keys and mouse position.
;
DragDropEvent_IsText($wParam)
DragDropEvent_IsFile($wParam)
;   Can invoke by $WM_DRAGENTER or $WM_DROP, to check what data is being dragged.
;
DragDropEvent_GetText($wParam)
DragDropEvent_GetFile($wParam)
;   Can invoke by $WM_DRAGENTER or $WM_DROP, to get related data. Path of file is splited by "|".
;

 

== Requirement ==

 

Attachment not includes above requirement files, but includes more examples.

 

== Update 2012/3/10 ==

* Fix x64 problem. (Thanks to trancexx)

* Remove dependency to AutoItObject and Associative Array UDF. (Suggestion by wraithdu)

 

== Update 2012/3/15==

* Remove dependency to Bianry UDF.

* Remove extra DllStructGetPtr(). (Suggestion by trancexx)

* Fix bug in DataObject_GetFile().

 

DragDropEvent.zip

Edited by Ward
  • Like 1

新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites
trancexx

Excellent as always with you.

Are you sure you got the x64 issue correctly. By looking at the code the problem with x64 could be struct parameter for methods of that interface. You have used POINTL = uint;uint logic, but that's valid only for x86 (it should be long;long btw).


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
outdated

good examples

but dunno where u can use it

$WS_EX_ACCEPTFILES for me it enough

Share this post


Link to post
Share on other sites
Ward

@trancexx

Thank you for always find the problem. :oops:

Now I use uint64 to receive the POINTL struct. It works both x86 and x64.

@macwcodvs

$WS_EX_ACCEPTFILES and $WM_DROPFILES are what I use before.

If you don't want to handle text and mouse enter / leave / over event. They are enough.

I wrote these UDF because my new program need to drag files to a TreeView control. However, when use WM_DROPFILES, I don't know where to insert the new node.


新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites
wraithdu

Could this be updated to use the new internal ObjCreateInterface function? That would remove the req for AutoItObject.

Edited by wraithdu

Share this post


Link to post
Share on other sites
Ward

@wraithdu, using ObjCreateInterface need to write a replacement of _AutoItObject_ObjectFromDtag.

It should not hard, just copy the code from AutoItObject.au3...


新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites
Ward

@wraithdu, I just done what you suggested !

Since need to rewrite _AutoItObject_ObjectFromDtag, I also removed a memory leakage and the dependency to associative array UDF (instead of using associative array, I store the hwnd data just in the interface vtable).


新版 _ArrayAdd 的白痴作者,不管是誰,去死一死好了

 

Share this post


Link to post
Share on other sites
trancexx

By using built-in function you have some new data types available, like struct*. If you specify that inside description strings instead of ptr, you don't need tedious DllStructGetPtr() every time you try to pass pointer of a struct.

struct* will accept either pointer or a structure itself (in which case it will query for pointer internally).

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites
Saiph

Hi,

your udf is wonderful and works with Opera and Chrome but not with Firefox. When I drag and drop an image from Firefox to a your example Gui it says me C:UsersmyuserAppDataLocalTempagkri35bho.bmp and not the internet address.

Can you suufest me a solution?

Thanks

Share this post


Link to post
Share on other sites
prazetto

@Saiph

Thats aren't UDF fault but what browser like Mozillia Firefox or Seamonkey add to DragDrop source.


# Button. Progressbar - Graphical AutoIt3 Control (UDF) # GTK on AutoIt3 - GTK+ Framework | Widgets

Share this post


Link to post
Share on other sites
Chimp
1 hour ago, Zedna said:

Please can somebody upload missing file DragDropEvent.zip?

Thanks

I haven't the zip file, but probably these three listings were in that zip:

DragDropEvent.au3

; ===============================================================================================================================
; File     : DragDropEvent.au3 (2012/3/15)
; Purpose  : Convert OLE drag-and-drop event to "Windows Message" that AutoIt3 can handle by GUIRegisterMsg
;            Provide 4 message: $WM_DRAGENTER, $WM_DRAGOVER, $WM_DRAGLEAVE, and $WM_DROP
; Author   : Ward
; ===============================================================================================================================

#Include-once
#Include <Memory.au3>
#Include <SendMessage.au3>
#Include <WindowsConstants.au3>

; ===============================================================================================================================
; Public Functions:
;
; DragDropEvent_Startup()
;   DragDropEvent UDF startup.
;
; DragDropEvent_Register($hWnd, $hWndToReceiveMsg = $hWnd)
;   Register a window or control that can be the target. $hWndToReceiveMsg is needed only when $hWnd is a control.
;
; DragDropEvent_Revoke($hWnd)
;   Revokes the registration of the specified window or control.
;
; DragDropEvent_GetHWnd($wParam)
;   Can invoke by all message handler, to get what window or control is the target.
;
; DragDropEvent_GetX($wParam)
; DragDropEvent_GetY($wParam)
; DragDropEvent_GetKeyState($wParam)
;   Can invoke by all message handler except $WM_DRAGLEAVE, to get the modifier keys and mouse position.
;
; DragDropEvent_IsText($wParam)
; DragDropEvent_IsFile($wParam)
;   Can invoke by $WM_DRAGENTER or $WM_DROP, to check what data is being dragged.
;
; DragDropEvent_GetText($wParam)
; DragDropEvent_GetFile($wParam)
;   Can invoke by $WM_DRAGENTER or $WM_DROP, to get related data. Path of file is splited by "|".
;
; ===============================================================================================================================

; ===============================================================================================================================
; Internal Functions:
;
; IDropTarget_QueryInterface($pSelf, $pRIID, $pObj)
; IDropTarget_AddRef($pSelf)
; IDropTarget_Release($pSelf)
; IDropTarget_DragEnter($pSelf, $DataObj, $KeyState, $X, $Y, $pEffect)
; IDropTarget_DragLeave($pSelf)
; IDropTarget_DragOver($pSelf, $KeyState, $X, $Y, $pEffect)
; IDropTarget_Drop($pSelf, $DataObj, $KeyState, $X, $Y, $pEffect)
; IDropTarget_SetEffect($pEffect, $Value)
;   Methods of IDropTarget interface.
;
; IDropTarget_SetHWnd($pSelf, $hWnd, $hWndToReceiveMsg)
; IDropTarget_GetHWnd($pSelf, ByRef $hWnd, ByRef $hWndToReceiveMsg)
;   To set and get data store in IDropTarget interface.
;
; DataObject_QueryText($DataObj)
; DataObject_QueryFile($DataObj)
; DataObject_GetText($DataObj)
; DataObject_GetFile($DataObj)
;   Functions to handle DataObject.
;
; DragDropEvent_InfoCreate($hWnd, $DataObj, $KeyState, $X, $Y)
; DragDropEvent_Get($wParam, $Name)
;   Functions to handle infomation data for DragDropEvent.
;
; __CreateCOMInterface($sFunctionPrefix, $dtagInterface, $fNoUnknown = False, $ExtraSpace = 0)
;   To create vtable of a COM interface. Modify from _AutoItObject_ObjectFromDtag.
;
; ===============================================================================================================================

; ===============================================================================================================================
; Global const and variables
; ===============================================================================================================================

; Define 4 kind of DragDropEvent: DragEnter, DragOver, DragLeave, and Drop
Global Enum $WM_DRAGENTER = $WM_USER + 0x1001, $WM_DRAGOVER, $WM_DRAGLEAVE, $WM_DROP

; Message handler return one of these flags, which indicates what the result of the drop operation would be.
Global Enum $DROPEFFECT_NONE = 0, $DROPEFFECT_COPY = 1, $DROPEFFECT_MOVE = 2, $DROPEFFECT_LINK = 4, $DROPEFFECT_SCROLL = 0x80000000

Global Const $IID_IDataObject = "{0000010e-0000-0000-C000-000000000046}"

Global Const $dtagIDropTarget = "DragEnter hresult(ptr;uint;uint64;ptr);DragOver hresult(uint;uint64;ptr);DragLeave hresult();Drop hresult(ptr;uint;uint64;ptr);"
Global Const $dtagIDataObject = "GetData hresult(struct*;struct*);GetDataHere hresult(struct*;struct*);QueryGetData hresult(struct*);GetCanonicalFormatEtc hresult(struct*;struct*);SetData hresult(struct*;struct*;int);EnumFormatEtc hresult(uint;ptr);DAdvise hresult(struct*;uint;ptr;ptr);DUnadvise hresult(uint);EnumDAdvise hresult(ptr);"

Global Const $tagFORMATETC = "struct;uint Format;ptr ptd;uint Aspect;int lindex;uint tymed;endstruct"
Global Const $tagSTGMEDIUM = "struct;uint tymed;ptr hGlobal;ptr UnkForRelease;endstruct"
Global Const $tagDragDropEventInfo = "ptr hwnd;ptr DataObj;uint KeyState;uint x;uint y"

Global Const $__KERNEL32_DLL = DllOpen("kernel32.dll")
Global Const $__OLE32_DLL = DllOpen("ole32.dll")
Global $__IDropTargetLen = 0

; ===============================================================================================================================
; DragDropEvent startup and register functions
; ===============================================================================================================================

Func DragDropEvent_Startup()
    ; If @AutoItVersion < "3.3.8.0" Then Exit MsgBox(16, "DragDropEvent Fail", "Require AutoIt Version 3.3.8.0 at least")

    DllCall($__OLE32_DLL, "int", "OleInitialize", "ptr", 0)
EndFunc

Func DragDropEvent_Register($hWnd, $hWndToReceiveMsg = Default)
    If IsKeyword($hWndToReceiveMsg) Then $hWndToReceiveMsg = $hWnd

    Local $IDropTarget = __CreateCOMInterface("IDropTarget_", $dtagIDropTarget, True, 2) ; add 2 extra space to store hWnd
    If $IDropTarget Then
        $__IDropTargetLen = @Extended

        IDropTarget_SetHWnd($IDropTarget, $hWnd, $hWndToReceiveMsg)
        DllCall($__OLE32_DLL, "int", "RegisterDragDrop", "hwnd", $hWnd, "ptr", $IDropTarget)
    EndIf
EndFunc

Func DragDropEvent_Revoke($hWnd)
    DllCall($__OLE32_DLL, "int", "RevokeDragDrop", "hwnd", $hWnd)
EndFunc

; ===============================================================================================================================
; Methods of IDropTarget interface
; ===============================================================================================================================

Func IDropTarget_QueryInterface($pSelf, $pRIID, $pObj)
    Return 0x80004002 ; E_NOINTERFACE
EndFunc

Func IDropTarget_AddRef($pSelf)
EndFunc

Func IDropTarget_Release($pSelf)
    DllCall($__OLE32_DLL, "none", "CoTaskMemFree", "ptr", $pSelf)
EndFunc

Func IDropTarget_DragEnter($pSelf, $DataObj, $KeyState, $Point, $pEffect)
    Local $hWnd, $hWndToReceiveMsg
    IDropTarget_GetHWnd($pSelf, $hWnd, $hWndToReceiveMsg)

    Local $X = BitAND($Point, 0xFFFFFFFF), $Y = Dec(StringTrimRight(Hex($Point), 8))
    Local $Info = DragDropEvent_InfoCreate($hWnd, $DataObj, $KeyState, $X, $Y)
    Local $Ret = _SendMessage($hWndToReceiveMsg, $WM_DRAGENTER, DllStructGetPtr($Info), 0)
    DllStructSetData(DllStructCreate("dword", $pEffect), 1, $Ret)
EndFunc

Func IDropTarget_DragLeave($pSelf)
    Local $hWnd, $hWndToReceiveMsg
    IDropTarget_GetHWnd($pSelf, $hWnd, $hWndToReceiveMsg)

    Local $Info = DragDropEvent_InfoCreate($hWnd, 0, 0, 0, 0)
    _SendMessage($hWndToReceiveMsg, $WM_DRAGLEAVE, DllStructGetPtr($Info), 0)
EndFunc

Func IDropTarget_DragOver($pSelf, $KeyState, $Point, $pEffect)
    Local $hWnd, $hWndToReceiveMsg
    IDropTarget_GetHWnd($pSelf, $hWnd, $hWndToReceiveMsg)

    Local $X = BitAND($Point, 0xFFFFFFFF), $Y = Dec(StringTrimRight(Hex($Point), 8))
    Local $Info = DragDropEvent_InfoCreate($hWnd, 0, $KeyState, $X, $Y)
    Local $Ret = _SendMessage($hWndToReceiveMsg, $WM_DRAGOVER, DllStructGetPtr($Info), 0)
    DllStructSetData(DllStructCreate("dword", $pEffect), 1, $Ret)
EndFunc

Func IDropTarget_Drop($pSelf, $DataObj, $KeyState, $Point, $pEffect)
    Local $hWnd, $hWndToReceiveMsg
    IDropTarget_GetHWnd($pSelf, $hWnd, $hWndToReceiveMsg)

    Local $X = BitAND($Point, 0xFFFFFFFF), $Y = Dec(StringTrimRight(Hex($Point), 8))
    Local $Info = DragDropEvent_InfoCreate($hWnd, $DataObj, $KeyState, $X, $Y)
    Local $Ret = _SendMessage($hWndToReceiveMsg, $WM_DROP, DllStructGetPtr($Info), 0)
    DllStructSetData(DllStructCreate("dword", $pEffect), 1, $Ret)
EndFunc

Func IDropTarget_SetHWnd($pSelf, $hWnd, $hWndToReceiveMsg)
    Local $Buffer = DllStructCreate("ptr[" & ($__IDropTargetLen + 2) & "]", $pSelf)
    DllStructSetData($Buffer, 1, $hWnd, $__IDropTargetLen + 1)
    DllStructSetData($Buffer, 1, $hWndToReceiveMsg, $__IDropTargetLen + 2)
EndFunc

Func IDropTarget_GetHWnd($pSelf, ByRef $hWnd, ByRef $hWndToReceiveMsg)
    Local $Buffer = DllStructCreate("ptr[" & ($__IDropTargetLen + 2) & "]", $pSelf)
    $hWnd = DllStructGetData($Buffer, 1, $__IDropTargetLen + 1)
    $hWndToReceiveMsg = DllStructGetData($Buffer, 1, $__IDropTargetLen + 2)
EndFunc

; ===============================================================================================================================
; Functions to handle DataObject
; ===============================================================================================================================

Func DataObject_QueryText($DataObj)
    Local $IDataObj = ObjCreateInterface($DataObj, $IID_IDataObject, $dtagIDataObject)
    If Not IsObj($IDataObj) Then Return -1
    $IDataObj.AddRef()

    Local $FORMATETC = DllStructCreate($tagFORMATETC)
    DllStructSetData($FORMATETC, "Format", 13) ; 13 = CF_UNICODETEXT
    DllStructSetData($FORMATETC, "Aspect", 1)
    DllStructSetData($FORMATETC, "lindex", -1)
    DllStructSetData($FORMATETC, "tymed", 1) ; 1 = TYMED_HGLOBAL

    Local $Ret = $IDataObj.QueryGetData($FORMATETC)
    If $Ret <> 0 Then
        DllStructSetData($FORMATETC, "Format", 1) ; 1 = CF_TEXT
        $Ret = $IDataObj.QueryGetData($FORMATETC)
    EndIf
    Return $Ret
EndFunc

Func DataObject_QueryFile($DataObj)
    Local $IDataObj = ObjCreateInterface($DataObj, $IID_IDataObject, $dtagIDataObject)
    If Not IsObj($IDataObj) Then Return -1
    $IDataObj.AddRef()

    Local $FORMATETC = DllStructCreate($tagFORMATETC)
    DllStructSetData($FORMATETC, "Format", 15) ; 15 = CF_HDROP
    DllStructSetData($FORMATETC, "Aspect", 1)
    DllStructSetData($FORMATETC, "lindex", -1)
    DllStructSetData($FORMATETC, "tymed", 1) ; 1 = TYMED_HGLOBAL
    Return $IDataObj.QueryGetData($FORMATETC)
EndFunc

Func DataObject_GetText($DataObj)
    Local $IDataObj = ObjCreateInterface($DataObj, $IID_IDataObject, $dtagIDataObject)
    If Not IsObj($IDataObj) Then Return -1
    $IDataObj.AddRef()

    Local $FORMATETC = DllStructCreate($tagFORMATETC)
    Local $STGMEDIUM = DllStructCreate($tagSTGMEDIUM)
    DllStructSetData($FORMATETC, "Format", 13) ; 13 = CF_UNICODETEXT
    DllStructSetData($FORMATETC, "Aspect", 1)
    DllStructSetData($FORMATETC, "lindex", -1)
    DllStructSetData($FORMATETC, "tymed", 1) ; 1 = TYMED_HGLOBAL

    Local $IsUnicode = True
    Local $Ret = $IDataObj.QueryGetData($FORMATETC)
    If $Ret <> 0 Then
        $IsUnicode = False
        DllStructSetData($FORMATETC, "Format", 1) ; 1 = CF_TEXT
        $Ret = $IDataObj.QueryGetData($FORMATETC)
    EndIf
    If $Ret <> 0 Then Return SetError(1, 0, "")

    Local $Error = 1, $Text = ""
    If $IDataObj.GetData($FORMATETC, $STGMEDIUM) = 0 Then
        If DllStructGetData($STGMEDIUM, "tymed") = 1 Then
            Local $Ptr = _MemGlobalLock(DllStructGetData($STGMEDIUM, "hGlobal"))
            Local $Tag
            If $IsUnicode Then
                $Tag = "wchar[" & (_MemGlobalSize($Ptr) / 2) & "]"
            Else
                $Tag = "char[" & _MemGlobalSize($Ptr) & "]"
            EndIf
            $Text = DllStructGetData(DllStructCreate($Tag, $Ptr), 1)
            _MemGlobalUnlock($Ptr)
            If DllStructGetData($STGMEDIUM, "UnkForRelease") = 0 Then _MemGlobalFree($Ptr)
            $Error = 0
        EndIf
    EndIf
    Return SetError($Error, 0, $Text)
EndFunc

Func DataObject_GetFile($DataObj)
    Local $IDataObj = ObjCreateInterface($DataObj, $IID_IDataObject, $dtagIDataObject)
    If Not IsObj($IDataObj) Then Return -1
    $IDataObj.AddRef()

    Local $FORMATETC = DllStructCreate($tagFORMATETC)
    Local $STGMEDIUM = DllStructCreate($tagSTGMEDIUM)
    DllStructSetData($FORMATETC, "Format", 15) ; 15 = CF_HDROP
    DllStructSetData($FORMATETC, "Aspect", 1)
    DllStructSetData($FORMATETC, "lindex", -1)
    DllStructSetData($FORMATETC, "tymed", 1) ; 1 = TYMED_HGLOBAL

    Local $Error = 1, $FileList = ""
    If $IDataObj.GetData($FORMATETC, $STGMEDIUM) = 0 Then
        If DllStructGetData($STGMEDIUM, "tymed") = 1 Then
            Local $Ptr = _MemGlobalLock(DllStructGetData($STGMEDIUM, "hGlobal"))
            Local $StrPtr = $Ptr + DllStructGetData(DllStructCreate("dword", $Ptr), 1)
            Do
                Local $Ret = DllCall($__KERNEL32_DLL, "uint", "lstrlenW", "ptr", $StrPtr)
                Local $StrLen = $Ret[0]
                If $StrLen Then
                    Local $Str = DllStructGetData(DllStructCreate("wchar[" & $StrLen & "]", $StrPtr), 1)
                    $FileList &= $Str & "|"
                    $StrPtr += $StrLen * 2 + 2
                EndIf
            Until $StrLen = 0
            If StringRight($FileList, 1) = "|" Then $FileList = StringTrimRight($FileList, 1)
            _MemGlobalUnlock($Ptr)
            If DllStructGetData($STGMEDIUM, "UnkForRelease") = 0 Then _MemGlobalFree($Ptr)
            $Error = 0
        EndIf
    EndIf
    Return SetError($Error, 0, $FileList)
EndFunc

; ===============================================================================================================================
; Functions to handle infomation data for DragDropEvent
; ===============================================================================================================================

Func DragDropEvent_InfoCreate($hWnd, $DataObj, $KeyState, $X, $Y)
    Local $Info = DllStructCreate($tagDragDropEventInfo)
    DllStructSetData($Info, "hwnd", $hWnd)
    DllStructSetData($Info, "DataObj", $DataObj)
    DllStructSetData($Info, "KeyState", $KeyState)
    DllStructSetData($Info, "x", $X)
    DllStructSetData($Info, "y", $Y)
    Return $Info
EndFunc

Func DragDropEvent_Get($wParam, $Name)
    If Not $wParam Then Return SetError(1, 0, 0)
    Local $Info = DllStructCreate($tagDragDropEventInfo, $wParam)
    Return DllStructGetData($Info, $Name)
EndFunc

Func DragDropEvent_GetHWnd($wParam)
    Local $Ret = DragDropEvent_Get($wParam, "hwnd")
    Return SetError(@Error, 0, $Ret)
EndFunc

Func DragDropEvent_GetX($wParam)
    Local $Ret = DragDropEvent_Get($wParam, "x")
    Return SetError(@Error, 0, $Ret)
EndFunc

Func DragDropEvent_GetY($wParam)
    Local $Ret = DragDropEvent_Get($wParam, "y")
    Return SetError(@Error, 0, $Ret)
EndFunc

Func DragDropEvent_GetKeyState($wParam)
    Local $Ret = DragDropEvent_Get($wParam, "KeyState")
    Return SetError(@Error, 0, $Ret)
EndFunc

Func DragDropEvent_IsText($wParam)
    Local $DataObj = DragDropEvent_Get($wParam, "DataObj")
    Return DataObject_QueryText($DataObj) = 0
EndFunc

Func DragDropEvent_IsFile($wParam)
    Local $DataObj = DragDropEvent_Get($wParam, "DataObj")
    Return DataObject_QueryFile($DataObj) = 0
EndFunc

Func DragDropEvent_GetText($wParam)
    Local $DataObj = DragDropEvent_Get($wParam, "DataObj")
    Return DataObject_GetText($DataObj)
EndFunc

Func DragDropEvent_GetFile($wParam)
    Local $DataObj = DragDropEvent_Get($wParam, "DataObj")
    Return DataObject_GetFile($DataObj)
EndFunc

; ===============================================================================================================================
; Functions to create COM interface
; ===============================================================================================================================

Func __CreateCOMInterface($sFunctionPrefix, $dtagInterface, $fNoUnknown = False, $ExtraSpace = 0)
    ; Original is _AutoItObject_ObjectFromDtag in AutoItObject.au3 by AutoItObject-Team
    ; Modify by Ward

    Local Const $__PtrSize = DllStructGetSize(DllStructCreate('ptr', 1))
    Local Const $dtagIUnknown = "QueryInterface hresult(ptr;ptr*);AddRef dword();Release dword();"

    If $fNoUnknown Then $dtagInterface = $dtagIUnknown & $dtagInterface
    Local $sMethods = StringReplace(StringRegExpReplace($dtagInterface, "\h*(\w+)\h*(\w+\*?)\h*(\((.*?)\))\h*(;|;*\z)", "$1\|$2;$4" & @LF), ";" & @LF, @LF)
    If $sMethods = $dtagInterface Then $sMethods = StringReplace(StringRegExpReplace($dtagInterface, "\h*(\w+)\h*(;|;*\z)", "$1\|" & @LF), ";" & @LF, @LF)
    $sMethods = StringTrimRight($sMethods, 1)
    $sMethods = StringReplace(StringReplace(StringReplace(StringReplace($sMethods, "object", "idispatch"), "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 $AllocSize = $__PtrSize * ($iUbound + 1 + $ExtraSpace)
    Local $Ret = DllCall($__OLE32_DLL, "ptr", "CoTaskMemAlloc", "uint_ptr", $AllocSize)
    If @error Then Return SetError(1, 0, 0)
    Local $AllocPtr = $Ret[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

        ; To avoid repeat allocate the same callback, a memory leakage
        $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 SetExtended($iUbound + 1, $AllocPtr) ; Return interface size as @Extended for access extra space
EndFunc

DragDropEvent_Example_1.au3

; ===============================================================================================================================
; File     : DragDropEvent_Example_1.au3 (2012/3/9)
; Purpose  : Demonstrate the usage of DragDropEvent UDF
; Author   : Ward
; ===============================================================================================================================

#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>
#Include "DragDropEvent.au3"

Opt("MustDeclareVars", 1)

DragDropEvent_Startup()
Main()
Exit

Func Main()
    Local $MainWin = GUICreate("DragDropEvent Example", 380, 130, -1, -1, -1, $WS_EX_TOPMOST)
    GUISetFont(12, 900)
    GUICtrlCreateLabel("(Drop text or files on me)", 40, 40)

    DragDropEvent_Register($MainWin)

    GUIRegisterMsg($WM_DRAGENTER, "OnDragDrop")
    GUIRegisterMsg($WM_DRAGOVER, "OnDragDrop")
    GUIRegisterMsg($WM_DRAGLEAVE, "OnDragDrop")
    GUIRegisterMsg($WM_DROP, "OnDragDrop")

    GUISetState(@SW_SHOW)
    While GUIGetMsg() <> $GUI_EVENT_CLOSE
    WEnd
    GUIDelete()
EndFunc

Func OnDragDrop($hWnd, $Msg, $wParam, $lParam)
    Static $DropAccept

    Switch $Msg
        Case $WM_DRAGENTER, $WM_DROP
            ToolTip("")
            Select
                Case DragDropEvent_IsFile($wParam)
                    If $Msg = $WM_DROP Then
                        Local $FileList = DragDropEvent_GetFile($wParam)
                        MsgBox(262144, "DragDropEvent", StringReplace($FileList, "|", @LF))
                    EndIf
                    $DropAccept = $DROPEFFECT_COPY

                Case DragDropEvent_IsText($wParam)
                    If $Msg = $WM_DROP Then
                        MsgBox(262144, "DragDropEvent", DragDropEvent_GetText($wParam))
                    EndIf
                    $DropAccept = $DROPEFFECT_COPY

                Case Else
                    $DropAccept = $DROPEFFECT_NONE

            EndSelect
            Return $DropAccept

        Case $WM_DRAGOVER
            Local $X = DragDropEvent_GetX($wParam)
            Local $Y = DragDropEvent_GetY($wParam)
            ToolTip("(" & $X & "," & $Y & ")")
            Return $DropAccept

        Case $WM_DRAGLEAVE
            ToolTip("")

    EndSwitch
EndFunc

DragDropEvent_Example_2.au3

; ===============================================================================================================================
; File     : DragDropEvent_Example_2.au3 (2012/3/9)
; Purpose  : Demonstrate the usage of DragDropEvent UDF
; Author   : Ward
; ===============================================================================================================================

#Include <GUIConstantsEx.au3>
#Include <WindowsConstants.au3>
#Include "DragDropEvent.au3"

Opt("MustDeclareVars", 1)

Global $Button1, $Button2, $Button3, $Button4

DragDropEvent_Startup()
Main()
Exit

Func Main()
    Local $MainWin = GUICreate("DragDropEvent Example", 460, 400, -1, -1, -1, $WS_EX_TOPMOST)
    GUISetFont(12, 900)

    $Button1 = GUICtrlCreateButton("Drop Text", 20, 20, 200, 150)
    $Button2 = GUICtrlCreateButton("Drop Files", 240, 20, 200, 150)
    $Button3 = GUICtrlCreateButton("Drop Anything", 20, 190, 200, 150)
    $Button4 = GUICtrlCreateButton("Don't Drop", 240, 190, 200, 150)
    GUICtrlCreateLabel("(Click button to revoke the target)", 40, 350)

    DragDropEvent_Register(GUICtrlGetHandle($Button1), $MainWin)
    DragDropEvent_Register(GUICtrlGetHandle($Button2), $MainWin)
    DragDropEvent_Register(GUICtrlGetHandle($Button3), $MainWin)
    DragDropEvent_Register(GUICtrlGetHandle($Button4), $MainWin)

    GUIRegisterMsg($WM_DRAGENTER, "OnDragDrop")
    GUIRegisterMsg($WM_DRAGOVER, "OnDragDrop")
    GUIRegisterMsg($WM_DRAGLEAVE, "OnDragDrop")
    GUIRegisterMsg($WM_DROP, "OnDragDrop")

    GUISetState(@SW_SHOW)
    While 1
        Local $Msg = GUIGetMsg()
        Switch $Msg
            Case $Button1, $Button2, $Button3, $Button4
                DragDropEvent_Revoke(GUICtrlGetHandle($Msg))

            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd

    GUIDelete()
EndFunc

Func OnDragDrop($hWnd, $Msg, $wParam, $lParam)
    Static $DropAccept

    Switch $Msg
        Case $WM_DRAGENTER, $WM_DROP
            ToolTip("")
            Local $Target = DragDropEvent_GetHWnd($wParam)
            Select
                Case DragDropEvent_IsFile($wParam)
                    If $Target = GUICtrlGetHandle($Button1) Or $Target = GUICtrlGetHandle($Button4) Then
                        $DropAccept = $DROPEFFECT_NONE
                    Else
                        If $Msg = $WM_DROP Then
                            Local $FileList = DragDropEvent_GetFile($wParam)
                            MsgBox(262144, "DragDropEvent", StringReplace($FileList, "|", @LF))
                        EndIf
                        $DropAccept = $DROPEFFECT_COPY
                    EndIf

                Case DragDropEvent_IsText($wParam)
                    If $Target = GUICtrlGetHandle($Button2) Or $Target = GUICtrlGetHandle($Button4) Then
                        $DropAccept = $DROPEFFECT_NONE
                    Else
                        If $Msg = $WM_DROP Then
                            MsgBox(262144, "DragDropEvent", DragDropEvent_GetText($wParam))
                        EndIf
                        $DropAccept = $DROPEFFECT_COPY
                    EndIf

                Case Else
                    $DropAccept = $DROPEFFECT_NONE

            EndSelect
            Return $DropAccept

        Case $WM_DRAGOVER
            Local $X = DragDropEvent_GetX($wParam)
            Local $Y = DragDropEvent_GetY($wParam)
            Local $KeyState = DragDropEvent_GetKeyState($wParam)
            ToolTip("(" & $X & "," & $Y & "," & $KeyState & ")")
            Return $DropAccept

        Case $WM_DRAGLEAVE
            ToolTip("")

    EndSwitch
EndFunc

 

  • Like 1

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

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

×