Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3456562
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T09:45:06+00:00 2026-05-18T09:45:06+00:00

In Delphi XE can I allow my form to accept file ‘drag and drop’

  • 0

In Delphi XE can I allow my form to accept file ‘drag and drop’ but without having to handle bare windows messages?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T09:45:07+00:00Added an answer on May 18, 2026 at 9:45 am

    You don’t need to handle messages to implement this. You just need to implement IDropTarget and call RegisterDragDrop/RevokeDragDrop. It’s really very very simple. You can actually implement IDropTarget in your form code but I prefer to do it in a helper class that looks like this:

    uses
      Winapi.Windows,
      Winapi.ActiveX,
      Winapi.ShellAPI,
      System.StrUtils,
      Vcl.Forms;
    
    type
      IDragDrop = interface
        function DropAllowed(const FileNames: array of string): Boolean;
        procedure Drop(const FileNames: array of string);
      end;
    
      TDropTarget = class(TObject, IInterface, IDropTarget)
      private
        // IInterface
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
      private
        // IDropTarget
        FHandle: HWND;
        FDragDrop: IDragDrop;
        FDropAllowed: Boolean;
        procedure GetFileNames(const dataObj: IDataObject; var FileNames: TArray<string>);
        procedure SetEffect(var dwEffect: Integer);
        function DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult; stdcall;
        function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;
        function DragLeave: HResult; stdcall;
        function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall;
      public
        constructor Create(AHandle: HWND; const ADragDrop: IDragDrop);
        destructor Destroy; override;
      end;
    
    { TDropTarget }
    
    constructor TDropTarget.Create(AHandle: HWND; const ADragDrop: IDragDrop);
    begin
      inherited Create;
      FHandle := AHandle;
      FDragDrop := ADragDrop;
      RegisterDragDrop(FHandle, Self)
    end;
    
    destructor TDropTarget.Destroy;
    begin
      RevokeDragDrop(FHandle);
      inherited;
    end;
    
    function TDropTarget.QueryInterface(const IID: TGUID; out Obj): HResult;
    begin
      if GetInterface(IID, Obj) then begin
        Result := S_OK;
      end else begin
        Result := E_NOINTERFACE;
      end;
    end;
    
    function TDropTarget._AddRef: Integer;
    begin
      Result := -1;
    end;
    
    function TDropTarget._Release: Integer;
    begin
      Result := -1;
    end;
    
    procedure TDropTarget.GetFileNames(const dataObj: IDataObject; var FileNames: TArray<string>);
    var
      i: Integer;
      formatetcIn: TFormatEtc;
      medium: TStgMedium;
      dropHandle: HDROP;
    begin
      FileNames := nil;
      formatetcIn.cfFormat := CF_HDROP;
      formatetcIn.ptd := nil;
      formatetcIn.dwAspect := DVASPECT_CONTENT;
      formatetcIn.lindex := -1;
      formatetcIn.tymed := TYMED_HGLOBAL;
      if dataObj.GetData(formatetcIn, medium)=S_OK then begin
        (* This cast needed because HDROP is incorrectly declared as Longint in ShellAPI.pas.  It should be declared as THandle
           which is an unsigned integer.  Without this fix the routine fails in top-down memory allocation scenarios. *)
        dropHandle := HDROP(medium.hGlobal);
        SetLength(FileNames, DragQueryFile(dropHandle, $FFFFFFFF, nil, 0));
        for i := 0 to high(FileNames) do begin
          SetLength(FileNames[i], DragQueryFile(dropHandle, i, nil, 0));
          DragQueryFile(dropHandle, i, @FileNames[i][1], Length(FileNames[i])+1);
        end;
      end;
    end;
    
    procedure TDropTarget.SetEffect(var dwEffect: Integer);
    begin
      if FDropAllowed then begin
        dwEffect := DROPEFFECT_COPY;
      end else begin
        dwEffect := DROPEFFECT_NONE;
      end;
    end;
    
    function TDropTarget.DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
    var
      FileNames: TArray<string>;
    begin
      Result := S_OK;
      Try
        GetFileNames(dataObj, FileNames);
        FDropAllowed := (Length(FileNames)>0) and FDragDrop.DropAllowed(FileNames);
        SetEffect(dwEffect);
      Except
        Result := E_UNEXPECTED;
      End;
    end;
    
    function TDropTarget.DragLeave: HResult;
    begin
      Result := S_OK;
    end;
    
    function TDropTarget.DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
    begin
      Result := S_OK;
      Try
        SetEffect(dwEffect);
      Except
        Result := E_UNEXPECTED;
      End;
    end;
    
    function TDropTarget.Drop(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;
    var
      FileNames: TArray<string>;
    begin
      Result := S_OK;
      Try
        GetFileNames(dataObj, FileNames);
        if Length(FileNames)>0 then begin
          FDragDrop.Drop(FileNames);
        end;
      Except
        Application.HandleException(Self);
      End;
    end;
    

    The idea here is to wrap up the complexity of the Windows IDropTarget in TDropTarget. All you need to do is to implement IDragDrop which is much simpler. Anyway, I think this should get you going.

    Create the drop target object from your control’s CreateWnd. Destroy it in the DestroyWnd method. That point is important because VCL window re-creation means that a control can have its window handle destroyed and re-created during its lifetime.

    Note that reference counting on TDropTarget is suppressed. That is because when RegisterDragDrop is called it increments the reference count. This creates a circular reference and this code to suppress reference counting breaks that. This means that you would use this class through a class variable rather than an interface variable, in order to avoid leaking.

    The usage would look something like this:

    type
      TMainForm = class(TForm, IDragDrop)
        ....
      private
        FDropTarget: TDropTarget;
    
        // implement IDragDrop
        function DropAllowed(const FileNames: array of string): Boolean;
        procedure Drop(const FileNames: array of string);
      protected
        procedure CreateWindowHandle; override;
        procedure DestroyWindowHandle; override;
      end;
    
    ....
    
    procedure TMainForm.CreateWindowHandle;
    begin
      inherited;
      FDropTarget := TDropTarget.Create(WindowHandle, Self);
    end;
    
    procedure TMainForm.DestroyWindowHandle;
    begin
      FreeAndNil(FDropTarget);
      inherited;
    end;
    
    function TMainForm.DropAllowed(const FileNames: array of string): Boolean;
    begin
      Result := True;
    end;
    
    procedure TMainForm.Drop(const FileNames: array of string);
    begin
      ; // do something with the file names
    end;
    

    Here I am using a form as the drop target. But you could use any other windowed control in a similar fashion.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

With Delphi 2010 you can get the pixelformat of a jpg file with TJPEGImage
How can allow the usage of the symbol (') in DELPHI TEdit and other
In Delphi I can do something like: var hWin : HWnd; hWin := GetForegroundWindow;
In Delphi you can create a standalone Windows VCL Forms application. You can also
In Delphi I can do the following with a boolean variable: If NOT bValue
In Delphi you can do something like this : TArray = array[1..3] of byte;
Virtual method interception - introduced with Delphi XE - can be used to 'proxify'
I have such a basic problem in Delphi,I can't solve it. My Code: Note:DataR
We have a delphi application which can also run as a sevice . We
How can I check using Delphi 2007 that a box is AVX capable. My

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.