“依米魔法邮箱”开发笔记
软件用MFC开发而成,具体有以下功能、特色:
- 文档加密解密
- 保存自定义后缀的文件(*.yimi)
- 打开自定义后缀的文件(*.yimi)
- 改变窗口背景色
- 改变窗口形状
- 改变光标图案
- 生成动态自定义软件图标
效果图如下
功能实现方法
我所选的是MFC基本对话框类型的应用程序,布局如下:
文档加密解密
加密核心代码:
//加密
char str;
for(int i = ; i < m_strContent.GetLength(); i++)
{
str = m_strContent.GetAt(i);
str = str+i;
m_strContent.SetAt(i, str);
}
解密核心代码:
//判断是否是.yimi文件
if(dlg.GetFileExt()=="yimi")//是.yimi文件,则解密
{//解密
char str;
for(int i = ; i < m_strContent.GetLength(); i++)
{
str = m_strContent.GetAt(i);
str = str-i;
m_strContent.SetAt(i, str);
}
UpdateData(FALSE);//更新数据
}
具体请参见下面的“保存与打开自定义后缀的文件”。
保存自定义后缀的文件(*.yimi)
为编辑框空间关联Value类型的CString变量m_strContent;
为顶部静态文本关联Value类型的CString变量m_strTitle;
为“另存为”按钮添加BN_CLICKED消息映射,并添加映射函数,代码如下(包括保存文件、顶部显示文件相关信息和对*.yimi类型的文件进行加密处理):
void CMyDlg::OnButtonSave()
{
CFile file;
CString filter;
//“依米魔法文件(*.yimi)”即文件类型选择项,“*.yimi”即要求显示的类型文件
filter = "依米魔法文件(*.yimi)|*.yimi||";
//第一个参数为TRUE时为“打开文件”对话框;为FALSE时为“另存为”对话框。
CFileDialog dlg(FALSE, filter, NULL, OFN_HIDEREADONLY, filter);
if(dlg.DoModal()!=IDOK) return;
//要写CFile::modeCreate,若无该文件则创建;要写CFile::modeWrite,若已有该同名文件则重写覆盖
if(!file.Open(dlg.GetPathName(), CFile::modeCreate|CFile::modeWrite))
{
AfxMessageBox(dlg.GetPathName() + "保存失败╮(╯▽╰)╭");
return;
}
UpdateData();
//静态文本
CString strFileName = dlg.GetPathName();
CFileStatus status;
if(!CFile::GetStatus(strFileName, status))
{
MessageBox("该文件不存在!");
return;
}
//为顶端静态文本设置为以下格式的内容:文件路径全名[年-月-日, 字节数]
m_strTitle.Format("%s[%s, %ld字节]", strFileName,
status.m_ctime.Format("%Y-%m-%d"), status.m_size);
UpdateData(FALSE);
//加密
char str;
for(int i = ; i < m_strContent.GetLength(); i++)
{
str = m_strContent.GetAt(i);
str = str+i;
m_strContent.SetAt(i, str);
}
//文档保存
file.Write(m_strContent, m_strContent.GetLength());
file.Close();
}
打开自定义后缀的文件(*.yimi)
为“打开”按钮添加BN_CLICKED消息映射,并添加映射函数,代码如下(包括打开文件、顶部显示文件相关信息和对*.yimi类型的文件进行解密)
void CMyDlg::OnButtonOpen()
{
CString filter;
//“依米魔法文件(*.yimi)”即文件类型选择项,“*.yimi”即要求显示的类型文件
filter = "依米魔法文件(*.yimi)|*.yimi|(*.*)|*.*||";
//第一个参数为TRUE时为“打开文件”对话框;为FALSE时为“另存为”对话框。
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, filter);
if(dlg.DoModal()!=IDOK) return;
//静态文本
CString strFileName = dlg.GetPathName();
CFileStatus status;
if(!CFile::GetStatus(strFileName, status))
{
MessageBox("该文件不存在!");
return;
}
//为顶端静态文本设置为以下格式的内容:文件路径全名[年-月-日, 字节数]
m_strTitle.Format("%s[%s, %ld字节]", strFileName,
status.m_ctime.Format("%Y-%m-%d"), status.m_size);
UpdateData(FALSE);//更新数据
//打开文件,并读取数据
m_strContent.Empty(); //清空内容
CFile theFile;
if(!theFile.Open(strFileName, CFile::modeRead))
{
MessageBox("该文件无法打开!");
return;
}
char szBuffer[];
UINT nActual = ;
while(nActual = theFile.Read(szBuffer, sizeof(szBuffer)))
{
CString str(szBuffer, nActual);
m_strContent = m_strContent + str;
}
theFile.Close();
//判断是否是.yimi文件
if(dlg.GetFileExt()=="yimi")//是.yimi文件,则解密
{//解密
char str;
for(int i = ; i < m_strContent.GetLength(); i++)
{
str = m_strContent.GetAt(i);
str = str-i;
m_strContent.SetAt(i, str);
}
UpdateData(FALSE);//更新数据
}
}
改变窗口背景色
用MFC ClassWizard向导为CMyDlg类添加WM_CTLCOLOR消息映射,并添加以下代码:
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
COLORREF color = RGB(, , );//天蓝色
m_Brush.Detach();
m_Brush.CreateSolidBrush(color);
pDC->SetBkColor(color);
// return hbr; //只编辑框有背景颜色
return (HBRUSH)m_Brush;//整个窗体的背景色
}
改变窗口形状
在ResourceView中添加Bitmap资源,ID设为IDB_BITMAP_DLG。注意,白色为将来可显示的窗体部分,其他色均为透明显示,所绘制的Bitmap图形大小应与窗体实际大小一致。
绘制如图:
然后在BOOL CMyDlg::OnInitDialog()函数的return TRUE;语句前添加如下代码:
//异形窗体
COLORREF TransColor=RGB(,,);//白色为显示的部分
CBitmap cBitmap;
cBitmap.LoadBitmap(IDB_BITMAP_DLG);//加载描述窗口形状的BMP图片
CDC* pDC=this->GetDC();
CDC memDC;
memDC.CreateCompatibleDC(pDC);//创建与传入DC兼容的临时DC
CBitmap *pOldMemBmp=NULL;
pOldMemBmp=memDC.SelectObject(&cBitmap);//将位图选入临时DC,方便对图片在控件环境中进行操作
static CRgn wndRgn;
wndRgn.CreateRectRgn(,,,);//创建总的窗体区域,初始region为0
BITMAP bit;
cBitmap.GetBitmap (&bit);//取得位图参数,这里要用到位图的长和宽
int y;
CRgn rgnTemp; //保存临时region
for(y=;y<=bit.bmHeight ;y++)
{
int iX = ;
do
{
//跳过透明色找到下一个非透明色的点.
while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) != TransColor)
iX++;
//记住这个起始点
int iLeftX = iX;
//寻找下个透明色的点
while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) == TransColor)
++iX;
//创建一个包含起点与重点间高为1像素的临时“region”
rgnTemp.CreateRectRgn(iLeftX, y, iX, y+);
//合并到主"region".
wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR);
//删除临时"region",否则下次创建时和出错
rgnTemp.DeleteObject();
}while(iX<bit.bmWidth);
}
this->SetWindowRgn(wndRgn,TRUE);
memDC.DeleteDC();
具体请参见
MFC异形窗口-多边形窗口-根据图片自定义窗口形状-CRgn
最终效果如图:
改变光标图案
在ResourceView的Cursor下绘制一个光标资源,ID默认为IDC_CURSOR1。单击“新建设备图像”按钮新建设备图像 单击“自定义”按钮设置好大小颜色后按“确定”。注意:很重要的一点,接下来要在“设备”选项中选择系统原来默认已有的“单色[32*32]”,然后选择“图像”菜单的“删除设备图像”命令。这样才能把我们自定义的光标正常使用。
接下来,为CMyDlg类添加HCURSOR类型的成员变量m_hCursor,并为CMyDlg类添加WM_SETCURSOR的消息映射函数,代码如下:
BOOL CMyDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if(nHitTest == HTCAPTION)
{
m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);
SetCursor(m_hCursor);
}else if(nHitTest == HTCLIENT)
{
m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);
SetCursor(m_hCursor);
}
return true;
}
生成动态自定义软件图标
在ResourceView的Icon下添加若干图标资源,如下:
为CMyDlg添加成员函数ChangeIcon(UINT nIconID),代码如下:
void CMyDlg::ChangeIcon(UINT nIconID)
{
HICON hIconNew = AfxGetApp()->LoadIcon(nIconID);
HICON hIconOld = (HICON)GetClassLong(m_hWnd, GCL_HICON);
if(hIconNew!=hIconOld)
{
DestroyIcon(hIconOld);
SetClassLong(m_hWnd, GCL_HICON, (long)hIconNew);
RedrawWindow();
}
}
接下来,要实现动画效果,即软件图标不断变化,需要用到计时器。
在BOOL CMyDlg::OnInitDialog()中添加计时器设置代码:
其中第一个参数指定改计时器标识值,任写一个非零数字即可;第二个参数表示调用计时器的时间间隔,此处为以500毫秒的时间为间隔更换图标,从而实现动画效果;第三个参数是一个回调函数指针,一般设为NULL即可。
接下来,为CMyDlg添加WM_TIMER的消息映射函数,代码如下:
void CMyDlg::OnTimer(UINT nIDEvent)
{
if(nIDEvent==)
{//改图标,nIDEvent即SetTimer函数的第一个参数——计时器标识值
static int icons[] = {IDI_ICON1, IDI_ICON2, IDI_ICON3, IDI_ICON4};//图标
static int index = ;
ChangeIcon(icons[index]);
index++;
if(index>) index = ;
}
CDialog::OnTimer(nIDEvent);
}
接下来,为CMyDlg添加WM_DESTROY的消息映射函数,代码如下:
void CMyDlg::OnDestroy()
{
CDialog::OnDestroy();
KillTimer();
}
OK,可以运行看结果啦~
源码及程序下载
下载源码及程序