Let's say that we have a standard TForm class that defines our application's main window.
And we also have a method to open files in the program (in the TApp instance):
unit MainWindow;
interface
type
TMainWindow = class(TForm)
private
FApp: TApp;
. . .
end;
To implement the handling of file drag-n-drop operations from outside the application, we need to do two things:
First, we need to define the main window as a valid target of drag-n-drop operations:
unit MainWindow;
interface
type
TMainWindow = class(TForm)
private
FApp: TApp;
protected
procedure CreateParams(var AParams: TCreateParams); override;
end;
implementation
procedure TMainWindow.CreateParams(var AParams: TCreateParams);
begin
inherited CreateParams(AParams);
AParams.ExStyle := AParams.ExStyle or WS_EX_ACCEPTFILES;
end;
Another way of doing this is by calling DragAcceptFiles in FormCreate,
but since I don't like auto-generated event handlers too much, let's go with this first solution.
Second, we need to define a handler for the drop event (when the user drops the dragged file onto our application's window);
note the additional uses statement (ShellAPI is needed to import drag-n-drop specific declarations):
unit MainWindow;
interface
uses ShellAPI;
type
TMainWindow = class(TForm)
private
FApp: TApp;
protected
procedure CreateParams(var AParams: TCreateParams); override;
procedure WMDropFiles(var AMessage: TWMDropFiles); message WM_DropFiles;
end;
implementation
procedure TMainWindow.CreateParams(var AParams: TCreateParams);
begin
inherited CreateParams(AParams);
AParams.ExStyle := AParams.ExStyle or WS_EX_ACCEPTFILES;
end;
procedure TMainWindow.WMDropFiles(var AMessage: TWMDropFiles);
var
LDropHandle: HDrop;
LFileCount, LFileIndex, LFilePathLength: integer;
LFilePath: string;
begin
LDropHandle := AMessage.Drop;
try
LFileCount := DragQueryFile(LDropHandle, $FFFFFFFF, NIL, 0);
for LFileIndex := 0 to LFileCount - 1 do
begin
LFilePathLength := DragQueryFile(LDropHandle, LFileIndex, NIL, 0) + 1;
SetLength(LFilePath, LFilePathLength);
DragQueryFile(LDropHandle, LFileIndex, @LFilePath[1], LFilePathLength);
LFilePath := PAnsiChar(LFilePath);
FApp.OpenFile(LFilePath);
end;
finally
DragFinish(LDropHandle);
end;
end;
This code could be a bit nicer, but we need to get around the zero-terminated strings of the C interface to the Windows API.
Hence the +1 when setting LFilePathLength and the call to PAnsiChar later on
(to allocate place for the null character and then to get rid of it, respectively).
The first call to DragQueryFile (with $FFFFFFFF) is to get the number of files being dragged.
The second call - with the current file's index, and FileName set to NIL) - gets the length of the file's path (without the terminating null character).
And the final call to DragQueryFile gets the file's path.
Finally, the DragFinish call deallocates space allocated by the system to pass all these file path parameters.
And that's pretty much it...
Top
|