从资源管理器如何拖放文件给窗体的两个Edit控件?

ooolinux 2024-07-13 01:52:21

暂时用了笨办法,如果Edit1为空,拖放文件名给Edit1,否则给Edit2。
有没有办法让拖放接受目标为Edit(直接拖放给Edit),而不是Form?

 

...全文
405 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复

你们说了半天,我都不知道楼主的意思是干什么?哈哈哈

@秋天之落叶 就是从外部程序,比如资源管理器,拖放文件到窗体的某个组件上
  • 举报
回复
@日立奔腾浪潮微软松下联想 拖到上面是打开?还是保存?目的是什么?
  • 举报
回复
@日立奔腾浪潮微软松下联想 难道是仅仅取得文件名?
1条回复
  • 打赏
  • 举报
回复

解决这个问题呢,不需要派生一个新的TEdit来解决问题,第一是写一大堆垃圾代码毫无必要;第二是没有通用性,要用TMemo之类的接收文件,再派生一个?而且如果不是窗口控制你怎么派生;第三是对单元的引用顺序有要求。
简单说(比如用CB吧,用Delphi代码还要少一点):
第一步,窗体的初始化部分增加一行:
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
DragAcceptFiles(this->Handle, true);
// ...
}
第二步,增加一个消息映射方法:
void __fastcall TForm1::OnWM_DROPFILES(TMessage &Msg)
{
String name;
UINT len = DragQueryFile((HDROP)Msg.WParam, 0, NULL, 0);
name.SetLength(len);
DragQueryFile((HDROP)Msg.WParam, 0, &name[1], len + 1); // 只接收第一个文件,可以循环接收多个拖放的文件
Edit1->Text = name;

Msg.Result = 0;
}
然后修改窗体声明,加一个消息映射:
private: // User declarations
void __fastcall OnWM_DROPFILES(TMessage &Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_DROPFILES, TMessage, OnWM_DROPFILES)
END_MESSAGE_MAP(TForm)

BlueStorm 07-17
  • 举报
回复
@日立奔腾浪潮微软松下联想 ```c 完全不接受你的说法, 理由如下: 1.我的代码并没有一大堆, 相比你的代码我的代码并没有多很多, 况且Delphi里面没有消息映射. 2.TEdit的派生定义完全可以放在一个独立unit里面, 这样就可以和Form1的代码作最大限度的隔离. 3.你的代码只反映了一个Edit的情况, 如果Form上有100个Edit接收文件名, 那你是不是要写 100个DragAcceptFiles(this->Handle, true); 100个TForm1::OnWM_DROPFILES(TMessage &Msg) 100个OnWM_DROPFILES(TMessage &Msg); 4.如果考虑到要适用除TEdit外的控件如TMemo、TListbox等 可以使用泛型定义控件TCustComp<T>, 然后定义TMemo = TCustComp<Vcl.StdCtrls.TEdit> TListbox = TCustComp<Vcl.StdCtrls.TListbox> 就可以了,不需要增加重复代码。 ```
@BlueStorm 首先,你没有看懂我的代码,我的代码处理的是顶层窗口,也就是TForm这一级别,所以TForm及其所有可视子控制都可以接收拖放,而且不仅是TWinControl,TGraphicControl也可以。不管多少可视组件接收拖放,那些代码只需要写一次,不是n次。 第二,多个可视组件接收拖放,只需要在OnWM_DROPFILES中判断一下:DragQueryPoint、ControlAtPos即可,只增加极少的代码。 第三,Delphi有消息映射,而且比CB还简单,只需要在窗体的声明部分加一行: procedure OnWM_DROPFILES(var Msg: TMessage); message WM_DROPFILES; 第四,即便用泛型实现,派生新类的方法也只能处理TWinControl,也就是有窗口句柄的类型,自绘制的类型比如TGraphicControl处理不了。而且与之前的代码不能兼容,必须写成: Edit1: TXXX<TEdit>这种形式。 第五,我的代码可以用于FMX程序(当然只限于windows平台),派生新类的方法不行,因为FMX下绝大部分组件都是无窗口句柄的。 第六,你贴的代码(不管是不是你写的)真的很多,代码不是老^二,越长越好~~~
@BlueStorm 啊,我理解你说的泛型实现是返回一个派生后的同名类型,这样的话,“与之前的代码不能兼容,必须写成...”这句无效,不过只能处理TWinControl,也就是有窗口句柄的类型,这是没错的。
13条回复
BlueStorm 07-16
  • 打赏
  • 举报
回复

如果你只想部分Edit能接收文件, 那就改为:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Winapi.ShellAPI;

type
  TEdit =  class(Vcl.StdCtrls.TEdit)
  strict private
    FOldWindowProc: TWndMethod;
    procedure NewWindowProc(var Msg: TMessage);
    procedure FileDrop(var Msg: TWMDROPFILES);
  public
    procedure AcceptFiles;
  end;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    procedure FormCreate(Sender: TObject);
  private
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TEdit.AcceptFiles;
begin
  DragAcceptFiles(Handle, True);

  FOldWindowProc := WindowProc;
  WindowProc := NewWindowProc;
end;

procedure TEdit.NewWindowProc(var Msg: TMessage);
begin
  if Msg.Msg = WM_DROPFILES then
    FileDrop(TWMDROPFILES(Msg))
  else
    FOldWindowProc(Msg);
end;

procedure TEdit.FileDrop(var Msg: TWMDROPFILES);
var
  I: Integer;
  S: String;
  FileCount : Integer;
  Buffer : array[0..MAX_PATH] of char;
begin
  FileCount := DragQueryFile(Msg.Drop, $FFFFFFFF, nil, 0);
  S := '';
  for I := 0 to FileCount - 1 do
  begin
    if I > 0 then S := S + ', ';

    DragQueryFile(Msg.Drop, I, Buffer, SizeOf(Buffer));
    S := S + ExtractFileName(StrPas(Buffer));
  end;
  Text := S;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.AcceptFiles;
  Edit2.AcceptFiles;
  //Edit3.AcceptFiles;
end;

end.


ooolinux 07-16
  • 举报
回复
@BlueStorm 代码大概能懂,需要 TEdit = class(Vcl.StdCtrls.TEdit)
BlueStorm 07-16
  • 打赏
  • 举报
回复

直接修改TEdit, 这样不论你有几个Edit, 都能接收文件名了:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Winapi.ShellAPI;

type
  TEdit =  class(Vcl.StdCtrls.TEdit)
  strict private
    FOldWindowProc: TWndMethod;
    procedure NewWindowProc(var Msg: TMessage);
    procedure FileDrop(var Msg: TWMDROPFILES);
    procedure EditChange(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
  end;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
  private
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TEdit.Create(AOwner: TComponent);
begin
  inherited;
  OnChange := EditChange;
end;

procedure TEdit.EditChange(Sender: TObject);
begin
  OnChange := nil;
  DragAcceptFiles(Handle, True);

  FOldWindowProc := WindowProc;
  WindowProc := NewWindowProc;
end;

procedure TEdit.NewWindowProc(var Msg: TMessage);
begin
  if Msg.Msg = WM_DROPFILES then
    FileDrop(TWMDROPFILES(Msg))
  else
    FOldWindowProc(Msg);
end;

procedure TEdit.FileDrop(var Msg: TWMDROPFILES);
var
  I: Integer;
  S: String;
  FileCount : Integer;
  Buffer : array[0..MAX_PATH] of char;
begin
  FileCount := DragQueryFile(Msg.Drop, $FFFFFFFF, nil, 0);
  S := '';
  for I := 0 to FileCount - 1 do
  begin
    if I > 0 then S := S + ', ';

    DragQueryFile(Msg.Drop, I, Buffer, SizeOf(Buffer));
    S := S + ExtractFileName(StrPas(Buffer));
  end;
  Text := S;
end;

end.
ooolinux 07-16
  • 举报
回复
@BlueStorm 学习了,我参考一下
  • 打赏
  • 举报
回复

不需要那么复杂,
第一步,DragAcceptFiles(edit1->Handle, true);
第二步,消息映射,处理WM_DROPFILES消息即可~

ooolinux 07-16
  • 举报
回复
@日立奔腾浪潮微软松下联想 我把Form的消息映射没变,然后改成第一步,Edit1得不到文件名
@ooolinux 抱歉,DragAcceptFiles需要程序主窗口的句柄,用edit1的不行,我写个例子
tanqth 07-14
  • 打赏
  • 举报
回复

没试过直接拖放给Edit

ooolinux 07-15
  • 举报
回复
@tanqth 我原来也指定Edit的Handle却得不到拖放文件名,从盒子了解了原来是需要替换Edit的窗口过程处理消息
  • 打赏
  • 举报
回复

真是学习了!

tcmakebest 07-13
  • 打赏
  • 举报
回复

判断鼠标落点即可.

ooolinux 07-13
  • 举报
回复
@tcmakebest 也是一个办法

5,716

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧