文件拖放功能
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实现应用程序的文件拖放功能
时间:2008-04-09 04:17来源:互联网
在Delphi中有许多控件支持拖放操作,但仅限于应用程序内部,而不能实现从Windows 环境里向应用程序拖放文件,本文将要介绍的就是如何用Delphi编写支持文件拖放的应用程序,由于主要使用WindowsAPI函数,因此也可供其它语言使用者参考. 首先要说明的是下面的三个API函数
在Delphi中有许多控件支持拖放操作,但仅限于应用程序内部,而不能实现从Windows环境里向应用程序拖放文件,本文将要介绍的就是如何用Delphi编写支持文件拖放的应用程序,由于主要使用WindowsAPI函数,因此也可供其它语言使用者参考.
首先要说明的是下面的三个API函数,为通用起见, 函数说明使用C语言格式,
1.VOIDDragAcceptFiles(
HWNDhWnd,
BOOLfAccept);
DragAcceptFiles函数是用来为拖放文件作初始化, 它的第一个参数hWnd 指明目标窗体的句柄,第二个参数fAccept是一个布尔型变量,为True时则hWnd所指向的窗体可以接受拖放的文件.
2.UINTDragQueryFile(
HDROPhDrop,
UINTiFile,
LPTSTRlpszFile,
UINTcch)
DragQueryFile函数用来查询拖放文件的文件名,其本身的返回值是一个无符号整数,参数hDrop是一个存放所拖放文件名称的数据结构的句柄, 也就是文件名缓冲区的句柄,需要从Windows消息WM_DROPFILES中获得.iFile指明所要查询文件的序号,它有两种取值方式,1.值为十六进制数FFFFFFFF
时,DragQueryFile的返回值为所拖放文件的数目;2.值在0到拖放文件总数之间时,DragQueryFile函数将相应序号的文件名放入参数lpszFile所指向的缓冲区内,若此时lpszFile的值为NULL,则DragQueryFile会返回相应文件名的长度.参数cch决定缓冲区的长度,由于Windows95支持长文件名,它的值不能设得太小.
3.VOIDDragFinish(HDROPhDrop);
使用DragFinish函数告诉Windows拖放操作结束,使其释放文件名缓冲区,它的参数hDrop与DragQueryFiles函数中的一样,也由Windows消息
WM_DROPFILES 的hDrop参数获得.
下面将结合一个我编写的例子来说明具体的编程步骤.本例中窗体上放置了一个Memo控件memo1,在Windows中选取数个文件拖至程序窗体放下,则memo1中便会显示所选文件的总数及每个文件的各自名称.程序代码如下:
unitUnit1;
interface
uses
Windows,Messages,SysUtils,Classes,
Graphics,Controls,Forms,Dialogs,
StdCtrls;
type
TForm1=class(TForm)
Memo1:TMemo;
procedureFormCreate(Sender:TObject);
procedureLabel3Click(Sender:TObject);
procedureLabel4Click(Sender:TObject);
private
PROCEDUREFinishDropped(VARMsg:TMessage);
MessageWM_DropFiles;
{Privatedeclarations}
public
{Publicdeclarations}
end;
var
Form1:TForm1;
implementation
usesshellapi;
{$R*.DFM}
pro ureTForm1.FormCreate(Sender:TObject);
begin
//initializethedragprocess;
DragAcceptFiles(Handle,True);
end;
ProcedureTForm1.FinishDropped(VARMsg:TMessage);
Var
hDrop:THandle;
iFile:Uint;
lpszFile:pchar;
CountOfFiles:integer;
FileIndex:integer;
ReSults:string;
begin
hDrop:=Msg.WParam;
getmem(pchar,255);
iFile:=$FFFFFFFF;
CountOfFiles:=DragQueryFile(hDrop,iFile,lpszFile,254); ReSults:=;
forFileIndex:=0CountOfFiles-1do
begin
iFile:=FileIndex;
DragQueryFile(hDrop,iFile,lpszFile,254);
//GettheFilenamesbyorder;
ReSults:=ReSults #13#10 lpszFile;
end;
Dispose(lpszFile);
memo1.Clear;
memo1.lines.add(拖放了 IntToStr
(CountOfFiles) 个文件: ReSults);
DragFinish(hDrop);
end;
end.
从以上代码可以看出,首先应该在窗体的OnCreate事件中用DragAccepteFiles来说明程序窗体支持文件的拖放.
另外,除了调用以上3个API函数,在Delphi中还应编写针对WM_DROPFILES 的消息处理过程FinishDropped,截取了WM_DROPFILES,由其wParam 才能够得到文件名缓冲区的句柄.
在FinishDropped过程里,有两处DragQueryFile 函数,第一处其iFile参数为$FFFFFFFF,得到拖放文件的总数;第二处iFile参数为每个文件的序号,则可在lpszFile中可得到相应的文件名.当然,为了明显的对比iFile的值对DragQueryFile 函数的影响,这里的代码不够简练.有一点需要注意的
是,lpszFile是Pchar型的变量,为了程序运行安全,它使用前需用getmem过程为其分配内存,使用后再用dispose过程将其释放. 在FinishDropped过程的最后,用DragFinish函数释放文件名缓冲区.
以上范例代码在Delphi4中通过.
VC6.0中实现文件拖拽- -
我们经常使用到文件拖拽的方法,来对某一个或者某一些文件进行操作。
在VC中,我们可以不利用打开文件对话框来选择文件,从而对文件进行操作,我们也可以使用拖拽来实现这样的功能。
具体如下:
1.首先,把一个对话框或者窗体的扩展属性【接受文件】勾选上。
2.我们对WM_DROPFILES消息进行处理。
在这里我们使用到了一个API函数:DragQueryFile,它的原型如下:
UINT DragQueryFile(
HDROP hDrop,
UINT iFile,
LPTSTR lpszFile,
UINT cch
);
当第二个参数iFile为0xFFFFFFFF 时返回的是拖曳到窗体上的文件的个数。
第三个参数是文件名,第四个参数是文件名的长度。
具体使用方法:
unsigned int count;
char filepath[100];
count=::DragQueryFile(hDropInfo,0xFFFFFFFF,NULL,NULL);//首先获取文件的个数。
if(count)
{ for(unsigned int i=0;i<count;i++)
{ int pathlen=::DragQueryFile(hDropInfo,i,filepath,sizeof(filepath));//获取文件路径。
this->MessageBox(filepath);
}
}
就是这么简单!
当我们把一个窗体的标题栏去掉以后,如果需要左键移动窗体的位置,只需要在处理
WM_LBUTTONDOWN
消息的代码中加入:
PostMessage(WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(point.x,point.y)) ;
void CCHTMLOptimizerDlg::OnDropFiles(HDROP hDropInfo)
{
UINT nCount = ::DragQueryFile(hDropInfo,0xFFFFFFFF,NULL,0);
UINT i;
CString strFileName;
for(i=0;i<nCount;i++)
{
::DragQueryFile(hDropInfo,i,strFileName.GetBuffer(MAX_PATH),MAX_PATH); strFileName.ReleaseBuffer();
AddFilesInDir(this,strFileName); //这是我的函数strFilename就是文件地址
}
CDialog::OnDropFiles(hDropInfo);
}
在Ondrop事件里先用UINT nNumFilesDropped = DragQueryFile(hFileDroped,
0xFFFFFFFF, NULL, 0);获得拖拽的数量然后
DragQueryFile(hFileDroped, nFile,szFilename, MAX_PATH + 1);就可以了得到文件信息了。
VC实现文件管理器拖拽(Drag-and-Drop)
在日常的程序中,为了操作的方便,经常需要使用鼠标拖拽的方式把文件管理器中的文件拖拽到我们自己写的程序中,以下就简单介绍以下实现该操作的方法。
其实文件管理器的拖拽方式实现起来很简单,主要通过几个函数来实现,消息WM_DROPFILES 的响应函数OnDropFiles,还有三个API函数:DragQueryFile,DragQueryPoint和DragFinish。
在启动拖拽动作时,操作系统会分配一块内存存储拖拽的文件的信息,并通过一个HDROP类型的句柄把该块内存的地址传递给函数OnDropFiles函数。
文件管理器拖拽方式的实质就是处理WM_DROPFILES消息,要让窗口或控件响应该消息,需要先设置Accept Files属性,可以通过在窗口或控件的属性页中勾选Accept Files,也可以通过调用CWnd类的成员函数DragAcceptFiles(TRUE)或API函数DragAcceptFiles(HWND hWnd,BOOL fAccept),可以在OnCreate或OnInitDialog之类的函数中调用,它们的效果都是一样的。
设置了Accept Files属性后,就可以添加WM_DROPFILES消息的响应函数OnDropFiles 了,ClassWizard不支持该函数,所以需要手动添加此函数,然后在该函数中调用上述的三个API函数,其代码如下:
void DragDemo::OnDropFiles(HDROP hDrop)
{
// 定义一个缓冲区来存放读取的文件名信息
char szFileName[MAX_PATH + 1] = {0};
// 通过设置iFiles参数为0xFFFFFFFF,可以取得当前拖动的文件数量,
// 当设置为0xFFFFFFFF,函数间忽略后面连个参数。
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
// 通过循环依次取得拖动文件的File Name信息,并把它添加到ListBox中
for(UINT i=0; i<nFiles; i++)
{
DragQueryFile(hDrop, i, szFileName, MAX_PATH);
m_listCtrl.AddString(szFileName);
}
// 结束此次拖拽操作,并释放分配的资源
DragFinish(hDrop);
}
其中三个API函数的具体用法可以参照MSDN。
由于本例的操作是直接拖拽的对话框上,所以不需要通过DragQueryPoint来取得鼠标松开时的位置,在实际的实现中,最好是为空间派生出一个类,在该类中定义消息响应函数OnDropFiles,这样就不需要查询鼠标的位置,也不需要设置鼠标的指针样式。