我使用 WTL 创建了一个对话框,继承自 CDialogImpl 类,在主对话框中我创建了另一个对话框,并在第二个子对话框中创建了一个列表控件。我想向列表控件添加拖放功能,我在网上阅读了有关 WM_DROPFILES 方法和 Ole Drop Target 的信息,我选择了后者。 我已经按照 this 实现了 IDropTarget 接口(interface)方法。 我已在所有对话中将接受文件选项设置为 TRUE,我已在子对话类中实例化 IDropTarget 并在其 WM_INITDIALOGUE 处理程序中调用以下方法:
//drag& drop
lpDropTarget = (LPDROPTARGET)new TDropTarget(m_hWnd);
CoLockObjectExternal(lpDropTarget, true, true);
// register the HWND as a drop target
RegisterDragDrop(m_hWnd, lpDropTarget);
lpDropTarget 实例化如下:
LPDROPTARGET lpDropTarget;
就是这样。之前没有真正使用过 Ole,所以我尝试了以下场景来寻求运气:
我已向 List 控件 HWND 注册了 RegisterDragDrop,并将其父对话框设置为接收我发送的通知
WM_OLEDROP WM_USER + 1
。好的,拖放光标已显示,但没有调用 IDataTarget 函数的实现。RegisterDragDrop 用于子对话和通知。
为主对话框及其通知注册DragDrop。
在后面的情况(2和3)中,用于拖放的光标甚至没有出现,它向我显示了不允许拖放的光标。 现在,所有对话框和列表控件都已设置为接受来自 Visual Studio 设计器的文件。 我仅限于使用ATL/WTL/WINAPI,不能使用MFC。 我做错了什么?
最佳答案
对于您来说,WM_DROPFILES
是您唯一需要处理的事情。无需摆弄 IDropTarget
等。
如果您的应用程序不需要在管理模式下运行,请不要在管理模式下运行。禁用相同的链接器设置(UAC 执行级别 = asInvoker
)。另外,在非管理员模式下运行 VS,以便您的应用程序也以非管理员进程启动。这样,Explorer.exe 就能够向您的应用程序发送 WM_DROPFILES
消息。
如果您的应用程序需要以管理员模式运行,您需要允许其他应用程序向您的应用程序(窗口)发送一组消息。执行以下操作:
ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD);
ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD);
ChangeWindowMessageFilter(0x0049, MSGFLT_ADD);
您可能还想使用更新的函数:ChangeWindowMessageFilterEx .
请注意,如果您的应用程序必须以管理员身份运行,并且您需要使用 GetProcAddress
动态定位其中一个函数,以便您的应用程序可以在该函数不可用的操作系统上运行(例如.Windows XP)。
关于c++ - Ole 拖放故障排除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13570160/