//========================================================================
//TITLE:
//    CWndBase更新至v0.1.6
//AUTHOR:
//    norains
//DATE:
//    Saturday  12-January-2008
//Environment:
//    VS2005 + SDK-WINCE5.0-MIPSII  
//    EVC + SDK-WINCE5.0-MIPSII 
//========================================================================

    v0.1.0版本见:http://blog.csdn.net/norains/archive/2007/11/10/1878218.aspx
   
    相对v0.1.0版本,有如下变动:
    1.创建窗口时将WS_VISIBLE属性换成WS_TABSTOP,因为并不是每次创建的时候都需要显示
    2.修正采用该类创建子窗口的bug
    3.改进在非主线程中也可正常创建窗口.
   
    关于第三点,只需要在调用Create()函数时,将bMsgThrdInside形参设置为TRUE即可.

//////////////////////////////////////////////////////////////////////
// WndBase.h: interface for the CWndBase class.
//
//Version:
//    0.1.6
//
//Date:
//    2008.01.03
//////////////////////////////////////////////////////////////////////
#pragma once

class CWndBase
{
public:
    
virtual BOOL ShowWindow(BOOL bShow);
    
virtual BOOL Create(HINSTANCE hInst,HWND hWndParent,const TCHAR *pcszWndClass,const TCHAR *pcszWndName,BOOL bMsgThrdInside = FALSE);
    CWndBase();
    
virtual ~CWndBase();

protected:
    
virtual LRESULT WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
    
virtual BOOL RegisterWnd(HINSTANCE hInst, const TCHAR *pcszWndClass);
    
virtual void OnDestroy(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
    
static LRESULT StaticWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);


    HINSTANCE m_hInst;
    HWND m_hWnd;
    HWND m_hWndParent;
    TCHAR 
*m_pszWndClass;
    TCHAR 
*m_pszWndName;

private:
    
static DWORD CreateProc(PVOID pArg);
    BOOL CreateWnd(
void);

    BOOL m_bCreated;
    BOOL m_bMsgThrdInside;
    HANDLE m_hEventCreated;


    
};


//////////////////////////////////////////////////////////////////////
// WndBase.cpp
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include 
"WndBase.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CWndBase::CWndBase():
m_hInst(NULL),
m_hWnd(NULL),
m_hWndParent(NULL),
m_pszWndClass(NULL),
m_pszWndName(NULL),
m_bCreated(FALSE),
m_hEventCreated(NULL),
m_bMsgThrdInside(FALSE)
{

}

CWndBase::
~CWndBase()
{
    
if(m_pszWndClass != NULL)
    {
        delete []m_pszWndClass;
        m_pszWndClass 
= NULL;
    }

    
if(m_pszWndName != NULL)
    {
        delete []m_pszWndName;
        m_pszWndName 
= NULL;
    }
}

//----------------------------------------------------------------------
//Description:
//    Create the window
//
//Parameters:
//    hInst : [in] The handle of instance of the application
//    hWndParent : [in] The parent window
//    pcszWndClass : [in] The class of the window
//    pcszWndName : [in] The name of the windows
//    bMsgThrdInside : [in] The message thread process is inside or not
//
//----------------------------------------------------------------------
BOOL CWndBase::Create(HINSTANCE hInst, HWND hWndParent, const TCHAR *pcszWndClass, const TCHAR *pcszWndName,BOOL bMsgThrdInside)
{
    m_hInst 
= hInst;
    m_hWndParent 
= hWndParent;
    m_bMsgThrdInside 
= bMsgThrdInside;

    
//Store the window class name
    if(m_pszWndClass != NULL)
    {
        delete []m_pszWndClass;
        m_pszWndClass 
= NULL;
    }

    
int iLen = _tcslen(pcszWndClass);
    m_pszWndClass 
= new TCHAR[iLen + 1];
    
if(m_pszWndClass == NULL)
    {
        
return FALSE;
    }
    _tcscpy(m_pszWndClass,pcszWndClass);



    
//Store the window name
    if(m_pszWndName != NULL)
    {
        delete []m_pszWndName;
        m_pszWndName 
= NULL;
    }

    iLen 
= _tcslen(pcszWndName);
    m_pszWndName 
= new TCHAR[iLen + 1];
    
if(m_pszWndName == NULL)
    {
        
return FALSE;
    }
    _tcscpy(m_pszWndName,pcszWndName);


    
//Create the window
    if(bMsgThrdInside == TRUE)
    {

        HANDLE hdThrd 
= CreateThread(NULL,0,CreateProc,this,0,NULL);
        
if(hdThrd == NULL )
        {
            
return FALSE;
        }
        
else
        {
            CloseHandle(hdThrd);

            
//Create the event and wait
            m_hEventCreated = CreateEvent(NULL,FALSE,FALSE,NULL);
            
if(m_hEventCreated != NULL)
            {
                WaitForSingleObject(m_hEventCreated,INFINITE);
                CloseHandle(m_hEventCreated);
                m_hEventCreated 
= NULL;

                
return m_bCreated;
            }
            
else
            {
                
return FALSE;
            }
            
        }
    }
    
else
    {
        
return CreateWnd();
    }


}

//----------------------------------------------------------------------
//Description:
//    Register window
//
//----------------------------------------------------------------------
BOOL CWndBase::RegisterWnd(HINSTANCE hInst,const TCHAR *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 
= pcszWndClass;

    
return RegisterClass(&wc);

    
}


//----------------------------------------------------------------------
//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)
{
    
switch(wMsg)
    {
        
case WM_DESTROY:
            OnDestroy(hWnd,wMsg,wParam,lParam);
            
break;
    }
    
return DefWindowProc(hWnd,wMsg,wParam,lParam);
}


//----------------------------------------------------------------------
//Description:
//    Show the window
//
//----------------------------------------------------------------------
BOOL CWndBase::ShowWindow(BOOL bShow)
{
    
if(m_hWnd == NULL)
    {
        
return FALSE;
    }

    
if(bShow == TRUE)
    {
        SetForegroundWindow(m_hWnd);
        SetWindowPos(m_hWnd,HWND_TOP,
0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);            
    }
    
else
    {
        ::ShowWindow(m_hWnd,SW_HIDE);
    }
    


    
return TRUE;
}


//----------------------------------------------------------------------
//Description:
//    The process thread is for creating the window
//
//----------------------------------------------------------------------
DWORD CWndBase::CreateProc(PVOID pArg)
{
    
//Get the object instance
    CWndBase *pObject = (CWndBase *)pArg;
    
    
//Create the window
    pObject->m_bCreated = pObject->CreateWnd();

    
//Set the event
    if(pObject->m_hEventCreated != NULL)
    {
        SetEvent(pObject
->m_hEventCreated);
    }

    
if(pObject->m_bCreated == FALSE)
    {
        
//Failed in creating the window, so return and needn't the message loop
        return 0x01;
    }


    
//The message loop    
    MSG msg;
    
while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(
&msg);
        DispatchMessage(
&msg);
    }

    
return 0;

}



//----------------------------------------------------------------------
//Description:
//    Create the window
//
//----------------------------------------------------------------------
BOOL CWndBase::CreateWnd(void)
{    

    
if(RegisterWnd(m_hInst,m_pszWndClass) == FALSE)
    {
        
return FALSE;
    }

    RECT rcArea 
= {0};
    SystemParametersInfo(SPI_GETWORKAREA, 
0&rcArea, 0);

    m_hWnd 
= CreateWindowEx(0,
                m_pszWndClass,
                m_pszWndName,
                WS_TABSTOP,
                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:
//    On Message WM_DESTROY
//
//----------------------------------------------------------------------
void CWndBase::OnDestroy(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{

    
if(m_bMsgThrdInside == TRUE)
    {
        
//Exit the inside thread
        PostQuitMessage(0x00);
    }


}