ATTENTION: You are viewing a page formatted for mobile devices; to view the full web page, click HERE.

DonationCoder.com Software > Post New Requests Here

IDEA: Drop Zone for Web Images

(1/4) > >>

magician62:
First of all based on the following criteria, does this already exist? If not a request.

Place a dropzone on the desktop (Win7-64)

Left click an image on the internet and drag to the dropzone.

Ideally provide an option to bypass the Windows Security warning. or auto accept if cursor over dropzone

On dropping on the dropzone, provide a rename function to use a standardised format such as

PREFIX YYYY-MM-DD_HH-SS SUFFIX

Auto move to predefined default location.

Ideally
Permit multiple instances, or preferably multiple dockable zones with separate settings probably 3-4 would suffice for most needs

Possibly with the option for the user to assign an icon/image for each box.

See, not looking for much :)

ayryq:
I wonder how much of this could be done by dropping on an IrfanView shortcut with the appropriate command-line arguments.

http://www.etcwiki.org/wiki/IrfanView_Command_Line_Options

ayryq:
OK, it works, but not quite how I wanted. You have to create a batch file and drop pictures from your webbrowser onto that. Here's one I made:

test.bat

--- ---"C:\Program Files (x86)\IrfanView\i_view32.exe" %1 /convert=c:\users\Eric\Desktop\IView\test-$U.jpg

When I drop the file onto this bat, it converts it to jpg, names it test-(current system time).jpg, and saves it to a IView folder on my desktop.

If you look at the link above, irfanview supports TONS of command line arguments, and has very powerful renaming wildcards (documented in the help files). I can't imagine there's something you'd want to do that you couldn't do with this method. That %1 is important, by the way; it's what passes the filename to the batch file, and it's the reason I couldn't get it to work with a simple shortcut. Only think this method isn't is easy, point-and-click, etc. But I think it'll work.

Edit: Figured out how to keep the existing extension: 

--- ---/convert=c:\prefix-$U$O
Edit again to note that you can hide the batch file somewhere and drop a file onto a shortcut to it instead - it works the same but you can freely rename and change the icon of a shortcut.

lifeweaver:
Hi magician62,

Here is a script for you written in AutoHotkey.
Also I had the same problem with the security thing and fixed it by following directions in this link.


Script runs on: Windows 7 Professional, AutoHotkey 1.1.22.07 Unicode build

To use:

* Install AutoHotkey, if you have problems see their tutorial about running scripts
* Copy the script into a '.ahk' file
* Double click on the script icon to start it
* Fill out the form fields for a new dropzone
* Click the 'DropZone Position' button to select the size of the dropZone
* Click and hold the mouse button to select the top left corner of the dropZone
* Let go of the mouse to select the bottom left corner of the dropZone
* Click the 'Create/Update' button to save the new dropzone
* Close the config window to create the dropZones
* Now you merely need to drag images from the browsers to the dropZones!
Notes:
The next time you start the script the dropZones will be created instantly and the config window won't open automatically.
If you need to open the config window again click the 'H' icon on your taskbar tray.
You can hide the dropZone windows by right clicking on the try icon and selecting 'Toggle DropZones'.
The tray icon also allows you to exit the script.

Special Note:
Please realize that when you do an image search on yahoo/bing/etc you are seeing thumbnails not actual images as such. Trying to drag these images will only create a shortcut to wherever that thumbnail goes, not an image.

For google I able to find the actual image so their search is good, I might be able to figure out how to do it in the instances of the other other search engines but have exhausted all the time I have for this week.


--- ---; -------------------------------------------------- Auto Execute --------------------------------------------------
#Persistent
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force
SetBatchLines, -1
SetKeyDelay, -1
title := "Web Images Drop Zone"

iniPath := A_ScriptDir . "\WIDZ.data"


Menu, Tray, NoStandard
Menu, Tray, Add, &Config, Show
Menu, Tray, Default, &Config
Menu, Tray, Add, &Toggle DropZones, toggleDropZones
Menu, Tray, Add, E&xit, Exit
Menu, Tray, Click, 1
Menu, Tray, Tip, %title%
LoadSettings(iniPath)

if(firstTimeOpenShowConfig)
{
  firstTimeOpenShowConfig := false
  gosub, show
  WinWaitClose, %title% - Config
}

dropZoneGuis := CreateDropZoneGuis(iniPath)
OnExit("Exit")
return

; -------------------------------------------------- Labels --------------------------------------------------
createOrUpdateDropZone:
  ; Get dropZone info info
  GuiControlGet, dropZone,, dropZone
  GuiControlGet, timeFormat,, timeFormat
  GuiControlGet, fileDrop,, fileDrop
  GuiControlGet, icon,, icon
  GuiControlGet, prefix,, prefix
  GuiControlGet, suffix,, suffix
 
  ; Check if the dropZone already exists
  Loop % LV_GetCount()
  {
    Lv_GetText(dropZoneName, A_index)
    if(dropZoneName = dropZone)
    {
      LV_Modify(A_Index,,dropZone, prefix, suffix, lastDropWindowPos, fileDrop, icon, timeFormat)
      return
    }
  }
 
  LV_Add(,dropZone, prefix, suffix, lastDropWindowPos, fileDrop, icon, timeFormat)
return

drawDropWindow:
  ;http://www.autohotkey.com/board/topic/111196-drawing-boxes-on-screen-need-help-finishing/?p=655416
  GuID := "dropzone"
  LetUserSelectRect(GuiID, x1, y1, x2, y2)
  lastDropWindowPos := x1 . ":" . x2 . ":" . y1 . ":" . y2
  GuiControl,, pos, %lastDropWindowPos%

  Loop 4
    Gui, % GuiID A_Index ": Destroy"
return

dropZoneList:
  ; populate fields on a double click
  if(A_GuiEvent = "Normal")
    CopyDropZoneToForm(A_EventInfo)
  else if(A_GuiEvent = "RightClick")
    DeleteDropZoneData(A_EventInfo)
return

Exit:
  IfWinExist, %title% - Config
    SaveData(iniPath)
  ExitApp
return

fileDrop:
  FileSelectFolder, fileDrop,,, Select file folder
  if(fileDrop)
    GuiControl, , fileDrop, %fileDrop%
  else
    msgbox your folder wasn't found please select a valid folder, i.e. no the virtual ones like Libraries/Documents/Music/etc
return

icon:
  FileSelectFile, icon, 3, %A_MyDocuments%,Choose an Icon, Image files (*.jpg; *.jpeg; *.gif; *.png)
  GuiControl, , icon, %icon%
return

show:
  DeleteAllDropZones(dropZoneGuis)
  Gui, WebImageDropZoneConfig: New, hwndWIDZ, Web Image Drop Zone
  global WIDZ
  Gui, Add, ListView, x12 y10 w450 r15 gdropZoneList AltSubmit, DropZone|Prefix|Suffix|Pos|Save Path|Icon|TimeFormat
  Gui, Add, Text, x12 y300 w60 h20 , DropZone:
  Gui, Add, Edit, x72 y300 w90 h20 vdropZone , dropzone
  Gui, Add, Text, x172 y300 w60 h20 , TimeFormat:
  Gui, Add, Edit, x232 y300 w230 h20 vtimeFormat , yyyy-MM-dd_hh-ss
 
  Gui, font, s11 bold, MS sans serif
  Gui, Add, Link, x462 y300 w10 h20 , <a href="http://www.autohotkey.com/docs/commands/FormatTime.htm">?</a>
  gui, font
 
  Gui, Add, Text, x12 y330 w50 h20 , File Drop:
  Gui, Add, Edit, x72 y330 w320 h20 vfileDrop , file drop
  Gui, Add, Button, x392 y330 w70 h20 gfileDrop , Browse
 
  Gui, Add, Text, x12 y360 w40 h20 , Icon:
  Gui, Add, Edit, x72 y360 w320 h20 vicon, Edit
  Gui, Add, Button, x392 y360 w70 h20 gicon , Browse
 
  Gui, Add, Text, x12 y390 w40 h20 , Prefix:
  Gui, Add, Edit, x72 y390 w110 h20 vprefix , prefix
  Gui, Add, Text, x192 y390 w40 h20 , Suffix:
  Gui, Add, Edit, x232 y390 w110 h20 vsuffix , suffix
  Gui, Add, Button, x12 y420 w110 h20 gdrawDropWindow, DropZone Position
  Gui, Add, Edit, x132 y420 w210 h20 ReadOnly vpos , 0:100:0:100
  Gui, Add, Button, x352 y390 w110 h50 gcreateOrUpdateDropZone , Create/Update
 
  ; Generated using SmartGUI Creator 4.0
  Gui, Show, x138 y90 h450 w479, %title% - Config
  PopulateDropZoneList(iniPath)
  OnMessage(0x200, "GuiToolTip")
  Loop 6
      LV_ModifyCol(A_Index, "AutoHdr")
 
return

toggleDropZones:
for index, array in dropZoneGuis
{
  hwnd := array["hwnd"]
 
  if WinExist("ahk_id " . hwnd)
    gui, %hwnd%:Hide
  else
    gui, %hwnd%:Show
}
return

WebImageDropZoneConfigGuiClose:
WebImageDropZoneConfigGuiEscape:
  IfWinExist, %title% - Config
    SaveData(iniPath)
  Gui, WebImageDropZoneConfig:Destroy
 
  ; Update the dropzones
  dropZoneGuis := CreateDropZoneGuis(iniPath)
return



; -------------------------------------------------- Methods --------------------------------------------------
CopyDropZoneToForm(eventInfo)
{
  global lastDropWindowPos
  ; get row text
  LV_GetText(dropZone, eventInfo, 1)
  LV_GetText(prefix, eventInfo, 2)
  LV_GetText(suffix, eventInfo, 3)
  LV_GetText(pos, eventInfo, 4)
  LV_GetText(fileDrop, eventInfo, 5)
  LV_GetText(icon, eventInfo, 6)
  LV_GetText(TimeFormat, eventInfo, 7)
 
  ; update fields
  GuiControl,, dropZone, %dropZone%
  GuiControl,, prefix, %prefix%
  GuiControl,, suffix, %suffix%
  GuiControl,, pos, %pos%
  lastDropWindowPos := pos
  GuiControl,, fileDrop, %fileDrop%
  GuiControl,, icon, %icon%
  GuiControl,, TimeFormat, %TimeFormat%
}

CreateDropZoneGuis(path)
{
  dropZoneGuis := Array()
  dropZoneData := LoadData(path)
 
  for index, array in dropZoneData
  {
    extractedPos := StrSplit(array["pos"], ":")
    guiHwnd := DropZoneGui(array["dropZone"], array["icon"], extractedPos[1], extractedPos[2], extractedPos[3], extractedPos[4])
    IDT_WIDZ := IDropTarget_Create(guiHwnd, "_WIDZ", [1, 13, 15]) ; CF_TEXT, CF_UNICODETEXT, CF_HDROP
    dropZoneGuis.insert({dropZone: array["dropZone"], hwnd: guiHwnd, iDropTarget: IDT_WIDZ})
  }

  return dropZoneGuis
}

; Custom message box for the confirm dropzone delete.
Custom_MsgBox(msg_text)
{
  global showCancelConfirm, dontShowAgain
  Gui, CustomMsgBox: New, hwndCMB
  Gui, Add, Text, x12 y10 w430 h70, %msg_text%
  Gui, Add, CheckBox, x12 y90 w140 h30 vdontShowAgain , Don't show this again?
  Gui, Add, Button, x232 y90 w100 h30 gCustomMsgBoxGuiSubmit , OK
  Gui, Add, Button, x342 y90 w100 h30 gCustomMsgBoxGuiSubmit Default , Cancel
  ; Generated using SmartGUI Creator 4.0
  Gui, Show
  WinWaitClose, ahk_id %CMB%
  return buttonClicked
 
  CustomMsgBoxGuiSubmit:
    GuiControlGet, dontShowAgainChecked,, dontShowAgain
    if(dontShowAgainChecked)
      showCancelConfirm := false
   
    buttonClicked := A_GuiControl
    gosub, CustomMsgBoxGuiClose
  return

  CustomMsgBoxGuiClose:
  CustomMsgBoxGuiEscape:
  Gui, CustomMsgBox:Destroy
  return
}

DeleteDropZoneData(eventInfo)
{
  global showCancelConfirm
 
  Gui, WebImageDropZoneConfig:Default
  LV_GetText(thisDropZone, eventInfo)
 
  if(showCancelConfirm)
  {
    if(Custom_MsgBox("Are you sure you want to delete the '" . thisDropZone . "' drop zone?") = "OK")
      LV_Delete(eventInfo)
  }
  else
    LV_Delete(eventInfo)
}

DeleteAllDropZones(dropZoneGuis)
{
  ; dropZone, hwnd, iDropTarget
  for index, array in dropZoneGuis
  {
    ;~ Revoke the registration of the ListView as a potential target for OLE drag-and-drop operations.
    array["iDropTarget"].RevokeDragDrop()
    hwnd := array["hwnd"]
    Gui, %hwnd%:Destroy
  }
}

determineRealURL(url)
{
  origUrl := url
  if(InStr(url, "google.com"))
    RegExMatch(url, "(?<=\?imgurl=).*?(?=&)", url)
 
  ;~ msgbox % "url: " url "`n`norigUrl: " origUrl
  return url
}

downloadFile(origUrl, foundUrl, dropZoneInfo)
{
  SplitPath, foundUrl,,, imageFileExt
  fileDropDir := dropZoneInfo["fileDrop"]
  prefix := dropZoneInfo["prefix"]
  suffix := dropZoneInfo["suffix"]
  timeFormat := dropZoneInfo["timeFormat"]
  FormatTime, nowTime,, % timeFormat

  Inputbox, fileName, File Name Entry, Please Enter a file name. (no extension),,,,,,,, %prefix% %nowTime% %suffix%
  if(fileName = "")
    fileName :=  %prefix% %nowTime% %suffix%
 
 
  ; Only try to download the file if its a jpg, otherwise create a link
  if(RegExMatch(foundUrl, "\.\w{3,4}$"))
  {
    try
    {
      URLDownloadToFile, %foundUrl%, %fileDropDir%\%fileName%.%imageFileExt%
      if(ErrorLevel)
        return "Unable to download '" . foundUrl . "' parsed from '" . origUrl . "'"
     
      return true
    }
    catch, e
    {
      msgbox % "ErrorLevel: " ErrorLevel "`nA_LastError: " A_LastError "`nmessage: " e.message "`nWhat: " e.what "`nExtra: " e.extra "`nLine: " e.line
      return "Unable to download '" . foundUrl . "' parsed from '" . origUrl . "'"
    }
  }
  else
  {
    FileCreateShortcut, %foundUrl%, %fileDropDir%\%fileName%.lnk
    TrayTip, Link Created, Couldn't find image so a link was created instead., 15
    return true
  }
}

DropFile(dropZoneGuis, targetHwnd, url)
{
  dropZoneInfo := findDropZoneInfo(dropZoneGuis, targetHwnd)
  foundUrl := determineRealURL(url)
 
  return downloadFile(url, foundUrl, dropZoneInfo)
}

; Called to create/display dropZone gui
DropZoneGui(label, icon, x1, x2, y1, y2)
{
  static index = 0
  index += 1
 
  ; If no pos data was provided
  if(!x1)
  {
    x1 := 0
    x2 := 100
    y1 := 0
    y1 := 100
  }
 
  width := x2 - x1
  height := y2 - y1
  labelWidth := StrLen(label) * 25
  labelHeight := 32
 
  ; If the label is too long we set the labelsPerRow to 1 otherwise nothing would be displayed
  labelsPerColumn := height / labelHeight < 1 ? 1 : height / labelHeight
  labelsPerRow := width / labelWidth < 1 ? 1 : width / labelWidth

  CustomColor = EEAA99  ; Can be any RGB color (it will be made transparent below).
  Gui, New, hwndDZG%index% +LastFound +AlwaysOnTop -Caption +ToolWindow ; +ToolWindow avoids a taskbar button and an alt-tab menu item.
  Gui, Color, %CustomColor%
 
  ; If an icon was provided make it the size of the gui else use the label text
  if(icon)
    Gui, Add, Picture, w%width% h%height%, %icon%
  else
  {
    Gui, Font, s32  ; Set a large font size (32-point).
    x := 0
   
    Loop %labelsPerRow%
    {
      y := 0
      Loop %labelsPerColumn%
      {
        Gui, Add, Text, % "x" x " y" y " cLime", %label%
        y += 50
      }
      x += labelWidth
    }
  }
  ; Make all pixels of this color transparent and make the text itself translucent (150):
  WinSet, TransColor, %CustomColor% 150
  Gui, Show, x%x1% y%y1% w%width% h%height% NoActivate  ; NoActivate avoids deactivating the currently active window.
  return DZG%index%
}

Exit(ExitReason, ExitCode)
{
  global dropZoneGuis

  DeleteAllDropZones(dropZoneGuis)
  ExitApp
}

findDropZoneInfo(dropZoneGuis, targetHwnd)
{
  global iniPath
 
  data := LoadData(iniPath)
  for index, array in dropZoneGuis
    if(array["hwnd"] = targetHwnd)
      for dindex, darray in data
        if(darray["dropZone"] = array["dropZone"])
          return darray
}

GuiToolTip(wParam, lParam, Msg)
{
  MouseGetPos,,,mhwnd, OutputVarControl
 
  if(OutputVarControl = "Button3" && mhwnd = WIDZ)
Help := "After pressing 'Dropzone Position' move your mouse to the desired location; hold down the mouse button then move the mouse to select your area."
  else
    Help := ""

  ToolTip % Help
}

LetUserSelectRect(ByRef ID, ByRef X1, ByRef Y1, ByRef X2, ByRef Y2)
{ ;http://www.autohotkey.com/board/topic/111196-drawing-boxes-on-screen-need-help-finishing/?p=655416
    CoordMode, Mouse ; Required: change coord mode to screen vs relative.
    static r := 3
    ; Create the "selection rectangle" GUIs (one for each edge).
    Loop 4 {
        Gui, % ID A_Index ": -Caption +ToolWindow +AlwaysOnTop"
        Gui, % ID A_Index ": Color", Red
    }
    ; Disable LButton.
    Hotkey, *LButton, lusr_return, On
    ; Wait for user to press LButton.
    KeyWait, LButton, D
    ; Get initial coordinates.
    MouseGetPos, xorigin, yorigin
    ; Set timer for updating the selection rectangle.
    SetTimer, lusr_update, 10
    ; Wait for user to release LButton.
    KeyWait, LButton
    ; Re-enable LButton.
    Hotkey, *LButton, Off
    ; Disable timer.
    SetTimer, lusr_update, Off
    return
 
    lusr_update:
        CoordMode, Mouse ; Required: change coord mode to screen vs relative.
        MouseGetPos, x, y
        if (x = xlast && y = ylast)
            ; Mouse hasn't moved so there's nothing to do.
            return
        if (x < xorigin)
             x1 := x, x2 := xorigin
        else x2 := x, x1 := xorigin
        if (y < yorigin)
             y1 := y, y2 := yorigin
        else y2 := y, y1 := yorigin
        ; Update the "selection rectangle".
        Gui, % ID "1:Show", % "NA X" x1 " Y" y1 " W" x2-x1 " H" r
        Gui, % ID "2:Show", % "NA X" x1 " Y" y2-r " W" x2-x1 " H" r
        Gui, % ID "3:Show", % "NA X" x1 " Y" y1 " W" r " H" y2-y1
        Gui, % ID "4:Show", % "NA X" x2-r " Y" y1 " W" r " H" y2-y1
    lusr_return:
    return
}

;~ LV_Add(, array[1], array[2], array[3], array[4], array[5], array[6], array[7])
LoadData(path)
{
  FileRead, data, %path%
  dataArray := Object()
 
  Loop, Parse, data, `n, `r`n
  {
    ; If not the setttings row
    if(A_Index != 1)
    {
      array := StrSplit(A_LoopField, "|")
      if(array[1])
      {
        dataArray.Insert({dropZone: array[1], prefix: array[2], suffix: array[3], pos: array[4], fileDrop: array[5], icon: array[6], timeFormat: array[7]})
      }
    }
  }
 
  return dataArray
}

LoadSettings(path)
{
  global showCancelConfirm, firstTimeOpenShowConfig
 
  FileReadLine, data, %path%, 1
 
  array := StrSplit(data, "|")
  firstTimeOpenShowConfig := array[1] = 0 ? false : true
  showCancelConfirm := array[2] = 0 ? false : true
}

PopulateDropZoneList(path)
{
  data := LoadData(path)
  for index, array in data
    LV_Add(, array["dropZone"], array["prefix"], array["suffix"], array["pos"], array["fileDrop"], array["icon"], array["timeFormat"])
}

SaveData(path)
{
  global showCancelConfirm, firstTimeOpenShowConfig
  FileCopy, %path%, %path%.bak
  FileDelete, %path%
  data := ""
 
  ; Save the setttings
  data := firstTimeOpenShowConfig . "|"  . showCancelConfirm . "`n"
  FileAppend, %data%, %path%
 
  ; Save the list data
  Loop, % LV_GetCount()
  {
    rowData := RowText(A_Index)
    data := rowData[1] . "|" .  rowData[2] . "|" .  rowData[3] . "|" .  rowData[4] . "|" .  rowData[5] . "|" .  rowData[6] . "|" . rowData[7] . "`n"
    FileAppend, %data%, %path%
  }
  FileDelete, %path%.bak
}

RowText(rowNumber)
{
  LV_GetText(dropZone, rowNumber, 1)
  LV_GetText(prefix, rowNumber, 2)
  LV_GetText(suffix, rowNumber, 3)
  LV_GetText(pos, rowNumber, 4)
  LV_GetText(location, rowNumber, 5)
  LV_GetText(icon, rowNumber, 6)
  LV_GetText(TimeFormat, rowNumber, 7)
  return [dropZone, prefix, suffix, pos, location, icon, TimeFormat]
}

IDropTargetOnDrop_WIDZ(TargetObject, pDataObj, KeyState, X, Y, DropEffect)
{
  Static CF_NATIVE := A_IsUnicode ? 13 : 1 ; CF_UNICODETEXT  : CF_TEXT
  global dropZoneGuis
  ; if valid
  If (pEnumObj := IDataObject_EnumFormatEtc(pDataObj))
  {
    ; Loop through structure
    While IEnumFORMATETC_Next(pEnumObj, FORMATETC)
    {
      ; Populate variables with current item data
      IDataObject_ReadFormatEtc(FORMATETC, Format, Device, Aspect, Index, Type)
     
      ; We only want the text since it will have the shortcut url so continue looping until it shows up
      if(Format != CF_NATIVE)
            continue
      else
      {
        IDataObject_GetData(pDataObj, FORMATETC, Size, Data)
        url := StrGet(&Data)
        response := DropFile(dropZoneGuis, TargetObject.hwnd, url)
        if(response != true)
          msgbox % response
       
        break
      }
    }
  }
}

; ************************************************ All the code below is from https://github.com/AHK-just-me and wasn't written by me
; from https://github.com/AHK-just-me/DoDragDrop/blob/master/sources/IDropTarget.ahk
; ==================================================================================================================================
; IDropTarget interface -> msdn.microsoft.com/en-us/library/ms679679(v=vs.85).aspx
; Requires: IDataObject.ahk
; ==================================================================================================================================
; Creates a new instance of the IDropTarget object.
; Parameters:
;     HWND              -  HWND of the Gui window or control which shall be used as a drop target.
;     UserFuncSuffix    -  The suffix for the names of the user-defined functions which will be called on events (see Remarks).
;     RequiredFormats   -  An array containing the numeric clipboard formats required to permit drop.
;                          If omitted, only 15 (CF_HDROP) used for dropping files will be required.
;     Register          -  If set to True the target will be registered as a drop target on creation.
;                          Otherwise you have to call the RegisterDragDrop() method manually to activate the drop target.
;     UseHelper         -  Use the shell helper object if available (True/False).
; Return value:
;     New IDropTarget instance on success; in case of parameter errors, False.
; Remarks:
;     The interface permits up to 4 user-defined functions which will be called from the related methods:
;        IDropTargetOnEnter      Optional, called from IDropTarget.DragEnter()
;        IDropTargetOnOver       Optional, called from IDropTarget.DragOver()
;        IDropTargetOnLeave      Optional, called from IDropTarget.DragLeave()
;        IDropTargetOnDrop       Mandatory, called from IDropTarget.Drop()
;     The suffix passed in UserFuncSuffix which will be appended to this names to identify the instance specific functions.
;
;     Function parameters:
;        IDropTargetOnDrop and IDropTargetOnEnter must accept at least 6 parameters:
;           TargetObject   -  This instance.
;           pDataObj       -  A pointer to the IDataObject interface on the data object being dropped.
;           KeyState       -  The current state of the mouse buttons and keyboard modifier keys.
;           X              -  The current X coordinate of the cursor in screen coordinates.
;           Y              -  The current Y coordinate of the cursor in screen coordinates.
;           DropEffect     -  The drop effect determined by the Drop() method.
;        IDropTargetOnOver must accept at least 5 parameters:
;           TargetObject   -  This instance.
;           KeyState       -  The current state of the mouse buttons and keyboard modifier keys.
;           X              -  The current X coordinate of the cursor in screen coordinates.
;           Y              -  The current Y coordinate of the cursor in screen coordinates.
;           DropEffect     -  The drop effect determined by the Drop() method.
;        IDropTargetOnLeave must accept at least 1 parameter:
;           TargetObject   -  This instance.
;
;     What the functions must return:
;        The return value of IDropTargetOnDrop, IDropTargetOnEnter, and IDropTargetOnOver is used as the drop effect reported
;        as the result of the drop operation. In the easiest case the function returns the value passed in DropEffect.
;        Otherwise, it must return one of the following values:
;           0 (DROPEFFECT_NONE)
;           1 (DROPEFFECT_COPY)
;           2 (DROPEFFECT_MOVE)
;        The return value of IDropTargetOnLeave is not used.
;
;     As is the interface supports only left-dragging and permits DROPEFFECT_COPY and DROPEFFECT_MOVE. The default effect is
;     DROPEFFECT_COPY. It will be switched to DROPEFFECT_MOVE if either Ctrl or Shift is pressed. You can overwrite the default
;     from the IDropTargetOnEnter user function.
;
;     The dropped data have to be processed completely by the IDropTargetOnDrop user function.
; ==================================================================================================================================
IDropTarget_Create(HWND, UserFuncSuffix, RequiredFormats := "", Register := True, UseHelper := True) {
   Return New IDropTarget(HWND, UserFuncSuffix, RequiredFormats, Register, UseHelper)
}
; ==================================================================================================================================
Class IDropTarget {
   __New(HWND, UserFuncSuffix, RequiredFormats := "", Register := True, UseHelper := True) {
      Static Methods := ["QueryInterface", "AddRef", "Release", "DragEnter", "DragOver", "DragLeave", "Drop"]
      Static Params := (A_PtrSize = 8 ? [3, 1, 1, 5, 4, 1, 5] : [3, 1, 1, 6, 5, 1, 6])
      Static DefaultFormat := 15 ; CF_HDROP
      Static DropFunc := "IDropTargetOnDrop"
      Static EnterFunc := "IDropTargetOnEnter"
      Static OverFunc := "IDropTargetOnOver"
      Static LeaveFunc := "IDropTargetOnLeave"
      Static CLSID_IDTH := "{4657278A-411B-11D2-839A-00C04FD918D0}" ; CLSID_DragDropHelper
      Static IID_IDTH := "{4657278B-411B-11D2-839A-00C04FD918D0}"   ; IID_IDropTargetHelper
      If This.Base.HasKey("Ptr")
         Return False
      UserFunc := DropFunc . UserFuncSuffix
      If !IsFunc(UserFunc) || (Func(UserFunc).MinParams < 6)
         Return False
      This.DropUserFunc := Func(UserFunc)
      UserFunc := EnterFunc . UserFuncSuffix
      If (IsFunc(UserFunc) && (Func(UserFunc).MinParams > 5))
         This.EnterUserFunc := Func(UserFunc)
      UserFunc := OverFunc . UserFuncSuffix
      If (IsFunc(UserFunc) && (Func(UserFunc).MinParams > 4))
         This.OverUserFunc := Func(UserFunc)
      UserFunc := LeaveFunc . UserFuncSuffix
      If (IsFunc(UserFunc) && (Func(UserFunc).MinParams > 0))
         This.LeaveUserFunc := Func(UserFunc)
      This.HWND := HWND
      This.Registered := False
      If IsObject(RequiredFormats)
         This.Required := RequiredFormats
      Else
         This.Required := [DefaultFormat]
      This.PreferredDropEffect := 0
      SizeOfVTBL := (Methods.Length() + 2) * A_PtrSize
      This.SetCapacity("VTBL", SizeOfVTBL)
      This.Ptr := This.GetAddress("VTBL")
      DllCall("RtlZeroMemory", "Ptr", This.Ptr, "UInt", SizeOfVTBL)
      NumPut(This.Ptr + A_PtrSize, This.Ptr + 0, "UPtr")
      For Index, Method In Methods {
         CB := RegisterCallback("IDropTarget." . Method, "", Params[Index], &This)
         NumPut(CB, This.Ptr + 0, A_Index * A_PtrSize, "UPtr")
      }
      This.Helper := ComObjCreate(CLSID_IDTH, IID_IDTH)
      If (Register)
         If !This.RegisterDragDrop()
            Return False
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   ; Registers window/control as a drop target.
   ; -------------------------------------------------------------------------------------------------------------------------------
   RegisterDragDrop() {
      If !(This.Registered)
         If DllCall("Ole32.dll\RegisterDragDrop", "Ptr", This.HWND, "Ptr", This.Ptr, "Int")
            Return False
      Return (This.Registered := True)
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   ; Revokes registering of the window/control as a drop target.
   ; This method should be called before the window/control will be destroyed.
   ; -------------------------------------------------------------------------------------------------------------------------------
   RevokeDragDrop() {
      If (This.Registered)
         DllCall("Ole32.dll\RevokeDragDrop", "Ptr", This.HWND)
      Return !(This.Registered := False)
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   ; Notifies the drag-image manager, if used, to show or hide the drag image.
   ; Parameter:
   ;     Show  -  If true, the drag image will be shown; otherwise it will be hidden.
   ; -------------------------------------------------------------------------------------------------------------------------------
   HelperShow(Show := True) {
      Static HelperShow := A_PtrSize * 7
      If (This.Helper) {
         pVTBL := NumGet(This.Helper + 0, "UPtr")
         , DllCall(NumGet(pVTBL + HelperShow, "UPtr"), "Ptr", This.Helper, "UInt", !!Show)
         Return True
      }
      Return False
   }
   ; ===============================================================================================================================
   ; The following methods must not be called directly, they are reserved for internal and system use.
   ; ===============================================================================================================================
   __Delete() {
      This.RevokeDragDrop()
      While (CB := NumGet(This.Ptr + (A_PtrSize * A_Index), "Ptr"))
         DllCall("GlobalFree", "Ptr", CB)
      If (This.Helper)
         ObjRelease(This.Helper)
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   QueryInterface(RIID, PPV) {
      ; IUnknown -> msdn.microsoft.com/en-us/library/ms682521(v=vs.85).aspx
      Static IID := "{00000122-0000-0000-C000-000000000046}"
      VarSetCapacity(QID, 80, 0)
      QIDLen := DllCall("Ole32.dll\StringFromGUID2", "Ptr", RIID, "Ptr", &QID, "Int", 40, "Int")
      If (StrGet(&QID, QIDLen, "UTF-16") = IID) {
         NumPut(This, PPV + 0, "Ptr")
         Return 0 ; S_OK
      }
      Else {
         NumPut(0, PPV + 0, "Ptr")
         Return 0x80004002 ; E_NOINTERFACE
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   AddRef() {
      ; IUnknown -> msdn.microsoft.com/en-us/library/ms691379(v=vs.85).aspx
      ; Reference counting is not needed in this case.
      Return 1
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   Release() {
      ; IUnknown -> msdn.microsoft.com/en-us/library/ms682317(v=vs.85).aspx
      ; Reference counting is not needed in this case.
      Return 0
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   DragEnter(pDataObj, grfKeyState, P3 := "", P4 := "", P5 := "") {
      ; DragEnter -> msdn.microsoft.com/en-us/library/ms680106(v=vs.85).aspx
      ; Params 32: IDataObject *pDataObj, DWORD grfKeyState, LONG x, LONG y, DWORD *pdwEffect
      ; Params 64: IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect
      Static HelperEnter := A_PtrSize * 3
      Instance := Object(A_EventInfo)
      If (A_PtrSize = 8)
         X := P2 & 0xFFFFFFFF, Y := P2 >> 32
      Else
         X := P2, Y := P3
      Effect := 0
      If !(grfKeyState & 0x02) { ; right-drag isn't supported by default
         For Each, Format In Instance.Required {
            IDataObject_CreateFormatEtc(FORMATETC, Format)
            If (Effect := IDataObject_QueryGetData(pDataObj, FORMATETC))
               Break
         }
      }
      If (Effect) && (Instance.EnterUserFunc)
         Effect := Instance.EnterUserFunc.Call(Instance, pDataObj, grfKeyState, X, Y, Effect)
      Instance.PreferredDropEffect := Effect
      ; If Ctrl and/or Shift is pressed swap the effect
      Effect ^= grfKeyState & 0x0C ? 3 : 0
      ; Call IDropTargetHelper, if created
      If (Instance.Helper) {
         VarSetCapacity(PT, 8, 0)
         , NumPut(X, PT, 0, "Int")
         , NumPut(Y, PT, 0, "Int")
         , pVTBL := NumGet(Instance.Helper + 0, "UPtr")
         , DllCall(NumGet(pVTBL + HelperEnter, "UPtr")
                 , "Ptr", Instance.Helper, "Ptr", Instance.HWND, "Ptr", pDataObj, "Ptr", &PT, "UInt", Effect, "Int")
      }
      NumPut(Effect, (A_PtrSize = 8 ? P4 : P5) + 0, "UInt")
      Return 0 ; S_OK
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   DragOver(grfKeyState, P2 := "", P3 := "", P4 := "") {
      ; DragOver -> msdn.microsoft.com/en-us/library/ms680129(v=vs.85).aspx
      ; Params 32: DWORD grfKeyState, LONG x, LONG y, DWORD *pdwEffect
      ; Params 64: DWORD grfKeyState, POINTL pt, DWORD *pdwEffect
      Static HelperOver := A_PtrSize * 5
      Instance := Object(A_EventInfo)
      If (A_PtrSize = 8)
         X := P2 & 0xFFFFFFFF, Y := P2 >> 32
      Else
         X := P2, Y := P3
      ; If Ctrl and/or Shift is pressed swap the effect
      Effect := Instance.PreferredDropEffect ^ (grfKeyState & 0x0C ? 3 : 0)
      If (Effect) && (Instance.OverUserFunc)
         Effect := Instance.OverUserFunc.Call(Instance, grfKeyState, X, Y, Effect)
      If (Instance.Helper) {
         VarSetCapacity(PT, 8, 0)
         , NumPut(X, PT, 0, "Int")
         , NumPut(Y, PT, 0, "Int")
         , pVTBL := NumGet(Instance.Helper + 0, "UPtr")
         , DllCall(NumGet(pVTBL + HelperOver, "UPtr"), "Ptr", Instance.Helper, "Ptr", &PT, "UInt", Effect, "Int")
      }
      NumPut(Effect, (A_PtrSize = 8 ? P3 : P4) + 0, "UInt")
      Return 0 ; S_OK
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   DragLeave() {
      ; DragLeave -> msdn.microsoft.com/en-us/library/ms680110(v=vs.85).aspx
      Static HelperLeave := A_PtrSize * 4
      Instance := Object(A_EventInfo)
      Instance.PreferredDropEffect := 0
      If (Instance.LeaveUserFunc)
         Instance.LeaveUserFunc.Call(Instance)
      If (Instance.Helper) {
         pVTBL := NumGet(Instance.Helper + 0, "UPtr"), DllCall(NumGet(pVTBL + HelperLeave, "UPtr"), "Ptr", Instance.Helper)
      }
      Return 0 ; S_OK
   }
   ; -------------------------------------------------------------------------------------------------------------------------------
   Drop(pDataObj, grfKeyState, P3 := "", P4 := "", P5 := "") {
      ; Drop -> msdn.microsoft.com/en-us/library/ms687242(v=vs.85).aspx
      ; Params 32: IDataObject *pDataObj, DWORD grfKeyState, LONG x, LONG y, DWORD *pdwEffect
      ; Params 64: IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect
      Static HelperDrop := A_PtrSize * 6
      Instance := Object(A_EventInfo)
      If (A_PtrSize = 8)
         X := P3 & 0xFFFFFFFF, Y := P3 >> 32
      Else
         X := P3, Y := P4
      Effect := Instance.PreferredDropEffect ^ (grfKeyState & 0x0C ? 3 : 0)
      Effect := Instance.DropUserFunc.Call(Instance, pDataObj, grfKeyState, X, Y, Effect)
      NumPut(Effect, (A_PtrSize = 8 ? P4 : P5) + 0, "UInt")
      If (Instance.Helper) {
         VarSetCapacity(PT, 8, 0)
         , NumPut(X, PT, 0, "Int")
         , NumPut(Y, PT, 0, "Int")
         , pVTBL := NumGet(Instance.Helper + 0, "UPtr")
         , DllCall(NumGet(pVTBL + HelperDrop, "UPtr"), "Ptr", Instance.Helper, "Ptr", pDataObj, "Ptr", &PT, "UInt", Effect, "Int")
      }
      ObjRelease(pDataObj)
      Return 0 ; S_OK
   }
}
; ==================================================================================================================================


; from https://github.com/AHK-just-me/DoDragDrop/blob/master/sources/IDataObject.ahk
; ==================================================================================================================================
; IDataObject interface -> msdn.microsoft.com/en-us/library/ms688421(v=vs.85).aspx
; Partial implementation.
; Requires: IEnumFORMATETC.ahk
; ==================================================================================================================================
IDataObject_EnumFormatEtc(pDataObj) {
   ; EnumFormatEtc -> msdn.microsoft.com/en-us/library/ms683979(v=vs.85).aspx
   ; DATADIR_GET = 1
   Static EnumFormatEtc := A_PtrSize * 8
   pVTBL := NumGet(pDataObj + 0, "UPtr")
   If !DllCall(NumGet(pVTBL + EnumFormatEtc, "UPtr"), "Ptr", pDataObj, "UInt", 1, "PtrP", ppenumFormatEtc, "Int")
      Return ppenumFormatEtc
   Return False
}
; ==================================================================================================================================
IDataObject_GetData(pDataObj, ByRef FORMATETC, ByRef Size, ByRef Data) {
   ; GetData -> msdn.microsoft.com/en-us/library/ms678431(v=vs.85).aspx
   Static GetData := A_PtrSize * 3
   Data := ""
   , Size := -1
   , VarSetCapacity(STGMEDIUM, 24, 0) ; 64-bit
   , pVTBL := NumGet(pDataObj + 0, "UPtr")
   If !DllCall(NumGet(pVTBL + GetData, "UPtr"), "Ptr", pDataObj, "Ptr", &FORMATETC, "Ptr", &STGMEDIUM, "Int") {
      If (NumGet(STGMEDIUM, "UInt") = 1) { ; TYMED_HGLOBAL
         hGlobal := NumGet(STGMEDIUM, A_PtrSize, "UPtr")
         , pGlobal := DllCall("GlobalLock", "Ptr", hGlobal, "Uptr")
         , Size := DllCall("GlobalSize", "Ptr", hGlobal, "UPtr")
         , VarSetCapacity(Data, Size, 0)
         , DllCall("RtlMoveMemory", "Ptr", &Data, "Ptr", pGlobal, "Ptr", Size)
         , DllCall("GlobalUnlock", "Ptr", hGlobal)
         , DllCall("Ole32.dll\ReleaseStgMedium", "Ptr", &STGMEDIUM)
         Return True
      }
      DllCall("Ole32.dll\ReleaseStgMedium", "Ptr", &STGMEDIUM)
   }
   Return False
}
; ==================================================================================================================================
IDataObject_QueryGetData(pDataObj, ByRef FORMATETC) {
   ; QueryGetData -> msdn.microsoft.com/en-us/library/ms680637(v=vs.85).aspx
   Static QueryGetData := A_PtrSize * 5
   pVTBL := NumGet(pDataObj + 0, "UPtr")
   Return !DllCall(NumGet(pVTBL + QueryGetData, "UPtr"), "Ptr", pDataObj, "Ptr", &FORMATETC, "Int")
}
; ==================================================================================================================================
IDataObject_SetData(pDataObj, ByRef FORMATETC, ByRef STGMEDIUM) {
   ; SetData -> msdn.microsoft.com/en-us/library/ms686626(v=vs.85).aspx
   Static SetData := A_PtrSize * 7
   pVTBL := NumGet(pDataObj + 0, "UPtr")
   Return !DllCall(NumGet(pVTBL + SetData, "UPtr"), "Ptr", pDataObj, "Ptr", &FORMATETC, "Ptr", &STGMEDIUM, "Int", True, "Int")
}
; ==================================================================================================================================
; Auxiliary functions to get/set data of the data object.
; ==================================================================================================================================
; FORMATETC structure -> msdn.microsoft.com/en-us/library/ms682242(v=vs.85).aspx
; ==================================================================================================================================
IDataObject_CreateFormatEtc(ByRef FORMATETC, Format, Aspect := 1, Index := -1, Tymed := 1) {
   ; DVASPECT_CONTENT = 1, Index all data = -1, TYMED_HGLOBAL = 1
   VarSetCapacity(FORMATETC, 32, 0) ; 64-bit
   , NumPut(Format, FORMATETC, 0, "Ushort")
   , NumPut(Aspect, FORMATETC, A_PtrSize = 8 ? 16 : 8 , "UInt")
   , NumPut(Index, FORMATETC, A_PtrSIze = 8 ? 20 : 12, "Int")
   , NumPut(Tymed, FORMATETC, A_PtrSize = 8 ? 24 : 16, "UInt")
   Return &FORMATETC
}
; ==================================================================================================================================
IDataObject_ReadFormatEtc(ByRef FORMATETC, ByRef Format, ByRef Device, ByRef Aspect, ByRef Index, ByRef Tymed) {
   Format := NumGet(FORMATETC, OffSet := 0, "UShort")
   , Device := NumGet(FORMATETC, Offset += A_PtrSize, "UPtr")
   , Aspect := NumGet(FORMATETC, Offset += A_PtrSize, "UInt")
   , Index  := NumGet(FORMATETC, Offset += 4, "Int")
   , Tymed  := NumGet(FORMATETC, Offset += 4, "UInt")
}
; ==================================================================================================================================
; Get/Set format data.
; ==================================================================================================================================
IDataObject_GetDroppedFiles(pDataObj, ByRef DroppedFiles) {
   ; msdn.microsoft.com/en-us/library/bb773269(v=vs.85).aspx
   IDataObject_CreateFormatEtc(FORMATETC, 15) ; CF_HDROP
   DroppedFiles := []
   If IDataObject_GetData(pDataObj, FORMATETC, Size, Data) {
      Offset := NumGet(Data, 0, "UInt")
      CP := NumGet(Data, 16, "UInt") ? "UTF-16" : "CP0"
      Shift := (CP = "UTF-16")
      While (File := StrGet(&Data + Offset, CP)) {
         DroppedFiles.Push(File)
         Offset += (StrLen(File) + 1) << Shift
      }
   }
   Return DroppedFiles.Length()
}
; ==================================================================================================================================
IDataObject_GetLogicalDropEffect(pDataObj, ByRef DropEffect) {
   Static LogicalDropEffect := DllCall("RegisterClipboardFormat", "Str", "Logical Performed DropEffect")
   IDataObject_CreateFormatEtc(FORMATETC, LogicalDropEffect)
   DropEffect := ""
   If IDataObject_GetData(pDataObj, FORMATETC, Size, Data) {
      DropEffect := NumGet(Data, "UChar")
      Return True
   }
   Return False
}
; ==================================================================================================================================
IDataObject_GetPerformedDropEffect(pDataObj, ByRef DropEffect) {
   Static PerformedDropEffect := DllCall("RegisterClipboardFormat", "Str", "Performed DropEffect")
   IDataObject_CreateFormatEtc(FORMATETC, PerformedDropEffect)
   DropEffect := ""
   If IDataObject_GetData(pDataObj, FORMATETC, Size, Data) {
      DropEffect := NumGet(Data, "UChar")
      Return True
   }
   Return False
}
; ==================================================================================================================================
IDataObject_GetText(pDataObj, ByRef Txt) {
   Static CF_NATIVE := A_IsUnicode ? 13 : 1 ; CF_UNICODETEXT : CF_TEXT
   IDataObject_CreateFormatEtc(FORMATETC, CF_NATIVE)
   Txt := ""
   If IDataObject_GetData(pDataObj, FORMATETC, Size, Data) {
      Txt := StrGet(Data, Size >> !!A_IsUnicode)
      Return True
   }
   Return False
}
; ==================================================================================================================================
IDataObject_SetLogicalDropEffect(pDataObj, DropEffect) {
   Static LogicalDropEffect := DllCall("RegisterClipboardFormat", "Str", "Logical Performed DropEffect")
   IDataObject_CreateFormatEtc(FORMATETC, LogicalDropEffect)
   , VarSetCapacity(STGMEDIUM, 24, 0) ; 64-bit
   , NumPut(1, STGMEDIUM, "UInt") ; TYMED_HGLOBAL
   ; 0x42 = GMEM_MOVEABLE (0x02) | GMEM_ZEROINIT (0x40)
   , hMem := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", 4, "UPtr")
   , pMem := DllCall("GlobalLock", "Ptr", hMem)
   , NumPut(DropEffect, pMem + 0, "UChar")
   , DllCall("GlobalUnlock", "Ptr", hMem)
   , NumPut(hMem, STGMEDIUM, A_PtrSize, "UPtr")
   Return IDataObject_SetData(pDataObj, FORMATETC, STGMEDIUM)
}
; ==================================================================================================================================
IDataObject_SetPerformedDropEffect(pDataObj, DropEffect) {
   Static PerformedDropEffect := DllCall("RegisterClipboardFormat", "Str", "Performed DropEffect")
   IDataObject_CreateFormatEtc(FORMATETC, PerformedDropEffect)
   , VarSetCapacity(STGMEDIUM, 24, 0) ; 64-bit
   , NumPut(1, STGMEDIUM, "UInt") ; TYMED_HGLOBAL
   ; 0x42 = GMEM_MOVEABLE (0x02) | GMEM_ZEROINIT (0x40)
   , hMem := DllCall("GlobalAlloc", "UInt", 0x42, "UInt", 4, "UPtr")
   , pMem := DllCall("GlobalLock", "Ptr", hMem)
   , NumPut(DropEffect, pMem + 0, "UChar")
   , DllCall("GlobalUnlock", "Ptr", hMem)
   , NumPut(hMem, STGMEDIUM, A_PtrSize, "UPtr")
   Return IDataObject_SetData(pDataObj, FORMATETC, STGMEDIUM)
}
; ==================================================================================================================================
IDataObject_SHFileOperation(pDataObj, TargetPath, Operation, HWND := 0) {
   ; SHFileOperation -> msdn.microsoft.com/en-us/library/bb762164(v=vs.85).aspx
   If Operation Not In 1,2
      Return False
   IDataObject_CreateFormatEtc(FORMATETC, 15) ; CF_HDROP
   If IDataObject_GetData(pDataObj, FORMATETC, Size, Data) {
      Offset := NumGet(Data, 0, "UInt") ; offset of the file list
      IsUnicode := NumGet(Data, 16, "UInt") ; 1: Unicode, 0: ANSI
      TargetLen := StrPut(TargetPath, IsUnicode ? "UTF-16" : "CP0") + 2
      VarSetCapacity(Target, TargetLen << !!IsUnicode, 0)
      StrPut(TargetPath, &Target, IsUnicode ? "UTF-16" : "CP0")
      SHFOSLen := A_PtrSize * (A_PtrSize = 8 ? 7 : 8)
      VarSetCapacity(SHFOS, SHFOSLen, 0) ; SHFILEOPSTRUCT
      NumPut(HWND, SHFOS, 0, "UPtr")
      NumPut(Operation, SHFOS, A_PtrSize, "UInt") ; FO_MOVE = 1, FO_COPY = 2, so we have to swap the DropEffect
      NumPut(&Data + Offset, SHFOS, A_PtrSize * 2, "UPtr")
      NumPut(&Target, SHFOS, A_PtrSize * 3, "UPtr")
      NumPut(0x0200, SHFOS, A_PtrSize * 4, "UInt") ; FOF_NOCONFIRMMKDIR
      If (IsUnicode)
         Return DllCall("Shell32.dll\SHFileOperationW", "Ptr", &SHFOS, "Int")
      Else
         Return DllCall("Shell32.dll\SHFileOperationA", "Ptr", &SHFOS, "Int")
   }
}
; ==================================================================================================================================

; from https://github.com/AHK-just-me/DoDragDrop/blob/master/sources/IEnumFORMATETC.ahk
; ==================================================================================================================================
; IEnumFORMATETC interface -> msdn.microsoft.com/en-us/library/ms682337(v=vs.85).aspx
; Partial implementation, 'Clone' method is missing.
; ==================================================================================================================================
IEnumFORMATETC_Next(pEnumObj, ByRef FORMATETC) {
   ; Next -> msdn.microsoft.com/en-us/library/dd542673(v=vs.85).aspx
   Static Next := A_PtrSize * 3
   VarSetCapacity(FORMATETC, A_PtrSize = 8 ? 32 : 20, 0)
   , pVTBL := NumGet(pEnumObj + 0, "UPtr")
   Return !DllCall(NumGet(pVTBL + Next, "UPtr"), "Ptr", pEnumObj, "UInt", 1, "Ptr", &FORMATETC, "Ptr", 0, "Int")
}
; ----------------------------------------------------------------------------------------------------------------------------------
IEnumFORMATETC_Reset(pEnumObj) {
   ; Reset -> msdn.microsoft.com/en-us/library/dd542674(v=vs.85).aspx
   Static Reset := A_PtrSize * 5
   pVTBL := NumGet(pEnumObj + 0, "UPtr")
   Return !DllCall(NumGet(pVTBL + Reset, "UPtr"), "Ptr", pEnumObj, "Int")
}
; ----------------------------------------------------------------------------------------------------------------------------------
IEnumFORMATETC_Skip(pEnumObj, ItemCount) {
   ; Skip -> msdn.microsoft.com/en-us/library/dd542674(v=vs.85).aspx
   Static Skip := A_PtrSize * 4
   pVTBL := NumGet(pEnumObj + 0, "UPtr")
   Return !DllCall(NumGet(pVTBL + Skip, "UPtr"), "Ptr", pEnumObj, "UInt", ItemCount, "Int")
}
; ==================================================================================================================================

Special thanks to the users 'jballi' and 'just me' on ahkscript.org for the drag and drop portion.

ayryq:
Please realize that when you do an image search on yahoo/bing/etc you are seeing thumbnails not actual images as such. Trying to drag these images will only create a shortcut to wherever that thumbnail goes, not an image.

-lifeweaver (October 09, 2015, 01:43 PM)
--- End quote ---

My irfanview/bat method with Pale Moon web browser gets the actual, full size, image, from the google image search results list. Also, no security warning has ever been shown on my Windows 10 system.

Navigation

[0] Message Index

[#] Next page

Go to full version