Drag & Drop from AHK GUI [DAW Reaper]
Drag & Drop from AHK GUI [DAW Reaper]
Is there as way to drag and drop a file FROM the AHK GUI ?
Say it is link to a song.wav in a folder and I want to drag into an application, rather than dragging a song.wav onto the AHK GUI.
So if I process a wav file with the script then when it has been processed I can drag it from a point on th AHK GUI into an application.
Say it is link to a song.wav in a folder and I want to drag into an application, rather than dragging a song.wav onto the AHK GUI.
So if I process a wav file with the script then when it has been processed I can drag it from a point on th AHK GUI into an application.
Last edited by BoBo on 20 Jan 2022, 01:14, edited 1 time in total.
Reason: Added [DAW Reaper] to the subject line to "search-tag" the thread.
Reason: Added [DAW Reaper] to the subject line to "search-tag" the thread.
Re: Drag & Drop from AHK GUI
Say if I have a list box with the a list of files in a folder and I want to drag a file name from the list into an application using windows drag n drop function.
Any way to do this in a AHK GUI ?
Any way to do this in a AHK GUI ?
Re: Drag & Drop from AHK GUI
sure, u just need to:
https://github.com/AHK-just-me/DoDragDrop
- determine when someone is "trying to drag away a listbox entry from the listbox"
- implement an IDropSource interface and initiate DoDragDrop()
https://github.com/AHK-just-me/DoDragDrop
-
- Posts: 4352
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Drag & Drop from AHK GUI
I tried to implement dragging from the listbox:
It seems to work, but there is an issue. DoDragDrop doesn't return until the mouse is reliesed, so it blocks all ListBox notifications, ListBox doesn't understand what's happening and behaves strangely. Maybe someone has ideas how to workaround this.
Code: Select all
folderToParse := A_MyDocuments
FileArr := {}, fileNames := ""
Loop, Files, % folderToParse . "\*.*", FD
{
fileNames .= (A_Index = 1 ? "" : "|") . A_LoopFileName
FileArr[A_Index - 1] := A_LoopFileFullPath
}
Gui, Font, s10
Gui, Add, ListBox, r15 w300 hwndhLB, % fileNames
Gui, Show
DllCall("MakeDragList", "Ptr", hLB)
DRAGLISTMSGSTRING := "commctrl_DragListMsg"
msg := DllCall("RegisterWindowMessage", "Str", DRAGLISTMSGSTRING)
OnMessage(msg, Func("OnDrag").Bind(FileArr))
Return
OnDrag(FileArr, wp, lp) {
static DL_BEGINDRAG := 1157, DROPEFFECT_COPY := 1
notification := NumGet(lp + 0, "UInt")
hListBox := NumGet(lp + A_PtrSize)
POINT := NumGet(lp + A_PtrSize*2, "UInt64")
item := DllCall("LBItemFromPt", "Ptr", hListBox, "UInt64", POINT, "UInt", true)
if (notification = DL_BEGINDRAG) {
DropSource := new IDropSource
IDataObject := GetDataObject(FileArr[item])
DllCall("Ole32\DoDragDrop", "Ptr", IDataObject, "Ptr", DropSource.ptr, "UInt", DROPEFFECT_COPY, "UIntP", effect)
ObjRelease(IDataObject), DropSource := ""
Return true
}
}
GetDataObject(filePath) {
static IID_IDataObject := "{0000010e-0000-0000-c000-000000000046}"
, IID_IShellFolder := "{000214E6-0000-0000-C000-000000000046}"
, SFGAO_FOLDER := 0x20000000
SplitPath, filePath, fileName, dir
DllCall("shell32\SHGetDesktopFolder", "PtrP", IShellFolder)
DllCall("shell32\SHParseDisplayName", "WStr", dir, "Ptr", 0, "PtrP", _pidl, "UInt", SFGAO_FOLDER, "Ptr", 0)
; IShellFolder::BindToObject
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*5), "Ptr", IShellFolder, "Ptr", _pidl, "Ptr", 0
, "Ptr", CLSIDFromString(IID_IShellFolder, _), "PtrP", pIShellFolder)
ObjRelease(IShellFolder), IShellFolder := pIShellFolder
; IShellFolder::ParseDisplayName
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*3), "Ptr", IShellFolder, "Ptr", 0, "Ptr", 0
, "WStr", fileName, "Ptr", 0, "PtrP", pidl, "Ptr", 0)
VarSetCapacity(parr, A_PtrSize)
NumPut(pidl, parr)
; IShellFolder::GetUIObjectOf
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*10), "Ptr", IShellFolder, "Ptr", 0, "UInt", 1, "Ptr", &parr
, "Ptr", CLSIDFromString(IID_IDataObject, _), "Ptr", 0, "PtrP", IDataObject)
DllCall("Ole32\CoTaskMemFree", "Ptr", pidl)
ObjRelease(IShellFolder)
Return IDataObject
}
GuiClose() {
ExitApp
}
class IDropSource
{
__New() {
this._Create()
}
_Create() {
static Methods := [ {name: "QueryInterface" , paramCount: 3}
, {name: "AddRef" , paramCount: 1}
, {name: "Release" , paramCount: 1}
, {name: "QueryContinueDrag", paramCount: 3}
, {name: "GiveFeedback" , paramCount: 2} ]
this.SetCapacity("memArea", A_PtrSize*(Methods.Count() + 1))
pMemArea := this.GetAddress("memArea")
this.SetCapacity("IUnknown", A_PtrSize)
NumPut(pMemArea, this.ptr := this.GetAddress("IUnknown"))
refOffset := A_PtrSize * Methods.Count()
this.table := new this.VTable(refOffset)
this.Callbacks := []
for k, v in Methods {
Callback := new BoundFuncCallback( ObjBindMethod(this.table, v.name), v.paramCount, "Fast" )
NumPut(Callback.addr, pMemArea + A_PtrSize*(k - 1))
this.Callbacks.Push(Callback)
}
NumPut(0, pMemArea + refOffset)
}
class VTable
{
__New(refOffset) {
this.refOffset := refOffset
}
QueryInterface(pIDropSource, riid, ppvObject) {
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
, IID_IDropSource := "{00000121-0000-0000-C000-000000000046}"
, E_NOINTERFACE := 0x80004002, S_OK := 0, _, __
, p1 := CLSIDFromString(IID_IUnknown , _)
, p2 := CLSIDFromString(IID_IDropSource, __)
if !( DllCall("Ole32\IsEqualGUID", "Ptr", riid, "Ptr", p1)
|| DllCall("Ole32\IsEqualGUID", "Ptr", riid, "Ptr", p2) )
{ ; if riid doesn't match IID_IUnknown nor IID_IDropSource
NumPut(0, ppvObject + 0)
Return E_NOINTERFACE
}
else {
NumPut(pIDropSource, ppvObject + 0)
DllCall(NumGet(NumGet(ppvObject + 0) + A_PtrSize), "Ptr", ppvObject)
Return S_OK
}
}
AddRef(pIDropSource) {
refAddr := NumGet(pIDropSource + 0) + this.refOffset
NumPut(refCount := NumGet(refAddr + 0, "UInt") + 1, refAddr, "UInt")
Return refCount
}
Release(pIDropSource) {
refAddr := NumGet(pIDropSource + 0) + this.refOffset
NumPut(refCount := NumGet(refAddr + 0, "UInt") - 1, refAddr, "UInt")
Return refCount
}
QueryContinueDrag(pIDropSource, fEscapePressed, grfKeyState) {
static DRAGDROP_S_DROP := 0x00040100
, DRAGDROP_S_CANCEL := 0x00040101
, MK_LBUTTON := 0x00000001
, S_OK := 0x00000000
Return fEscapePressed ? DRAGDROP_S_CANCEL : !(grfKeyState & MK_LBUTTON) ? DRAGDROP_S_DROP : S_OK
}
GiveFeedback(pIDropSource, dwEffect) {
Return DRAGDROP_S_USEDEFAULTCURSORS := 0x00040102
}
}
__Delete() {
this.Delete("Callbacks")
this.SetCapacity("memArea", 0), this.Delete("memArea")
this.Delete("table")
}
}
class BoundFuncCallback
{
__New(BoundFuncObj, paramCount, options := "") {
this.pInfo := Object( {BoundObj: BoundFuncObj, paramCount: paramCount} )
this.addr := RegisterCallback(this.__Class . "._Callback", options, paramCount, this.pInfo)
}
__Delete() {
ObjRelease(this.pInfo)
DllCall("GlobalFree", "Ptr", this.addr, "Ptr")
}
_Callback(Params*) {
Info := Object(A_EventInfo), Args := []
Loop % Info.paramCount
Args.Push( NumGet(Params + A_PtrSize*(A_Index - 2)) )
Return Info.BoundObj.Call(Args*)
}
}
CLSIDFromString(IID, ByRef CLSID) {
VarSetCapacity(CLSID, 16, 0)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt")
throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return &CLSID
}
Re: Drag & Drop from AHK GUI
What exactly do you mean?teadrinker wrote:... ListBox doesn't understand what's happening and behaves strangely.
BTW: Good work!
-
- Posts: 4352
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Drag & Drop from AHK GUI
The window doesn't recieve DL_DRAGGING and DL_DROPPED. After the object is dropped, ListBox behaves like the mouse is not released:
This is better:
Code: Select all
folderToParse := A_MyDocuments
FileArr := {}, fileNames := ""
Loop, Files, % folderToParse . "\*.*", FD
{
fileNames .= (A_Index = 1 ? "" : "|") . A_LoopFileName
FileArr[A_Index - 1] := A_LoopFileFullPath
}
Gui, Font, s10
Gui, Add, ListBox, r15 w300 hwndhLB, % fileNames
Gui, Show
OnMessage(0x201, Func("WM_LBUTTONDOWN").Bind(FileArr, hLB))
Return
WM_LBUTTONDOWN(FileArr, hLB, wp, lp, msg, hwnd) {
if !(hLB = hwnd)
Return
DllCall("GetCursorPos", "UInt64P", POINT)
item := DllCall("LBItemFromPt", "Ptr", hLB, "UInt64", POINT, "UInt", true)
timer := Func("DoDragDrop").Bind(FileArr[item])
SetTimer, % timer, -100
}
DoDragDrop(filePath) {
DropSource := new IDropSource
IDataObject := GetDataObject(filePath)
DllCall("Ole32\DoDragDrop", "Ptr", IDataObject, "Ptr", DropSource.ptr, "UInt", DROPEFFECT_COPY := 1, "UIntP", effect)
ObjRelease(IDataObject), DropSource := ""
}
GetDataObject(filePath) {
static IID_IDataObject := "{0000010e-0000-0000-c000-000000000046}"
, IID_IShellFolder := "{000214E6-0000-0000-C000-000000000046}"
, SFGAO_FOLDER := 0x20000000
SplitPath, filePath, fileName, dir
DllCall("shell32\SHGetDesktopFolder", "PtrP", IShellFolder)
DllCall("shell32\SHParseDisplayName", "WStr", dir, "Ptr", 0, "PtrP", _pidl, "UInt", SFGAO_FOLDER, "Ptr", 0)
; IShellFolder::BindToObject
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*5), "Ptr", IShellFolder, "Ptr", _pidl, "Ptr", 0
, "Ptr", CLSIDFromString(IID_IShellFolder, _), "PtrP", pIShellFolder)
ObjRelease(IShellFolder), IShellFolder := pIShellFolder
; IShellFolder::ParseDisplayName
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*3), "Ptr", IShellFolder, "Ptr", 0, "Ptr", 0
, "WStr", fileName, "Ptr", 0, "PtrP", pidl, "Ptr", 0)
VarSetCapacity(parr, A_PtrSize)
NumPut(pidl, parr)
; IShellFolder::GetUIObjectOf
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*10), "Ptr", IShellFolder, "Ptr", 0, "UInt", 1, "Ptr", &parr
, "Ptr", CLSIDFromString(IID_IDataObject, _), "Ptr", 0, "PtrP", IDataObject)
DllCall("Ole32\CoTaskMemFree", "Ptr", pidl)
ObjRelease(IShellFolder)
Return IDataObject
}
GuiClose() {
ExitApp
}
class IDropSource
{
__New() {
this._Create()
}
_Create() {
static Methods := [ {name: "QueryInterface" , paramCount: 3}
, {name: "AddRef" , paramCount: 1}
, {name: "Release" , paramCount: 1}
, {name: "QueryContinueDrag", paramCount: 3}
, {name: "GiveFeedback" , paramCount: 2} ]
this.SetCapacity("memArea", A_PtrSize*(Methods.Count() + 1))
pMemArea := this.GetAddress("memArea")
this.SetCapacity("IUnknown", A_PtrSize)
NumPut(pMemArea, this.ptr := this.GetAddress("IUnknown"))
refOffset := A_PtrSize * Methods.Count()
this.table := new this.VTable(refOffset)
this.Callbacks := []
for k, v in Methods {
Callback := new BoundFuncCallback( ObjBindMethod(this.table, v.name), v.paramCount, "Fast" )
NumPut(Callback.addr, pMemArea + A_PtrSize*(k - 1))
this.Callbacks.Push(Callback)
}
NumPut(0, pMemArea + refOffset)
}
class VTable
{
__New(refOffset) {
this.refOffset := refOffset
}
QueryInterface(pIDropSource, riid, ppvObject) {
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
, IID_IDropSource := "{00000121-0000-0000-C000-000000000046}"
, E_NOINTERFACE := 0x80004002, S_OK := 0, _, __
, p1 := CLSIDFromString(IID_IUnknown , _)
, p2 := CLSIDFromString(IID_IDropSource, __)
if !( DllCall("Ole32\IsEqualGUID", "Ptr", riid, "Ptr", p1)
|| DllCall("Ole32\IsEqualGUID", "Ptr", riid, "Ptr", p2) )
{ ; if riid doesn't match IID_IUnknown nor IID_IDropSource
NumPut(0, ppvObject + 0)
Return E_NOINTERFACE
}
else {
NumPut(pIDropSource, ppvObject + 0)
DllCall(NumGet(NumGet(ppvObject + 0) + A_PtrSize), "Ptr", ppvObject)
Return S_OK
}
}
AddRef(pIDropSource) {
refAddr := NumGet(pIDropSource + 0) + this.refOffset
NumPut(refCount := NumGet(refAddr + 0, "UInt") + 1, refAddr, "UInt")
Return refCount
}
Release(pIDropSource) {
refAddr := NumGet(pIDropSource + 0) + this.refOffset
NumPut(refCount := NumGet(refAddr + 0, "UInt") - 1, refAddr, "UInt")
Return refCount
}
QueryContinueDrag(pIDropSource, fEscapePressed, grfKeyState) {
static DRAGDROP_S_DROP := 0x00040100
, DRAGDROP_S_CANCEL := 0x00040101
, MK_LBUTTON := 0x00000001
, S_OK := 0x00000000
Return fEscapePressed ? DRAGDROP_S_CANCEL : !(grfKeyState & MK_LBUTTON) ? DRAGDROP_S_DROP : S_OK
}
GiveFeedback(pIDropSource, dwEffect) {
Return DRAGDROP_S_USEDEFAULTCURSORS := 0x00040102
}
}
__Delete() {
this.Delete("Callbacks")
this.SetCapacity("memArea", 0), this.Delete("memArea")
this.Delete("table")
}
}
class BoundFuncCallback
{
__New(BoundFuncObj, paramCount, options := "") {
this.pInfo := Object( {BoundObj: BoundFuncObj, paramCount: paramCount} )
this.addr := RegisterCallback(this.__Class . "._Callback", options, paramCount, this.pInfo)
}
__Delete() {
ObjRelease(this.pInfo)
DllCall("GlobalFree", "Ptr", this.addr, "Ptr")
}
_Callback(Params*) {
Info := Object(A_EventInfo), Args := []
Loop % Info.paramCount
Args.Push( NumGet(Params + A_PtrSize*(A_Index - 2)) )
Return Info.BoundObj.Call(Args*)
}
}
CLSIDFromString(IID, ByRef CLSID) {
VarSetCapacity(CLSID, 16, 0)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt")
throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return &CLSID
}
Thanks, I learned from you!just me wrote:BTW: Good work!
Re: Drag & Drop from AHK GUI
Thank you ! works perfect.
-
- Posts: 4352
- Joined: 29 Mar 2015, 09:41
- Contact:
Re: Drag & Drop from AHK GUI
Added some improvements.
Code: Select all
folderToParse := A_MyDocuments
FileArr := {}, fileNames := ""
Loop, Files, % folderToParse . "\*.*", FD
{
fileNames .= (A_Index = 1 ? "" : "|") . A_LoopFileName
FileArr[A_Index - 1] := A_LoopFileFullPath
}
Gui, Font, s10
Gui, Add, ListBox, r15 w300 hwndhLB, % fileNames
Gui, Show,, Drag and Drop
OnMessage(0x200, Func("WM_MOUSEMOVE").Bind(FileArr, hLB))
Return
GuiClose() {
ExitApp
}
WM_MOUSEMOVE(FileArr, hLB, wp, lp, msg, hwnd) {
static MK_LBUTTON := 0x0001, DROPEFFECT_COPY := 1
if !(hLB = hwnd && wp & MK_LBUTTON)
Return
DllCall("GetCursorPos", "UInt64P", POINT)
item := DllCall("LBItemFromPt", "Ptr", hLB, "UInt64", POINT, "UInt", true)
if (item = -1)
Return
filePath := FileArr[item]
DropSource := new IDropSource
IDataObject := GetDataObject(filePath)
hBitmap := GetThumbnailOrIcon(filePath, 96, 96, true)
DragSourceHelper := new IDragSourceHelper
DragSourceHelper.InitializeFromBitmap(48, 96, hBitmap, 0xFFFFFFFF, IDataObject)
DllCall("Ole32\DoDragDrop", "Ptr", IDataObject, "Ptr", DropSource.ptr, "UInt", DROPEFFECT_COPY, "UIntP", effect)
DllCall("DeleteObject", "Ptr", hBitmap)
ObjRelease(IDataObject), DropSource := DragSourceHelper := ""
}
GetDataObject(filePath) {
static IID_IDataObject := "{0000010e-0000-0000-c000-000000000046}"
, IID_IShellFolder := "{000214E6-0000-0000-C000-000000000046}"
, SFGAO_FOLDER := 0x20000000
SplitPath, filePath, fileName, dir
DllCall("shell32\SHGetDesktopFolder", "PtrP", IShellFolder)
DllCall("shell32\SHParseDisplayName", "WStr", dir, "Ptr", 0, "PtrP", _pidl, "UInt", SFGAO_FOLDER, "Ptr", 0)
; IShellFolder::BindToObject
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*5), "Ptr", IShellFolder, "Ptr", _pidl, "Ptr", 0
, "Ptr", CLSIDFromString(IID_IShellFolder, _), "PtrP", pIShellFolder)
ObjRelease(IShellFolder), IShellFolder := pIShellFolder
; IShellFolder::ParseDisplayName
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*3), "Ptr", IShellFolder, "Ptr", 0, "Ptr", 0
, "WStr", fileName, "Ptr", 0, "PtrP", pidl, "Ptr", 0)
VarSetCapacity(parr, A_PtrSize)
NumPut(pidl, parr)
; IShellFolder::GetUIObjectOf
DllCall(NumGet(NumGet(IShellFolder + 0) + A_PtrSize*10), "Ptr", IShellFolder, "Ptr", 0, "UInt", 1, "Ptr", &parr
, "Ptr", CLSIDFromString(IID_IDataObject, _), "Ptr", 0, "PtrP", IDataObject)
DllCall("Ole32\CoTaskMemFree", "Ptr", pidl)
ObjRelease(IShellFolder)
Return IDataObject
}
GetThumbnailOrIcon(filePath, width, height := 0, iconOnly := false) {
static IID_IShellItemImageFactory := "{BCC18B79-BA16-442F-80C4-8A59C30C463B}"
, SIIGBF_ICONONLY := 0x00000004
CLSIDFromString(IID_IShellItemImageFactory, GUID)
hr := DllCall("Shell32\SHCreateItemFromParsingName", "WStr", filePath, "Ptr", 0, "Ptr", &GUID, "PtrP", IShellItemImageFactory)
if (hr != 0)
Return 0
flag := iconOnly ? SIIGBF_ICONONLY : 0
; IShellItemImageFactory::GetImage
DllCall(NumGet(NumGet(IShellItemImageFactory+0) + A_PtrSize*3), "Ptr", IShellItemImageFactory
, "Int64", height << 32 | width, "Int", flag, "PtrP", hBitmap, "Int")
ObjRelease(IShellItemImageFactory)
Return hBitmap
}
class IDragSourceHelper
{
__New() {
static CLSID_DragDropHelper := "{4657278A-411B-11D2-839A-00C04FD918D0}"
, IID_IDropSourcetHelper := "{DE5BF786-477A-11D2-839D-00C04FD918D0}"
this.ptr := ComObjCreate(CLSID_DragDropHelper, IID_IDropSourcetHelper)
}
__Delete() {
ObjRelease(this.ptr)
}
InitializeFromBitmap(x_offset, y_offset, hBitmap, BGR, IDataObject) {
VarSetCapacity(BITMAP, size := 16 + A_PtrSize*2)
DllCall("GetObject", "Ptr", hBitmap, "UInt", size, "Ptr", &BITMAP)
width := NumGet(BITMAP, 4, "UInt")
height := NumGet(BITMAP, 8, "UInt")
VarSetCapacity(SHDRAGIMAGE, size := 16 + A_PtrSize*2)
NumPut(width , SHDRAGIMAGE)
NumPut(height , SHDRAGIMAGE, 4)
NumPut(x_offset, SHDRAGIMAGE, 8)
NumPut(y_offset, SHDRAGIMAGE, 12)
NumPut(hBitmap , SHDRAGIMAGE, 16)
NumPut(BGR , SHDRAGIMAGE, 16 + A_PtrSize)
; IDragSourceHelper::InitializeFromBitmap
DllCall(NumGet(NumGet(this.ptr) + A_PtrSize*3), "Ptr", this.ptr, "Ptr", &SHDRAGIMAGE, "Ptr", IDataObject)
}
}
class IDropSource
{
__New() {
static Methods := [ {name: "QueryInterface" , paramCount: 3}
, {name: "AddRef" , paramCount: 1}
, {name: "Release" , paramCount: 1}
, {name: "QueryContinueDrag", paramCount: 3}
, {name: "GiveFeedback" , paramCount: 2} ]
this.SetCapacity("memArea", A_PtrSize*(Methods.Count() + 1))
pMemArea := this.GetAddress("memArea")
this.SetCapacity("IUnknown", A_PtrSize)
NumPut(pMemArea, this.ptr := this.GetAddress("IUnknown"))
refOffset := A_PtrSize * Methods.Count()
this.VTable.refOffset := refOffset
this.Callbacks := []
for k, v in Methods {
Callback := new this.BoundFuncCallback( ObjBindMethod(this.VTable, v.name), v.paramCount, "Fast" )
NumPut(Callback.addr, pMemArea + A_PtrSize*(k - 1))
this.Callbacks.Push(Callback)
}
NumPut(0, pMemArea + refOffset)
}
__Delete() {
this.Delete("Callbacks")
this.SetCapacity("memArea", 0), this.Delete("memArea")
}
class VTable
{
QueryInterface(pIDropSource, riid, ppvObject) {
static IID_IUnknown := "{00000000-0000-0000-C000-000000000046}"
, IID_IDropSource := "{00000121-0000-0000-C000-000000000046}"
, E_NOINTERFACE := 0x80004002, S_OK := 0, _, __
, p1 := CLSIDFromString(IID_IUnknown , _)
, p2 := CLSIDFromString(IID_IDropSource, __)
if !( DllCall("Ole32\IsEqualGUID", "Ptr", riid, "Ptr", p1)
|| DllCall("Ole32\IsEqualGUID", "Ptr", riid, "Ptr", p2) )
{ ; if riid doesn't match IID_IUnknown nor IID_IDropSource
NumPut(0, ppvObject + 0)
Return E_NOINTERFACE
}
else {
NumPut(pIDropSource, ppvObject + 0)
DllCall(NumGet(NumGet(ppvObject + 0) + A_PtrSize), "Ptr", ppvObject)
Return S_OK
}
}
AddRef(pIDropSource) {
refAddr := NumGet(pIDropSource + 0) + this.refOffset
NumPut(refCount := NumGet(refAddr + 0, "UInt") + 1, refAddr, "UInt")
Return refCount
}
Release(pIDropSource) {
refAddr := NumGet(pIDropSource + 0) + this.refOffset
NumPut(refCount := NumGet(refAddr + 0, "UInt") - 1, refAddr, "UInt")
Return refCount
}
QueryContinueDrag(pIDropSource, fEscapePressed, grfKeyState) {
static DRAGDROP_S_DROP := 0x00040100
, DRAGDROP_S_CANCEL := 0x00040101
, MK_LBUTTON := 0x00000001
, S_OK := 0x00000000
Return fEscapePressed ? DRAGDROP_S_CANCEL : !(grfKeyState & MK_LBUTTON) ? DRAGDROP_S_DROP : S_OK
}
GiveFeedback(pIDropSource, dwEffect) {
Return DRAGDROP_S_USEDEFAULTCURSORS := 0x00040102
}
}
class BoundFuncCallback
{
__New(BoundFuncObj, paramCount, options := "") {
this.pInfo := Object( {BoundObj: BoundFuncObj, paramCount: paramCount} )
this.addr := RegisterCallback(this.__Class . "._Callback", options, paramCount, this.pInfo)
}
__Delete() {
ObjRelease(this.pInfo)
DllCall("GlobalFree", "Ptr", this.addr, "Ptr")
}
_Callback(Params*) {
Info := Object(A_EventInfo), Args := []
Loop % Info.paramCount
Args.Push( NumGet(Params + A_PtrSize*(A_Index - 2)) )
Return Info.BoundObj.Call(Args*)
}
}
}
CLSIDFromString(IID, ByRef CLSID) {
VarSetCapacity(CLSID, 16, 0)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", &CLSID, "UInt")
throw Exception("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return &CLSID
}