5,716
社区成员
暂时用了笨办法,如果Edit1为空,拖放文件名给Edit1,否则给Edit2。
有没有办法让拖放接受目标为Edit(直接拖放给Edit),而不是Form?
你们说了半天,我都不知道楼主的意思是干什么?哈哈哈
解决这个问题呢,不需要派生一个新的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)
如果你只想部分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.
直接修改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.
不需要那么复杂,
第一步,DragAcceptFiles(edit1->Handle, true);
第二步,消息映射,处理WM_DROPFILES消息即可~
没试过直接拖放给Edit
真是学习了!
判断鼠标落点即可.