如何实现WinForms与OS间的拖拽?如文件拖拽。(100分)

  • 主题发起人 主题发起人 WebBar
  • 开始时间 开始时间
W

WebBar

Unregistered / Unconfirmed
GUEST, unregistred user!
在同一个应用程序中很简单,可是用在与资源管理器间拖拽就不行了。我能得到消息,可是取不出被拖的文件等信息。
 
你能知道被拖拽的文件信息的格式?
 
一般都是能得到被拖的完整文件路径及文件名,以及模式:拷贝或移动。
这就足够完成一次拖拽所需要的信息了,可是我现在就是得不到被拖拽的文件。
 
话题136111的标题是: 怎样实现文件的拖放? (50分)
分类:系统相关 wangrui (1999-09-20 21:40:00)
怎样实现将文件从资源管理器中拖放到应用程序中?
DragAcceptFiles(),DragQueryFiles() 这些函数该怎样使用?
敬请高手们不吝赐教!多谢!多谢!

Jams (1999-09-20 21:45:00)
静候佳音!

bluebird (1999-09-20 21:49:00)
一般用下面的消息,然后由DRAGQUERFILE返回值得到文件多少,然后LPSZFILE得到
文件名。stringlist
查看DELPHI原码可以看到定义。
WM_DROPFILES
hDrop = (HANDLE) wParam;
// handle of internal drop structure
UINT DragQueryFile(
HDROP hDrop, // handle to structure for dropped files
UINT iFile, // index of file to query
LPTSTR lpszFile, // buffer for returned filename
UINT cch // size of buffer for filename
);

Parameters
hDrop
Identifies the structure containing the filenames of the dropped files.
iFile
Specifies the index of the file to query. If the value of the iFile parameter is 0xFFFFFFFF, DragQueryFile returns a count of the files dropped. If the value of the iFile parameter is between zero and the total number of files dropped, DragQueryFile copies the filename with the corresponding value to the buffer pointed to by the lpszFile parameter.
lpszFile
Points to a buffer to receive the filename of a dropped file when the function returns. This filename is a null-terminated string. If this parameter is NULL, DragQueryFile returns the required size, in characters, of the buffer.
cch
Specifies the size, in characters, of the lpszFile buffer.

Return Values
When the function copies a filename to the buffer, the return value is a count of the characters copied, not including the terminating null character.
If the index value is 0xFFFFFFFF, the return value is a count of the dropped files.
If the index value is between zero and the total number of dropped files and the lpszFile buffer address is NULL, the return value is the required size, in characters, of the buffer, not including the terminating null character.

killgates (1999-09-21 0:20:00)
//需要use ShellAPI
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
PROCEDURE FileIsDropped ( VAR Msg : TMessage ) ;
Message WM_DropFiles ;//消息处理
public
{ Public declarations }
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
DragAcceptFiles( Handle,True ) ;
end;
PROCEDURE TForm1.FileIsDropped ( VAR Msg : TMessage ) ;
VAR
hDrop : THandle ;
fName : ARRAY[0..254] OF CHAR ;
NumberOfFiles : INTEGER ;
fCounter : INTEGER ;
Names : TSTRINGLIST ;
begin

hDrop := Msg.WParam ;
NumberOfFiles := DragQueryFile(hDrop,-1,fName,254);
FOR fCounter := 1 TO NumberOfFilesdo

begin
DragQueryFile(hDrop,fCounter,fName,254);
Names.Add(fName) ;
END ;
ShowMessage('Droped '+IntToStr(NumberOfFiles) + ' Files : ' +
Names.Text );
//你想干吗就干吗吧
DragFinish ( hDrop);
end;
end.


barton (1999-09-21 4:55:00)
我用一个控件,从不失手,支持:
拖放文件到一个快捷图标中,从而打开这个快捷方式;
拖放文件到一个已开启的Form中,你可以放心地一个一个处理文件;
继而扩展到任何一个基于TWinControl的控件...
这个控件很小,有源代码 :-)

liuge (1999-09-21 11:02:00)
下面的程序可以实现将文件从资源管理器中拖放到应用程序中,Listbox中显示文
件名和路径。
在Form1上放置一个Listbox.
TForm1定义如下:
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure WMDropFiles(VAR Msg: TWMDropFiles);message WM_DROPFILES;
procedure AppOnMessage(VAR Msg: TMsg;VAR Handled : Boolean);
public
{ Public declarations }
end;

WMDropFiles,AppOnMessage如下,
procedure TForm1.WMDropFiles(VAR Msg: TWMDropFiles);
VAR
N : Word;
buffer : ARRAY[0..180] OF Char;
begin

WITH Msgdo
begin
FOR N := 0 TO DragQueryFile(Drop, $FFFFFFFF, buffer,1)-1do
begin
DragQueryFile(Drop, N, Buffer, 80);
ListBox1.Items.Add(StrPas(Buffer));
end;
DragFinish(Drop);
end;
end;

procedure TForm1.AppOnMessage(VAR Msg: TMsg;
VAR Handled : Boolean);
VAR WMD : TWMDropFiles;
begin
IF Msg.message = WM_DROPFILES then
begin
MessageBeep(0);
WMD.Msg := Msg.message;
WMD.Drop := Msg.wParam;
WMD.Unused := Msg.lParam;
WMD.Result := 0;
WMDropFiles(WMD);
Handled := TRUE;
end;
end;

TForm1的create事件:
procedure TForm1.FormCreate(Sender: TObject);
begin
DragAcceptFiles(Handle, True);
DragAcceptFiles(Application.Handle, True);
Application.OnMessage := AppOnMessage;
end;


duz (1999-09-21 14:58:00)
嘿嘿,如果用VC,你一句代码都不要写。

cAkk (1999-09-21 15:50:00)
to duz:是吗? VC如何实现的呢? 很感兴趣.

wangrui (1999-09-21 21:52:00)
barton 发给我一个好吗?
E-mail: towangrui@263.net

DNChen (1999-09-22 18:29:00)
呵呵,如果用VC,你怎么写菜单?

barton (1999-09-23 4:31:00)
to wangrui:
当然好。好东东应该共享。收好,只好2K多一点。

wangrui (1999-09-23 7:42:00)
感谢大家的热情指教!这个问题我已经明白了!

barton-15,bluebird-5,killgates-15,liuge-15,的回答最终被接受。
 
楼上有没有看清楚我是在C#版中提这个问题的?
 
不用那么麻烦!例如在WinForm中用ListView(playList)控件接收拖放,代码如下:
private void playList_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
//如果拖放的对象是文件
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
//得到拖放的文件名
string fullPath = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
if (Is_A_Valid_File(fullPath)) //如果文件符合我的要求,则允许产生DragDrop事件
{
e.Effect = DragDropEffects.All; //改变鼠标样式,允许产生DragDrop事件
}
else
{
e.Effect = DragDropEffects.None; //改变鼠标样式,不允许产生DragDrop事件
}
}
else
{
e.Effect = DragDropEffects.None; //改变鼠标样式,不允许产生DragDrop事件
}
}
private void playList_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
//在这里增加你的代码
//string fullPath = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
//AddFileToFileArray(fullPath);
}
 
经测试楼上提供的代码完全正确。
积分全部捧上,再次感谢。
 

Similar threads

后退
顶部