VC启动窗口的制作

作者: 华南理工大学计算机系 刘正喜
下载本文示例源代码
  源代码运行效果图如下:
  

  
1. 概述
  前几天在设计软件时,选择VC作为开发工具,想做个启动画面,由于以前没有制作过,所以到网上搜了一通。网上有几篇相关文章,有两篇我觉得很有价值:一篇是关于 为方便显示图像制作的CPicture类的文章,原文是由Paul DiLascia写的解答,很有影响力;还有一篇是关于制作真彩启动画面的文章,不过其限制对位图操作,而不支持jpg, gif,而且使用繁琐,基本上是对Splash Screen组件导入后的代码进行简单修改。琢磨了好大一会儿才学会使用。
  有感于现有材料使用起来不方便,随进行了整合和再封装处理,设计了CSplashWnd类,使用起来非常简便。下面就把我设计的类介绍给大家。有什么不当或错误之处,敬请指正。我的Email: [email protected]
  
2.CSplashWnd功能
  能够显示真彩启动画面,能在画面上显示初始化文字信息,支持jpg,gif,bmp图像文件。
  
3. CSplashWnd的设计
  3.1 用户关心的接口
  用户使用的公开接口:
  public:
  CSplashWnd(LPCTSTR lpszFileName);// 指定作为启动画面的图像文件,并装载
  BOOL ShowSplash();//显示画面
  void CloseSplash();//关闭画面
  void ShowText(LPCTSTR pCh);在显示的图像上中间位置处显示初始化信息文字
  3.2 其他接口
  系统使用的公开接口:(用户不关心)~CSplashWnd()
  void PostNcDestroy();
  私有接口:(用户不关心)BOOL Create(CWnd* pParentWnd = NULL);
  int OnCreate(LPCREATESTRUCT lpCreateStruct);
  void OnPaint();
  3.3 数据设计(用户不关心)BOOL fileIsValid//指示
  CPicture pic;//用于对图像文件进行操作的类
  int width,height;
  3.4 限制
  √ 不允许继承。
  √ 为简化接口,只提供从文件装载图像
  3.5 需要的头文件
  StdAfx.h, VC++6.0自动生成的对MFC的支持,不同的工程选项会产生不同的StdAfx.h。
  afxwin.h 支持CRect类
  atlbase.h 提供对IPicture (COM类)的支持。
  afxpriv2.h提供对CArchiveStream类的支持。
  
4.类的健壮性和可调试性设计
  图像文件是否有效?
  需要检查文件是否有效,当装载图像文件失败时,fileIsValid为false,否则为true。这样在调用ShowSplash时将什么都不做,返回false。这时,用户应检查图像文件是否存在,文件名称拼写是否正确。
  

5. 用法
  √ 将CSplashWnd类加入项目中
  √ 在使用CSplashWnd类的文件中#include “Splash.h”
  √ 在合适的位置定义一个CSplashWnd对象
  √ 在想显示启动画面的地方调用ShowSplash显示于屏幕上
  √ 如果想在启动画面上显示一些初始化或其他提示信息,调用ShowText。
  √ 在你想关闭启动画面的地方
  在你的App类InitInstance函数中,显示主窗口之前使用,进行上述步骤,这是最典型的用法,如下面代码所示。
  BOOL CTsApp::InitInstance()
  {
   AfxEnableControlContainer();
  #ifdef _AFXDLL
   Enable3dControls(); // Call this when using MFC in a shared DLL
  #else
   Enable3dControlsStatic(); // Call this when linking to MFC statically
  #endif
   SetRegistryKey(_T("Local AppWizard-Generated Applications"));
   LoadStdProfileSettings(); // Load standard INI file options (including MRU)
   CSingleDocTemplate* pDocTemplate;
   pDocTemplate = new CSingleDocTemplate(
   IDR_MAINFRAME,
   RUNTIME_CLASS(CTsDoc),
   RUNTIME_CLASS(CMainFrame), // main SDI frame window
   RUNTIME_CLASS(CTsView));
   AddDocTemplate(pDocTemplate);
   CCommandLineInfo cmdInfo;
   ParseCommandLine(cmdInfo);
   if (!ProcessShellCommand(cmdInfo))
   return FALSE;
  /////////////////////////////////////////////////////////////////////////////////////
   CSplashWnd* pCsw = new CSplashWnd("fx.jpg");//located in the local directory,or else full-path file name is needed
   pCsw->ShowSplash();
   Sleep(750);//delay some time to observe the image displayed.
   pCsw->CloseSplash();
   delete pCsw;
   pCsw = NULL;
  /////////////////////////////////////////////////////////////////////////////////////
   // The one and only window has been initialized, so show and update it.
   m_pMainWnd->ShowWindow(SW_SHOW);
   m_pMainWnd->UpdateWindow();
   return TRUE;
  }
  6. 类代码
6.1 Splash.h

/////////////////////////////////////////////////////////////////////////////
// Written by Liu Zhengxi
// May 5,2003
// Compiles with Visual C++ 6.0 for Windows 98 and probably Windows 2000 
//  too.
/////////////////////////////////////////////////////////////////////////////
#ifndef _SPLASH
#define  _SPLASH
#include 
< atlbase.h >
#include 
< afxpriv2.h >

//  Splash.h : header file
//

/////////////////////////////////////////////////////////////////////////////
//    Splash Screen class
#pragma  once

///////////////////////////////////////////////////////////////////////////
//  Picture object-encapsulates IPicture
// Written by Paul DiLascia.
// used to display picture
//
//  declare CPicture class
//
class  CPicture  {
public:
    BOOL Render(CDC
* pDC,CRect rc,LPCRECT prcMFBounds=NULL) const;
   CPicture();
   
~CPicture();

   
// Load from various resources
   BOOL Load(UINT nIDRes);
   BOOL Load(LPCTSTR pszPathName);
   BOOL Load(CFile
& file);
   BOOL Load(CArchive
& ar);
   BOOL Load(IStream
* pstm);

   
// render to device context
   

   CSize GetImageSize(CDC
* pDC=NULL) const;

   
operator IPicture*() {
      
return m_spIPicture;
   }


   
void GetHIMETRICSize(OLE_XSIZE_HIMETRIC& cx, OLE_YSIZE_HIMETRIC& cy) 
      
const {
      cx 
= cy = 0;
      const_cast
<CPicture*>(this)->m_hr = m_spIPicture->get_Width(&cx);
      ASSERT(SUCCEEDED(m_hr));
      const_cast
<CPicture*>(this)->m_hr = m_spIPicture->get_Height(&cy);
      ASSERT(SUCCEEDED(m_hr));
   }


   
void Free() {
      
if (m_spIPicture) {
         m_spIPicture.Release();
      }

   }


protected:
   CComQIPtr
<IPicture>m_spIPicture;     // ATL smart pointer to IPicture
   HRESULT m_hr;                        // last error code
}
;


///////////////////////////////////////////////////////////////////
//
// declare CSplashWnd
//
class  CSplashWnd :  public  CWnd
{
// Construction
public:
    CSplashWnd(LPCTSTR lpszFileName);

// Operations
public:
    BOOL ShowSplash();
    BOOL PreTranslateAppMessage(MSG
* pMsg);   
    
void ShowText(LPCTSTR lpStr);
    
void CloseSplash();

// Overrides
    
// ClassWizard generated virtual function overrides
    
//{{AFX_VIRTUAL(CSplashWnd)
    
//}}AFX_VIRTUAL

// Implementation
public:
    
~CSplashWnd();
    
virtual void PostNcDestroy();

private:
    BOOL Create(CWnd
* pParentWnd = NULL);

// Generated message map functions
private:
    
//{{AFX_MSG(CSplashWnd)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg 
void OnPaint();
    
//}}AFX_MSG
    DECLARE_MESSAGE_MAP()
private:
    
int height;//the height of the displayed picture
    int width;//the width of the displayed picture
    CPicture pic;//used to operate the picture
   BOOL fileIsValid;
}
;

#endif

6.2 Splash.cpp

 

///////////////////////////////////////////////////////////////////////////////
// Written by Liu Zhengxi 
// May 5,2003
// Compiles with Visual C++ 6.0 for Windows 98 and probably Windows 2000 
//  too.
/////////////////////////////////////////////////////////////////////////////

//
//  Splash.cpp : implementation file
//

#include 
< atlbase.h >
#include 
< afxwin.h >
#include 
< afxpriv2.h >

#include 
" stdafx.h "    //  e. g. stdafx.h
#include  " Splash.h "    //  e.g. splash.h

#ifdef _DEBUG
#define  new DEBUG_NEW
#undef  THIS_FILE
static   char  BASED_CODE THIS_FILE[]  =  __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
//    CSplashWnd class

////////////////////////////////////////////////////////////////////////////
// constructor
// Load image from the given file
//
CSplashWnd::CSplashWnd(LPCTSTR lpszFileName)
{
    fileIsValid 
= pic.Load(lpszFileName);
    
if(fileIsValid)
    
{
        CSize cz 
= pic.GetImageSize(NULL);
        width 
= cz.cx;
        height 
= cz.cy;
    }

}



////////////////////////////////////////////////////////////////////////////////
// nothing to do
// deconstructor
//
CSplashWnd:: ~ CSplashWnd()
{
}


////////////////////////////////////////////////////////////////////////////////
// message map
//
BEGIN_MESSAGE_MAP(CSplashWnd, CWnd)
    
// {{AFX_MSG_MAP(CSplashWnd)
    ON_WM_CREATE()
    ON_WM_PAINT()
    ON_WM_TIMER()
    
// }}AFX_MSG_MAP
END_MESSAGE_MAP()


////////////////////////////////////////////////////////////////////////////////
// ShowSplash
// to display the given image on screen
//
BOOL CSplashWnd::ShowSplash()
{
    
    
if(fileIsValid)
    
{
        
if (!Create(AfxGetMainWnd()))
            
return false;
        
else
        
{
            UpdateWindow();
            
return true;
        }

    }

    
else
    
{
        
return false;
    }

}



////////////////////////////////////////////////////////////////////////////////
// PreTranslateAppMessage
//
BOOL CSplashWnd::PreTranslateAppMessage(MSG *  pMsg)
{
    
// If we get a keyboard or mouse message, hide the splash screen.
    if (pMsg->message == WM_KEYDOWN ||
        pMsg
->message == WM_SYSKEYDOWN ||
        pMsg
->message == WM_LBUTTONDOWN ||
        pMsg
->message == WM_RBUTTONDOWN ||
        pMsg
->message == WM_MBUTTONDOWN ||
        pMsg
->message == WM_NCLBUTTONDOWN ||
        pMsg
->message == WM_NCRBUTTONDOWN ||
        pMsg
->message == WM_NCMBUTTONDOWN)
    
{
        CloseSplash();
        
return TRUE;    // message handled here
    }


    
return FALSE;    // message not handled
}



////////////////////////////////////////////////////////////////////////////////
// Create
// make a popup splash window
//
BOOL CSplashWnd::Create(CWnd *  pParentWnd  /*= NULL*/ )
{

    
return CreateEx(0,
        AfxRegisterWndClass(
0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
        NULL, WS_POPUP 
| WS_VISIBLE, 00, width, height, pParentWnd->GetSafeHwnd(), NULL);
}



////////////////////////////////////////////////////////////////////////////////
// CloseSplash
// Quit the splash window
//
void  CSplashWnd::CloseSplash()
{
    
// Destroy the window, and update the mainframe.
    DestroyWindow();
}



////////////////////////////////////////////////////////////////////////////////
// do nothing
//
void  CSplashWnd::PostNcDestroy()
{

}


////////////////////////////////////////////////////////////////////////////////
// OnCreate
// put the splash window on center
//
int  CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    
if (CWnd::OnCreate(lpCreateStruct) == -1)
        
return -1;

    
// Center the window.
    CenterWindow();

    
return 0;
}


////////////////////////////////////////////////////////////////////////////////
// OnPaint
// Display the given image
//
void  CSplashWnd::OnPaint()
{
    
if(fileIsValid)
    
{
        CPaintDC dc(
this);
        CRect rc(
0,0,0,0);;
        pic.Render(
&dc, rc);
    }

}



////////////////////////////////////////////////////////////////////////////////
// ShowText
// sometimes if we show what we are doing (I display the information on the center of  // the picture ), the customer will be more patient
//
//
void  CSplashWnd::ShowText(LPCTSTR lpStr)
{
    
if(fileIsValid)
    
{
        Invalidate();
        CPaintDC dc(
this);
        dc.SetBkMode(TRANSPARENT);
        SIZE sz;
        sz 
= (SIZE)dc.GetTextExtent(lpStr,strlen(lpStr));
        dc.TextOut((width
-sz.cx)/2,height/2,lpStr);
    }

}


////////////////////////////////////////////////////////////////
//  MSDN Magazine - October 2001
//  If this code works, it was written by Paul DiLascia.
//  If not, I don't know who wrote it.
//  Compiles with Visual C++ 6.0 for Windows 98 and probably Windows 2000 
//  too.
//  Set tabsize = 3 in your editor.
//

////////////////////////////////////////////////////////////////
//  CPicture implementation
//

CPicture::CPicture()
{
}


CPicture::
~ CPicture()
{
}


//////////////////
//  Load from resource. Looks for "IMAGE" type.
//
BOOL CPicture::Load(UINT nIDRes)
{
   
// find resource in resource file
   HINSTANCE hInst = AfxGetResourceHandle();
   HRSRC hRsrc 
= ::FindResource(hInst,
      MAKEINTRESOURCE(nIDRes),
      
"IMAGE"); // type
   if (!hRsrc)
      
return FALSE;

   
// load resource into memory
   DWORD len = SizeofResource(hInst, hRsrc);
   BYTE
* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
   
if (!lpRsrc)
      
return FALSE;

   
// create memory file and load it
   CMemFile file(lpRsrc, len);
   BOOL bRet 
= Load(file);
   FreeResource(hRsrc);
   
return bRet;
}


//////////////////
//  Load from path name.
//
BOOL CPicture::Load(LPCTSTR pszPathName)
{
   CFile file;
   
if (!file.Open(pszPathName, CFile::modeRead|CFile::shareDenyWrite))
      
return FALSE;
   BOOL bRet 
= Load(file);
   file.Close();
   
return bRet;
}


//////////////////
//  Load from CFile
//
BOOL CPicture::Load(CFile &  file)
{
   CArchive ar(
&file, CArchive::load | CArchive::bNoFlushOnDelete);
   
return Load(ar);
}


//////////////////
//  Load from archive-create stream and load from stream.
//
BOOL CPicture::Load(CArchive &  ar)
{
   CArchiveStream arcstream(
&ar);
   
return Load((IStream*)&arcstream);
}


//////////////////
//  Load from stream (IStream). This is the one that really does it: call
//  OleLoadPicture to do the work.
//
BOOL CPicture::Load(IStream *  pstm)
{
   Free();
   HRESULT hr 
= OleLoadPicture(pstm, 0, FALSE,
      IID_IPicture, (
void**)&m_spIPicture);
   ASSERT(SUCCEEDED(hr) 
&& m_spIPicture); 
   
return TRUE;
}



//////////////////
//  Get image size in pixels. Converts from HIMETRIC to device coords.
//
CSize CPicture::GetImageSize(CDC *  pDC)  const
{
   
if (!m_spIPicture)
      
return CSize(0,0);
   
   LONG hmWidth, hmHeight; 
// HIMETRIC units
   m_spIPicture->get_Width(&hmWidth);
   m_spIPicture
->get_Height(&hmHeight);
   CSize sz(hmWidth,hmHeight);
   
if (pDC==NULL) {
      CWindowDC dc(NULL);
      dc.HIMETRICtoDP(
&sz); // convert to pixels
   }
 else {
      pDC
->HIMETRICtoDP(&sz);
   }

   
return sz;
}


//////////////////
//  Render to device context. Covert to HIMETRIC for IPicture.
//
BOOL CPicture::Render(CDC *  pDC, CRect rc, LPCRECT prcMFBounds)  const
{
   ASSERT(pDC);

   
if (rc.IsRectNull()) {
      CSize sz 
= GetImageSize(pDC);
      rc.right 
= sz.cx;
      rc.bottom 
= sz.cy;
   }

   
long hmWidth,hmHeight; // HIMETRIC units
   GetHIMETRICSize(hmWidth, hmHeight);
   m_spIPicture
->Render(*pDC, rc.left, rc.top, rc.Width(), rc.Height(),
      
0, hmHeight, hmWidth, -hmHeight, prcMFBounds);

   
return TRUE;
}

参考连接:

jpg/gif图像显示文章(英文)
真彩启动画面的制作(中文)

你可能感兴趣的:(VC启动窗口的制作)