最近为了管理编程任务,自己写了个工作任务管理软件,没想到一个小小的软件居然花了我好几天的时间。尽管用的是古老的MFC的程序,但突然发现先前很多MFC技术都不是很熟悉了,借这个机会重新温习下MFC的相关技术,就以这个软件作为背景例子。
首先看看软件的界面:
二进制文件类
二进制文件的操作是最基本的文件操作,主要包括打开文件,文件读写,文件读写关闭,文件访问定位。
这里封装了个文件处理类,直接从二进制文件中读写大的结构体,
头文件:
define MESSAGE_CAPACITY 1000 //消息能力值
#define TASK_LENGTH 256
enum TASK_STATE
{
TASK_FUTURE=0,
TASK_WORKING,
TASK_COMPLETE,
};
typedef struct TASKINFO
{
DWORD dwData;
//DWORD dwID;
char chTask[TASK_LENGTH];
TASK_STATE nState;
}Task_info;
简单讲下这个类,它类似一个智能索引生成,在一个给定范围的数组中,动态为每个文件中的结构动态生成索引号,它很好的解决了,在删除中间一结构时候,其它结构对应的索引号需要重新分配和移动它存储的位置,就像stl中的vector新增和删除一项后,里面的所有存储数据的位置需要平移。它实现的原理是,首先将数组中每个索引值置为零,每当新增一个结构时候,从左向右遍历数组,找到第一个0的索引号,并返回索引值赋给结构;删除一结构的时候,读取结构中的索引号,然后在数组中找到索引所对应的值,并将其值置为0。
class CMakeIndex
{
public:
CMakeIndex(DWORD dwsize=MESSAGE_CAPACITY)
{
m_dwSize=dwsize;
m_pIndexList=new DWORD[m_dwSize];
if (!m_pIndexList)
{
return;
}
memset(m_pIndexList,0,sizeof(DWORD)*m_dwSize);
}
~CMakeIndex()
{
if (m_pIndexList)
{
delete []m_pIndexList;
m_pIndexList=NULL;
return ;
}
}
CMakeIndex(const CMakeIndex& ref)
{
m_dwSize=ref.m_dwSize;
m_pIndexList=new DWORD[m_dwSize];
memset(m_pIndexList,0,sizeof(DWORD)*m_dwSize);
}
CMakeIndex & operator=(const CMakeIndex&ref)
{
if (m_pIndexList)
{
delete[] m_pIndexList;
}
m_dwSize=ref.m_dwSize;
m_pIndexList=new DWORD[m_dwSize];
memset(m_pIndexList,0,sizeof(DWORD)*m_dwSize);
return *this;
}
int Make()
{
for (int i=0;i<(int)m_dwSize;++i)
{
if (0==m_pIndexList[i])
{
m_pIndexList[i]=1;
return i;
}
}
return -1;
}
BOOL Clear(DWORD dwIndex)
{
if (dwIndex>m_dwSize)
{
return FALSE;
}
m_pIndexList[dwIndex]=0;
return TRUE;
}
int GetCount()
{
int count=0;
for (int i=0;i<(int)m_dwSize;++i)
{
if (0!=m_pIndexList[i])
{
count++;
}
}
return count;
}
private:
DWORD m_dwSize; //索引个数;
DWORD *m_pIndexList; //索引链表;
};
二进制文件处理类
class CFileOP
{
public:
CFileOP(); //默认构造函数
~CFileOP(); //析构函数
CFileOP (const CFileOP&); 拷贝构造函数
CFileOP&operator=(const CFileOP& ref); 赋值运算符重载
void setFullPathName(const char* filename="Task.cfg"); 设置文件完整路径
static CFileOP*GetFileMngObject(); 获取单例对象
void purgeFileMng(); 自动释放对象,类似构造函数
public:
void ReadData(); //从文件中读取数据;
void WriteData(); //向文件中写入信息
int AddTaskItem(Task_info *pInfo); 向文件中写入一个大结构
BOOL DelTaskItem(DWORD dwIndex); 删除索引指定的结构
int GetTaskCount(); 获取文件中包含结构对象的数目
void UpdataTaskData(DWORD dwData,Task_info ti); 更新结构对象
private:
static CFileOP* s_pFileOp; 单例对象
char* m_pFullPathName; 二进制文件完整路径
CMakeIndex m_Mi; 结构实例的存储索引制作
public:
Task_info *m_pTaskInfo[MESSAGE_CAPACITY]; 当前结构实例地址数组
}
cpp文件
CFileOP* CFileOP::s_pFileOp=NULL; 静态单例对象初始赋值
//获取当前二进制文件路径
static void getCurrentPath()
{
if (!s_pszFilePath[0])
{
WCHAR wszPath[MAX_PATH]={0};
int Num=WideCharToMultiByte(CP_ACP,0,wszPath,
GetCurrentDirectoryW(sizeof(wszPath),wszPath),
s_pszFilePath,MAX_PATH,NULL,NULL);
s_pszFilePath[Num]='\\';
}
}
static std::string utfTogbk(const char*src)
{
int len = MultiByteToWideChar(CP_UTF8, 0, src, -1, NULL, 0);
unsigned short * wszGBK = new unsigned short[len + 1];
memset(wszGBK, 0, len * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)src, -1, (LPWSTR)wszGBK, len);
len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wszGBK, -1, NULL, 0, NULL, NULL);
char *szGBK = new char[len + 1];
memset(szGBK, 0, len + 1);
WideCharToMultiByte(CP_ACP,0, (LPCWSTR)wszGBK, -1, szGBK, len, NULL, NULL);
std::string strTemp(szGBK);
if (strTemp.find('?') != std::string::npos)
{
strTemp.assign(src);
}
delete[]szGBK;
delete[]wszGBK;
return strTemp;
}
构造函数
CFileOP::CFileOP():m_Mi(MESSAGE_CAPACITY),m_pFullPathName(NULL)
{
ReadData();
}
析构函数
CFileOP::~CFileOP()
{
//WriteData();
if (m_pFullPathName)
{
delete []m_pFullPathName;
m_pFullPathName=NULL;
}
for (int i=0;i<MESSAGE_CAPACITY;++i)
{
if (NULL==m_pTaskInfo[i])
{
continue;
}
else
{
delete m_pTaskInfo[i];
m_pTaskInfo[i]=NULL;
}
}
}
CFileOP::CFileOP(const CFileOP&ref):m_Mi(MESSAGE_CAPACITY),m_pFullPathName(NULL)
{
size_t lenth=strlen(ref.m_pFullPathName);
m_pFullPathName=new char[lenth+1];
m_pFullPathName[lenth]='\0';
strcpy_s(m_pFullPathName,lenth,ref.m_pFullPathName);
ReadData();
}
CFileOP& CFileOP::operator =(const CFileOP&ref)
{
if (m_pFullPathName)
{
delete []m_pFullPathName;
}
size_t lenth=strlen(ref.m_pFullPathName);
m_pFullPathName=new char[lenth+1];
m_pFullPathName[lenth]='\0';
strcpy_s(m_pFullPathName,lenth,ref.m_pFullPathName);
ReadData();
return *this;
}
void CFileOP::setFullPathName(const char* filename)
{
getCurrentPath();
std::string fullpath=utfTogbk(s_pszFilePath);
fullpath+=utfTogbk(filename);
size_t lenth=strlen(fullpath.c_str());
if (m_pFullPathName)
{
delete m_pFullPathName;
}
const char*pfile=fullpath.c_str();
m_pFullPathName=new char[lenth+1];
m_pFullPathName[lenth]='\0';
strcpy(m_pFullPathName,pfile);
}
CFileOP*CFileOP::GetFileMngObject()
{
if (!s_pFileOp)
{
s_pFileOp=new CFileOP();
}
return s_pFileOp;
}
void CFileOP::ReadData()
{
memset(m_pTaskInfo,0,sizeof(m_pTaskInfo));
if (!m_pFullPathName)
{
setFullPathName();
}
FILE* fp=fopen(m_pFullPathName,"rb");
if (!fp)
{
return;
}
int temp;
const char chrelationship[]="TaskInfo";
char chCmpTag[100]={0};
//校验头
int nReadSize=fread(chCmpTag,1,strlen(chrelationship),fp);
if (nReadSize!=strlen(chrelationship)|| 0!=strcmp(chCmpTag,chrelationship))
{
fclose(fp);
return;
}
int dwTaskCount=0;
nReadSize=fread(&dwTaskCount,1,sizeof(int),fp);
if (nReadSize>MESSAGE_CAPACITY ||nReadSize!=sizeof(dwTaskCount))
{
fclose(fp);
return;
}
Task_info taskInfo;
//从文件中读出每一条任务内容
for(int i=0;i<dwTaskCount;i++)
{
fread(&taskInfo,1,sizeof(TASKINFO),fp);
AddTaskItem(&taskInfo);
}
fclose(fp);
return;
}
int CFileOP::AddTaskItem(Task_info *pInfo)
{
int nIndex=0;
nIndex=m_Mi.Make();
if (-1==nIndex)
{
return -1;
}
m_pTaskInfo[nIndex]=new Task_info;
*m_pTaskInfo[nIndex]=*pInfo;
return nIndex;
}
void CFileOP::WriteData()
{
if (!m_pFullPathName)
{
setFullPathName();
}
FILE *fp=fopen(m_pFullPathName,"wb");
if (NULL==fp)
{
return ;
}
//写文件标记、
char chrelationship[]="TaskInfo";
fwrite(chrelationship,1,strlen(chrelationship),fp);
DWORD dwTaskCount=GetTaskCount();
fwrite(&dwTaskCount,1,sizeof(dwTaskCount),fp);
for (int i=0;i<MESSAGE_CAPACITY;++i)
{
if (NULL==m_pTaskInfo[i])
{
continue;
}
else
{
fwrite(m_pTaskInfo[i],1,sizeof(TASKINFO),fp);
}
}
fseek(fp,0L,SEEK_END);
int num=ftell(fp);
fclose(fp);
return ;
}
int CFileOP::GetTaskCount()
{
return m_Mi.GetCount();
}
BOOL CFileOP::DelTaskItem(DWORD dwIndex)
{
BOOL bRet=m_Mi.Clear(dwIndex);
if (!bRet)
{
return FALSE;
}
delete m_pTaskInfo[dwIndex];
m_pTaskInfo[dwIndex]=NULL;
return TRUE;
}
void CFileOP::purgeFileMng()
{
WriteData();
if (m_pFullPathName)
{
delete []m_pFullPathName;
m_pFullPathName=NULL;
}
for (int i=0;i<MESSAGE_CAPACITY;++i)
{
if (NULL==m_pTaskInfo[i])
{
continue;
}
else
{
delete m_pTaskInfo[i];
m_pTaskInfo[i]=NULL;
}
}
delete this;
}
void CFileOP::UpdataTaskData(DWORD dwData/* =0 */,Task_info ti)
{
if (dwData>MESSAGE_CAPACITY)
{
return;
}
for (int i=0;i<GetTaskCount();++i)
{
if (dwData==m_pTaskInfo[i]->dwData)
{
*m_pTaskInfo[i]=ti;
return;
}
else
{
continue;
}
}