在看本文之前,希望你看下《worker线程与UI线程的学习》《手写VC向导代码》两文,如果你没有很好的基础的话。为了浅析好这个小程序,我特意写的那两篇文章。
首先创建一个基于对话框的工程,工程名为Splash。我们从CWnd类派生一个子类CSplashWnd,作为系统启动界面的窗口。我们这个类不手写实现,直接利用VC的类向导。然后我们添加WM_PAINT消息。
写入代码:
void CSplashWnd::OnPaint()
{
CPaintDC dc(this); // device context for painting
BITMAP bm;
GetObject(hbmp,sizeof(bm),&bm);
CDC memdc;
memdc.CreateCompatibleDC(&dc);
memdc.SelectObject(hbmp);
dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&memdc,0,0,SRCCOPY);
// Do not call CWnd::OnPaint() for painting messages
}
关于BitBlt()与CreateCompatibleDC()两个函数还有下面的LoadImage函数,我在《学习心得之八------实现从磁盘读入图片文件》中解释了,你可以去那里看看。在这里我补充句,CreateCompatibleDC函数就是创建兼容的DC,实际上就是将函数的参数拷贝给调用这个函数的另一个DC。
接下来我们添加个显示窗口的函数ShowSplashWindow():
void CSplashWnd::ShowSplashWindow()
{
UpdateWindow();//更新窗口
SetTimer(1,1,NULL);
}
然后就是定时器函数的消息响应:
void CSplashWnd::OnTimer()
{
KillTimer(1);
Sleep(5000);
SendMessage(WM_CLOSE);
//CWnd::OnTimer(nIDEvent);
}
然后就是消息响应函数OnCreate()(该函数是windows消息句柄),这个函数主要就是改变窗口界面的位置,如果不添加这个函数,那么,最后得结果就是界面窗口会在屏幕的左上角。我们添加这个函数来移动界面窗口,使它居中:
int CSplashWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CenterWindow();
return 0;
}
下面就是添加函数以创建界面窗口了:不过我们先添加一个CWnd类的变量,用它来调用CreateEx函数来创建窗口。同时添加一个HBITMAP类的变量hbmp。
BOOL CSplashWnd::Create(CWnd* pParentWnd)
{
hbmp=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),"mr.bmp",IMAGE_BITMAP,
0,0,LR_LOADFROMFILE|LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
BITMAP bm;
GetObject(hbmp,sizeof(bm),&bm);
//创建默认窗体
LPCTSTR pszWndClass=AfxRegisterWndClass(0);
VERIFY(m_wndbase.CreateEx(0,pszWndClass, _T(""),WS_POPUP,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, NULL, 0));
//创建图片大小窗体
pszWndClass=AfxRegisterWndClass(0,AfxGetApp()->LoadStandardCursor(IDC_ARROW));
VERIFY(CreateEx(0,pszWndClass,_T(""),WS_POPUP|WS_VISIBLE,0,0,
bm.bmWidth,bm.bmHeight,m_wndbase.GetSafeHwnd(),NULL));
::SetWindowPos(m_wndbase.GetSafeHwnd(),HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
return true;
}
在这里CreateEx函数的两种重载形式都用上了,第一个帮我们创建窗口,第二个就是将我们创建的窗体适应我们加载启动界面的图片。在这里我们加载了一个“mr.bmp"的图片,但是首先你得先在项目的文件夹中加载这个图片哦!
我的工程是在C盘里的MyProjects里,工程名叫Splash。在里面加上个“mr.bmp”图片,就好了。
下面我们手写一个类CSplashThread,该类派生自CWinThread类,我们利用这个类来创建UI界面线程(请看《worker线程与UI线程的学习》),双击CSplashWnd类,进入头文件,我们在其间写入代码,不过你得注意哦!CSplashThread类中除了构造函数,析构函数外,还有两个虚函数哦!那就是InitInstance()与ExitInstance()函数,这两个虚函数是必备的。接着我们在这个类的头文件中,声明一个CSplashWnd类的变量-m_mysplash。我们利用这个变量,在CSplashThread类的InitInstance()函数中调用Create函数与ShowSplashWindow函数。
BOOL CSplashThread::InitInstance()
{
m_mysplash.Create();
m_mysplash.ShowSplashWindow();
return TRUE;
}
最后就是创建UI界面线程了,不过我们得在CSplashApp类的InitInstance函数中实现,至于理由,你可以在《学习心得之七(续)-字体启动程序的设计》或《学习心得之七》两文中找到相关解释哦!
我们看看需写入的代码:
CSplashThread* pSplashThread = (CSplashThread*) AfxBeginThread(RUNTIME_CLASS(CSplashThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
if (pSplashThread == NULL)
{
MessageBox(NULL,"创建闪屏失败!","提示",MB_OK);
return FALSE;
}
pSplashThread->ResumeThread();
我们创建的CSplashThread类就是为了这里的函数AfxBeginThread的返回值,用来创建UI界面线程。
看看实现结果吧!