MFC制作的文件打包工具
由于个人以前对VC6.0比较熟悉,当然也尝试使用VS2008,还是感觉VC6.0比较简单明了!!!
1.编译工具:VC6.0
新建工程:新建->弹出框->工程->MFC AppWizarp(exe)->填上工程名
2.图形使用:基本控件如按钮、编辑框、标签等都是可以通过拉取来布局,右键属性修改一些设置如ID,名称等,双击生成函数会提示函数名命名。
3.按钮控件:在生成的函数里,就是按钮按下所要执行的事件。
4.编辑框:SetDlgItemText(IDC_FILEPATH_EDIT,filename);//在一个地址为IDC_FILEPATH_EDIT的editbox中显示文件名
5.CFile类的使用:CFileDialog opendlg (TRUE,_T("*"),NULL,OFN_OVERWRITEPROMPT, _T("所有文件(*.*;)|*.*||"),NULL);
if (opendlg.DoModal()==IDOK)
{
filename=opendlg.GetPathName();
}
if (opendlg.DoModal()==IDOK)
{
filename=opendlg.GetPathName();
}
CFileDialog Dlg( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );
各个参数的意义说明如下:
bOpenFileDialog 为TRUE则显示打开文件对话框,为FALSE则显示保存文件对话框。
lpszDefExt 指定默认的文件扩展名。
lpszFileName 指定默认的文件名。
dwFlags 指明一些特定风格。
lpszFilter 是最重要的一个参数,它指明可供选择的文件类型和相应的扩展名。
各个参数的意义说明如下:
bOpenFileDialog 为TRUE则显示打开文件对话框,为FALSE则显示保存文件对话框。
lpszDefExt 指定默认的文件扩展名。
lpszFileName 指定默认的文件名。
dwFlags 指明一些特定风格。
lpszFilter 是最重要的一个参数,它指明可供选择的文件类型和相应的扩展名。
5.新建自己的类
插入->类->选择类的类型下的generic class->填上名字确定即可
6.文件的打包解包
直接上代码:
class packFile
{
public:
packFile();
virtual ~packFile();
int OpenMasFile(const char* path, const byte onlyOpen);
int WriteFileToPak(const char* path);
int ReadFileFromPak(const FilesMsg msg, byte* _dst);
int GetFileMessage( const char* path, FilesMsg* msg);
int CloseMasFile( void );
};
{
public:
packFile();
virtual ~packFile();
int OpenMasFile(const char* path, const byte onlyOpen);
int WriteFileToPak(const char* path);
int ReadFileFromPak(const FilesMsg msg, byte* _dst);
int GetFileMessage( const char* path, FilesMsg* msg);
int CloseMasFile( void );
};
// 打开包文件
int packFile::OpenMasFile(const char* path, const byte onlyOpen)
{
uint uWriteCount; // 写入文件信息次数
byte bIsNew = 0; // 是否新建的
MaseHeader header; // 文件头结构定义
FilesMsg msg; //文件信息结构定义
g_pMasFile = fopen(path, "rb"); //用来判断是否存在
if (g_pMasFile == NULL)
{
if (onlyOpen == 1) // 只打开不新建
return -1;
bIsNew = 1;
g_pMasFile = fopen(path, "wb");
if (g_pMasFile == NULL)
return -1;
}
//先关闭,然后在用"rb+"方式打开 二进制读写打开文件
fclose( g_pMasFile );
g_pMasFile = fopen(path, "rb+");
if(g_pMasFile == NULL)
return -1;
if(bIsNew == 1)// 新建的文件
{
header.uFileFlag = 'ESAM';
header.uFileCount= 0;
header.uFileListOfs = sizeof(MaseHeader); //紧跟着就是文件列表
header.uMaxFileCount = MAX_FILE_COUNT;
header.uFileSize = sizeof(MaseHeader)+(MAX_FILE_COUNT * sizeof(FilesMsg));
//写入头信息
fwrite(&header, sizeof(MaseHeader), 1, g_pMasFile);
memset(&msg, 0, sizeof(FilesMsg));
uWriteCount = MAX_FILE_COUNT;
//写入文件列表用0占位
while(uWriteCount--)
fwrite(&msg, sizeof(FilesMsg), 1, g_pMasFile);
}
else//文件存在
{
//则读取头文件信息
fread(&header, sizeof(MaseHeader), 1, g_pMasFile);
}
//检查文件头标记
if (header.uFileFlag != 'ESAM')
{
fclose(g_pMasFile);
printf("文件头标记不对,错误!\n");
return -1;
}
//检查数据是否完整
if (header.uMaxFileCount != MAX_FILE_COUNT)
{
fclose(g_pMasFile);
printf("数据不完整,错误!\n");
return -1;
}
return 0;
}
//写文件到包里
int packFile::WriteFileToPak(const char* path)
{
FilesMsg fileMsg; //此文件的文件信息结构
MaseHeader header; //包文件头结构定义
uint uFileSize;
uint uFileListEndOfs;
byte* pBuff;
FILE* pFile = NULL;
if (g_pMasFile == NULL)
return -1;
memset(&fileMsg, 0, sizeof(FilesMsg));
fseek(g_pMasFile, 0, SEEK_SET); //定位到文件头,读取头文件信息
//则读取头文件信息
fread(&header,sizeof(MaseHeader), 1, g_pMasFile);
uFileListEndOfs = header.uFileCount * sizeof(FilesMsg) + header.uFileListOfs;
pFile = fopen(path, "rb");
if(pFile == NULL)
return -1;
fseek(pFile, 0, SEEK_END);
uFileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
//文件名长度不能超过260
strcpy(fileMsg.szFileName,path);
fileMsg.uFileOfs = header.uFileSize;
fileMsg.uFileSize = uFileSize;
// 写入文件信息
// 将文件指针定位到uFileListEndOfs处,以便写入新的文件信息结构
fseek(g_pMasFile, uFileListEndOfs, SEEK_SET);
fwrite(&fileMsg,sizeof(FilesMsg),1,g_pMasFile);
// 申请空间
pBuff = (byte*)malloc(uFileSize);
fread(pBuff,uFileSize,1,pFile);
// 写数据到包文件里
fseek(g_pMasFile,header.uFileSize,SEEK_SET);
fwrite(pBuff, uFileSize, 1, g_pMasFile);
// 释放内存
free(pBuff);
//重新填充header
header.uFileCount += 1;
header.uFileSize += uFileSize;
fseek( g_pMasFile,0,SEEK_SET);
// 重新写入包文件头
fwrite(&header,sizeof(MaseHeader),1,g_pMasFile);
return 0;
}
//从包文件里读数据
int packFile::ReadFileFromPak(const FilesMsg msg, byte* _dst)
{
if ( g_pMasFile == NULL )
return -1;
fseek(g_pMasFile, msg.uFileOfs,SEEK_SET);
fread(_dst, msg.uFileSize, 1, g_pMasFile);
return 0;
}
//获取包中某个文件的信息
int packFile::GetFileMessage( const char* path, FilesMsg* msg)
{
FilesMsg fileMsg; // 此文件的文件信息结构
MaseHeader header; // 包头结构
uint uFileCount; // 文件个数
if ( g_pMasFile == NULL || msg == NULL )
return -1;
// 则读取头文件信息
fseek(g_pMasFile, 0, SEEK_SET);
fread(&header, sizeof(MaseHeader), 1, g_pMasFile);
uFileCount = header.uFileCount;
while (uFileCount--)
{
fread(&fileMsg, sizeof(FilesMsg), 1,g_pMasFile);
// 判断是否是要获取的文件
if (stricmp(fileMsg.szFileName, path) == 0 )
{
*msg = fileMsg;
return 0;
}
}
return -1;
}
// 关闭包文件
int packFile::CloseMasFile( void )
{
if ( g_pMasFile == NULL );
return -1;
fclose( g_pMasFile );
g_pMasFile = NULL;
return 0;
}
int packFile::OpenMasFile(const char* path, const byte onlyOpen)
{
uint uWriteCount; // 写入文件信息次数
byte bIsNew = 0; // 是否新建的
MaseHeader header; // 文件头结构定义
FilesMsg msg; //文件信息结构定义
g_pMasFile = fopen(path, "rb"); //用来判断是否存在
if (g_pMasFile == NULL)
{
if (onlyOpen == 1) // 只打开不新建
return -1;
bIsNew = 1;
g_pMasFile = fopen(path, "wb");
if (g_pMasFile == NULL)
return -1;
}
//先关闭,然后在用"rb+"方式打开 二进制读写打开文件
fclose( g_pMasFile );
g_pMasFile = fopen(path, "rb+");
if(g_pMasFile == NULL)
return -1;
if(bIsNew == 1)// 新建的文件
{
header.uFileFlag = 'ESAM';
header.uFileCount= 0;
header.uFileListOfs = sizeof(MaseHeader); //紧跟着就是文件列表
header.uMaxFileCount = MAX_FILE_COUNT;
header.uFileSize = sizeof(MaseHeader)+(MAX_FILE_COUNT * sizeof(FilesMsg));
//写入头信息
fwrite(&header, sizeof(MaseHeader), 1, g_pMasFile);
memset(&msg, 0, sizeof(FilesMsg));
uWriteCount = MAX_FILE_COUNT;
//写入文件列表用0占位
while(uWriteCount--)
fwrite(&msg, sizeof(FilesMsg), 1, g_pMasFile);
}
else//文件存在
{
//则读取头文件信息
fread(&header, sizeof(MaseHeader), 1, g_pMasFile);
}
//检查文件头标记
if (header.uFileFlag != 'ESAM')
{
fclose(g_pMasFile);
printf("文件头标记不对,错误!\n");
return -1;
}
//检查数据是否完整
if (header.uMaxFileCount != MAX_FILE_COUNT)
{
fclose(g_pMasFile);
printf("数据不完整,错误!\n");
return -1;
}
return 0;
}
//写文件到包里
int packFile::WriteFileToPak(const char* path)
{
FilesMsg fileMsg; //此文件的文件信息结构
MaseHeader header; //包文件头结构定义
uint uFileSize;
uint uFileListEndOfs;
byte* pBuff;
FILE* pFile = NULL;
if (g_pMasFile == NULL)
return -1;
memset(&fileMsg, 0, sizeof(FilesMsg));
fseek(g_pMasFile, 0, SEEK_SET); //定位到文件头,读取头文件信息
//则读取头文件信息
fread(&header,sizeof(MaseHeader), 1, g_pMasFile);
uFileListEndOfs = header.uFileCount * sizeof(FilesMsg) + header.uFileListOfs;
pFile = fopen(path, "rb");
if(pFile == NULL)
return -1;
fseek(pFile, 0, SEEK_END);
uFileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
//文件名长度不能超过260
strcpy(fileMsg.szFileName,path);
fileMsg.uFileOfs = header.uFileSize;
fileMsg.uFileSize = uFileSize;
// 写入文件信息
// 将文件指针定位到uFileListEndOfs处,以便写入新的文件信息结构
fseek(g_pMasFile, uFileListEndOfs, SEEK_SET);
fwrite(&fileMsg,sizeof(FilesMsg),1,g_pMasFile);
// 申请空间
pBuff = (byte*)malloc(uFileSize);
fread(pBuff,uFileSize,1,pFile);
// 写数据到包文件里
fseek(g_pMasFile,header.uFileSize,SEEK_SET);
fwrite(pBuff, uFileSize, 1, g_pMasFile);
// 释放内存
free(pBuff);
//重新填充header
header.uFileCount += 1;
header.uFileSize += uFileSize;
fseek( g_pMasFile,0,SEEK_SET);
// 重新写入包文件头
fwrite(&header,sizeof(MaseHeader),1,g_pMasFile);
return 0;
}
//从包文件里读数据
int packFile::ReadFileFromPak(const FilesMsg msg, byte* _dst)
{
if ( g_pMasFile == NULL )
return -1;
fseek(g_pMasFile, msg.uFileOfs,SEEK_SET);
fread(_dst, msg.uFileSize, 1, g_pMasFile);
return 0;
}
//获取包中某个文件的信息
int packFile::GetFileMessage( const char* path, FilesMsg* msg)
{
FilesMsg fileMsg; // 此文件的文件信息结构
MaseHeader header; // 包头结构
uint uFileCount; // 文件个数
if ( g_pMasFile == NULL || msg == NULL )
return -1;
// 则读取头文件信息
fseek(g_pMasFile, 0, SEEK_SET);
fread(&header, sizeof(MaseHeader), 1, g_pMasFile);
uFileCount = header.uFileCount;
while (uFileCount--)
{
fread(&fileMsg, sizeof(FilesMsg), 1,g_pMasFile);
// 判断是否是要获取的文件
if (stricmp(fileMsg.szFileName, path) == 0 )
{
*msg = fileMsg;
return 0;
}
}
return -1;
}
// 关闭包文件
int packFile::CloseMasFile( void )
{
if ( g_pMasFile == NULL );
return -1;
fclose( g_pMasFile );
g_pMasFile = NULL;
return 0;
}
调用
void CPackToolDlg::OnSelectFile()
{
// TODO: Add your control notification handler code here
//ifstream fin(filename);
//ofstream fout("a.txt");
//CString filename;//保存路径
CFileDialog opendlg (TRUE,_T("*"),NULL,OFN_OVERWRITEPROMPT, _T("所有文件(*.*;)|*.*||"),NULL);
if (opendlg.DoModal()==IDOK)
{
filename=opendlg.GetPathName();
SetDlgItemText(IDC_FILEPATH_EDIT,filename);//在一个地址为IDC_FILEPATH_EDIT的editbox中显示文件名
}
}
void CPackToolDlg::OnPack()
{
// TODO: Add your control notification handler code here
int ret;
packFile *packTemp;
char changName[100]="";
if(filename=="")
{
INT_PTR nRes;
// 显示消息对话框
nRes = MessageBox(_T("没有选择文件"), _T("警告"), MB_OK | MB_ICONWARNING);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
}
sprintf(changName,"%s.dat",filename);
ret = packTemp->OpenMasFile(changName,0);
if ( ret == -1 )
goto __exit;
//WriteFileToPak( "E:\\珍贵.jpg" );
//WriteFileToPak( "E:\\123.docx" );
packTemp->WriteFileToPak(filename);
MessageBox(_T("打包完成"), _T("提醒"), MB_OK | MB_ICONINFORMATION);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
__exit:
packTemp->CloseMasFile();
MessageBox(_T("打包失败"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
void CPackToolDlg::OnUnpack()
{
// TODO: Add your control notification handler code here
packFile *packTemp;
byte* pBuff;
FILE* pOutFile;
FilesMsg getFileMsg;
int ret;
char changName[100]="";
int len=0;
if(filename=="")
{
INT_PTR nRes;
// 显示消息对话框
nRes = MessageBox(_T("没有选择文件"), _T("警告"), MB_OK | MB_ICONWARNING);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
}
sprintf(changName,"%s",filename);
len = strlen(changName);
if (changName[len - 4] == '.') changName[len - 4] = '\0';
ret = packTemp->OpenMasFile(filename, 1);
if (ret == -1)
goto __exit;
ret = packTemp->GetFileMessage(changName, &getFileMsg);
if(ret == -1)
goto __exit;
pBuff = (byte*)malloc(getFileMsg.uFileSize);
ret = packTemp->ReadFileFromPak(getFileMsg, pBuff);
if(ret == -1)
goto __exit_free;
pOutFile = fopen(changName, "wb"); // 注意使用的是二进制模式
if(ret == -1)
goto __exit_free;
fwrite( pBuff, getFileMsg.uFileSize, 1, pOutFile );
fclose( pOutFile );
MessageBox(_T("解包完成"), _T("提醒"), MB_OK | MB_ICONINFORMATION);
return;
__exit_free:
free( pBuff );
__exit:
packTemp->CloseMasFile();
MessageBox(_T("解包失败,可能文件格式不对"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
{
// TODO: Add your control notification handler code here
//ifstream fin(filename);
//ofstream fout("a.txt");
//CString filename;//保存路径
CFileDialog opendlg (TRUE,_T("*"),NULL,OFN_OVERWRITEPROMPT, _T("所有文件(*.*;)|*.*||"),NULL);
if (opendlg.DoModal()==IDOK)
{
filename=opendlg.GetPathName();
SetDlgItemText(IDC_FILEPATH_EDIT,filename);//在一个地址为IDC_FILEPATH_EDIT的editbox中显示文件名
}
}
void CPackToolDlg::OnPack()
{
// TODO: Add your control notification handler code here
int ret;
packFile *packTemp;
char changName[100]="";
if(filename=="")
{
INT_PTR nRes;
// 显示消息对话框
nRes = MessageBox(_T("没有选择文件"), _T("警告"), MB_OK | MB_ICONWARNING);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
}
sprintf(changName,"%s.dat",filename);
ret = packTemp->OpenMasFile(changName,0);
if ( ret == -1 )
goto __exit;
//WriteFileToPak( "E:\\珍贵.jpg" );
//WriteFileToPak( "E:\\123.docx" );
packTemp->WriteFileToPak(filename);
MessageBox(_T("打包完成"), _T("提醒"), MB_OK | MB_ICONINFORMATION);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
__exit:
packTemp->CloseMasFile();
MessageBox(_T("打包失败"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
void CPackToolDlg::OnUnpack()
{
// TODO: Add your control notification handler code here
packFile *packTemp;
byte* pBuff;
FILE* pOutFile;
FilesMsg getFileMsg;
int ret;
char changName[100]="";
int len=0;
if(filename=="")
{
INT_PTR nRes;
// 显示消息对话框
nRes = MessageBox(_T("没有选择文件"), _T("警告"), MB_OK | MB_ICONWARNING);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
}
sprintf(changName,"%s",filename);
len = strlen(changName);
if (changName[len - 4] == '.') changName[len - 4] = '\0';
ret = packTemp->OpenMasFile(filename, 1);
if (ret == -1)
goto __exit;
ret = packTemp->GetFileMessage(changName, &getFileMsg);
if(ret == -1)
goto __exit;
pBuff = (byte*)malloc(getFileMsg.uFileSize);
ret = packTemp->ReadFileFromPak(getFileMsg, pBuff);
if(ret == -1)
goto __exit_free;
pOutFile = fopen(changName, "wb"); // 注意使用的是二进制模式
if(ret == -1)
goto __exit_free;
fwrite( pBuff, getFileMsg.uFileSize, 1, pOutFile );
fclose( pOutFile );
MessageBox(_T("解包完成"), _T("提醒"), MB_OK | MB_ICONINFORMATION);
return;
__exit_free:
free( pBuff );
__exit:
packTemp->CloseMasFile();
MessageBox(_T("解包失败,可能文件格式不对"), _T("警告"), MB_OK | MB_ICONWARNING);
return;
}
7.消息框
INT_PTR nRes;
// 显示消息对话框
nRes = MessageBox(_T("没有选择文件"), _T("警告"), MB_OK | MB_ICONWARNING);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
// 显示消息对话框
nRes = MessageBox(_T("没有选择文件"), _T("警告"), MB_OK | MB_ICONWARNING);
// 判断消息对话框返回值。如果为IDCANCEL就return,否则继续向下执行
return;
8.MFC初始化
BOOL CPackToolDlg::OnInitDialog()
9.MFC获取时间
CTime m_time;
CString m_strDateTime;
m_time=CTime::GetCurrentTime(); //获取当前时间日期
m_strDateTime=m_time.Format(_T("%Y-%m-%d %H:%M:%S")); //格式化日期时间
CString m_strDateTime;
m_time=CTime::GetCurrentTime(); //获取当前时间日期
m_strDateTime=m_time.Format(_T("%Y-%m-%d %H:%M:%S")); //格式化日期时间
10.编辑框填入信息与获取信息
SetDlgItemText(IDC_TIME_EDIT,m_strDateTime);
CString version,time,md5;
GetDlgItem(IDC_VERSION_EDIT)->GetWindowText(version);
GetDlgItem(IDC_TIME_EDIT)->GetWindowText(time);
GetDlgItem(IDC_MD5_EDIT)->GetWindowText(md5);
CString version,time,md5;
GetDlgItem(IDC_VERSION_EDIT)->GetWindowText(version);
GetDlgItem(IDC_TIME_EDIT)->GetWindowText(time);
GetDlgItem(IDC_MD5_EDIT)->GetWindowText(md5);
11.全局变量的定义
在.cpp文件里的定义全局变量不会报错
附上一张效果图:
12.main函数传参
int main(int argc, char* argv[])
运行命令为:
hello.exe I LOVE YOU
那么,argc的值是 4,argv[0]是"hello.exe",argv[1]是"I",argv[2]是"LOVE"