//========================================================================
//TITLE:
// 使用CWnDBase快速創建窗口
//AUTHOR:
// norains
//DATE:
// Saturday 10-November-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
其實這篇文章從本質來說並不新鮮,充其量只是<四論在C++類中實現Windows窗口的創建>的補充實現而已,具體的原理可參考該篇,本文就不再重復.
首先請出我們今天的主角CWnDBase類,這是一個封裝了窗口創建的基本類,主要是方便能夠快速地書寫窗口代碼.
該類的實現代碼如下:
//////////////////////////////////////////////////////////////////////
// WndBase.h: interface for the CWnDBase class.
//
//Version:
// 0.1.0
//
//Date:
// 2007.11.10
//////////////////////////////////////////////////////////////////////
#ifndef WNDBase_H
#define WNDBase_H
class CWnDBase
{
public:
virtual BOOL ShowWindow(BOOL bShow);
virtual BOOL Create(HINSTANCE hInst,HWND hWndParent,const TCHAR *pcszWndClass,const TCHAR *pcszWndName);
CWnDBase();
virtual ~CWnDBase();
protected:
virtual LRESULT WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
BOOL RegisterWnd(HINSTANCE hInst, HWND hWndParent,const TCHAR *pcszWndClass,const TCHAR *pcszWndName);
static LRESULT StaticWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
HINSTANCE m_hInst;
HWND m_hWnd;
HWND m_hWndParent;
TCHAR *m_pszWndClass;
};
#endif
an> //#ifndef WNDBase_H
///////////////////////////////////////////////////////////////////////
// WndBase.cpp: implementation of the CWnDBase class.
//
//////////////////////////////////////////////////////////////////////
#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:
// Create the window
//
//----------------------------------------------------------------------
BOOL CWnDBase::Create(HINSTANCE hInst, HWND hWndParent, const TCHAR *pcszWndClass, const TCHAR *pcszWndName)
{
m_hInst = hInst;
m_hWndParent = hWndParent;
if(RegisterWnd(m_hInst,m_hWndParent,pcszWndClass,pcszWndName) == FALSE)
{
return FALSE;
}
RECT rcArea = {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
"COLOR: #000000"> FALSE;
}
// If the window is created successfully, store this object so the
//static wrapper can pass calls to the real WndProc.
SetWindowLong(m_hWnd, GWL_USERDATA, (DWord)this);
return TRUE;
}
//----------------------------------------------------------------------
//Description:
// Register window
//
//----------------------------------------------------------------------
BOOL CWnDBase::RegisterWnd(HINSTANCE hInst, HWND hWndParent,const TCHAR *pcszWndClass,const TCHAR *pcszWndName)
{
if(m_pszWndClass == NULL)
{
COLOR: #0000ff">int iLen = _tcslen(pcszWndClass);
m_pszWndClass = new TCHAR[iLen + 1];
if(m_pszWndClass == NULL)
{
return FALSE;
}
_tcscpy(m_pszWndClass,pcszWndClass);
WNDCLASS wc = {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:
// Static WndProc wrapper and actual WndProc
//
//----------------------------------------------------------------------
>
LRESULT CWnDBase::StaticWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
CWndBase *pObject = (CWnDBase*)GetWindowLong(hWnd, GWL_USERDATA);
if(pObject)
{
return pObject->WndProc(hWnd,wMsg,wParam,lParam);
}
else
{
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
}
//----------------------------------------------------------------------
//Description:
// Actual WndProc
//
//----------------------------------------------------------------------
LRESULT CWnDBase::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
0">//----------------------------------------------------------------------
//Description:
// Actual WndProc
//
//----------------------------------------------------------------------
BOOL CWnDBase::ShowWindow(BOOL bShow)
{
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使用也非常簡單,如:
CWndBase wnDBase;
wnDBase.Create(hInstance,NULL,TEXT("BASE_WND000">"),TEXT("BASE_WND"));
wnDBase.ShowWindow(TRUE);
但這意義不大,因為也就創建了一個簡單無用的窗口而已,其實CWnDBase正如其名所語,最適合的角色是作為可繼承的基類.
還是以實際用途做例子,如果我們需要建立一個CMainWnd窗口,點擊該窗口時會自動銷毀.有了CWndBase後一切就變得及其簡單,我們只要繼承CWnDBase,然後重載WndProc消息處理過程即可.
CMainWnd代碼如下:
//////////////////////////////////////////////////////////////////////
// MainWnd.h: interface for the CMainWnd class.
//
//////////////////////////////////////////////////////////////////////
#ifndef MAINWAN_H
#define MAINWAN_H
#include "WnDBase.h"
class CMainWnd:public CWnDBase
{
public:
CMainWnd();
virtual ~CMainWnd();
protected:
void
0"> OnLButtonUp(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam);
LRESULT WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
};
#endif //#ifndef MAINWAN_H
//////////////////////////////////////////////////////////////////////
// MainWnd.cpp: implementation of the CMainWnd class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MainWnd.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMainWnd::CMainWnd()
{
}
CMainWnd::~CMainWnd()
{
}
//----------------------------------------------------------------------
//Description:
// Actual WndProc
//
//----------------------------------------------------------------------
LRESULT CMainWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch(wMsg)
{
case WM_LBUTTONUP:
OnLButtonUp(hWnd, wMsg, wParam, lParam);
return 0;
}
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}
//----------------------------------------------------------------------
//Description:
// On message WM_LBUTTONUP
//
//----------------------------------------------------------------------
void CMainWnd::OnLButtonUp(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
DestroyWindow(hWnd);
}
由上面的例子可以清楚的看出,繼承了CWnDBase的CMainWnd代碼量大為減少,而這在有多個窗口類的情況下,顯得更為重要.
當然咯,還有一點,就是各窗口類都繼承CWnDBase的話,那麼就可以方便的使用指針調用窗口實例了:
CWnDBase *pWnd = NULL;
CWndBase wnDBase;
pWnd = &wnDBase;
pWnd->Create(hInstance,NULL,TEXT("BASE_WND"),TEXT("BASE_WND"));
pWnd->ShowWindow(TRUE);
CMainWnd mainWnd1;
pWnd = &mainWnd1;
pWnd->Create(hInstance,NULL,TEXT("MAIN_WND_1"),TEXT("MAIN_WND_1"));
pWnd->ShowWindow(TRUE);