Created
April 29, 2016 18:31
-
-
Save Aatoz/b5433898a3835349b5f423e5bcb741c5 to your computer and use it in GitHub Desktop.
Drag n Drop onto AutoHotKey GUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
************************************************************************************* | |
***************************** Drag n Drop Like a Boss ***************************** | |
************************************************************************************* | |
This class supports Drag n Drop from EXPLORER windows to AutoHotKey GUIs -- that's it. | |
I recommend having your GUI still retain the label for GUIDropFiles for 2 reasons: | |
1. Win7 and earlier natively support DnD. It's better to NOT use this class when you don't need to. | |
2. The mouse becomes a No/X icon when you try to drag & drop onto the AutoHotKey GUI | |
In this case, drag & drop *does* still work, but that's unintuitive to the user. | |
Highlights: | |
This uses a global mouse hook. This isn't common, but if you have one set, there may be performance issues. | |
DragDrop.ShouldUseDD() -- call this to determine whether or not you need to use this class. | |
This class std lib compliant. | |
How to use: | |
_DragDrop() ; Init stb lib. | |
if (DragDrop.ShouldUseDD()) | |
g_vDD := new DragDrop("SimulateDragNDrop", g_hQL) | |
...when you're done with the object... | |
g_vDD := ; Delete this object to unregister it from the super class and release it from the mouse hook. | |
Credits: | |
Joshua A. Kinnison for great Explorer functions. | |
License: | |
Attribution 3.0 -- just give Verdlin credit | |
*/ | |
_DragDrop() | |
{ } ; for stb lib | |
class DragDrop | |
{ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Verdlin | |
Function: __New(0 | |
Purpose: Initialize DragDrop object | |
Parameters | |
hCallback: String of callback function. Callback function takes a COM object of selected items from the dragged explorer window. | |
hDropWnd: Target hWnd. IMPORTANT: Must be a window handle! Also used to attach class to hWnd. | |
*/ | |
__New(hCallback, hDropWnd) | |
{ | |
this.m_hCallback := Func(hCallback) | |
if (!IsFunc(this.m_hCallback)) | |
{ | |
Msgbox 8256,, Error: %hCallback% is not a valid function. | |
return false | |
} | |
global g_hMouseHook | |
if (!g_hMouseHook) ; Only set hook once. | |
g_hMouseHook := DllCall("SetWindowsHookEx", "int", WH_MOUSE_LL:=14 , "uint", RegisterCallback("DD_MouseProc", "Fast"), "uint", 0, "uint", 0) | |
sPrev := A_DetectHiddenWindows ; Preserve existing setting. | |
DetectHiddenWindows, on ; So we can get this script's hWnd. | |
this.m_hScriptWnd := WinExist("Ahk_PID " DllCall("GetCurrentProcessId")) | |
DetectHiddenWindows, %sPrev% ; Restore existing setting. | |
; Override obscure window message. | |
OnMessage(WM_CAP_SET_CALLBACK_ERRORW:=1126, "DragDropProc") | |
; Register this instance in super class. | |
this.m_hDropWnd := hDropWnd | |
DragDrop.ForHwnd[hDropWnd] := &this ; for DD_WatchForDD | |
return this | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Verdlin | |
Function: __Delete() | |
Purpose: Properly delete object | |
Parameters | |
*/ | |
__Delete() | |
{ | |
global g_hMouseHook | |
; Unregister instance from super class. | |
DragDrop.ForHwnd.Remove(this.m_hDropWnd) | |
; Apparently MaxIndex() doesn't work :\ | |
for k, v in DragDrop.ForHwnd | |
iClassCnt++ | |
; If that was the last DD, unhook | |
if (!iClassCnt) | |
DllCall("UnhookWindowsHookEx", "Uint", g_hMouseHook) | |
return | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Verdlin | |
Function: ShouldUseDD | |
Purpose: Help to conditionally use DragDrop | |
You can call using the super class instantiator like this: DragDrop.ShouldUseDD() | |
Parameters | |
*/ | |
ShouldUseDD() | |
{ | |
return A_OSVersion != "WIN_7" && A_OSVersion != "WIN_VISTA" && A_OSVersion != "WIN_XP" | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Verdlin | |
Function: GetExplorerDDContents | |
Purpose: To get the contents (if any) of explorer's DD. | |
Returns COM object of explorer contents or else false if empty. | |
Parameters | |
hExplorerWnd: Explorer wnd to get contents from | |
*/ | |
GetExplorerDDContents(hExplorerWnd) | |
{ | |
; This prevents the code from firing if you simply click on the QL. | |
vSelItems := this.Explorer_GetWindow(hExplorerWnd).Document.SelectedItems | |
if (vSelItems.Count < 1) | |
return false | |
return vSelItems | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Joshua A. Kinnison 2011-04-27, 16:12 | |
Function: Explorer_GetWindow | |
Purpose: Get explorer window COM object | |
Parameters | |
hWnd="" | |
*/ | |
Explorer_GetWindow(hwnd="") | |
{ | |
hwnd := hwnd ? hwnd : WinExist("A") | |
WinGetClass class, ahk_id %hwnd% | |
if (class="CabinetWClass" or class="ExploreWClass" or class="Progman") | |
for window in ComObjCreate("Shell.Application").Windows | |
{ | |
if (window.hwnd==hwnd) | |
return window | |
} | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Verdlin | |
Function: DragDropProc | |
Purpose: To simulate do Drag n Drop! | |
Parameters | |
hExplorerWnd: Explorer window to grab selection from | |
pDragDrop: Pointer to DragDrop class object. | |
*/ | |
DragDropProc(hExplorerWnd, pDragDrop) | |
{ | |
; Get the DD contents out of explorer now. | |
vDragDrop := Object(pDragDrop) | |
vDDContents := vDragDrop.GetExplorerDDContents(hExplorerWnd) | |
; Is there something to drag and drop? | |
if (vDDContents.Count) | |
vDragDrop.m_hCallback.(vDDContents) ; Do it! | |
return | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
/* | |
Author: Verdlin | |
Function: DD_MouseProc | |
Purpose: Global mouse hook to detect click n drag and trigger Drag n Drop event. | |
Parameters | |
nCode: | |
wParam: Window message WM_ | |
lParam: | |
*/ | |
DD_MouseProc(nCode, wParam, lParam) | |
{ | |
; Variables used to filter out clicks. | |
static s_hWndOnClick := 0, s_bTrackingClickNDrag := false, s_bIsDragging := false, s_iPrevMouseX, s_iPrevMouseY | |
Critical 5000 | |
WM_MOUSEMOVE := 0x200 | |
WM_LBUTTONDOWN := 0x201 | |
WM_LBUTTONUP := 0x202 | |
CoordMode, Mouse, Screen | |
MouseGetPos, iMouseX, iMouseY, hMouseWnd | |
if (wParam == WM_LBUTTONDOWN:=513) | |
s_hWndOnClick := hMouseWnd | |
vDragDrop := Object(DragDrop.ForHwnd[hMouseWnd]) ; DragDrop is a super class or super global or something...it just works, OK? | |
bMouseOverDropWnd := IsObject(vDragDrop) | |
; If we started clicking ON the drop wnd, there's nothing to click n drag. | |
bDraggingDropWnd := (s_hWndOnClick == vDragDrop.m_hDropWnd) | |
if (bDraggingDropWnd) | |
return DD_CallNextHookEx(nCode, wParam, lParam) | |
bMouseMove := (wParam == WM_MOUSEMOVE) | |
bLButtonUp := (wParam == WM_LBUTTONUP) | |
bLButtonDown := (wParam == WM_LBUTTONDOWN) | |
bLButtonDown_P := GetKeyState("LButton", "P") | |
bLButtonDown_Valid := (bLButtonDown_P && !bMouseOverDropWnd) | |
; If the LButton is down or the mouse is moving AND click n drag did NOT start on a drop hwnd... | |
if (bLButtonDown_Valid && (bLButtonDown || bMouseMove)) | |
{ | |
; If we are clicking and dragging... | |
if (bLButtonDown_P && bMouseMove) | |
{ | |
; X delta | |
if (s_iPrevMouseX == "") | |
iXDelta := 0 | |
else iXDelta := abs(iMouseX-s_iPrevMouseX) | |
; Y delta | |
if (s_iPrevMouseY == "") | |
iYDelta := 0 | |
else iYDelta := abs(iMouseY-s_iPrevMouseY) | |
; Detect if we are dragging uses delta. | |
s_bIsDragging := (s_bIsDragging || iXDelta || iYDelta) | |
} | |
s_bTrackingClickNDrag := s_bTrackingClickNDrag || s_bIsDragging | |
s_iPrevMouseX := iMouseX | |
s_iPrevMouseY := iMouseY | |
} | |
else if (bMouseOverDropWnd && s_bTrackingClickNDrag && s_bIsDragging && bLButtonUp) | |
{ | |
s_bTrackingClickNDrag := false | |
s_bIsDragging := false | |
; PostMessage because we can't call GetExplorerDDContents while dispatching an input-synchronous call. | |
PostMessage, WM_CAP_SET_CALLBACK_ERRORW:=1126, s_hWndOnClick, &vDragDrop,, % "ahk_id" vDragDrop.m_hScriptWnd | |
} | |
else if (bLButtonUp) | |
{ | |
; Reset click n drag vars. | |
s_bTrackingClickNDrag := s_bIsDragging := false | |
s_hWndOnClick := s_iPrevMouseX := s_iPrevMouseY := "" | |
} | |
return DD_CallNextHookEx(nCode, wParam, lParam) | |
} | |
DD_CallNextHookEx(nCode, wParam, lParam) | |
{ | |
global g_hMouseHook | |
return DllCall("CallNextHookEx", "uint", g_hMouseHook, "int", nCode, "uint", wParam, "uint", lParam) | |
} | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for leaving this treasure here I built one of these years ago for renaming objects quickly and I need a new one actually I need the more or less the combination tools I can remember how I did it so thank you for putting this up . Been using AK for minute. 2010.