標籤:
作者資訊:羅樹鵬 http://www.cnblogs.com/luoshupeng
由於筆者在實踐過程中走了一些彎路,所以把這些情況記錄下來,希望為後來者提供一些經驗。
在VC6.0時代,可以通過組件為工程加入SplashScreen,具體方法是通過IDE中的菜單Project->Add to Project->Componentsand Controls,就可以從Visual C++ Components中選擇Splash Screen這個組件插入工程。
但進入到VC. NET時代,這種方法就不行了,需要程式作者自己加入SplashScreen類,自己處理一些系統訊息。下面筆者就把實踐過程記錄下來,並指出需要注意的地方。
一、 建立一個SplashScreen類,並聲明成員和方法
建立基類為CWnd的CSplashWnd類(當然類名可以自由書寫),並聲明如下成員:
CBitmap m_bitmap; //載入SplashScreen圖片用
static CSplashWnd*c_pSplashWnd; //CSplashWnd類的控制代碼,可以用來判定CSplashWnd是否已經建立或消毀
static BOOLc_bShowSplashWnd; //標識是否顯示顯示用來,靜態成員需要在類外進行初始化
類成員一般聲明為保護類型(protected)。接下來聲明幾個靜態方法來處理這些成員:
static BOOLc_bShowSplashWnd; //標識是否顯示顯示用來,靜態成員需要在類外進行初始化
static void ShowSplashScreen(CWnd* pParentWnd = NULL); //用來顯示SplashScreen視窗
static BOOLPreTranslateAppMessage(MSG* pMsg); //用來處理一些訊息 注意這裡不是繼承於CWnd類的PreTranslateMessage方法
這些方法一定要聲明成公開類型的(public),因為要在外部調用這些方法。接下來再聲明兩個自訂方法:
BOOL Create(CWnd*pParentWnd = NULL); //建立視窗
void HideSplashScreen(void); //隱藏視窗
我把這些方法聲明為保護類型(protected)。接下來再聲明一些處理系統訊息的函數:
virtual void PostNcDestroy();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnPaint();
至此,類已經設計完畢。完整的標頭檔如下:
#pragma once
#include "afxwin.h"
//CSplashWnd
class CSplashWnd : public CWnd
{
DECLARE_DYNAMIC(CSplashWnd)
protected:
CSplashWnd();
public:
virtual~CSplashWnd();
protected:
CBitmap m_bitmap; //載入SplashScreen圖片用
staticCSplashWnd* c_pSplashWnd; //CSplashWnd類的控制代碼,可以用來判定CSplashWnd是否已經建立或消毀
staticBOOL c_bShowSplashWnd; //標識是否顯示顯示用來,靜態成員需要在類外進行初始化
public:
static void EnableSplashScreen(BOOL bEnable = TRUE); //用來設定c_bShowSplashWnd
static void ShowSplashScreen(CWnd* pParentWnd = NULL); //用來顯示SplashScreen視窗
staticBOOL PreTranslateAppMessage(MSG* pMsg); //用來處理一些訊息 注意這裡不是繼承於CWnd類的PreTranslateMessage方法
protected:
virtualvoid PostNcDestroy();
afx_msg intOnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg voidOnTimer(UINT_PTR nIDEvent);
afx_msg voidOnPaint();
BOOL Create(CWnd* pParentWnd = NULL); //建立視窗
voidHideSplashScreen(void); //隱藏視窗
DECLARE_MESSAGE_MAP()
};
二、 CSplashWnd類方法的實現
這裡需要注意的事項是在解構函式中一定要把c_pSplashWnd成員置為NULL類型,否則程式收到訊息後會出現異常。其它沒有什麼了,直接看代碼吧。
//Splash.cpp : implementation file
//
#include "stdafx.h"
#include "Splash.h"
CSplashWnd*CSplashWnd::c_pSplashWnd;
BOOLCSplashWnd::c_bShowSplashWnd;
//CSplashWnd
IMPLEMENT_DYNAMIC(CSplashWnd,CWnd)
CSplashWnd::CSplashWnd()
{
}
CSplashWnd::~CSplashWnd()
{
ASSERT(c_pSplashWnd == this);
c_pSplashWnd = NULL;
}
BEGIN_MESSAGE_MAP(CSplashWnd,CWnd)
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_PAINT()
END_MESSAGE_MAP()
//CSplashWnd message handlers
voidCSplashWnd::EnableSplashScreen(BOOL bEnable/* =TRUE*/)
{
c_bShowSplashWnd = bEnable;
}
voidCSplashWnd::ShowSplashScreen(CWnd* pParentWnd/* =NULL*/)
{
//如果不要顯示SplashScreen或SplashWnd對象已經被建立則返回
if (!c_bShowSplashWnd || c_pSplashWnd!=NULL)
{
return;
}
c_pSplashWnd = newCSplashWnd;
if ( !c_pSplashWnd->Create(pParentWnd))
{
deletec_pSplashWnd;
}
else
{
c_pSplashWnd->UpdateWindow();
}
}
BOOLCSplashWnd::PreTranslateAppMessage(MSG* pMsg)
{
if(c_pSplashWnd == NULL)
returnFALSE;
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)
{
c_pSplashWnd->HideSplashScreen();
returnTRUE;
}
returnFALSE;
}
void CSplashWnd::PostNcDestroy()
{
delete this;
}
intCSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CWnd::OnCreate(lpCreateStruct) == -1)
return-1;
// TODO: Add your specialized creation code here
CenterWindow();
SetTimer(1,3000,NULL);
return0;
}
voidCSplashWnd::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Addyour message handler code here and/or call default
if(nIDEvent == 1)
{
HideSplashScreen();
}
/*CWnd::OnTimer(nIDEvent);*/
}
voidCSplashWnd::OnPaint()
{
CPaintDC dc(this);// device context for painting
// TODO: Addyour message handler code here
// Do notcall CWnd::OnPaint() for painting messages
CDC dcImg;
if ( !dcImg.CreateCompatibleDC(&dc))
{
return;
}
BITMAP bm;
m_bitmap.GetBitmap(&bm);
// paint theimage
CBitmap* pOldBit =dcImg.SelectObject(&m_bitmap);
dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&dcImg,0,0,SRCCOPY);
dcImg.SelectObject(pOldBit);
}
BOOLCSplashWnd::Create(CWnd* pParentWnd)
{
if ( !m_bitmap.LoadBitmap(IDB_SPLASH))
{
returnFALSE;
}
BITMAP bm;
m_bitmap.GetBitmap(&bm);
returnCreateEx(0,
AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
NULL,
WS_POPUP|WS_VISIBLE,
0,
0,
bm.bmWidth,
bm.bmHeight,
pParentWnd->GetSafeHwnd(),
NULL);
}
void CSplashWnd::HideSplashScreen(void)
{
DestroyWindow();
AfxGetMainWnd()->UpdateWindow();
}
三、 在SDI或者MDI中使用CSplashWnd類
(1) 在CWinApp::InitInstance()中調用CSplashWnd::EnableSplashScreen()設定c_bShowSplashWnd;
在PreTranslateMessage()中調用CSplashWnd::PreTranslateAppMessage(),將鍵盤和滑鼠訊息傳遞給CSplashWnd對象
(2) (2)在CMainFrame對象的OnCreate()中調用CSplashWnd::ShowSplashScreen()建立一個靜態SplashScreen視窗對象c_pSplashWnd,並設定其父視窗為CMainFrame.
代碼如下:
BOOLCDrawApp::InitInstance()
{
//用來處理是否顯示SplashScreen
{
CCommandLineInfo cmdinfo;
ProcessShellCommand(cmdinfo);
CSplashWnd::EnableSplashScreen(cmdinfo.m_bShowSplash);
}
………..
}
BOOLCDrawApp::PreTranslateMessage(MSG* pMsg)
{
if(CSplashWnd::PreTranslateAppMessage(pMsg))
returnTRUE;
returnCWinAppEx::PreTranslateMessage(pMsg);
}
intCMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
return-1;
………..
CSplashWnd::ShowSplashScreen(this);
return0;
}
在此過程中不會出現什麼錯誤,但編譯時間會提示:IDB_SPLASH沒有定義。這需要在資源中加入個位元影像資源,並將”resource.h” 標頭檔包含到CSlashWnd.cpp檔案中。
四、 在對話方塊中使用CSplashWnd類
在對話方塊中使用和在SDI或MDI中使用基本相似,首先在CWinApp的繼承類中處理InitInstance()和PreTranslateMessage(MSG* pMsg)兩個訊息函數,然後在對話方塊類的WM_CREATE響應函數中顯示SplashScreen。
BOOLCDLGApp::InitInstance()
{
//用來處理是否顯示SplashScreen
{
CCommandLineInfo cmdinfo;
ProcessShellCommand(cmdinfo);
CSplashWnd::EnableSplashScreen(cmdinfo.m_bShowSplash);
}
……….
}
BOOLCDLGApp::PreTranslateMessage(MSG* pMsg)
{
if (CSplashWnd::PreTranslateAppMessage(pMsg) )
{
returnTRUE;
}
returnCWinApp::PreTranslateMessage(pMsg);
}
intCDLGDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CDialogEx::OnCreate(lpCreateStruct) == -1)
return-1;
// TODO: Add your specialized creation code here
CSplashWnd::ShowSplashScreen(this);
return0;
}
【轉】vs2010中添加splashScreen