【问题标题】:Drag&Drop using Winapi for Third-Party Control使用 Winapi 进行拖放以进行第三方控制
【发布时间】:2014-09-03 10:19:46
【问题描述】:

我需要将现有应用程序的拖放功能与新组件集成。

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

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

据我了解,您不能覆盖拖放注册,也就是说,如果我在组件上调用 RegisterDragDrop 之前他们在代码中的某处执行此操作,我将是持有注册的人。

然而,观察到的行为是调用 RegisterDragDrop 报告成功,但在控件上拖动某些东西不会导致 IDropTarget 上的 DragEnter 事件。他们的拖放事件触发得很好,即使在 RegisterDragDrop 之后也是如此,但正如我所说,返回的数据对象仅保存少数几种类型的可拖动对象的有效数据。

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

你有什么建议?

更新:

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

我想我表述的不是很清楚,但问题是,你如何为一个已经有自己实现的闭源组件实现拖放,这并没有为你的口味提供足够的灵活性?

我能想到的:

  1. Bug 组件的开发人员,直到他们更改组件。
  2. 在组件的实现和操作系统之间进行一些 API 挂钩。
  3. 希望是其他简单的东西。

更新:

到目前为止,谢谢,现在我可以按照我想要的方式将东西拖到控件中。 下一步是将事情拖出去。这里的问题是应用程序中的其他放置目标不理解控件的 IDataObject。对于不同的控件,我们已经有代码使用 IDataObject::SetData 以所有应用程序的放置目标都可以理解的格式附加数据。

但是,与新控件的不同之处在于,当它启动拖放操作时,它不使用实现了 IDataObject::SetData 的 IDataObject(返回 E_NOTIMPL);有没有办法在 d&d 操作正在进行时用不同的 IDataObject 替换?

【问题讨论】:

  • 尝试RevokeDragDrop,然后使用您自己的IDropTarget 实现再次注册。

标签: delphi winapi drag-and-drop activex


【解决方案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 函数。

【讨论】:

  • 这是一个很棒的主意。现在我使用 GetProp 来获取控件的内部 IDropTarget,然后我可以在需要时调用控件的内部拖放处理。这有助于我找出 d&d 操作是否源自控件内部。
猜你喜欢
  • 2015-05-03
  • 2012-02-12
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多