| 
				 一、前言 
许多应用软件在刚启动时,经常会显示“每天提示”(“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(); 
} 
四、结语 
    通过“每日提示”对话框的设计,从某种程度上讲,可以增强应用软件的成熟性,虽然只是一个微小的细节,有时候可以达到事半功倍的效果。 			
				 |