五笔反查工具

1. 五笔反查工具

     也许你会说,反查什么的,直接一个MAP容器就搞定了,有什么好说的。的确,最简单的就是这样。但即使是这样,还要准备字,五笔码,字根图,以及它们的对应关系。而这些在网上是没有现成的,也就是说要自己准备。我准备的方法是写个小爬虫,到一个五笔反查网站上将这些东西一并弄下来(具体可参考上一篇文章)。准备好最重要的部分后,如果还要弄得像样一点,就要再花一番功夫。所以说,还是有点东西写的。

     先放几张图,再来分享做这东西时遇到的难点。

五笔反查工具

五笔反查工具

 

2. 字根图

      一共有6763张字根图,如果直接发布,显然不美观。因此有必要打包下,再发布。可惜的是,在网上没找到合适的打包工具(如果知道,还请告诉偶一下>_<)。剩下的就只有一条路了——自己打包。我用的打包方法看简单:做一个记录文件偏移的文件头,然后将图片按顺序放到文件头之后。

      记录文件偏移用以下这个类表示:

struct FileIndex { //辅助类,打包文件中,单个文件的偏移信息
DWORD dwOffset; //离文件头偏移多少
DWORD dwSize; //图片本身多大
char szName[256]; //图片原本的名称
};

      假如我将1.GIF,2.GIF打包到0.ZERO这个文件中,那么0.ZERO的文件结构应该是这样的

(2) (FileIndex) (FileIndex) (content of 1.GIF) (content of 2.GIF)

上面的2表示一共有两个文件或者两个FileIndex,第一个FileIndex就是第1.GIF的信息,第二个FileIndex是2.GIF的信息,接着的是1.GIF和2.GIF的内容

      具体的打包代码如下:

//将strSrcDirectory目录下的全部文件打包到strDestFile中
BOOL CFilePack::MakePack(const std::string& strSrcDirectory, const std::string& strDestFile) {
std::vector<std::string> arFileList;
CString szDirectory;
szDirectory.Format("%s", strSrcDirectory.c_str());
GetAllFileNameInDirectory(szDirectory, arFileList); //将指定文件夹内的文件名都放到vector容器中

FILE* fp = fopen(strDestFile.c_str(), "wb");
if (!fp) {
return FALSE;
}

DWORD dwSize = arFileList.size();
fwrite(&dwSize, 1, 4, fp); //写入一共有几个文件

FileIndex* pFileList = new FileIndex[arFileList.size()];
fwrite(pFileList, 1, arFileList.size() * sizeof(FileIndex), fp); //先预留一块地方保存文件偏移信息

//按顺序打包文件
for (int i = 0; i < arFileList.size(); ++i)
{
strcpy(pFileList[i].szName, arFileList[i].c_str());
std::string filePath = strSrcDirectory + "\\" + arFileList[i];
FILE* fbuf = fopen(filePath.c_str(), "rb");
if (!fbuf)
{
fclose(fp);
delete pFileList;
return FALSE;
}
DWORD fsize = filelength(fileno(fbuf));

pFileList[i].dwSize = fsize;
pFileList[i].dwOffset = ftell(fp);

char* buf = new char[fsize];
fread(buf, 1, fsize, fbuf);
fclose(fbuf);

fwrite(buf, 1, fsize, fp);
delete buf;
}

//将文件的偏移信息写到之前预留的地方
fseek(fp, 4, SEEK_SET);
fwrite(pFileList, 1, arFileList.size() * sizeof(FileIndex), fp);

fclose(fp);
delete pFileList;

return TRUE;
}

        打好包,要取出来也很简单:先读出全部的FileIndex,再根据文件名查找到相应的FileIndex,最后根据偏移值和文件大小就能将原来的内容读出来了。

 

3. 显示GIF

     字根图全是GIF格式的,MFC自带的Picture控件不支持GIF格式,所以。。。不幸中的万幸,第三方图片显示支持很容易就能找到。经过一番比较后,最后选择的是PictureEx。原因是PictureEx很小,只有一个头文件和一个CPP文件。此外,使用也很方便:调用Load(图片路径),再调用Draw()就能将图显示出来了。不过前面已经将图片全部打包成一个文件了,难道使用时还要将图片内容读出来,再写到XX.GIF上吗?回答这个问题前,先来看下Load有哪些重载形式吧

 // loads a picture from a file
// i.e. Load(_T("mypic.gif"));
BOOL Load(LPCTSTR szFileName);

// loads a picture from a global memory block (allocated by GlobalAlloc)
// Warning: this function DOES NOT free the global memory, pointed to by hGlobal
BOOL Load(HGLOBAL hGlobal, DWORD dwSize);

// loads a picture from a program resource
// i.e. Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));
BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType);

     从以上描述看,能用的是第二个重载形式——将一个内存块的内容当图片内容显示。具体的做法是将图片内容从打包文件中读出来后,再拷贝到hGlobal所指的内存块,最后调用Load函数。代码如下:

//显示fileName指定的图片
void CWuBiFangCha_ZeroDlg::Display86ZiGen(CString fileName) {
std::string strFileName(fileName.GetBuffer(0));
char* buf = m_packFile.GetFile(strFileName); //从打包文件中,读取fileName指定文件的内容

if( buf ) {
int iFileSize = m_packFile.GetFileSize(strFileName); //得到fileName指定文件的大小
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, iFileSize);
if( hGlobal == NULL ) {
MessageBox(_T("内存不足"));
AfxPostQuitMessage(0); //退出程序
}

LPVOID pvData = GlobalLock(hGlobal);
if( pvData == NULL ) {
GlobalUnlock(hGlobal);
MessageBox(_T("无法锁定内存"));
AfxPostQuitMessage(0);
}

memcpy(pvData, buf, iFileSize);
GlobalUnlock(hGlobal);
m_86ZiGen.Load(hGlobal, iFileSize); //读图片内容
m_86ZiGen.Draw(); //显示图片

delete[] buf;
::GlobalFree(hGlobal);
}

fileName.ReleaseBuffer();
}

     
4. 资源

a. PictureEx

http://ishare.iask.sina.com.cn/f/22351801.html

b. 五笔反查_零式 V1.0

http://ishare.iask.sina.com.cn/f/22375411.html

c. MFC42D.DLL的介绍

http://www.cppblog.com/duqingwei/archive/2011/06/12/148545.html

 

//-----------------------------------------------------------------------------------------

2011.12.25下午更新

感谢lcs-帅提出的无法运行问题。缺少的MFC42D.DLL是DEBUG版才需要的DLL,现在改成了Release版本,并用了静态编译。

如果还有什么问题,请留言。

 

你可能感兴趣的:(工具)