我需要使用新组件整合现有应用程序的拖放。
我们的应用程序使用Winapi.ActiveX来实现这一点。新组件附带了自己的拖放事件,但这些事件并不是Winapi兼容的。
现在的主要问题是将内容拖入新控件。如果所有其他方法都失败了,那么拖出它应该是可以实现的,方法是在鼠标按下时缓存光标下的对象。
根据我的理解,你不能覆盖拖放注册,也就是说,如果我在代码中的某个地方调用RegisterDragDrop之前,我会成为持有注册的人。< / p>
然而,观察到的行为是调用RegisterDragDrop报告成功,但在控件上拖动某些内容并不会导致IDropTarget上的DragEnter事件。即使在RegisterDragDrop之后,它们的拖放事件也会很好地触发,但正如我所说,返回的数据对象只保存选定的几种可拖动对象的有效数据。
我还尝试注册包含此组件的面板进行拖放,但这也不起作用。
你会建议什么?
更新
我意识到,我试图注册错误的句柄。当我尝试注册正确的句柄时,我实际上得到了拖放已经注册的错误。
我想我没有太清楚地表达它,但问题是,你如何为已经拥有它自己的实现的闭源组件实现拖放操作,而这种组件并没有实现。为您的口味提供足够的灵活性?
我能想到的是:
更新
感谢到目前为止,现在我可以按照我想要的方式将内容拖入控件中。 下一步是拖延出来。这里的问题是应用程序中的其他丢弃目标无法理解控件的IDataObject。对于不同的控件,我们已经拥有使用IDataObject :: SetData的代码,以所有应用程序的放置目标都能理解的格式附加数据。
与新控件的区别在于,当它启动拖放操作时,它不会使用已实现IDataObject :: SetData的IDataObject(返回E_NOTIMPL);有没有办法用另一个替换IDataObject,而d&amp; d操作正在进行中?
答案 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函数。