//========================================================================
//TITLE:
// 使用CWndBase快速创建窗口
//AUTHOR:
// norains
//DATE:
// Saturday 10-November-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
其实这篇文章从本质来说并不新鲜,充其量只是<四论在C++类中实现Windows窗口的创建>的补充实现而已,具体的原理可参考该篇,本文就不再重复.
首先请出我们今天的主角CWndBase类,这是一个封装了窗口创建的基本类,主要是方便能够快速地书写窗口代码.
该类的实现代码如下:
/ /
// WndBase.h:interfacefortheCWndBaseclass.
//
// Version:
// 0.1.0
//
// Date:
// 2007.11.10
/ /
#ifndefWNDBASE_H
#define WNDBASE_H
class CWndBase
{
public :
virtual BOOLShowWindow(BOOLbShow);
virtual BOOLCreate(HINSTANCEhInst,HWNDhWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName);
CWndBase();
virtual ~ CWndBase();
protected :
virtual LRESULTWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
BOOLRegisterWnd(HINSTANCEhInst,HWNDhWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName);
static LRESULTStaticWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
HINSTANCEm_hInst;
HWNDm_hWnd;
HWNDm_hWndParent;
TCHAR * m_pszWndClass;
};
#endif // #ifndefWNDBASE_H
/ //
// WndBase.cpp:implementationoftheCWndBaseclass.
//
/ /
#include " stdafx.h "
#include " WndBase.h "
/ /
// Construction/Destruction
/ /
CWndBase::CWndBase():
m_hInst(NULL),
m_hWnd(NULL),
m_hWndParent(NULL),
m_pszWndClass(NULL)
{
}
CWndBase:: ~ CWndBase()
{
if (m_pszWndClass != NULL)
{
delete[]m_pszWndClass;
}
}
// ----------------------------------------------------------------------
// Description:
// Createthewindow
//
// ----------------------------------------------------------------------
BOOLCWndBase::Create(HINSTANCEhInst,HWNDhWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName)
{
m_hInst = hInst;
m_hWndParent = hWndParent;
if (RegisterWnd(m_hInst,m_hWndParent,pcszWndClass,pcszWndName) == FALSE)
{
return FALSE;
}
RECTrcArea = { 0 };
SystemParametersInfo(SPI_GETWORKAREA, 0 , & rcArea, 0 );
m_hWnd = CreateWindowEx( 0 ,
pcszWndClass,
pcszWndName,
WS_VISIBLE,
rcArea.left,
rcArea.top,
rcArea.right - rcArea.left,
rcArea.bottom - rcArea.top,
m_hWndParent,
NULL,
m_hInst,
0 );
if (IsWindow(m_hWnd) == FALSE)
{
return FALSE;
}
// Ifthewindowiscreatedsuccessfully,storethisobjectsothe
// staticwrappercanpasscallstotherealWndProc.
SetWindowLong(m_hWnd,GWL_USERDATA,(DWORD) this );
return TRUE;
}
// ----------------------------------------------------------------------
// Description:
// Registerwindow
//
// ----------------------------------------------------------------------
BOOLCWndBase::RegisterWnd(HINSTANCEhInst,HWNDhWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName)
{
if (m_pszWndClass == NULL)
{
int iLen = _tcslen(pcszWndClass);
m_pszWndClass = new TCHAR[iLen + 1 ];
if (m_pszWndClass == NULL)
{
return FALSE;
}
_tcscpy(m_pszWndClass,pcszWndClass);
WNDCLASSwc = { 0 };
wc.style = 0 ;
wc.lpfnWndProc = (WNDPROC)CWndBase::StaticWndProc;
wc.cbClsExtra = 0 ;
wc.cbWndExtra = 0 ;
wc.hInstance = m_hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = m_pszWndClass;
return RegisterClass( & wc);
}
return TRUE;
}
// ----------------------------------------------------------------------
// Description:
// StaticWndProcwrapperandactualWndProc
//
// ----------------------------------------------------------------------
LRESULTCWndBase::StaticWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
CWndBase * pObject = (CWndBase * )GetWindowLong(hWnd,GWL_USERDATA);
if (pObject)
{
return pObject -> WndProc(hWnd,wMsg,wParam,lParam);
}
else
{
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
}
// ----------------------------------------------------------------------
// Description:
// ActualWndProc
//
// ----------------------------------------------------------------------
LRESULTCWndBase::WndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
// ----------------------------------------------------------------------
// Description:
// ActualWndProc
//
// ----------------------------------------------------------------------
BOOLCWndBase::ShowWindow(BOOLbShow)
{
if (m_hWnd == NULL)
{
return FALSE;
}
if (bShow == TRUE)
{
::ShowWindow(m_hWnd,SW_SHOW);
SetForegroundWindow(m_hWnd);
}
else
{
::ShowWindow(m_hWnd,SW_HIDE);
}
return TRUE;
}
CWndBase使用也非常简单,如:
CWndBasewndBase;
wndBase.Create(hInstance,NULL,TEXT( " BASE_WND " ),TEXT( " BASE_WND " ));
wndBase.ShowWindow(TRUE);
wndBase.Create(hInstance,NULL,TEXT( " BASE_WND " ),TEXT( " BASE_WND " ));
wndBase.ShowWindow(TRUE);
但这意义不大,因为也就创建了一个简单无用的窗口而已,其实CWndBase正如其名所语,最适合的角色是作为可继承的基类.
还是以实际用途做例子,如果我们需要建立一个CMainWnd窗口,点击该窗口时会自动销毁.有了CWndBase后一切就变得及其简单,我们只要继承CWndBase,然后重载WndProc消息处理过程即可.
CMainWnd代码如下:
/ /
// MainWnd.h:interfacefortheCMainWndclass.
//
/ /
#ifndefMAINWAN_H
#define MAINWAN_H
#include " WndBase.h "
class CMainWnd: public CWndBase
{
public :
CMainWnd();
virtual ~ CMainWnd();
protected :
void OnLButtonUp(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
LRESULTWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
};
#endif // #ifndefMAINWAN_H
/ /
// MainWnd.cpp:implementationoftheCMainWndclass.
//
/ /
#include " stdafx.h "
#include " MainWnd.h "
/ /
// Construction/Destruction
/ /
CMainWnd::CMainWnd()
{
}
CMainWnd:: ~ CMainWnd()
{
}
// ----------------------------------------------------------------------
// Description:
// ActualWndProc
//
// ----------------------------------------------------------------------
LRESULTCMainWnd::WndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
switch (wMsg)
{
case WM_LBUTTONUP:
OnLButtonUp(hWnd,wMsg,wParam,lParam);
return 0 ;
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
// ----------------------------------------------------------------------
// Description:
// OnmessageWM_LBUTTONUP
//
// ----------------------------------------------------------------------
void CMainWnd::OnLButtonUp(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
DestroyWindow(hWnd);
}
由上面的例子可以清楚的看出,继承了CWndBase的CMainWnd代码量大为减少,而这在有多个窗口类的情况下,显得更为重要.
当然咯,还有一点,就是各窗口类都继承CWndBase的话,那么就可以方便的使用指针调用窗口实例了:
CWndBase
*
pWnd
=
NULL;
CWndBasewndBase;
pWnd = & wndBase;
pWnd -> Create(hInstance,NULL,TEXT( " BASE_WND " ),TEXT( " BASE_WND " ));
pWnd -> ShowWindow(TRUE);
CMainWndmainWnd1;
pWnd = & mainWnd1;
pWnd -> Create(hInstance,NULL,TEXT( " MAIN_WND_1 " ),TEXT( " MAIN_WND_1 " ));
pWnd -> ShowWindow(TRUE);
CWndBasewndBase;
pWnd = & wndBase;
pWnd -> Create(hInstance,NULL,TEXT( " BASE_WND " ),TEXT( " BASE_WND " ));
pWnd -> ShowWindow(TRUE);
CMainWndmainWnd1;
pWnd = & mainWnd1;
pWnd -> Create(hInstance,NULL,TEXT( " MAIN_WND_1 " ),TEXT( " MAIN_WND_1 " ));
pWnd -> ShowWindow(TRUE);