在局域网传输文件时所遇到的问题 在编写一些局域网应用软件时,有时需要在局域网的计算机间复制数据。如果我们将应用程序设计为网络应用程序,未免设计的有些复杂。Windows
系统提
供了一个外壳函数SHFileOperation能够实现局域网间的文件复制。该函数语法如下:
int SHFileOperation(LPSHFILEOPSTRUCT lpFileOp);
其中,lpFileOp参数是一个SHFILEOPSTRUCT结构指针,该结构定义如下: typedef struct _SHFILEOPSTRUCT {
HWND hwnd; //在文件操作过程中显示的对话框的句柄
UINT wFunc; //对文件进行的操作,FO_COPY表示复制文件,FO_DELETE表示删除文件,FO_MOVE表示移动文件,FO_RENAME表示重命名文件
LPCWSTR pFrom; //操作的源文件
LPCWSTR pTo; //目标文件
FILEOP_FLAGS fFlags; //文件操作标识
BOOL fAnyOperationsAborted; //暂未被使用
LPVOID hNameMappings; //暂未被使用
LPCWSTR lpszProgressTitle; //对话框标题
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;
下面我们通过一个实例来介绍局域网文件的复制。效果如图1所示。
图1 局域网文件复制
(1)创建一个基于对话框的工程,向对话框中添加静态文本、编辑框和按钮控件,效果如图2所示。
图2 对话框设计
(2)处理“复制文件”按钮的单击事件,将网络文件复制到本地磁盘。 void CNetworkFileDlg::OnCopy()
{
CString strnetwork,strlocal;
GetDlgItem(IDC_EDNETWORK)->GetWindowText(strnetwork); //获取编辑框文本
GetDlgItem(IDC_EDLOCAL)->GetWindowText(strlocal);
if(strnetwork.IsEmpty()) //验证信息是否为空
{
AfxMessageBox("请输入网络文件夹路径");
return;
}
if(strlocal.IsEmpty())
{
AfxMessageBox("请输入本地文件夹路径");
return;
}
if(strnetwork.Left(2)!="\\")
{
AfxMessageBox("路径首部应是\\");
return;
}
char fromname[80]="";
char toname[80]="";
strcpy(fromname,strnetwork);
strcpy(toname,strlocal);
strcat(fromname,"");
strcat(toname,"");
SHFILEOPSTRUCT lpFilestru; //定义一个SHFILEOPSTRUCT结构
lpFilestru.hwnd=GetSafeHwnd(); //设置窗口句柄
lpFilestru.wFunc=FO_COPY; //设置文件操作类型为复制文件操作
lpFilestru.pFrom=fromname; //设置源文件
lpFilestru.pTo=toname; //设置目标文件
lpFilestru.fFlags=FOF_ALLOWUNDO; //设置操作标识,允许取消复制操作
lpFilestru.fAnyOperationsAborted=FALSE;
BOOL bcopy=SHFileOperation(&lpFilestru); //开始复制文件
if(bcopy==0) //文件复制操作是否成功
{
if(lpFilestru.fAnyOperationsAborted==TRUE)
AfxMessageBox("复制被取消");
else
AfxMessageBox("复制成功");
}
else
{
AfxMessageBox("复制失败");
}
}
(3)运行程序,效果如图3所示。
图3 运行结果
注意红色所标出来的部分这是一体的,经鉴别例子中这应该是C语言中的用法 而VC++的用法列有不同:如下
//局域网将文件传到服务器 CString strnetwork,strlocal; GetDlgItem(IDC_EDNETWORK)->GetWindowText(strnetwork); GetDlgItem(IDC_EDLOCAL)->GetWindowText(strlocal); char fromname[80]="\0";
char toname[80]="\0"; USES_CONVERSION; //T2A将CString型转换为char型必须用 strcpy_s(fromname,T2A(strnetwork));//T2A将CString型转换为char型 strcpy_s(toname,T2A(strlocal)); strcat_s(fromname,"\0"); strcat_s(toname,"\0"); SHFILEOPSTRUCTA lpFilestru; //不同之处与C中的 lpFilestru.hwnd=GetSafeHwnd(); lpFilestru.wFunc=FO_COPY; lpFilestru.pFrom=toname; lpFilestru.pTo=fromname; //lpFilestru.pFrom=(LPCWSTR)(A2CW((LPCSTR)toname)); //lpFilestru.pTo=(LPCWSTR)(A2CW((LPCSTR)fromname)); lpFilestru.fFlags=FOF_ALLOWUNDO; lpFilestru.fAnyOperationsAborted=FALSE; BOOL bcopy=SHFileOperationA(&lpFilestru);//与C中的不同之处在于函数 /*BOOL bcopy=SHFileOperation(&lpFilestru);*/ if(bcopy==0) { if(lpFilestru.fAnyOperationsAborted==TRUE) AfxMessageBox(_T("复制被取消")); else AfxMessageBox(_T("复制成功")); } else { AfxMessageBox(_T("复制失败")); }
在VC++中的函数这是从Visual studio中考出来的,无误
typedef struct _SHFILEOPSTRUCTA
{
HWND hwnd;
UINT wFunc;
LPCSTR pFrom;
LPCSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCSTR lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
} SHFILEOPSTRUCTA, *LPSHFILEOPSTRUCTA;
typedef struct _SHFILEOPSTRUCTW
{
HWND hwnd;
UINT wFunc;
LPCWSTR pFrom;
LPCWSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCWSTR lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
} SHFILEOPSTRUCTW, *LPSHFILEOPSTRUCTW;
#ifdef UNICODE
typedef SHFILEOPSTRUCTW SHFILEOPSTRUCT;
typedef LPSHFILEOPSTRUCTW LPSHFILEOPSTRUCT;
#else
typedef SHFILEOPSTRUCTA SHFILEOPSTRUCT;
typedef LPSHFILEOPSTRUCTA LPSHFILEOPSTRUCT;
#endif // UNICODE
SHSTDAPI_(int) SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp);
SHSTDAPI_(int) SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp);
#ifdef UNICODE
#define SHFileOperation SHFileOperationW
#else
#define SHFileOperation SHFileOperationA
#endif // !UNICODE
SHSTDAPI_(void) SHFreeNameMappings(HANDLE hNameMappings);
typedef struct _SHNAMEMAPPINGA
{
LPSTR pszOldPath;
LPSTR pszNewPath;
int cchOldPath;
int cchNewPath;
} SHNAMEMAPPINGA, *LPSHNAMEMAPPINGA;
typedef struct _SHNAMEMAPPINGW
{
LPWSTR pszOldPath;
LPWSTR pszNewPath;
int cchOldPath;
int cchNewPath;
} SHNAMEMAPPINGW, *LPSHNAMEMAPPINGW;
#ifdef UNICODE
typedef SHNAMEMAPPINGW SHNAMEMAPPING;
typedef LPSHNAMEMAPPINGW LPSHNAMEMAPPING;
#else
typedef SHNAMEMAPPINGA SHNAMEMAPPING;
typedef LPSHNAMEMAPPINGA LPSHNAMEMAPPING;
#endif // UNICODE
SHFILEOPSTRUCT结构体和实例
CString与LPCWSTR的转化,格式转换
SHFILEOPSTRUCT结构体和实例
分类: Delphi技术讨论组 2007-03-15 16:21 1486人阅读 评论(0) 收藏 举报
delete代码分析delphistring
SHFILEOPSTRUCT结构体的定义如下:
typedef struct _SHFILEOPSTRUCT { // shfos
HWND hwnd; //显示状态信息窗口的句柄,一般设为主窗体的句柄 UINT wFunc; //要执行的操作
LPCSTR pFrom; //源文件或目录
LPCSTR pTo; //目标文件或目录
FILEOP_FLAGS fFlags; //控制文件操作的标志
BOOL fAnyOperationsAborted; //操作是否放弃
LPVOID hNameMappings; //文件名映射对象的句柄,很少用
LPCSTR lpszProgressTitle; //进度条标题,仅在fFlags标志中指定了//FO F_SIMPLEPROGRESS时有效
} SHFILEOPSTRUCT, FAR *LPSHFILEOPSTRUCT;
Delphi用记录TSHFileOpStruct对此结构做了两种封装:ANSI字符和宽字符版本。读者可 从ShellAPI单元的第265行看到如下代码:
_SHFILEOPSTRUCTA = packed record //ANSI版本
Wnd: HWND;
wFunc: UINT;
pFrom: PAnsiChar;
pTo: PAnsiChar;
fFlags: FILEOP_FLAGS;
fAnyOperationsAborted: BOOL;
hNameMappings: Pointer;
lpszProgressTitle: PAnsiChar; { only used if FOF_SIMPLEPROGRESS }
end;
{$EXTERNALSYM _SHFILEOPSTRUCTW}
_SHFILEOPSTRUCTW = packed record //宽字符版本
Wnd: HWND;
wFunc: UINT;
pFrom: PWideChar;
pTo: PWideChar;
fFlags: FILEOP_FLAGS;
fAnyOperationsAborted: BOOL;
hNameMappings: Pointer;
lpszProgressTitle: PWideChar; { only used if FOF_SIMPLEPROGRESS }
end;
{$EXTERNALSYM _SHFILEOPSTRUCT}
_SHFILEOPSTRUCT = _SHFILEOPSTRUCTA;
TSHFileOpStructA = _SHFILEOPSTRUCTA;
TSHFileOpStructW = _SHFILEOPSTRUCTW;
TSHFileOpStruct = TSHFileOpStructA;
//默认情况下TSHFileOpStruct为ANSI版本
{$EXTERNALSYM SHFILEOPSTRUCTA}
SHFILEOPSTRUCTA = _SHFILEOPSTRUCTA;
{$EXTERNALSYM SHFILEOPSTRUCTW}
SHFILEOPSTRUCTW = _SHFILEOPSTRUCTW;
{$EXTERNALSYM SHFILEOPSTRUCT}
SHFILEOPSTRUCT = SHFILEOPSTRUCTA;
//默认情况下SHFILEOPSTRUCT为ANSI版本
在ShellAPI单元的第200行对wFunc参数的取值定义了4种操作:
{$EXTERNALSYM FO_MOVE}
FO_MOVE = $0001; //移动操作,从pFrom到pTo
{$EXTERNALSYM FO_COPY}
FO_COPY = $0002; //复制操作,从pFrom到pTo
{$EXTERNALSYM FO_DELETE}
FO_DELETE = $0003; //删除操作,删除pFrom中指定的目录或文件(忽略// pTo参数)
{$EXTERNALSYM FO_RENAME}
FO_RENAME = $0004; //重命名操作,重命名pFrom中指定的目录或文件。 在ShellAPI单元的第210行对fFlags参数定义了如下可能取值:
{$EXTERNALSYM FOF_MULTIDESTFILES}
FOF_MULTIDESTFILES = $0001; //表明pTo 参数是多个文件而不是一个//目 录
{$EXTERNALSYM FOF_CONFIRMMOUSE}
FOF_CONFIRMMOUSE = $0002; //目前没有实现
{$EXTERNALSYM FOF_SILENT}
FOF_SILENT = $0004; //不创建进度条/报告
{$EXTERNALSYM FOF_RENAMEONCOLLISION}
FOF_RENAMEONCOLLISION = $0008; //当目标文件已存在时,将源文件改 //名再复制或移动
{$EXTERNALSYM FOF_NOCONFIRMATION}
FOF_NOCONFIRMATION = $0010; //操作过程中不显示确认信息,相当//于用 户选择了“yes to all”
{$EXTERNALSYM FOF_WANTMAPPINGHANDLE}
FOF_WANTMAPPINGHANDLE = $0020; //填充hNameMappings成员
{$EXTERNALSYM FOF_ALLOWUNDO}
FOF_ALLOWUNDO = $0040; //允许撤销操作
{$EXTERNALSYM FOF_FILESONLY}
FOF_FILESONLY = $0080; //只操作文件
{$EXTERNALSYM FOF_SIMPLEPROGRESS}
FOF_SIMPLEPROGRESS = $0100; //显示进度条对话框但不显示文件名 {$EXTERNALSYM FOF_NOCONFIRMMKDIR}
FOF_NOCONFIRMMKDIR = $0200; //新建目录时不提示确认
{$EXTERNALSYM FOF_NOERRORUI}
FOF_NOERRORUI = $0400; //如果操作出错,不显示用户借口 设计步骤
新建一应用程序,按照图3.1.1所示加入2个TStaticText组件、2个TEdit组件和5个TBut ton组件;TstaticText和TButton组件的Caption属性设置为如图所示,TEdit组件的Tex t属性清空。
在uses中加入FileCtrl,shellapi两单元。SelectDirectory函数用到FileCtrl单元,而 SHFileOperation函数及TSHFileOpStruct记录用到shellapi单元。
代码分析
在第一个“„”按钮的OnClick事件中加入如下代码,用于选择操作的源目录: procedure TForm1.Button4Click(Sender: TObject);
var
Dir: string;
begin
Dir := 'D:';
if SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt],0) then
//函数执行成功
// sdAllowCreate:允许创建目录
// sdPerformCreate:执行创建目录
// sdPrompt:显示提示信息
edit1.text:= Dir;
end;
在第二个“„”按钮的OnClick事件中加入如下代码,用于选择操作的目标目录: procedure TForm1.Button5Click(Sender: TObject);
var
Dir: string;
begin
Dir := 'D:';
if SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt],0) then
//解释同上
edit2.text:= Dir;
end;
在“复制”按钮的OnClick事件中加入如下代码,用于执行复制操作:
procedure TForm1.Button1Click(Sender: TObject);
var
OpStruc:TSHFileOpStruct;
FromBuf,ToBuf:Array[0..128] of Char;
begin
FillChar(FromBuf,Sizeof(FromBuf),0);
FillChar(ToBuf,Sizeof(ToBuf),0);
//用0初始化FromBuf和ToBuf数组
StrPCopy(FromBuf,Pchar(Edit1.Text));
StrPCopy(ToBuf,Pchar(Edit2.Text));
//分别在 FromBuf和ToBuf数组中填入操作的源目录及目标目录
//开始填充OpStruc记录
with OpStruc do
begin
Wnd:=Handle;
wFunc:=FO_COPY;
//复制操作
pFrom:=@FromBuf;
pTo:=@ToBuf;
fFlags:=FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;
fAnyOperationsAborted:=False;
hNameMappings:=nil;
lpszProgressTitle:=nil;
end;
if SHFileOperation(OpStruc)=0 then
//函数执行成功
MessageBox(Handle,'复制完毕。','复制信息',MB_OK+MB_ICONINFORMATION); end;
在“移动”按钮的OnClick事件中加入如下代码,用于执行移动操作: procedure TForm1.Button2Click(Sender: TObject);
var
OpStruc:TSHFileOpStruct;
FromBuf,ToBuf:Array[0..128] of Char;
begin
FillChar(FromBuf,Sizeof(FromBuf),0);
FillChar(ToBuf,Sizeof(ToBuf),0);
StrPCopy(FromBuf,Pchar(Edit1.Text));
StrPCopy(ToBuf,Pchar(Edit2.Text));
//开始填充OpStruc记录
with OpStruc do
begin
Wnd:=Handle;
wFunc:=FO_MOVE;
//移动操作
pFrom:=@FromBuf;
pTo:=@ToBuf;
fFlags:=FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;
fAnyOperationsAborted:=False;
hNameMappings:=nil;
lpszProgressTitle:='正在文件';
end;
if SHFileOperation(OpStruc)=0 then
//执行成功
MessageBox(Handle,'移动完毕。','移动信息',MB_OK+MB_ICONINFORMATION);
end;
在“删除”按钮的OnClick事件中加入如下代码,用于执行删除操作:
procedure TForm1.Button3Click(Sender: TObject);
var
OpStruc:TSHFileOpStruct;
FromBuf:Array[0..128] of Char;
begin
FillChar(FromBuf,Sizeof(FromBuf),0);
StrPCopy(FromBuf,Pchar(Edit1.Text));
//开始填充OpStruc记录
with OpStruc do
begin
Wnd:=Handle;
wFunc:=FO_DELETE;
pFrom:=@FromBuf;
pTo:=nil;
fFlags:=FOF_NOCONFIRMATION;
lpszProgressTitle:='正在删除';
end;
if SHFileOperation(OpStruc)=0 then
//执行成功
MessageBox(Handle,'删除完毕。','删除信息',MB_OK+MB_ICONINFORMATION);
end;
总结
注意:删除时(wFunc参数设为FO_DELETE)如果想将文件或目录放到回收站(fFlags参 数设置为FOF_ALLOWUNDO)则应该给出文件的绝对路径名,否则可能无法恢复。对于多个 文件的操作,文件名之间要以#0)字符分隔,整个字符串以两个# 0 结束。
在局域网传输文件时所遇到的问题 在编写一些局域网应用软件时,有时需要在局域网的计算机间复制数据。如果我们将应用程序设计为网络应用程序,未免设计的有些复杂。Windows
系统提
供了一个外壳函数SHFileOperation能够实现局域网间的文件复制。该函数语法如下:
int SHFileOperation(LPSHFILEOPSTRUCT lpFileOp);
其中,lpFileOp参数是一个SHFILEOPSTRUCT结构指针,该结构定义如下: typedef struct _SHFILEOPSTRUCT {
HWND hwnd; //在文件操作过程中显示的对话框的句柄
UINT wFunc; //对文件进行的操作,FO_COPY表示复制文件,FO_DELETE表示删除文件,FO_MOVE表示移动文件,FO_RENAME表示重命名文件
LPCWSTR pFrom; //操作的源文件
LPCWSTR pTo; //目标文件
FILEOP_FLAGS fFlags; //文件操作标识
BOOL fAnyOperationsAborted; //暂未被使用
LPVOID hNameMappings; //暂未被使用
LPCWSTR lpszProgressTitle; //对话框标题
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;
下面我们通过一个实例来介绍局域网文件的复制。效果如图1所示。
图1 局域网文件复制
(1)创建一个基于对话框的工程,向对话框中添加静态文本、编辑框和按钮控件,效果如图2所示。
图2 对话框设计
(2)处理“复制文件”按钮的单击事件,将网络文件复制到本地磁盘。 void CNetworkFileDlg::OnCopy()
{
CString strnetwork,strlocal;
GetDlgItem(IDC_EDNETWORK)->GetWindowText(strnetwork); //获取编辑框文本
GetDlgItem(IDC_EDLOCAL)->GetWindowText(strlocal);
if(strnetwork.IsEmpty()) //验证信息是否为空
{
AfxMessageBox("请输入网络文件夹路径");
return;
}
if(strlocal.IsEmpty())
{
AfxMessageBox("请输入本地文件夹路径");
return;
}
if(strnetwork.Left(2)!="\\")
{
AfxMessageBox("路径首部应是\\");
return;
}
char fromname[80]="";
char toname[80]="";
strcpy(fromname,strnetwork);
strcpy(toname,strlocal);
strcat(fromname,"");
strcat(toname,"");
SHFILEOPSTRUCT lpFilestru; //定义一个SHFILEOPSTRUCT结构
lpFilestru.hwnd=GetSafeHwnd(); //设置窗口句柄
lpFilestru.wFunc=FO_COPY; //设置文件操作类型为复制文件操作
lpFilestru.pFrom=fromname; //设置源文件
lpFilestru.pTo=toname; //设置目标文件
lpFilestru.fFlags=FOF_ALLOWUNDO; //设置操作标识,允许取消复制操作
lpFilestru.fAnyOperationsAborted=FALSE;
BOOL bcopy=SHFileOperation(&lpFilestru); //开始复制文件
if(bcopy==0) //文件复制操作是否成功
{
if(lpFilestru.fAnyOperationsAborted==TRUE)
AfxMessageBox("复制被取消");
else
AfxMessageBox("复制成功");
}
else
{
AfxMessageBox("复制失败");
}
}
(3)运行程序,效果如图3所示。
图3 运行结果
注意红色所标出来的部分这是一体的,经鉴别例子中这应该是C语言中的用法 而VC++的用法列有不同:如下
//局域网将文件传到服务器 CString strnetwork,strlocal; GetDlgItem(IDC_EDNETWORK)->GetWindowText(strnetwork); GetDlgItem(IDC_EDLOCAL)->GetWindowText(strlocal); char fromname[80]="\0";
char toname[80]="\0"; USES_CONVERSION; //T2A将CString型转换为char型必须用 strcpy_s(fromname,T2A(strnetwork));//T2A将CString型转换为char型 strcpy_s(toname,T2A(strlocal)); strcat_s(fromname,"\0"); strcat_s(toname,"\0"); SHFILEOPSTRUCTA lpFilestru; //不同之处与C中的 lpFilestru.hwnd=GetSafeHwnd(); lpFilestru.wFunc=FO_COPY; lpFilestru.pFrom=toname; lpFilestru.pTo=fromname; //lpFilestru.pFrom=(LPCWSTR)(A2CW((LPCSTR)toname)); //lpFilestru.pTo=(LPCWSTR)(A2CW((LPCSTR)fromname)); lpFilestru.fFlags=FOF_ALLOWUNDO; lpFilestru.fAnyOperationsAborted=FALSE; BOOL bcopy=SHFileOperationA(&lpFilestru);//与C中的不同之处在于函数 /*BOOL bcopy=SHFileOperation(&lpFilestru);*/ if(bcopy==0) { if(lpFilestru.fAnyOperationsAborted==TRUE) AfxMessageBox(_T("复制被取消")); else AfxMessageBox(_T("复制成功")); } else { AfxMessageBox(_T("复制失败")); }
在VC++中的函数这是从Visual studio中考出来的,无误
typedef struct _SHFILEOPSTRUCTA
{
HWND hwnd;
UINT wFunc;
LPCSTR pFrom;
LPCSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCSTR lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
} SHFILEOPSTRUCTA, *LPSHFILEOPSTRUCTA;
typedef struct _SHFILEOPSTRUCTW
{
HWND hwnd;
UINT wFunc;
LPCWSTR pFrom;
LPCWSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCWSTR lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
} SHFILEOPSTRUCTW, *LPSHFILEOPSTRUCTW;
#ifdef UNICODE
typedef SHFILEOPSTRUCTW SHFILEOPSTRUCT;
typedef LPSHFILEOPSTRUCTW LPSHFILEOPSTRUCT;
#else
typedef SHFILEOPSTRUCTA SHFILEOPSTRUCT;
typedef LPSHFILEOPSTRUCTA LPSHFILEOPSTRUCT;
#endif // UNICODE
SHSTDAPI_(int) SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp);
SHSTDAPI_(int) SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp);
#ifdef UNICODE
#define SHFileOperation SHFileOperationW
#else
#define SHFileOperation SHFileOperationA
#endif // !UNICODE
SHSTDAPI_(void) SHFreeNameMappings(HANDLE hNameMappings);
typedef struct _SHNAMEMAPPINGA
{
LPSTR pszOldPath;
LPSTR pszNewPath;
int cchOldPath;
int cchNewPath;
} SHNAMEMAPPINGA, *LPSHNAMEMAPPINGA;
typedef struct _SHNAMEMAPPINGW
{
LPWSTR pszOldPath;
LPWSTR pszNewPath;
int cchOldPath;
int cchNewPath;
} SHNAMEMAPPINGW, *LPSHNAMEMAPPINGW;
#ifdef UNICODE
typedef SHNAMEMAPPINGW SHNAMEMAPPING;
typedef LPSHNAMEMAPPINGW LPSHNAMEMAPPING;
#else
typedef SHNAMEMAPPINGA SHNAMEMAPPING;
typedef LPSHNAMEMAPPINGA LPSHNAMEMAPPING;
#endif // UNICODE
SHFILEOPSTRUCT结构体和实例
CString与LPCWSTR的转化,格式转换
SHFILEOPSTRUCT结构体和实例
分类: Delphi技术讨论组 2007-03-15 16:21 1486人阅读 评论(0) 收藏 举报
delete代码分析delphistring
SHFILEOPSTRUCT结构体的定义如下:
typedef struct _SHFILEOPSTRUCT { // shfos
HWND hwnd; //显示状态信息窗口的句柄,一般设为主窗体的句柄 UINT wFunc; //要执行的操作
LPCSTR pFrom; //源文件或目录
LPCSTR pTo; //目标文件或目录
FILEOP_FLAGS fFlags; //控制文件操作的标志
BOOL fAnyOperationsAborted; //操作是否放弃
LPVOID hNameMappings; //文件名映射对象的句柄,很少用
LPCSTR lpszProgressTitle; //进度条标题,仅在fFlags标志中指定了//FO F_SIMPLEPROGRESS时有效
} SHFILEOPSTRUCT, FAR *LPSHFILEOPSTRUCT;
Delphi用记录TSHFileOpStruct对此结构做了两种封装:ANSI字符和宽字符版本。读者可 从ShellAPI单元的第265行看到如下代码:
_SHFILEOPSTRUCTA = packed record //ANSI版本
Wnd: HWND;
wFunc: UINT;
pFrom: PAnsiChar;
pTo: PAnsiChar;
fFlags: FILEOP_FLAGS;
fAnyOperationsAborted: BOOL;
hNameMappings: Pointer;
lpszProgressTitle: PAnsiChar; { only used if FOF_SIMPLEPROGRESS }
end;
{$EXTERNALSYM _SHFILEOPSTRUCTW}
_SHFILEOPSTRUCTW = packed record //宽字符版本
Wnd: HWND;
wFunc: UINT;
pFrom: PWideChar;
pTo: PWideChar;
fFlags: FILEOP_FLAGS;
fAnyOperationsAborted: BOOL;
hNameMappings: Pointer;
lpszProgressTitle: PWideChar; { only used if FOF_SIMPLEPROGRESS }
end;
{$EXTERNALSYM _SHFILEOPSTRUCT}
_SHFILEOPSTRUCT = _SHFILEOPSTRUCTA;
TSHFileOpStructA = _SHFILEOPSTRUCTA;
TSHFileOpStructW = _SHFILEOPSTRUCTW;
TSHFileOpStruct = TSHFileOpStructA;
//默认情况下TSHFileOpStruct为ANSI版本
{$EXTERNALSYM SHFILEOPSTRUCTA}
SHFILEOPSTRUCTA = _SHFILEOPSTRUCTA;
{$EXTERNALSYM SHFILEOPSTRUCTW}
SHFILEOPSTRUCTW = _SHFILEOPSTRUCTW;
{$EXTERNALSYM SHFILEOPSTRUCT}
SHFILEOPSTRUCT = SHFILEOPSTRUCTA;
//默认情况下SHFILEOPSTRUCT为ANSI版本
在ShellAPI单元的第200行对wFunc参数的取值定义了4种操作:
{$EXTERNALSYM FO_MOVE}
FO_MOVE = $0001; //移动操作,从pFrom到pTo
{$EXTERNALSYM FO_COPY}
FO_COPY = $0002; //复制操作,从pFrom到pTo
{$EXTERNALSYM FO_DELETE}
FO_DELETE = $0003; //删除操作,删除pFrom中指定的目录或文件(忽略// pTo参数)
{$EXTERNALSYM FO_RENAME}
FO_RENAME = $0004; //重命名操作,重命名pFrom中指定的目录或文件。 在ShellAPI单元的第210行对fFlags参数定义了如下可能取值:
{$EXTERNALSYM FOF_MULTIDESTFILES}
FOF_MULTIDESTFILES = $0001; //表明pTo 参数是多个文件而不是一个//目 录
{$EXTERNALSYM FOF_CONFIRMMOUSE}
FOF_CONFIRMMOUSE = $0002; //目前没有实现
{$EXTERNALSYM FOF_SILENT}
FOF_SILENT = $0004; //不创建进度条/报告
{$EXTERNALSYM FOF_RENAMEONCOLLISION}
FOF_RENAMEONCOLLISION = $0008; //当目标文件已存在时,将源文件改 //名再复制或移动
{$EXTERNALSYM FOF_NOCONFIRMATION}
FOF_NOCONFIRMATION = $0010; //操作过程中不显示确认信息,相当//于用 户选择了“yes to all”
{$EXTERNALSYM FOF_WANTMAPPINGHANDLE}
FOF_WANTMAPPINGHANDLE = $0020; //填充hNameMappings成员
{$EXTERNALSYM FOF_ALLOWUNDO}
FOF_ALLOWUNDO = $0040; //允许撤销操作
{$EXTERNALSYM FOF_FILESONLY}
FOF_FILESONLY = $0080; //只操作文件
{$EXTERNALSYM FOF_SIMPLEPROGRESS}
FOF_SIMPLEPROGRESS = $0100; //显示进度条对话框但不显示文件名 {$EXTERNALSYM FOF_NOCONFIRMMKDIR}
FOF_NOCONFIRMMKDIR = $0200; //新建目录时不提示确认
{$EXTERNALSYM FOF_NOERRORUI}
FOF_NOERRORUI = $0400; //如果操作出错,不显示用户借口 设计步骤
新建一应用程序,按照图3.1.1所示加入2个TStaticText组件、2个TEdit组件和5个TBut ton组件;TstaticText和TButton组件的Caption属性设置为如图所示,TEdit组件的Tex t属性清空。
在uses中加入FileCtrl,shellapi两单元。SelectDirectory函数用到FileCtrl单元,而 SHFileOperation函数及TSHFileOpStruct记录用到shellapi单元。
代码分析
在第一个“„”按钮的OnClick事件中加入如下代码,用于选择操作的源目录: procedure TForm1.Button4Click(Sender: TObject);
var
Dir: string;
begin
Dir := 'D:';
if SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt],0) then
//函数执行成功
// sdAllowCreate:允许创建目录
// sdPerformCreate:执行创建目录
// sdPrompt:显示提示信息
edit1.text:= Dir;
end;
在第二个“„”按钮的OnClick事件中加入如下代码,用于选择操作的目标目录: procedure TForm1.Button5Click(Sender: TObject);
var
Dir: string;
begin
Dir := 'D:';
if SelectDirectory(Dir, [sdAllowCreate, sdPerformCreate, sdPrompt],0) then
//解释同上
edit2.text:= Dir;
end;
在“复制”按钮的OnClick事件中加入如下代码,用于执行复制操作:
procedure TForm1.Button1Click(Sender: TObject);
var
OpStruc:TSHFileOpStruct;
FromBuf,ToBuf:Array[0..128] of Char;
begin
FillChar(FromBuf,Sizeof(FromBuf),0);
FillChar(ToBuf,Sizeof(ToBuf),0);
//用0初始化FromBuf和ToBuf数组
StrPCopy(FromBuf,Pchar(Edit1.Text));
StrPCopy(ToBuf,Pchar(Edit2.Text));
//分别在 FromBuf和ToBuf数组中填入操作的源目录及目标目录
//开始填充OpStruc记录
with OpStruc do
begin
Wnd:=Handle;
wFunc:=FO_COPY;
//复制操作
pFrom:=@FromBuf;
pTo:=@ToBuf;
fFlags:=FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;
fAnyOperationsAborted:=False;
hNameMappings:=nil;
lpszProgressTitle:=nil;
end;
if SHFileOperation(OpStruc)=0 then
//函数执行成功
MessageBox(Handle,'复制完毕。','复制信息',MB_OK+MB_ICONINFORMATION); end;
在“移动”按钮的OnClick事件中加入如下代码,用于执行移动操作: procedure TForm1.Button2Click(Sender: TObject);
var
OpStruc:TSHFileOpStruct;
FromBuf,ToBuf:Array[0..128] of Char;
begin
FillChar(FromBuf,Sizeof(FromBuf),0);
FillChar(ToBuf,Sizeof(ToBuf),0);
StrPCopy(FromBuf,Pchar(Edit1.Text));
StrPCopy(ToBuf,Pchar(Edit2.Text));
//开始填充OpStruc记录
with OpStruc do
begin
Wnd:=Handle;
wFunc:=FO_MOVE;
//移动操作
pFrom:=@FromBuf;
pTo:=@ToBuf;
fFlags:=FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION;
fAnyOperationsAborted:=False;
hNameMappings:=nil;
lpszProgressTitle:='正在文件';
end;
if SHFileOperation(OpStruc)=0 then
//执行成功
MessageBox(Handle,'移动完毕。','移动信息',MB_OK+MB_ICONINFORMATION);
end;
在“删除”按钮的OnClick事件中加入如下代码,用于执行删除操作:
procedure TForm1.Button3Click(Sender: TObject);
var
OpStruc:TSHFileOpStruct;
FromBuf:Array[0..128] of Char;
begin
FillChar(FromBuf,Sizeof(FromBuf),0);
StrPCopy(FromBuf,Pchar(Edit1.Text));
//开始填充OpStruc记录
with OpStruc do
begin
Wnd:=Handle;
wFunc:=FO_DELETE;
pFrom:=@FromBuf;
pTo:=nil;
fFlags:=FOF_NOCONFIRMATION;
lpszProgressTitle:='正在删除';
end;
if SHFileOperation(OpStruc)=0 then
//执行成功
MessageBox(Handle,'删除完毕。','删除信息',MB_OK+MB_ICONINFORMATION);
end;
总结
注意:删除时(wFunc参数设为FO_DELETE)如果想将文件或目录放到回收站(fFlags参 数设置为FOF_ALLOWUNDO)则应该给出文件的绝对路径名,否则可能无法恢复。对于多个 文件的操作,文件名之间要以#0)字符分隔,整个字符串以两个# 0 结束。