【问题标题】:How to know user is dragging something when the cursor is not in my window?当光标不在我的窗口中时,如何知道用户正在拖动某些东西?
【发布时间】:2010-06-01 03:36:03
【问题描述】:

我们都知道您可以为您的窗口实现拖放功能,以便它接受拖放操作,但我的问题是,如何检测正在进行的拖放操作其他窗口,例如,在 Windows 资源管理器中拖动文件?我想要做的是,当用户拖动文件时,我的隐藏窗口就会显示出来。

谢谢!

【问题讨论】:

    标签: windows delphi


    【解决方案1】:

    您所要求的内容不受本机支持。在拖放操作期间,只有拖动的发起者知道该操作正在进行中,并且只有实际被拖动的窗口才会收到可能发生该操作的通知。

    我现在能想到的唯一选择是在 DLL 中通过 SetWindowsHookEx() 实现一个全局鼠标挂钩,并让它跟踪用户何时按住左键并将鼠标移出源窗口。但是无法获取有关正在拖动的内容的信息。

    【讨论】:

    • 嗨,雷米,感谢您的帮助。令人遗憾的是,“无法获取有关正在拖动的内容的信息”。而且由于Delphi DLL不能在64位窗口下工作,也许最好有一个后台程序来定期检查鼠标左键状态?
    • 定期检查很容易与用户的实际操作不同步,尤其是当用户进行快速拖动和小动作时。钩子是实时且详细的,但没有用于拦截基于 COM 的拖放操作的钩子。如果给定的目标窗口使用 DragAcceptFiles() 而不是 RegisterDragDrop(),那么您可以拦截发送给它的 WM_DROPFILES 消息,但这是一种老式的拖放方法。现在大多数应用都支持 IDragSource 和 IDropTarget 接口。
    • 感谢雷米的进一步评论!
    【解决方案2】:

    当大多数拖放操作开始时,系统会创建一个带有“SysDragImage”类的反馈窗口。可以捕获此反馈窗口的创建和销毁,并在您的应用程序中做出相应的反应。

    这是一个示例代码(跳过表单类声明以使其更短):

    procedure WinEventProc(hWinEventHook: THandle; event: DWORD;
      hwnd: HWND; idObject, idChild: Longint; idEventThread, dwmsEventTime: DWORD); stdcall;
    var
      ClassName: string;
    begin
      SetLength(ClassName, 255);
      SetLength(ClassName, GetClassName(hWnd, pchar(ClassName), 255));
    
      if pchar(ClassName) = 'SysDragImage' then
      begin
        if event = EVENT_OBJECT_CREATE then
          Form1.Memo1.Lines.Add('Drag Start')
        else
          Form1.Memo1.Lines.Add('Drag End');    
      end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FEvent1 := SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, 0, @WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
      FEvent2 := SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, 0, @WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      UnhookWinEvent(FEvent1);
      UnhookWinEvent(FEvent2);
    end;
    

    这里唯一的问题是当您在拖放开始后立即按 Escape 时,系统不会生成 EVENT_OBJECT_DESTROY 事件。但这可以通过在 EVENT_OBJECT_CREATE 上启动计时器来轻松解决,并定期监控反馈窗口是否仍然存在。

    【讨论】:

      【解决方案3】:

      我使用 Raize Software 的 DropMaster。 http://www.raize.com/devtools/Products.asp

      你也可以从 Melander 使用,但我没有测试这个。 http://melander.dk/delphi/dragdrop/.

      【讨论】:

      • 嗨 Ravaut,我是 DropMaster 的付费客户,我也在使用 Melander 的拖放组件套件,但它们用于实现标准的拖放操作,这意味着您的窗口在鼠标光标拖到您的表单上之前不会收到通知,这不是我在本主题中要求的。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 2019-04-02
      • 2020-02-26
      • 2016-10-08
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      相关资源
      最近更新 更多