“依米魔法郵箱”開發筆記
軟體用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,可以運作看結果啦~
源碼及程式下載下傳
下載下傳源碼及程式