一、前言
许多应用软件在刚启动时,经常会显示“每天提示”(“Tip of the day”)对话框。在对话框中显示与应用程序使用有关的一些小知识提示,而且每天都会显示一条新的小知识。这些“每日提示”对话框的界面基本上是统一的。
二、设计思路
虽然我们对软件启动时的每日提示并不关注,或是感觉比较厌烦,第一时间就是想着要关闭它,但对于编程爱好者来说,美化界面也是软件设计重要的一个方面。因此,有些环节是必不可少的。比如,“每日提示”对话框的制作,可以提供很多额外的软件帮助。下面介绍一下“每日提示”对话框的设计思路:用MFC AppWizard创建一单文档应用工程,如Tip;建立Tip对话框,并用ClassWizard作类的映射;制作一个每日提示菜单,加载其对话框,目的是当启动时,该提示对话框被关闭,可以通过菜单再次打开;在TipApp文件中的InitInstance()函数中加载提示对话框,此处就是程序启动时,自动显示“每日提示”对话框。
下面着重介绍一下Tip对话框中内容的设计。
在Tip对话框中,需要的控件如下表所示。
表 Tip对话框控件说明表
控件名 |
类型 |
主要功能 |
IDB_LIGHTBULB |
Bitmap |
提示对话框中的提示图片 |
IDC_STATIC |
Picture |
把type设置为frame,用来装其他控件 |
IDC_BULB |
Picture |
用来存放提示图片 |
IDC_TIPSTRING |
Edit |
用来显示提示信息 |
IDC_STARTUP |
CheckBox |
判断是否启动加载提示对话框 |
IDOK |
Button |
点击时显示下一条提示信息 |
IDCANCEL |
Button |
关闭对话框 |
在Tip对话框中是如何控制提示信息的显示的呢?下面看一下设计流程图,如下图所示。
图 软件设计流程
通过以上流程,实现了“每日提示”对话框的制作。下面介绍详细的实现过程。
三、实现过程
启动时加载提示对话框:该程序代码应该写在加再载文档主界面以后,即m_pMainWnd->UpdateWindow()之后,代码如下。
CCommandLineInfo cmdInfo;
CWinApp *pInfApp = AfxGetApp();
pInfApp->ParseCommandLine(cmdInfo);//调用系统的类来显示对话框界面
if (cmdInfo.m_bShowSplash)
{
CTipDlg dlg;
if (dlg.m_bStartup)
dlg.DoModal();
}
Tip对话框的设计:主要实现消息的显示,并能从前到后一条条显示,当到最后一条记录时,又回到文件的头部,重新开始显示。首先介绍程序变量的初始化和头文件信息。
#include <winreg.h>
#include <sys\stat.h>
#include <sys\types.h>
#define MAX_BUFLEN 1000//记录长度的定义
//初始化变量
TCHAR szTip[] = _T("Tip");
TCHAR szTipIntFilePos[] = _T("FilePos");
TCHAR szTipTimeStamp[] = _T("TimeStamp");
TCHAR szTipIntStartup[] = _T("StartUp");
(1)定位到构造函数CTipDlg::CTipDlg
CWinApp* pApp = AfxGetApp();
m_bStartup = !pApp->GetProfileInt(szTip, szTipIntStartup, 0);
UINT iFilePos = pApp->GetProfileInt(szTip, szTipIntFilePos, 0);
m_didYouKonwStr ="知道 TIP 吗?";
lpTipOfTheDayFileName = "c:\\TipLoc.txt";//文件存放的路径
m_pStream = fopen(lpTipOfTheDayFileName, "r");//读取文件
if (m_pStream == NULL)
{
MessageBox("文件没有找到!");
return;
}
//读取文件中的内容
struct _stat buf;
_fstat(_fileno(m_pStream), &buf);
CString strCurrentTime = ctime(&buf.st_ctime);
strCurrentTime.TrimRight();
CString strStoredTime =
pApp->GetProfileString(szTip, szTipTimeStamp, NULL);
if (strCurrentTime != strStoredTime)
{
iFilePos = 0;
pApp->WriteProfileString(szTip, szTipTimeStamp, strCurrentTime);
}
if (fseek(m_pStream, iFilePos, SEEK_SET) == 0)
{
GetNextTipString(m_strTip);
makeMultiLine(m_strTip);
}
(2)初始化对话框OnInitDialog()
if (m_pStream == NULL)
GetDlgItem(IDOK)->EnableWindow(FALSE);
CButton *pButton;
pButton = (CButton*)GetDlgItem(IDC_STARTUP);
pButton->SetCheck(m_bStartup);//设置选择按钮
(3)初始化界面OnPaint()
CWnd* pStatic = GetDlgItem(IDC_BULB);
CRect rect;
pStatic->GetWindowRect(&rect);
ScreenToClient(&rect);
CBrush brush;
brush.CreateStockObject(WHITE_BRUSH);
dc.FillRect(rect, &brush);
CBitmap bmp;
bmp.LoadBitmap(IDB_LIGHTBULB);//加载提示图片
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);
CDC dcTmp;
dcTmp.CreateCompatibleDC(&dc);
dcTmp.SelectObject(&bmp);
rect.bottom = bmpInfo.bmHeight + rect.top;
dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&dcTmp, 0, 0, SRCCOPY);
CString strMessage;
strMessage = m_didYouKonwStr;
rect.left += bmpInfo.bmWidth;
dc.DrawText(strMessage, rect, DT_VCENTER | DT_SINGLELINE);//加载提示题目
(4)信息的分条显示
void CTipDlg::OnOK()
{
GetNextTipString(m_strTip);
makeMultiLine(m_strTip);
UpdateData(FALSE);
}
void CTipDlg::makeMultiLine(CString& m_strTip)
{
char eol[3] = {13, 10};
CString multiLineStr, srcStr, extStr, tmpStr;
multiLineStr = _T("");
srcStr = m_strTip;
int idx;
while(!srcStr.IsEmpty()) {
idx = srcStr.Find("\\n");//以\n问判断标记
if(idx != -1) {
extStr = srcStr.Left(idx);
tmpStr.Format("%s%s", extStr, eol);
multiLineStr += tmpStr;
srcStr = srcStr.Mid(idx + 2);
} else {
multiLineStr += srcStr;
break;
}
}
idx = multiLineStr.ReverseFind('\n'); // end of the ONE tip
if(idx != -1) {
multiLineStr = multiLineStr.Left(idx);
tmpStr.Format("%s%s", multiLineStr, eol);
multiLineStr = tmpStr;
}
m_strTip = multiLineStr;
}
void CTipDlg::GetNextTipString(CString &strNext)
{
LPTSTR lpsz = strNext.GetBuffer(MAX_BUFLEN);
BOOL bStop = FALSE;
while (!bStop)
{//判断是否为空,或是超过字段最大范围,或是遇到特殊字符
if (_fgetts(lpsz, MAX_BUFLEN, m_pStream) == NULL)
{
if (fseek(m_pStream, 0, SEEK_SET) != 0)
MessageBox("不能读 '每日提示' 文件");
}
else
{
if (*lpsz != ' ' && *lpsz != '\t' &&
*lpsz != '\n' && *lpsz != ';')
{
bStop = TRUE;
}
}
}
strNext.ReleaseBuffer();
}
四、结语
通过“每日提示”对话框的设计,从某种程度上讲,可以增强应用软件的成熟性,虽然只是一个微小的细节,有时候可以达到事半功倍的效果。
|