【问题标题】:Highlight component while user is dragging用户拖动时突出显示组件
【发布时间】:2016-09-05 10:57:32
【问题描述】:

我正在尝试实现一个简单的拖放面板,用户可以在其中从 Windows 资源管理器中拖放文件。在我找到this Thread 之后,基本功能已经可以使用了。

现在我正在尝试更改面板的颜色,而用户正在将文件拖到面板上。我尝试使用 OnDragOver,但没有任何反应。我做错了什么?

这是我当前的代码:

unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ShellApi,
  Vcl.ExtCtrls, Vcl.Imaging.pngimage;

type
   TPanel = class(Vcl.ExtCtrls.TPanel)
     protected
       procedure WMDropFiles(var Message: TWMDropFiles); message WM_DROPFILES;
       procedure CreateWnd; override;
       procedure DestroyWnd; override;
     end;

  TfrmMain = class(TForm)
    panFileDrop: TPanel;
    lblFileName: TLabel;
    procedure panFileDropDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TPanel.CreateWnd;
begin
   inherited;
   DragAcceptFiles(Handle, true);
end;

procedure TPanel.DestroyWnd;
begin
   DragAcceptFiles(Handle, false);
   inherited;
end;

procedure TPanel.WMDropFiles(var Message: TWMDropFiles);
var
  c: integer;
  fn: array[0..MAX_PATH-1] of char;
begin

  c := DragQueryFile(Message.Drop, $FFFFFFFF, fn, MAX_PATH);

  if c <> 1 then
  begin
    MessageBox(Handle, 'Too many files.', 'Drag and drop error', MB_ICONERROR);
    Exit;
  end;

  if DragQueryFile(Message.Drop, 0, fn, MAX_PATH) = 0 then Exit;

  frmMain.lblFileName.Caption := fn;

end;

procedure TfrmMain.panFileDropDragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
   panFileDrop.Color := $00d4d3d2;
end;

end.

【问题讨论】:

  • 你调试过DragOver事件吗?
  • 是的,我使用了 ShowMessage 但它没有显示出来。
  • showmessage 不是一个好的调试器,在 onDragOver 事件的第一行设置一个断点并检查你是否到达那里,如果你这样做了,然后调试那里的每一行代码。如果您不这样做,那么我们看不到的某些代码中还有其他问题
  • 我会在我回到办公室时尝试。但我的做法对吗?
  • OnDragOver 是一个 VCL 鼠标拖动事件,与从资源管理器中拖动 shell 数据完全无关。如果你想接收拖动事件,那么用DragAcceptFiles 注册WM_DROPFILES 是不够的,因为这只会给你最终的放置事件,没有拖动。您需要通过实现IDropTarget 接口来关注Transferring Shell Objects with Drag-and-Drop and the Clipboard

标签: delphi drag-and-drop


【解决方案1】:

问题
Delphi 的 Drag'n'drop 概念与 COM 拖放完全无关。
Borland 实现了一个轻量级版本,用于在同一应用程序中拖放。
这非常有效且非常有效,但不支持应用程序之间的 DnD 操作。 COM 拖放需要您向操作系统注册一个拖放目标并接受相关的鼠标消息。 COM 拖放绝不会生成标准的OnDragOver 事件。
我担心the documentationit does not make clear 这个混淆来源时会产生误导。

您将基于 Windows 消息的代码 TPanel.WMDropFiles(var Message: TWMDropFiles) 与 Borland 的实现混合使用,仅供应用程序内部使用:TfrmMain.panFileDropDragOver(...)
这两个选项存在于平行宇宙中。
如果你想做COM方式,你需要一路走COM。

解决方案
WMDropFiles 选项仍然是一个“轻量级”解决方案,在您使用完整的 COM 并需要实现 IDropTarget 和所有需要的复杂性之前。

我对您的问题的回答是不要发明自己的拖放功能,而是继续使用 intertubes 并下载:https://github.com/DelphiPraxis/The-Drag-and-Drop-Component-Suite-for-Delphi

这是 Anders Melander 著名套件的最新版本,它曾经位于:http://melander.dk/delphi/dragdrop/

这实现了基于 COM 的拖放,一次性解决您的所有问题。
它本身也是漂亮代码的一个很好的例子。
采取special note of the demos。 shelldragdrop 的东西应该涵盖你的用例。

您想了解更多吗?
http://delphi.about.com/od/vclusing/a/dragdrop.htm

【讨论】:

  • 非常感谢您的详细解答!这对我帮助很大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 2010-10-12
  • 2013-03-01
相关资源
最近更新 更多