使用CWndBase快速创建窗口

//========================================================================
//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 //#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 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)
    {
        
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);
}


//----------------------------------------------------------------------
//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_WND"),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 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);
posted @ 2007-11-10 22:16  我的一天  阅读(207)  评论(0编辑  收藏  举报