samedi 1 septembre 2018

Drag & Drop between GWindows and Windows Explorer

This article refers to the programming framework GWindows available here.


Dragging files into your GWindow window is very easy:
Have a call to Accept_File_Drag_And_Drop when desired:

   Window.Accept_File_Drag_And_Drop (True);


   procedure On_File_Drop (Window : in out My_Window_Type; File_Names : in Array_Of_File_Names); process the list of dropped file names – that’s it!
A reason for this simplicity seems to be that the underlying message & event were introduced in Windows versions of the early 90’s, like perhaps 3.0 or 3.1 (did not dig too much into this…). Articles from various points in time of the last 25 years warn that feature will disappear “very soon, perhaps in the next version of Windows”, but as you may have seen all the way through Windows 10, Microsoft fortunately never removes features in Windows API – or do they?


The reverse operation, dragging things that represent files out of your program’s window is notoriously complicated and poorly documented. Doing it requires complicated stuff of the Windows 95+ era with what seems to be an active connection with Windows explorer – with good chances of crashing the latter, or having at least some interesting delays because you are dragging the mouse pointer over a window or a shortcut representing data located on the other side of the planet. From the programming perspective, some proposed implementations give headaches just by reading the code snippets.

Fortunately, there is a simple way used by some open-source software. Finally, you can be already happy with the file path indicated by the Windows Explorer window under the mouse cursor, right? Surprisingly, Windows lets you get the handle of any visible window (including buttons, edit boxes, …), and including those of foreign programs! Furthermore, you can get the root ancestor window of a window, then the tree of children, and for each child, their text (for instance button labels, contents of edit boxes, window titles). This technique leads to the knowledge of what kind of window is under the mouse cursor and to the contents of the address bar. If you are interested, you can see the details of the whole hack in the body of GWindows.Application (gwindows-application.adb). Fortunately the dirty stuff is hidden there, and the specification ( gives you access to those information through neat functions with only very innocent types: Integer, Boolean, GString.

   function Get_Window_Text_At_Location (X, Y : Integer) return GString;
   --  Returns the text of the window that contains the point (X, Y).
   --  It can be a window of any application, including the desktop.

   function Get_Window_Class_Name_At_Location (X, Y : Integer) return GString;
   --  Returns the class name of the window that contains the point (X, Y).
   --  It can be a window of any application, including the desktop.

   function Get_Window_Root_Class_Name_At_Location (X, Y : Integer)
      return GString;
   --  Returns the root class name of the window that contains
   --  the point (X, Y).
   --  It can be a window of any application, including the desktop.

   function Is_Desktop_At_Location (X, Y : Integer) return Boolean;

   function Explorer_Path_At_Location (X, Y : Integer) return GString;
   --  Returns the path from a Windows Explorer window (if meaningful),
   --  or the Desktop's path if (X, Y) points to the Desktop.
   --  In any other case, the returned string is empty.

The code sample, cap_test.adb (in gwindows/samples/mouse/), built seamlessly from the project file gwindows_samples.gpr, will demonstrate those recently added functions.
You can find a real usage of Explorer_Path_At_Location in the AZip Zip file manager, here:

Screenshots of cap_test follow:

The existing GWindows feature: identify a GWindows window (of any app) - click to enlarge

Here, new GWindows.Application feature: a Windows Explorer is found, its path is given - click to enlarge
Here, the desktop is under the mouse cursor, so the user's path to it is given - click to enlarge

Aucun commentaire:

Enregistrer un commentaire

The Corporate Bullshit Generator - the Crossroads of Data

Without fresh data from our fans, the Corporate Bullshit Generator could not stay at the cutting-edge of innovative data-centric business i...