“依米魔法郵箱”開發筆記
軟件用MFC開發而成,具體有以下功能、特色:
- 文檔加密解密
- 保存自定義後綴的文件(*.yimi)
- 打開自定義後綴的文件(*.yimi)
- 改變窗口背景色
- 改變窗口形狀
- 改變光標圖案
- 生成動態自定義軟件圖標
效果圖如下
功能實現方法
我所選的是MFC基本對話框類型的應用程序,佈局如下:
文檔加密解密
加密核心代碼:
//加密
char str;
for(int i = 0; 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 = 0; 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 = 0; 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[80];
UINT nActual = 0;
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 = 0; 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(180, 227, 239);//天藍色
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(255,255,255);//白色爲顯示的部分
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(0,0,0,0);//創建總的窗體區域,初始region爲0
BITMAP bit;
cBitmap.GetBitmap (&bit);//取得位圖參數,這裏要用到位圖的長和寬
int y;
CRgn rgnTemp; //保存臨時region
for(y=0;y<=bit.bmHeight ;y++)
{
int iX = 0;
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+1);
//合併到主"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()中添加計時器設置代碼:
SetTimer(1, 500, NULL);//改圖標
其中第一個參數指定改計時器標識值,任寫一個非零數字即可;第二個參數表示調用計時器的時間間隔,此處爲以500毫秒的時間爲間隔更換圖標,從而實現動畫效果;第三個參數是一個回調函數指針,一般設爲NULL即可。
接下來,爲CMyDlg添加WM_TIMER的消息映射函數,代碼如下:
void CMyDlg::OnTimer(UINT nIDEvent)
{
if(nIDEvent==1)
{//改圖標,nIDEvent即SetTimer函數的第一個參數——計時器標識值
static int icons[] = {IDI_ICON1, IDI_ICON2, IDI_ICON3, IDI_ICON4};//圖標
static int index = 0;
ChangeIcon(icons[index]);
index++;
if(index>3) index = 0;
}
CDialog::OnTimer(nIDEvent);
}
接下來,爲CMyDlg添加WM_DESTROY的消息映射函數,代碼如下:
void CMyDlg::OnDestroy()
{
CDialog::OnDestroy();
KillTimer(1);
}
OK,可以運行看結果啦~