Jump to content
direktor05

Drag Drop via Ole

Recommended Posts

Hello,

 

I want to do drag drop from Windows Explorer to my app via OLE interface IDropTarget. Question is how do I detect if OLE communication is working well. For now RegisterDragDrop function is working fine. But I can't get a call to DragEnter function when dragging starts. How can I check that OLE is working fine and that dragging somehow starts? But why I can't get DragEnter function to run? Here is some nice theory: https://delphidabbler.com/articles/article-24

 

I can't get any of this functions to work or be called. What is wrong? And how do I check if OLE can detect drag-drop in the first place?

function DragEnter(const dataObj: IDataObject; grfKeyState: Longint;  pt: TPoint; var dwEffect: Longint): 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;

Share this post


Link to post

RegisterDragDrop(Handle, Handler);

 

Handle: 722688

Handler: TFileDropTarget($23747B02490) as IDropTarget

 

So I have a pointer to IDropTarget, but it does not call IDropTarget.DropEnter function when I start the drag operation. Why not? And how can I check this?

 

Share this post


Link to post

procedure TForm1.Create(Sender: TObject);
begin
  RegisterDropTarget(TFileDropTarget.Create(FileDragEnter, FileDragOver, FileDragDrop, FileDragLeave));
end;

procedure TForm1.RegisterDropTarget(Handler: IDropTarget);
begin
  RegisterDragDrop(Handle, Handler);
  FDragDropHandle := Handle;
end;

procedure TForm1.FileDragEnter(Sender: TObject; FileList: TStrings; Point: TPoint; Shift: TShiftState; var Action: TFileDropAction);
begin
  IT NEVER ENTERS HERE
  FDragFromWindows := True;
  Point := ScreenToClient(Point);
  UpdateFileDragAction(FileList, Point, Action);
end;

Share this post


Link to post

How can I check if OLE is called? CoInitialize works OK. RegisterDragDrop also OK. There is no error anywhere but the thing does not work. How can I test a call to OLE dll?

Share this post


Link to post

Is there are reason why don't just use one of these?

If you don't want to use a ready-made library then I suggest you at least use the DragTargetAnalyzer example application in the above library to diagnose your target.

image.thumb.png.67e054ad4db457a66b24163771d22b08.png

Share this post


Link to post
7 hours ago, direktor05 said:

procedure TForm1.Create(Sender: TObject);
begin
  RegisterDropTarget(TFileDropTarget.Create(FileDragEnter, FileDragOver, FileDragDrop, FileDragLeave));
end;

The Form's OnCreate event is not the best place to register the drop target.  If your Form's window is ever recreated at runtime, you will lose your registration.  Instead, override the Form's virtual CreateWnd() method and do the registration there instead.

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

Anders your component probably does diagnostic according to your component functions not in general. I need a solution how do you check if a procedure of function is executed/called inside OLE/ActiveX dll, better yet specifically inside shell drag drop dll? Any hero here?

Share this post


Link to post
21 minutes ago, direktor05 said:

how do you check if a procedure of function is executed/called inside OLE/ActiveX dll, better yet specifically inside shell drag drop dll?

You don't.  The drag code is running inside of the Windows Explorer process.  If it is not invoking the IDropTarget object inside of your process, it means the call is being blocked outside of your process, most likely by UAC/UIPI if your app is running elevated.  Per the comments on your StackOverflow question on this topic:

Quote

Note that Windows doesn't support drag and drop between programs running at different integrity levels since Wndows Vista. Programs running with Administrator prviledge will not be a drop target for stuff dragged from programs not running with Administrator priviledge.

– Brian
Quote

It can work if you handle WM_DROPFILES (DragAcceptFiles()) instead of IDropTarget (RegisterDragDrop()), and then use ChangeWindowMessageFilter/Ex() to allow the WM_DROPFILES, WM_COPYDATA, and (undocumented) WM_COPYGLOBALDATA (0x0049) messages. ChangeWindowMessageFilter/Ex() doesn't work with IDropTarget, though. The alternative is to either 1) enable UIAccess=true for your app (this has very restrictive requirements, though), or 2) run a non-elevated process to accept the drag and then IPC the data into your elevated app.

- Remy Lebeau

 

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×