当前位置:   article > 正文

VC2010工程中加入SplashScreen及原理释解_enablesplashscreen

enablesplashscreen

一、VC2010中使用CSplashWnd类

由于VC2010中不能插入组件,只有手动添加CSplashWnd类,该类的代码可以由以前VC6.0的代码复制过来。添加该类后,以SDI或者MDI为例,使用CSplashWnd类的具体方法如下:

 (1)在CWinApp::InitInstance()中调用CSplashWnd::EnableSplashScreen()设置c_bShowSplashWnd;

代码如下:

  1. BOOL CDrawApp::InitInstance()
  2. {
  3. //用来处理是否显示SplashScreen
  4. {
  5. CCommandLineInfo cmdinfo;
  6. ProcessShellCommand(cmdinfo);
  7. CSplashWnd::EnableSplashScreen(cmdinfo.m_bShowSplash);
  8. }
  9. ………..
  10. }

(2)在PreTranslateMessage()中调用CSplashWnd::PreTranslateAppMessage(),将键盘和鼠标消息传递给CSplashWnd对象

代码如下:

//该函数为虚函数,需要重写

  1. BOOL CDrawApp::PreTranslateMessage(MSG* pMsg)
  2. {
  3. if (CSplashWnd::PreTranslateAppMessage(pMsg))
  4. return TRUE;
  5. return CWinAppEx::PreTranslateMessage(pMsg);
  6. }

(3)在CMainFrame对象的OnCreate()中调用CSplashWnd::ShowSplashScreen()创建一个静态的SplashScreen窗口对象c_pSplashWnd,并设置其父窗口为CMainFrame.

代码如下:

  1. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2. {
  3. if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
  4. return -1;
  5. ………..
  6. CSplashWnd::ShowSplashScreen(this);//创建一个静态的SplashScreen窗口对象
  7. return 0;
  8. }

需要注意的是,在上述过程中不会出现什么错误,但编译时会提示:IDB_SPLASH没有定义。这需要在资源中加入一个位图资源,并将其ID改为IDB_SPLASH,同时也要将”resource.h” 头文件包含到CSlashWnd.cpp文件中。插入的这个位图资源就是我们的启动画面。

上述方法转自文章:《VC++2010工程中加入SplashScreen》http://www.cnblogs.com/luoshupeng/archive/2011/09/16/2178449.html

示例代码:http://download.csdn.net/detail/luoshupeng/3606489

二、VC++工程中加入 SplashScreen 的原理

摘要

本文旨在剖析VC++工程中加入 SplashScreen 的原理,并给出在VC++ MFC(exe)工程中加入 SplashScreen 的步骤。

关键字:SplashScreen,原理

环境:Windows 98SE/2000,VC++ 6.0

SplashScreen - 我们使用 Word 之类的软件在启动的短暂时间里就会看到它的身影。它通常用以在程序启动时显示程序及用户名称,版权信息等。我也不知道它准确的名称是什么(是闪屏吗?),就这样称呼吧。也许你也想在自己的工程里加入这样的特性,本文将以创建实际工程的方式逐步剖析其实现原理。

注意:为避免实际所使用工程名给类或对象名带来的干扰,除非特别说明,在本文中将使用基类名如CWinApp、CMainFrame、CDialog来代替实际工程中的相应派生类名进行描述。

    Visual C++是一个相当强大的C++开发工具,它内嵌了对SplashScreen的支持。但是在MFC EXE类型工程中只是对带有主框架类的SDI或MDI工程提供了这一支持,基于对话框类的工程则被排除在外。现在让我们开始吧。第一步是在SDI工程中加入SplashScreen。

首先利用AppWizard生成一个SDI工程,除了其中Docking ToolBar必须选择外(我认为这是MFC的一个Bug,当然这与本文讨论的SplashScreen没有关系),其他的文档-视图支持、状态条之类的都可以不要,这样可以尽量减少无用的代码。

通过IDE中的菜单Project->Add to Project->Components and Controls,我们就可以从Visual C++ Components中选择Splash Screen这个组件插入工程。

 

在点击了"Insert"后会弹出一个如下图所示的对话框,这是设置插入该工程中的SplashScreen的类名、显示用位图的ID及文件名,采用缺省值即可。

通过以上几步的操作,就会在工程目录下生成Splash.CPP和Splash.H文件,这便是CSplashWnd类的实现文件与头文件。同时工程中CWinApp与CMainFrame类中的部分代码也会被修改,以实现CSplashWnd窗口的消息处理。

接着我们来看看 CSplashWnd 类的声明与主要的代码(已经过删减):

//类的声明

  1. class CSplashWnd : public CWnd
  2. {
  3.   CSplashWnd();
  4.   ~CSplashWnd();
  5.   virtual void PostNcDestroy();
  6.   static void EnableSplashScreen(BOOL bEnable = TRUE);
  7.   static void ShowSplashScreen(CWnd* pParentWnd = NULL);
  8.   static BOOL PreTranslateAppMessage(MSG* pMsg);
  9.   BOOL Create(CWnd* pParentWnd = NULL);
  10.   void HideSplashScreen();
  11.   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  12.   afx_msg void OnPaint();
  13.   afx_msg void OnTimer(UINT nIDEvent);
  14.   CBitmap m_bitmap;   //SplashScreen窗口显示用的位图对象
  15.   static BOOL c_bShowSplashWnd; //是否要显示SplashScreen的标志量
  16.   static CSplashWnd* c_pSplashWnd;
  17. };

 //是否使用SplashScreen

  1. void CSplashWnd::EnableSplashScreen(BOOL bEnable)
  2. {
  3.   c_bShowSplashWnd = bEnable;
  4. }

//创建CsplashWnd对象,并调用Create()创建窗口

  1. void CSplashWnd::ShowSplashScreen(CWnd* pParentWnd)
  2. {
  3.   //如果不要显示SplashScreen或SplashWnd对象已经被创建则返回
  4.   if (!c_bShowSplashWnd || c_pSplashWnd != NULL)
  5.     return;
  6.   c_pSplashWnd = new CSplashWnd;
  7.   if (!c_pSplashWnd->Create(pParentWnd))
  8.     delete c_pSplashWnd;
  9.   else
  10.     c_pSplashWnd->UpdateWindow();
  11. }

//装入SplashScreen欲显示位图,通过CreateEx()激发OnCreate()完成窗口创建与设置

  1. BOOL CSplashWnd::Create(CWnd* pParentWnd)
  2. {
  3.   if (!m_bitmap.LoadBitmap(IDB_SPLASH))
  4.     return FALSE;
  5.   BITMAP bm;
  6.   m_bitmap.GetBitmap(&bm);
  7.   return CreateEx(0,
  8.       AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
  9.       NULL,
  10.       WS_POPUP | WS_VISIBLE,
  11.       0,
  12.       0,
  13.       bm.bmWidth,
  14.       bm.bmHeight,
  15.       pParentWnd->GetSafeHwnd(),
  16.       NULL);
  17. }

//销毁窗口,刷新框架

  1. void CSplashWnd::HideSplashScreen()
  2. {
  3.   DestroyWindow();
  4.   AfxGetMainWnd()->UpdateWindow();
  5. }

//利用窗口创建结构创建窗口,并设置定时器在750ms后触发OnTimer()

  1. int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2. {
  3.   if (CWnd::OnCreate(lpCreateStruct) == -1)
  4.     return -1;
  5.   CenterWindow(); //窗口居中显示
  6.   SetTimer(1, 750, NULL); //设置定时器
  7.   return 0;
  8. }

//将键盘和鼠标消息传递给CSplashWnd对象,以销毁窗口

  1. BOOL CSplashWnd::PreTranslateAppMessage(MSG* pMsg)
  2. {
  3.   if (c_pSplashWnd == NULL)
  4.     return FALSE;
  5.   if (pMsg->message == WM_KEYDOWN ||
  6.     pMsg->message == WM_SYSKEYDOWN ||
  7.     pMsg->message == WM_LBUTTONDOWN ||
  8.     pMsg->message == WM_RBUTTONDOWN ||
  9.     pMsg->message == WM_MBUTTONDOWN ||
  10.     pMsg->message == WM_NCLBUTTONDOWN ||
  11.     pMsg->message == WM_NCRBUTTONDOWN ||
  12.     pMsg->message == WM_NCMBUTTONDOWN)
  13.     {
  14.       c_pSplashWnd->HideSplashScreen();
  15.       return TRUE;
  16.     }
  17.   return FALSE;
  18. }
  19. void CSplashWnd::OnTimer(UINT nIDEvent)
  20. {
  21.   HideSplashScreen();
  22. }

再看看CWinApp和CMainFrame类中发生了什么样的改变:

(1)在CWinApp::InitInstance()中调用CSplashWnd::EnableSplashScreen()设置c_bShowSplashWnd;

在PreTranslateMessage()中调用CSplashWnd::PreTranslateAppMessage(),将键盘和鼠标消息传递给CSplashWnd对象,从而进一步调用CSplashWnd::HideSplashScreen()实现SplashScreen窗口的自身销毁。

(2)在CMainFrame对象的OnCreate()中调用CSplashWnd::ShowSplashScreen()创建一个静态的SplashScreen窗口对象c_pSplashWnd,并设置其父窗口为CMainFrame。在这个过程中,CSplashWnd自身会通过创建来设置一个定时器,然后定时器在第一个周期触发时便调用HideSplashScreen()销毁自己。

(3) 而CMainFrame对象的窗口创建消息则是由CWinApp对象在InitInstance()中通过

m_pMainWnd->ShowWindow()调用触发的。

整个过程可以用下图表示,基本原理就是由CMainFrame来创建CSplashWnd,然后由CSplashWnd自己的定时器触发定时消息来销毁窗口。所以 CSplashWnd 的加入与SDI还是MDI都没有关系。

第二步,我们再来看看如何在基于对话框的工程中加入 SplashScreen。

通过对以上SDI工程中加入SplashScreen原理的剖析,我想大家也想到如何在基于对话框的工程中加入这一特性了。其实质就是由CDialog类完成SDI工程中CMainFrame类的工作,实现步骤如下:

(1)利用ClassWizard为CMyDialog添加WM_CREATE消息的处理函数OnCreate();(这里使用CMyDialog是为了与函数内的基类名CDialog区别。)

  1. int CMyDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2. {
  3.   if (CDialog::OnCreate(lpCreateStruct) == -1)
  4.     return -1;
  5.   CSplashWnd::ShowSplashScreen(this);
  6.   return 0;
  7. }

(2)利用ClassWizard为CWinApp添加消息转发处理函数PreTranslateMessage();

  1. BOOL CWinApp::PreTranslateMessage(MSG* pMsg)
  2. {
  3.   if (CSplashWnd::PreTranslateAppMessage(pMsg))
  4.     return TRUE;
  5.   return CWinApp::PreTranslateMessage(pMsg);
  6. }

(3)CWinApp::InitInstance()中加入如下调用: CSplashWnd::EnableSplashScreen(TRUE);

(4)当然你还需要将上一个SDI工程中生成的Splash.CPP与Splash.H文件拷贝到当前工程目录下,并利用Project->Add to Project->Files将这两个文件引入工程。同时还要在CWinApp与CMainFrame的实现文件中#include "Splash.H"。

(5)然后在资源管理器里添加一个ID为IDB_SPLASH的位图。由于VC++的IDE只能显示256色以下的位图,所以如果你想显示一幅真彩色的位图,就请用Import方式导入一幅预先制作好的位图。当然VC++会提示位图已经成功导入,只是无法在IDE的位图编辑器中显示,而在程序运行时就会显示了。如果你想象Word那样显示用户名等信息,可以在CSplashWnd::Create()中装载位图之后增加自己的代码来修改位图。

通过以上这几步操作,我们就完成了在基于对话框的工程中加入SplashScreen的工作。

上述文章转自:http://www.bianceng.cn/Programming/vc/201005/17004.htm

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/825280
推荐阅读
相关标签
  

闽ICP备14008679号