使用Winapi进行第三方控制拖放

时间:2014-09-03 10:19:46

标签: delphi winapi drag-and-drop activex

我需要使用新组件整合现有应用程序的拖放。

我们的应用程序使用Winapi.ActiveX来实现这一点。新组件附带了自己的拖放事件,但这些事件并不是Winapi兼容的。

现在的主要问题是将内容拖入新控件。如果所有其他方法都失败了,那么拖出它应该是可以实现的,方法是在鼠标按下时缓存光标下的对象。

根据我的理解,你不能覆盖拖放注册,也就是说,如果我在代码中的某个地方调用RegisterDragDrop之前,我会成为持有注册的人。< / p>

然而,观察到的行为是调用RegisterDragDrop报告成功,但在控件上拖动某些内容并不会导致IDropTarget上的DragEnter事件。即使在RegisterDragDrop之后,它们的拖放事件也会很好地触发,但正如我所说,返回的数据对象只保存选定的几种可拖动对象的有效数据。

我还尝试注册包含此组件的面板进行拖放,但这也不起作用。

你会建议什么?

更新

我意识到,我试图注册错误的句柄。当我尝试注册正确的句柄时,我实际上得到了拖放已经注册的错误。

我想我没有太清楚地表达它,但问题是,你如何为已经拥有它自己的实现的闭源组件实现拖放操作,而这种组件并没有实现。为您的口味提供足够的灵活性?

我能想到的是:

  1. 在更改组件之前,错误地检查组件的开发人员。
  2. 在组件的实现和操作系统之间进行一些API挂钩。
  3. 希望其他的东西很简单。
  4. 更新

    感谢到目前为止,现在我可以按照我想要的方式将内容拖入控件中。 下一步是拖延出来。这里的问题是应用程序中的其他丢弃目标无法理解控件的IDataObject。对于不同的控件,我们已经拥有使用IDataObject :: SetData的代码,以所有应用程序的放置目标都能理解的格式附加数据。

    与新控件的区别在于,当它启动拖放操作时,它不会使用已实现IDataObject :: SetData的IDataObject(返回E_NOTIMPL);有没有办法用另一个替换IDataObject,而d&amp; d操作正在进行中?

1 个答案:

答案 0 :(得分:1)

使用以下代码尝试在控件创建后重置已注册的ActiveX控件的IDropTarget:

const
  sOleDropTargetInterface = 'OleDropTargetInterface';

procedure ResetDropTarget(AWnd: HWND);
var
  Unknown: IUnknown;
begin
  Unknown := IUnknown(GetProp(AWnd, PChar(GlobalFindAtom(sOleDropTargetInterface))));
  if Assigned(Unknown) then
    try
      if not SetProp(AWnd, PChar(GlobalFindAtom(sOleDropTargetInterface)), 0) then
        RaiseLastOSError;
      Unknown._Release;
    finally
      Unknown := nil;
    end;
end;

更新

kobik指出了正确的解决方案:使用RevokeDragDrop函数。