MFC中添加SplashScreen

1. 新建一个MFC项目SDI或MDI。

2. 新建或导入一个ID为IDB_SPLASH的位图。

3. 添加现有项SplashWnd.h和SplashWnd.cpp。

SplashWnd.h源代码

#pragma once


// CSplashWnd

class CSplashWnd : public CWnd
{
	DECLARE_DYNAMIC(CSplashWnd)

public:
	CSplashWnd();
	virtual ~CSplashWnd();

protected:
	virtual void PostNcDestroy();
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnTimer(UINT_PTR nIDEvent);
	afx_msg void OnPaint();
	BOOL Create(CWnd* pParentWnd=NULL);
	void HideSplashScreen(void);
	DECLARE_MESSAGE_MAP()

protected:
	CBitmap m_bitmap;
	static CSplashWnd* c_pSplashWnd;
	static BOOL c_bShowSplashWnd;

public:
	static void EnableSplashScreen(BOOL bEnable=TRUE);
	static void ShowSplashScreen(CWnd* pParentWnd=NULL);
	static BOOL PreTranslateAppMessage(MSG* pMsg);
};

SplashWnd.cpp源代码:

// SplashWnd.cpp : 实现文件
//

#include "stdafx.h"
#include "SplashWindow.h"
#include "SplashWnd.h"
#include "resource.h"


// CSplashWnd
CSplashWnd* CSplashWnd::c_pSplashWnd;
BOOL CSplashWnd::c_bShowSplashWnd;
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 消息处理程序

void CSplashWnd::EnableSplashScreen(BOOL bEnable)
{
	c_bShowSplashWnd = bEnable;
}

void CSplashWnd::ShowSplashScreen(CWnd* pParentWnd)
{
	if ( !c_bShowSplashWnd || c_pSplashWnd != NULL )
	{
		return;
	}

	c_pSplashWnd = new CSplashWnd;
	if ( !c_pSplashWnd->Create(pParentWnd) )
	{
		delete c_pSplashWnd;
	}
	else
	{
		c_pSplashWnd->UpdateWindow();
	}
}

BOOL CSplashWnd::PreTranslateAppMessage(MSG* pMsg)
{
	if ( c_pSplashWnd == NULL )
	{
		return FALSE;
	}
	
	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();
		return TRUE;
	}

	return FALSE;
}

void CSplashWnd::PostNcDestroy()
{
	delete this;
}

int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if ( CWnd::OnCreate(lpCreateStruct) == -1 )
	{
		return -1;
	}

	CenterWindow();
	SetTimer(1, 3000, NULL);

	return 0;
}

void CSplashWnd::OnTimer(UINT_PTR nIDEvent)
{
	if ( nIDEvent == 1 )
	{
		HideSplashScreen();
	}
}

void CSplashWnd::OnPaint()
{
	CPaintDC dc(this);
	CDC dcImg;
	if ( !dcImg.CreateCompatibleDC(&dc) )
	{
		return;
	}

	BITMAP bm;
	m_bitmap.GetBitmap(&bm);

	CBitmap* pOldBit = dcImg.SelectObject(&m_bitmap);
	dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcImg, 0, 0, SRCCOPY);
	dcImg.SelectObject(pOldBit);
}

BOOL CSplashWnd::Create(CWnd* pParentWnd)
{
	if ( !m_bitmap.LoadBitmap(IDB_BITMAP1) )
	{
		return FALSE;
	}

	BITMAP bm;
	m_bitmap.GetBitmap(&bm);
	return CreateEx(0,
		AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
		NULL,
		WS_POPUP | WS_VISIBLE,
		0, 0,
		bm.bmWidth,
		bm.bmHeight,
		pParentWnd->GetSafeHwnd(),
		NULL);
}

void CSplashWnd::HideSplashScreen()
{
	DestroyWindow();
	AfxGetMainWnd()->UpdateWindow();
}

4. 在App主程序实现代码中把上面的头文件包含进去,并在InitInstance函数中添加下面一段代码。

{
  CCommandLineInfo cmdInfo;
  ParseCommandLine(cmdInfo);
  CSplashWnd::EnableSplashScreen(cmdInfo.m_bShowSplash);
}

5. 最后,在主框架窗口实现代码中包含Splash头文件,在OnCreate函数return前调用CSplashWnd类的ShowSplashScreen函数即可。

//显示Splash窗口
CSplashWnd::ShowSplashScreen(this);

6.在对话框中使用CSplashWnd类

    其实质就是由CDialog类完成SDI工程中CMainFrame类的工作,实现步骤如下:
(1)利用ClassWizard为CMyDialog添加WM_CREATE消息的处理函数OnCreate();(这里使用CMyDialog是为了与函数内的基类名CDialog区别。)

int CMyDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
CSplashWnd::ShowSplashScreen(this);

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

BOOL CWinApp::PreTranslateMessage(MSG* pMsg)
{
if (CSplashWnd::PreTranslateAppMessage(pMsg))
return TRUE;

return CWinApp::PreTranslateMessage(pMsg);
}
(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的工作。

你可能感兴趣的:(Windows)