当前位置:C++技术网 > 资讯 > 学习心得之七---程序启动画面的设计

学习心得之七---程序启动画面的设计

更新时间:2015-09-15 14:11:49浏览次数:1+次

                                                        学习心得之七---程序启动画面的设计

    我们基于对话框创建工程项目,命名为RunForm,然后,我们为工程添加一个对话框类,我们先在资源视图类上,增加一个对话框,双击该对话框,我们为它关联一个类,名字叫CRunMode,然后在头文件中添加为这个类添加两个成员变量,并在构造函数中实例化。
    

COLORREF m_BkColor;//背景颜色
CRgn m_Rgn;//区域变量

CRgn:封装Windows图形设备接口(GDI)区域

CRunMode::CRunMode(CWnd* pParent /*=NULL*/)
 : CDialog(CRunMode::IDD, pParent)
{
 //{{AFX_DATA_INIT(CRunMode)
  // NOTE: the ClassWizard will add member initialization here
 //}}AFX_DATA_INIT
 m_BkColor=RGB(0,0,255);//我喜欢蓝色,初始化就设为蓝色了
}


接下来我们设置字体,画笔,启动区域,设备上下文等,我们为CRunForm类,添加WM_InitDialog消息,

BOOL CRunMode::OnInitDialog() 
{
 CDialog::OnInitDialog();
 
 // TODO: Add extra initialization here
 SetTimer(1,1000,NULL);
 CFont font;
 font.CreateFont(50, 30, 0, 0, FW_HEAVY, TRUE, FALSE, 
  0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, 
  CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, 
  DEFAULT_PITCH | FF_SWISS, "宋体"); 
 CDC *pDC = GetDC();
 CPen pen(PS_SOLID, 2, RGB(255, 0, 0));
 pDC->SelectObject(&pen);      //选中画笔
 pDC->BeginPath();        //开始一个路径
 pDC->SetBkMode(OPAQUE );
 CFont *pOldFont = pDC->SelectObject(&font);   //选中创建的字体
 pDC->TextOut(10, 30, "C++技术网");    //输出文本
 pDC->EndPath();        //关闭路径
 pen.DeleteObject();
 font.DeleteObject();
 pDC->SelectObject(pOldFont);
 m_Rgn.CreateFromPath(pDC);
 SetWindowRgn(m_Rgn,TRUE);
 return TRUE;  // return TRUE unless you set the focus to a control
               // EXCEPTION: OCX Property Pages should return FALSE
}

我们为启动画面设置一个定时器,使得它每秒字体颜色变化一次,接着我们创建字体,调用函数CreateFont(...)

 

BOOL CreateFont(
   int nHeight,
   int nWidth,
   int nEscapement,
   int nOrientation,
   int nWeight,
   BYTE bItalic,
   BYTE bUnderline,
   BYTE cStrikeOut,
   BYTE nCharSet,
   BYTE nOutPrecision,
   BYTE nClipPrecision,
   BYTE nQuality,
   BYTE nPitchAndFamily,
   LPCTSTR lpszFacename 
);

 

对于参数,我就不一一讲解了,我们可以查MSDN,(给网站在线查MSDN链接),然后我们创建设备上下文描述表DC,当我们需要字体,画刷,画笔,实现对窗口显示区域的GDI操作,如划线、写文本、绘制位图、填充等,就构造DC,接下来们创建画笔,并将他选入设备描述表,当然最后我们要将设备对象删除。为了使用某种GDI对象,一般来说,需要构造新的GDI对象,然后将这个新的GDI对象选入一个设备描述表进行绘制,将设备描述表中原来的GDI对象保留。当绘制工作结束时,在退出应用程序前将旧的GDI对象在选回设备描述表,将先前的GDI对象删除。我们继续为字体启动程序设计背景模式,调用函数SetBkMode():

int SetBkMode(
   int nBkMode 
);
nBkMode:指定将架构集。 此参数可以是下列值之一:
OPAQUE :背景用该文本,已阴影的画笔之前的当前背景色,或者绘制钢笔。 这是默认背景模式。TRANSPARENT: 背景不在绘制图像之前已更改。

 

简单说就是,第一个参数使得区域里的字体透明,而非字体的部分,就用颜色填充,第二个,就相反咯。

下一句就是我们把我们创建的字体选入设备描述表,并将其返回给一个字体对象,以便最后重新将字体选回给描述表,这个是好习惯,我们创建字体,画笔,画刷等,在最后的时候最好将它选回描述表,万事具备了,我们已经用笔画好了,字的字体也选好了,现在就是写字咯。

 

m_Rgn.CreateFromPath(pDC);创建从中选择到特定设备上下文的路径的区域。简单点就是说,根据传入这个函数的参数,我们为它建立一个区域。

 

SetWindowRgn(m_Rgn,TRUE);
int SetWindowRgn(
   HRGN hRgn,
   BOOL bRedraw 
);

hRgn
对区域的句柄。

bRedraw
如果 TRUE,操作系统在设置该区域后重绘windows;否则,它不。 通常,因此,如果窗口可见,设置 bRedraw 到 TRUE。 如果设置为 TRUE,该系统发送 WM_WINDOWPOSCHANGING 和 WM_WINDOWPOSCHANGED 信息到窗口。

 

接下来我们设置定时器消息:

 

void CRunMode::OnTimer(UINT nIDEvent) 
{
 // TODO: Add your message handler code here and/or call default
 int nRed=rand()%255;
 int nGreen=rand()%255;
 int nBlue=rand()%255;
 Invalidate();//核心语句
 m_BkColor=RGB(nRed,nGreen,nBlue);

 CDialog::OnTimer(nIDEvent);
}    

 

rand(),使得我们随机的更改字体区域的颜色。我们看看核心语句,没有这句代码,我们的启动画面不会变换多种颜色。

 

void Invalidate(
   BOOL bErase = TRUE 
);

 

无效 CWnd整个工作区。bErase 参数指定是将清除在更新区域内的背景,当更新区域过程。 如果 bErase 是 TRUE,清除后台,当 BeginPaint 成员函数调用时;如果 bErase 是 FALSE,背景不变。 如果 bErase 是更新区域的任何部分的TRUE,在整个区域,而不仅仅用于在给定节中,清除背景。

 

void CRunMode::OnPaint() 
{
 CPaintDC dc(this); // device context for painting
 
 // TODO: Add your message handler code here
 
 CRect clientRC;
 GetClientRect(clientRC);
 dc.FillRect(clientRC,&CBrush(m_BkColor));
 // Do not call CDialog::OnPaint() for painting messages
}
void FillRect(
   LPCRECT lpRect,
   CBrush* pBrush 
);

 

查MSDN,我们看到CBrush()有四个重载函数,而其中恰好有参数是COLORREF类的重载函数,因此,我们可以为FillRect()的第二个参数传入那样的参数。我们现在做完了吗?程序代码都不缺了,该有的都有了,来,我们看看!我们直接运行试试,我们会发现压根没有出现启动画面!只是一个对话框,而且还不是我们自己新增的对话框,而是我们基于对话框创建的工程中的那个对话框,为什么?我们相信,当我们运行VC时,应用程序首先进去的是哪里?没错就是我们的CApp,因此,我们需要在这个类中写点代码,在哪写呢?那就是我们的InitInstance(),这个函数负责进行特定的应用程序的初始化我们来看看它的代码:

 

BOOL CRunFormApp::InitInstance()
{
 AfxEnableControlContainer();

 // Standard initialization
 // If you are not using these features and wish to reduce the size
 //  of your final executable, you should remove from the following
 //  the specific initialization routines you do not need.

#ifdef _AFXDLL
 Enable3dControls();   // Call this when using MFC in a shared DLL
#else
 Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

 CRunFormDlg dlg;/*这里*/
 m_pMainWnd = &dlg;
 int nResponse = dlg.DoModal();//看这里
 if (nResponse == IDOK)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with OK
 }
 else if (nResponse == IDCANCEL)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with Cancel
 }*/

 // Since the dialog has been closed, return FALSE so that we exit the
 //  application, rather than start the application's message pump.
 return FALSE;

 
// GetClientRect(clientRC);

}


我们看我所做的标记那,发现有一个DoModal()函数,我们知道他就是创建一个模态对话框的,再往前看,我们发现它是CRunFormDlg类的,因此,当我们运行时,出现的那个对话框就是我们这里创建的对话框,就是我们的工程所基于的那个对话框,那么,我们想要运行我们自己添加的那个对话框,也就是只要添加相似的代码就行了,但是你得注意位置哦!们应该放在我所标注的“这里”的前面,要不然还是没用。我们看看需要加的代码:

 

CRunMode runmode;
 runmode.DoModal();

 

本来想加几张运行图片的,但不知怎么老出错,我这就不上传了,你自己可以试试运行结果。

我们应该学得更多,因此下个程序就是实现图片启动画面哦,更深入的理解,学习界面启动画面的知识。