从 Windows 资源管理器拖动文件时检测 TcxGrid 中的鼠标移动时出现问题

发布于 2024-08-09 07:12:29 字数 1830 浏览 7 评论 0原文

我最近向用 Delphi(2009 版)编写的大型应用程序添加了一项功能,允许用户从 Windows 资源管理器中拖动文件并将其放在 TcxGrid 控件上。我通过将我自己的窗口过程附加到网格并拦截 WM_DROPFILES 消息的常用方法来实现此目的:

 originalGridWindowProc := cxGrid.WindowProc; // remember the old one
 cxGrid.WindowProc := GridWindowProc;  // assign the new one
 DragAcceptFiles(cxGrid.Handle, LongBool(True)); // setup to accept dropped files

我现在正在尝试增强此功能以检测用户何时将文件拖放到网格中的现有行上,这将开始用新版本覆盖现有文件的过程。

我的第一个想法是看看网格控件的鼠标悬停事件是否有效。确实如此,但不是在拖动操作期间。

然后,我使用一个名为 Winspector 的程序来查看当鼠标在网格上移动时哪些消息被发送到网格控件,现在我可以检测鼠标位于哪一行并突出显示它。我使用与上面相同的技术,但在这种情况下,我将覆盖 GridSite 的窗口过程,而不是网格本身,因为根据 Winspector,这就是消息出现的位置:

  originalGridSiteWindowProc := cxGrid.ActiveView.Site.WindowProc;
  cxGrid.ActiveView.Site.WindowProc := GridSiteWindowProc;

这是 GridSiteWindowProc 的主体:

procedure Tfrm.GridSiteWindowProc(var message: TMessage);
var
  hitTest: TcxCustomGridHitTest;
  gridRecord: TcxCustomGridRecord;
begin
  //Log(IntToStr(message.Msg));
  case message.Msg of
    WM_NCHITTEST: begin
      hitTest := cxGrid.ActiveView.GetHitTest(cxGrid.ScreenToClient(Mouse.CursorPos));
      if hitTest is TcxGridRecordCellHitTest then begin
        gridRecord := TcxGridRecordCellHitTest(HitTest).GridRecord;
        if Not gridRecord.Focused then
          gridRecord.Focused := True;
      end;
      originalGridSiteWindowProc(message);
    end
    else
      originalGridSiteWindowProc(message);
  end;
end;

正如您所看到的,我捕获 WM_NCHITTEST 消息来实现此目的。根据 Winspector 的说法,在拖动操作期间,此消息也会发送到网格站点窗口,但如果我取消注释 Log() 语句,该语句会将消息值输出到字符串列表(之后我手动转储到备注字段),我确定,由于某种原因,当将文件拖动到网格上时,我只会收到其中一两条消息。

现在 - 这是有趣的部分:如果我运行 Winspector 并监视发送到该窗口的消息,我会在文件拖动操作期间突然开始获取所有 WM_NCHITTEST 消息。如果我将进入窗口过程的所有消息的整数值直接输出到单独的日志窗口而不是首先输出到字符串列表缓冲区,情况也是如此。我希望有人能够提供一些线索来解释为什么会发生这种情况或如何让它发挥作用。

I recently added a feature to a large application written in Delphi (version 2009) that allows the user to drag files from Windows explorer and drop them on a TcxGrid control. I achieved this via the common method of attaching my own window proc to the grid and intercepting the WM_DROPFILES message:

 originalGridWindowProc := cxGrid.WindowProc; // remember the old one
 cxGrid.WindowProc := GridWindowProc;  // assign the new one
 DragAcceptFiles(cxGrid.Handle, LongBool(True)); // setup to accept dropped files

I now am trying to enhance this feature to detect when the user drops a file onto an existing row in the grid, which will begin the process of overwriting an existing file with a new version.

My first thought was to see if the grid control's mouseover event would work. It does, but not during the drag operation.

I then used a program called Winspector to see what messages were being sent to the grid control as the mouse is moved over the grid, and I can now detect what row the mouse is over and highlight it. I'm using the same technique as above, but in this case I am overriding the window proc for the GridSite and not the grid itself, because that is where the messages appear to be going according to Winspector:

  originalGridSiteWindowProc := cxGrid.ActiveView.Site.WindowProc;
  cxGrid.ActiveView.Site.WindowProc := GridSiteWindowProc;

Here is the body of GridSiteWindowProc:

procedure Tfrm.GridSiteWindowProc(var message: TMessage);
var
  hitTest: TcxCustomGridHitTest;
  gridRecord: TcxCustomGridRecord;
begin
  //Log(IntToStr(message.Msg));
  case message.Msg of
    WM_NCHITTEST: begin
      hitTest := cxGrid.ActiveView.GetHitTest(cxGrid.ScreenToClient(Mouse.CursorPos));
      if hitTest is TcxGridRecordCellHitTest then begin
        gridRecord := TcxGridRecordCellHitTest(HitTest).GridRecord;
        if Not gridRecord.Focused then
          gridRecord.Focused := True;
      end;
      originalGridSiteWindowProc(message);
    end
    else
      originalGridSiteWindowProc(message);
  end;
end;

As you can see, I'm trapping the WM_NCHITTEST message to achieve this. According to Winspector, this message also gets sent to the grid site window during the drag operation, but if I uncomment that Log() statement which will output the message value to a string list (which I manually dump to a memo field afterwards), I have determined that for some reason, I only get one or two of these messages when dragging a file over the grid.

Now - here's the interesting part: if I have Winspector running and monitoring messages going to that window, I suddenly start getting all the WM_NCHITTEST messages during the file drag operation. This is also the case if I output the integer value of all the messages coming to the window proc directly to a separate log window instead of to a string list buffer first. I am hoping that someone will be able to offer some clue as to why this is happening or how to get this to work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾`听者〃 2024-08-16 07:12:29

您应该使用 OLE Drag'n'Drop,而不是使用 WM_DROPFILES 消息。查看 RegisterDropTarget API。您可以获得有关拖放位置的更多详细信息。您还可以接受更多种类的拖动对象。

Rather than using the WM_DROPFILES message, you should use OLE Drag'n'Drop. Look at the RegisterDropTarget API. You can get more detailed information about where a drag or drop is taking place. You can also accept more kinds of drag objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文