【问题标题】:Simulate windows drag and drop with code?用代码模拟窗口拖放?
【发布时间】:2014-03-23 03:19:51
【问题描述】:

我想我过去可能问过类似的问题,但我仍然卡住了......

作为自动化流程的一部分,我必须将媒体文件的特定子集“导入”到闭源第三方应用程序(Dartfish,以防万一)。 情况如下:

  • 媒体(视频)文件都在一个文件夹中(有 1000 多个,不幸的是,重组不是一种选择)。
  • 在我正在编写的脚本的任何给定迭代中,只有 13 个特定文件必须导入到应用程序中。
  • 应用中没有必须接收文件的导入功能。
  • 这个相同的应用确实允许您将文件拖放到特定窗格中,这实际上允许您导入它们。

我目前使用的解决方法非常不稳定和丑陋,并且使用正则表达式查询的复杂过程来隔离 Xplorer2 中的文件,然后使用 AutoIT 选择它们,最后将它们拖到应用程序中。

建议的解决方案:

我需要一种在任何给定时间将我需要的特定视频文件子集拖放到此应用程序中的方法,最好不要自动单击和光标移动(此设置中有太多故障点)。

我本质上只是将文件名列表传递给应用程序(通过将它们拖到那里),所以我认为必须有一种方法可以纯粹在代码中自动进行这种拖放 - 可能使用 C/C#/C++ 和窗户API?如果解决方案可以以某种方式移植到 Python,则可以加分……但不是必需的。

如果有人能指出我正确的方向(编程语言无关紧要;我会学习我需要知道的任何东西),最好给我一个基本大纲或示例,说明我如何完成这样的任务, 我真的很感激!这已经让我发疯一年多了!

【问题讨论】:

    标签: c# c++ c winapi drag-and-drop


    【解决方案1】:

    1) 注入目标进程

    2) 获取目标窗口的IDropTarget

    function GetDropTargetFromWnd(AWnd: HWND): IDropTarget;
    var Unknow: IUnknown;
    begin
      Unknow := IUnknown(GetProp(AWnd, PChar(GlobalFindAtom('OleDropTargetInterface'))));
      if Assigned(Unknow) then
        Unknow.QueryInterface(IDropTarget, Result)
    end;
    

    3) 使用您的文件创建 IDataObject

    4) 调用 IDropTarget.DragEnter

    5) 调用 IDropTarget.Drop

    更新算法:

    1) 使用 RegisterWindowMessage 注册您的唯一消息

    2) 使用 WH_CALLWNDPROC 类型的 SetWindowsHookEx 安装全局挂钩(需要额外的 dll)

    3) 创建 13 个名称的固定文件

    4) 将步骤 1 中注册的唯一消息发送到目标窗口

    5) 你的钩子会被加载到目标进程中

    6) 内部钩子程序检查消息

    7) 如果消息是您的唯一消息

    7.1) 获取目标窗口的IDropTarget

    7.2) 从固定文件加载名称

    7.3) 使用您的文件创建 IDataObject

    7.4) 调用 IDropTarget.DragEnter

    7.5) 调用 IDropTarget.Drop

    8) 如果所有文件尚未处理,则转到 3

    9) 卸载全局钩子

    更新 2

    您也可以尝试从挂钩 dll 向目标窗口发送 WM_DROPFILES 消息。

    【讨论】:

    • 嗯,有趣...我实际上从未考虑过这个。这会是一个稳定的解决方案(例如,始终如一地工作并且不会使主机应用程序崩溃)吗?我之前做过一些琐碎的DLL注入,所以我愿意尝试一下......
    • 稳定性将取决于你如何实现算法:)
    • 好的,我已经设法(在我完全不熟悉的 C++ 中)注入了一个 DLL。这是 DLL 的主要代码:pastebin.com/SUz2XvPA 到目前为止,我了解我使用的注入技术是如何工作的,以及 DLL 的这个 BASIC 结构是如何工作的……但我现在卡住了。两个问题: (A):我应该在哪里写这个 DLL 中的主要代码?也许在 DLL_PROCESS_ATTACH 案例块中? ...和 ​​(B):在注入 DLL 后,我将如何将我正在“拖放”的文件列表传递给 DLL?我应该使用临时文件来读取列表吗?谢谢!
    • 好的,我刚开始新工作,没有时间做这方面的工作,所以很抱歉回复晚了。我正在阅读你的答案,但我很困惑......我不知道如何解释你的答案。如果我理解正确(不确定上面的代码是什么语言),我会创建一条独特的消息来告诉软件何时发送文件?当它收到这条消息时,它然后使用挂钩的 windows 过程执行拖放模拟?多一点解释不会有什么坏处。谢谢。
    • 当您发送您的独特消息时,您的钩子 dll 将被加载到目标进程中。它是注入机制。当你的钩子程序被调用时,你可以做所有你需要的拖放操作。
    【解决方案2】:

    在这种情况下,鼠标移动/单击可能是最好的解决方案。这是您可以尝试的方法。假设您使用的是 windows,因为您将 c# 放在标题中

    1. 打开文件夹
    2. 将鼠标移动到文件夹的搜索框(不一定是硬编码坐标,有的GUI工具可以识别)
    3. 使用发送字符串方法输入您要导入的文件的名称
    4. 移动鼠标选择第一个结果
    5. 鼠标向下
    6. 使用像素检测或 GUI 工具的检测来确定您希望放置的面板的坐标
    7. 删除它并进行一些错误检查。

    如果您是 Windows 专家,您可以尝试进行一些进程间通信,以将拖放事件发送到程序。

    【讨论】:

    • 就像我在问题中所说的那样,我不会自动化光标;相信我,当我说我已经将这种方法打死了......然后是一些。有太多事情可能出错(例如,如果用户在资源管理器中打开了另一个窗格,或者类似地更改了某些视图设置,它可能会移动文件,使它们每次都不在同一个坐标中)。此外,我真的认为这是一种解决方法。您的第二个建议是我愿意使用的方法;我不是 Windows 专家,但我熟悉 WinAPI。
    猜你喜欢
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    相关资源
    最近更新 更多