概述:

该类为主要是实现窗口的背景绘制和各种子控件的管理已经,通用控件的资源的加载等一些基础的工作,为我们使用
控件的核心。

代码实现如下:

#pragma once
#include "UserMessage.h"
#include "QsCtrls.h"
#include <vector>
#include "ResourceManager.h"

#pragma comment(lib, "ResourceManager.lib")

template< class T, bool _bIsChildWnd = false >
class CQsSkinWindowUI//: public CQsMaxMinBase<T>
{
public:
typedef enum
{
WINUI_FIRST = 0,
WINUI_TOPLEFT, //窗口左上角
WINUI_TOP, //窗口顶部
WINUI_TOPRIGHT, //窗口右上角
WINUI_CENTERLEFT, //窗口中部左边
WINUI_CENTER, //窗口中部
WINUI_CENTERRIGHT, //窗口中部右边
WINUI_BOTTOMLEFT, //窗口底部左边
WINUI_BOTTOM, //窗口底部
WINUI_BOTTOMRIGHT, //窗口底部右边
WINUI_LAST
};
//typedef CQsMaxMinBase<T> theMaxMinClass;
private:
CRect m_rcWnd; //当前画刷图像尺寸
Image *m_pImage[WINUI_LAST]; //窗口背景分解图
protected:
Bitmap *m_pBKImage; //当前窗口背景图片

bool m_bIsTransparent; // 窗口是否透明

public:
BEGIN_MSG_MAP(CQsSkinWindowUI)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER( WM_DRAWBKGNDUI, OnDrawBKGndUI )
MESSAGE_HANDLER( WM_DRAWBKGNDUIEX, OnDrawBKGndUIEx )
MESSAGE_HANDLER( WM_SIZE, OnSize )
MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBkgnd )
MESSAGE_HANDLER(WM_REDRAWBKGND, OnRedrawBkgnd )
//CHAIN_MSG_MAP(theMaxMinClass)
END_MSG_MAP()

DECLARE_WND_CLASS( _T("QsSkinWindow") )

/**
*@method CQsSkinWindowUI
*@brief CQsSkinWindowUI类构造函数
*
*@return
*/
CQsSkinWindowUI():
m_pBKImage( NULL )
{
for( int i = WINUI_FIRST; i < WINUI_LAST; i++ )
{
m_pImage[i] = NULL;
}
m_bIsTransparent = false;
}

/**
*@method ~CQsSkinWindowUI
*@brief CQsSkinWindowUI析构造函数
*
*@return
*/
virtual ~CQsSkinWindowUI()
{
//释放图片资源
for( int i = WINUI_FIRST; i < WINUI_LAST; i++ )
{
delete m_pImage[i];
}

//释放当前窗口背景图片
if( m_pBKImage )
{
delete m_pBKImage;
m_pBKImage = NULL;
}

//释放按钮控件
int nSize = m_ctlButtons.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQsButton *p = m_ctlButtons[i];
ATLASSERT( p );
delete p;
}
m_ctlButtons.RemoveAll();

//释放CheckBox
nSize = m_ctlCheckBoxs.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQsCheckBox *p = m_ctlCheckBoxs[i];
ATLASSERT( p );
delete p;
}
m_ctlCheckBoxs.RemoveAll();

//释放RadioBoxs
nSize = m_ctlRadioBoxs.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQsRadioBox *p = m_ctlRadioBoxs[i];
ATLASSERT( p );
delete p;
}
m_ctlRadioBoxs.RemoveAll();

//释放ComboBox
nSize = m_ctlComboBoxs.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQsComboBox *p = m_ctlComboBoxs[i];
ATLASSERT( p );
delete p;
}
m_ctlComboBoxs.RemoveAll();

//释放Edit
nSize = m_ctlEdits.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQsEdit *p = m_ctlEdits[i];
ATLASSERT( p );
delete p;
}
m_ctlEdits.RemoveAll();

//释放Edit
nSize = m_ctlProgs.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQSProgressBar *p = m_ctlProgs[i];
ATLASSERT( p );
delete p;
}
m_ctlProgs.RemoveAll();


//释放CCustomStatic2
nSize = m_ctlStaCtrls.GetSize();
for( int i = 0; i < nSize; i++ )
{
CQsStatic *p = m_ctlStaCtrls[i];
ATLASSERT( p );
delete p;
}
m_ctlStaCtrls.RemoveAll();

//释放控件状态图片对象
nSize = m_stImages.GetSize();
for( int i = 0; i < nSize; i++ )
{
STATEIMAGE *p = m_stImages[i];
delete p;
}
m_stImages.RemoveAll();
}

/**
*@method SetExSkin
*@brief 换肤时消息背景图片删除和公共控件图片的加载
*
*@return void
*/
void SetExSkin()
{
for( int i = WINUI_FIRST; i < WINUI_LAST; i++ ) //bei背景先清除掉
{
delete m_pImage[i];
}
//释放当前窗口背景图片
if( m_pBKImage )
{
delete m_pBKImage;
m_pBKImage = NULL;
}
SubClassImagePublic();
}

/**
*@method SetTransparent
*@brief 设置窗口是否透明
*
*@param bool bTrans
*@return void
*/
void SetTransparent( bool bTrans = true )
{
m_bIsTransparent = bTrans;
}

/**
*@method OnInitDialog
*@brief 对话框窗口初始化消息响应函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnInitDialog( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
T *pT = static_cast< T* >( this );
HMENU hSystemMenu = ::GetSystemMenu( pT->m_hWnd, FALSE );

if ( NULL != hSystemMenu )
{
::RemoveMenu( hSystemMenu, SC_MOVE, MF_BYCOMMAND );
}
//ShowMenuButton();
return 0;
}

protected:

/**
*@method OnSysCommand
*@brief 对话框窗口尺寸发生变化消息响应函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnSysCommand( UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
bHandled = FALSE;

return TRUE;
}

/**
*@method OnSize
*@brief 对话框窗口尺寸发生变化消息响应函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnSize( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled )
{
T *pT = static_cast< T* >( this );
int cx = LOWORD( lParam );
int cy = HIWORD( lParam );

//重新生成背景图片
if( !CreateBKImageEx( cx, cy ) )
{
return 0;
}
CRect rect;
pT->GetClientRect(&rect);
pT->InvalidateRect( rect );
bHandled = false;
return 0;
}

/**
*@method SubQSclassAllControls
*@brief 将窗口上的所有控件进行关联
*
*@param void
*@return BOOL
*/
virtual BOOL SubQSclassAllControls( void )
{
SubClassImagePublic();

SetPublicDefaultFont();

SetPublicDefaultColor();

return SubclassAllControls();
}

/**
*@method SetPublicDefaultColor
*@brief 设置默认字体的颜色
*
*@return void
*/
void SetPublicDefaultColor()
{
DWORD dword =0;
std::wstring sss = _T("default_color");
GetColor(sss,dword);

CCtrlImageMgr::SetDefaultFontColor(dword);
}

/**
*@method SetPublicDefaultFont
*@brief 设置窗口默认的字体
*
*@return void
*/
void SetPublicDefaultFont()
{
std::wstring strfontName;
double nfontsize=0;
int nfontstyle =0;
int fnWeight = FW_NORMAL;
BYTE bItalic = FALSE;
BYTE bUnderline = FALSE;
BYTE bStrikeOut = FALSE;

GetFontEx(_T("default_font"),strfontName,nfontsize,nfontstyle);

if(FontStyleRegular == nfontstyle)
{
fnWeight = FW_NORMAL;
}
else if(FontStyleBold == nfontstyle)
{
fnWeight = FW_BOLD;
}
else if(FontStyleItalic == nfontstyle)
{
bItalic = TRUE;
}
else if(FontStyleBoldItalic == nfontstyle)
{
bItalic = TRUE;
fnWeight = FW_BOLD;
}
else if(FontStyleUnderline == nfontstyle)
{
bUnderline = TRUE;
}
else if(FontStyleStrikeout == nfontstyle)
{
bStrikeOut = TRUE;
}
CCtrlImageMgr::SetDefaultFont(strfontName.c_str(),(int)nfontsize,fnWeight,bItalic,bUnderline,bStrikeOut);
}

/**
*@method SubClassImagePublic
*@brief 设置公共控件的Image
*
*@return void
*/
void SubClassImagePublic()
{
CCtrlImageMgr::ClearStateImage();
按钮
Image *pImg = NULL;
GetImage( _T("comm_button.png"), pImg);

if(NULL != pImg)
{
CCtrlImageMgr::SetStateImage( CONTROL_BTN_NORMAL, pImg, 0, 0, 84, 37 );
CCtrlImageMgr::SetStateImage( CONTROL_BTN_FOCUS, pImg, 84, 0, 84, 37 );
CCtrlImageMgr::SetStateImage( CONTROL_BTN_MOUSEIN, pImg, 84, 0, 84, 37 );
CCtrlImageMgr::SetStateImage( CONTROL_BTN_MOUSEDOWN, pImg, 168, 0, 84, 37 );
CCtrlImageMgr::SetStateImage( CONTROL_BTN_DISABLED, pImg, 252, 0, 84, 37 );
}

//复选框
GetImage( _T("comm_checkbox.png"), pImg);
if(NULL != pImg)
{
CCtrlImageMgr::SetStateImage( CONTROL_CHK_DISCHECKED, pImg,0,0,18,18 );
CCtrlImageMgr::SetStateImage( CONTROL_CHK_CHECKED, pImg,18,0,18,18);
CCtrlImageMgr::SetStateImage( CONTROL_CHK_DISUNCHECK, pImg,36,0,18,18 );
CCtrlImageMgr::SetStateImage( CONTROL_CHK_UNCHECK, pImg,54,0,18,18);
GetImage( _T("comm_checkbox_select_focus.png"), pImg);
if(NULL!= pImg)
{
CCtrlImageMgr::SetStateImage( CONTROL_CHK_FOUCS_CHECKED, pImg,0,0,18,18);
}
GetImage( _T("comm_checkbox_unselect_focus.png"), pImg);
if(NULL!= pImg)
{
CCtrlImageMgr::SetStateImage( CONTROL_CHK_FOUCS_UNCHECK, pImg,0,0,18,18);
}
}
//单选框
GetImage( _T("comm_radiobox.png"), pImg);
if(NULL != pImg)
{

CCtrlImageMgr::SetStateImage( CONTROL_RDB_UNCHECK, pImg, 0, 0, 20, 20 );
CCtrlImageMgr::SetStateImage( CONTROL_RDB_CHECKED, pImg, 20, 0, 20, 20 );
CCtrlImageMgr::SetStateImage( CONTROL_RDB_DISUNCHECK, pImg, 40, 0, 20, 20 );
CCtrlImageMgr::SetStateImage( CONTROL_RDB_DISCHECKED, pImg, 60, 0, 20, 20 );


}
GetImage( _T("comm_combox.png"), pImg);
if(NULL != pImg)
{

CCtrlImageMgr::SetStateImage( CONTROL_CBS_NORMAL, pImg, 0, 0, 24, 24 );
CCtrlImageMgr::SetStateImage( CONTROL_CBS_FOCUS, pImg, 0, 0, 24, 24 );
CCtrlImageMgr::SetStateImage( CONTROL_CBS_MOUSEIN, pImg, 24, 0, 24, 24 );
CCtrlImageMgr::SetStateImage( CONTROL_CBS_MOUSEDOWN, pImg, 48, 0, 24, 24 );
CCtrlImageMgr::SetStateImage( CONTROL_CBS_DISABLED, pImg, 72, 0, 24, 24 );
}
}

/**
*@method OnEraseBkgnd
*@brief 窗口背景绘制消息
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnEraseBkgnd( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
return FALSE;
}

LRESULT OnRedrawBkgnd( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
ReDraw();
return TRUE;
}


/**
*@method OnCtlColorStatic
*@brief 窗口绘制消息响应函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnCtlColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
T *pT = static_cast< T* >( this );
HWND hwnd = ( HWND )lParam;
for( int i = 0; i < m_ctlStaCtrls.GetSize(); i++ )
{
if( m_ctlStaCtrls[i]->m_hWnd == hwnd )
{

HDC hdc = ( HDC )wParam;

//用控件背景做一个画刷
WTL::CDC memDC;
memDC.CreateCompatibleDC( hdc );
WTL::CBitmap memBitmap;
CRect rc;
::GetWindowRect( hwnd, rc );
memBitmap.CreateCompatibleBitmap( hdc, rc.Width(), rc.Height() );
HBITMAP hOldBmp = memDC.SelectBitmap( memBitmap.m_hBitmap );

//获得控件背景
pT->SendMessage( WM_DRAWBKGNDUI, ( WPARAM )memDC.m_hDC, ( LPARAM )hwnd );

//创建画刷
HBRUSH hBrush = ::CreatePatternBrush( memBitmap.m_hBitmap );

memDC.SelectBitmap( hOldBmp );

return ( LRESULT )hBrush;//( LRESULT )::GetStockObject( NULL_BRUSH );
}
}

return DefWindowProc( pT->m_hWnd, uMsg, wParam, lParam );

}

/**
*@method OnDrawBKGndUI
*@brief 绘制子控件背景
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnDrawBKGndUI( UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
HDC hdc = ( HDC )wParam;
HWND hwnd = ( HWND )lParam;

//获得当前控件在窗口上的位置
T *pT = static_cast< T* >( this );

if( !m_pBKImage )
{
CRect rc;
pT->GetWindowRect( rc );

if( !CreateBKImageEx( rc.Width(), rc.Height() ) )
return FALSE;
}

//获得控件在当前窗口上的位置
CRect rc;
::GetWindowRect( hwnd, rc );
pT->ScreenToClient( rc );

//将图像复制给控件
Graphics graph( hdc );
graph.DrawImage( m_pBKImage, Rect( 0, 0, rc.Width(), rc.Height() ),
rc.left, rc.top, rc.Width(), rc.Height(), UnitPixel );
graph.ReleaseHDC( hdc );

return 0;
}

LRESULT OnDrawBKGndUIEx( UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
Graphics* pGraph = (Graphics*)wParam;
HWND hwnd = ( HWND )lParam;

//获得当前控件在窗口上的位置
T *pT = static_cast< T* >( this );

if( !m_pBKImage )
{
CRect rc;
pT->GetWindowRect( rc );

if( !CreateBKImageEx( rc.Width(), rc.Height() ) )
return FALSE;
}

//获得控件在当前窗口上的位置
CRect rc;
::GetWindowRect( hwnd, rc );
pT->ScreenToClient( rc );

pGraph->DrawImage( m_pBKImage, Rect( 0, 0, rc.Width(), rc.Height() ),
rc.left, rc.top, rc.Width(), rc.Height(), UnitPixel );

return TRUE;
}

/**
*@method OnPaint
*@brief 窗口绘制消息响应函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
T *pT = static_cast< T* >( this );
CRect rc;
pT->GetWindowRect( rc );

WTL::CPaintDC paintDC( pT->m_hWnd );

//创建窗口图片对象
WTL::CDC memDC;
memDC.CreateCompatibleDC( paintDC.m_hDC );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( paintDC.m_hDC, rc.Width(), rc.Height() );
HBITMAP hOldBmp = memDC.SelectBitmap( memBitmap.m_hBitmap );

BOOL bRet = CreateBkImage( memDC.m_hDC, rc.Width(), rc.Height() );
if( bRet )
{
paintDC.StretchBlt( 0, 0, rc.Width(), rc.Height(), memDC.m_hDC, 0, 0, rc.Width(), rc.Height(), SRCCOPY );
}
memDC.SelectBitmap( hOldBmp );


if( !bRet )
{
#ifdef _USERLOGFILE
_DEBUG_MSG( _LOGSTR( "创建窗口背景图片失败! cx=%d cy=%d" ), rc.Width(), rc.Height() );
#endif
return ::DefWindowProc( pT->m_hWnd, uMsg, wParam, lParam );
}

return 0;
}

/**
*@method OnCtlColorDlg
*@brief 获得对话框窗口背景
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL& bHandled 未被使用
*@return LRESULT
*/
LRESULT OnCtlColorDlg( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
T *pT = static_cast< T* >( this );
CRect rc;
pT->GetWindowRect( rc );
HBRUSH hBrush = CreateBkBrush( rc.Width(), rc.Height() );
if( !hBrush )
{
return ::DefWindowProc( pT->m_hWnd, uMsg, wParam, lParam );
}

return ( LRESULT ) hBrush;
}

/**
*@method CreateBkImage
*@brief 创建背景图像
*
*@param HDC hDC
*@param int width 宽度
*@param int height 高度
*@return BOOL
*/
BOOL CreateBkImage( HDC hDC, int width, int height )
{
CSize szBmp( 0, 0 ), szWnd( width, height );
if( m_pBKImage )
{
szBmp = CSize( m_pBKImage->GetWidth(), m_pBKImage->GetHeight() );
}

if( szBmp != szWnd )
{
if( !CreateBKImageEx( width, height ) )
{
#ifdef _USERLOGFILE
_DEBUG_MSG( _LOGSTR( "创建窗口背景图片失败! cx=%d cy=%d" ), width, height );
#endif
return FALSE;
}
}

//将图像送给指定设备
Graphics graph( hDC );
graph.DrawImage( m_pBKImage, Rect( 0, 0, width, height ), 0, 0, width, height, UnitPixel );
graph.ReleaseHDC( hDC );

return TRUE;

}

/**
*@method CreateBkBrush
*@brief 创建背景画刷
*
*@param int width 窗口宽度
*@param int height 窗口高度
*@return HBRUSH 成功返回创建的画刷句柄,否则返回NULL
*/
HBRUSH CreateBkBrush( int width, int height )
{
WTL::CDC memDC;
T *pT = static_cast< T* >( this );
HDC hdc = pT->GetDC();

//创建内存作图句柄
memDC.CreateCompatibleDC( hdc );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( hdc, width, height );
HBITMAP hOldBmp = memDC.SelectBitmap( memBitmap.m_hBitmap );
//创建背景
BOOL bRet = CreateBkImage( memDC.m_hDC, width, height );
memDC.SelectBitmap( hOldBmp );

if( !bRet )
return NULL;

return CreatePatternBrush( memBitmap.m_hBitmap );
}

private:

/**
*@method CreateBKImageEx
*@brief 创建当前背景图片
*
*@param int width 窗口宽度
*@param int height 窗口高度
*@return BOOL
*/
BOOL CreateBKImageEx( int width, int height )
{
T *pT = static_cast< T* >( this );

delete m_pBKImage;
m_pBKImage = new Bitmap( width, height );
if( NULL == m_pBKImage )
{
#ifdef _USERLOGFILE
_DEBUG_MSG( _LOGSTR( "创建窗口背景图片失败! cx=%d cy=%d" ), width, height );
#endif
return FALSE;
}
Graphics gh( m_pBKImage );
gh.SetPageScale( 1.0 );
gh.SetPageUnit( UnitPixel );
gh.SetSmoothingMode( SmoothingModeNone );

// 如果是透明窗口,需要向父窗口发送请求,绘制父窗口在该位置的别经
if ( m_bIsTransparent )
{
HWND hParent = pT->GetParent( );
if ( NULL != hParent )
{
::SendMessage( hParent, WM_DRAWBKGNDUIEX, (WPARAM)(&gh), ( LPARAM )pT->m_hWnd );
}
}
else
{
//填充白色背景
SolidBrush sb( Color( 255, 255, 255, 255 ) );
gh.FillRectangle( &sb, 0, 0, width, height );
}

//调用背景绘制函数
BOOL bRet = OnDrawBKGnd( gh );
if( !bRet )
{
#ifdef _USERLOGFILE
_DEBUG_MSG( _LOGSTR( "调用OnDrawBKGnd函数返回错误!" ) );
#endif
delete m_pBKImage;
m_pBKImage = NULL;
}

// if( !_bIsChildWnd )
// {
// //创建异形窗口
// HRGN rgn = ::CreateRoundRectRgn( 3, 0, width-3, height-3, 10, 10 );
// T *pT = static_cast< T* >( this );
// ::SetWindowRgn( pT->m_hWnd, rgn, TRUE );
// DeleteObject( rgn );
// }

return bRet;

}

/**
*@method CheckBKImage
*@brief 检查窗口背景分解图的完整性
*
*@param void
*@return BOOL
*/
BOOL CheckBKImage( void )
{
for( int i = 1; i < 10; i++ )
{
if( m_pImage[i] == NULL )
return FALSE;
}

return TRUE;
}


public:

/**
*@method ResizeWindow
*@brief 重新绘制窗口背景
*
*@param void
*@return BOOL
*/
BOOL ResizeWindow( void )
{
T* pT = static_cast< T* >( this );

CRect rc;
pT->GetWindowRect( rc );

if( !CreateBKImageEx( rc.Width(), rc.Height() ) )
return FALSE;

pT->InvalidateRect(rc);

return TRUE;
}

/**
*@method SetImage
*@brief 设置窗口背景图像
*
*@param UINT nState 详见CONTROL_STATE_IMG定义
*@param Image *pImg 指向图像的指针
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetImage( UINT nState, Image *pImg, int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
if( (nState >= WINUI_LAST ) || (nState <= WINUI_FIRST ) || ( NULL == pImg ) )
{
return FALSE;
}

int width = nWidth==0?pImg->GetWidth():nWidth;
int height = nHeight==0?pImg->GetHeight():nHeight;

Bitmap bmp( width, height );
Graphics graph( &bmp );

graph.DrawImage( pImg, Rect( 0, 0, width, height ), nx, ny, width, height, UnitPixel );
m_pImage[ nState ] = bmp.Clone( 0, 0, width, height, bmp.GetPixelFormat() );

return TRUE;
}

/**
*@method SetImage
*@brief 设置窗口背景图像
*
*@param UINT nState 详见CONTROL_STATE_IMG定义
*@param UINT uID 图片在资源中存放的ID
*@param LPCTSTR sTR 图片在资源中存放的资源标签
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetImage( UINT nState, UINT uID, LPCTSTR sTR, int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
Image *pImage = ImageFromIDResourceEx( uID, sTR );
if( NULL == pImage )
return FALSE;

BOOL bRet = SetImage( nState, pImage, nx, ny, nWidth, nHeight );

delete pImage;
return bRet;
}

/**
*@method SetImage
*@brief 设置窗口背景图像
*
*@param Image *pImg 窗口图像对象
*@param int width = 50 截取宽度
*@param int height = 50 截取高度
*@return BOOL
*/
BOOL SetImage( Image *pImg, int width = 50, int height = 50 )
{
int left = 0;
int top = 0;

int halfx = pImg->GetWidth() / 2;
int halfy = pImg->GetHeight() / 2;

int right = pImg->GetWidth() - width;
int bottom = pImg->GetHeight() - height;

SetImage( WINUI_TOPLEFT, pImg, left, top, width, height );
SetImage( WINUI_TOP, pImg, halfx, top, width, height );
SetImage( WINUI_TOPRIGHT, pImg, right, top, width, height );

SetImage( WINUI_CENTERLEFT, pImg, left, halfy, width, height );
SetImage( WINUI_CENTER, pImg, halfx, halfy, width, height );
SetImage( WINUI_CENTERRIGHT, pImg, right, halfy, width, height );

SetImage( WINUI_BOTTOMLEFT, pImg, left, bottom, width, height );
SetImage( WINUI_BOTTOM, pImg, halfx, bottom, width, height );
SetImage( WINUI_BOTTOMRIGHT, pImg, right, bottom, width, height );

return CheckBKImage();
}

/**
*@method SetImage
*@brief 设置窗口背景图像
*
*@param UINT uID 图片在资源中存放的ID
*@param LPCTSTR sTR 图片在资源中存放的资源标签
*@param int width = 50 截取宽度
*@param int height = 50 截取高度
*@return BOOL
*/
BOOL SetImage( UINT uID, LPCTSTR sTR, int width = 50, int height = 50 )
{
Image *pImage = ImageFromIDResourceEx( uID, sTR );
if( NULL == pImage )
return FALSE;

BOOL bRet = SetImage( pImage, width, height );

delete pImage;

return bRet;
}

/**
*@method OnDrawBKGnd
*@brief 绘制窗口背景
*
*@param Graphics &graph 用于作图的画布对象
*@return BOOL
*/
virtual BOOL OnDrawBKGnd(Graphics &graph)
{
if( !CheckBKImage() )
{
return FALSE;
}

T *pT = static_cast< T* >( this );

//获得当前窗口尺寸
CRect rc;
pT->GetWindowRect( rc );

//使用5填充整个区域
int nStart = m_pImage[WINUI_CENTERLEFT]->GetWidth();
int nEnd = rc.Width() - m_pImage[WINUI_CENTERRIGHT]->GetWidth();
int width = m_pImage[WINUI_CENTER]->GetWidth();
for( int x = nStart; x < nEnd; x += width )
{
if( ( nEnd - x ) < width )
width = nEnd - x;

int nTopStart = m_pImage[WINUI_TOP]->GetHeight();
int nTopEnd = rc.Height() - m_pImage[WINUI_BOTTOM]->GetHeight();
int height = m_pImage[WINUI_CENTER]->GetHeight();
for( int y = nTopStart; y < nTopEnd; y += height )
{
if( ( nTopEnd - y ) < height )
height = nTopEnd - y;

graph.DrawImage( m_pImage[WINUI_CENTER], Rect( x, y, width, height ),
0, 0, width, height, UnitPixel );
}
}

//画顶端横条
nStart = m_pImage[WINUI_TOPLEFT]->GetWidth();
nEnd = rc.Width() - m_pImage[WINUI_TOPRIGHT]->GetWidth();
width = m_pImage[WINUI_TOP]->GetWidth();
for( int x = nStart; x < nEnd ; x += width )
{
if( ( nEnd - x ) < width )
width = nEnd - x;

graph.DrawImage( m_pImage[WINUI_TOP], Rect( x, 0, width, m_pImage[WINUI_TOP]->GetHeight() ),
0, 0, width, m_pImage[WINUI_TOP]->GetHeight(), UnitPixel );
}

//画底部横条
nStart = m_pImage[WINUI_BOTTOMLEFT]->GetWidth();
nEnd = rc.Width() - m_pImage[WINUI_BOTTOMRIGHT]->GetWidth();
width = m_pImage[WINUI_BOTTOM]->GetWidth();
int top = rc.Height() - m_pImage[WINUI_BOTTOM]->GetHeight();
for( int x = nStart; x < nEnd ; x += width )
{
if( ( nEnd - x ) < width )
width = nEnd - x;

graph.DrawImage( m_pImage[WINUI_BOTTOM], Rect( x, top, width, m_pImage[WINUI_BOTTOM]->GetHeight() ),
0, 0, m_pImage[WINUI_BOTTOM]->GetWidth(), m_pImage[WINUI_BOTTOM]->GetHeight(), UnitPixel );
}

//画左部竖条
nStart = m_pImage[WINUI_TOPLEFT]->GetHeight();
nEnd = rc.Height() - m_pImage[WINUI_BOTTOMLEFT]->GetHeight();
int height = m_pImage[WINUI_CENTERLEFT]->GetHeight();
for( int y = nStart; y < nEnd ; y += height )
{
if( ( nEnd - y ) < height )
height = nEnd - y;

graph.DrawImage( m_pImage[WINUI_CENTERLEFT], Rect( 0, y, m_pImage[WINUI_CENTERLEFT]->GetWidth(), height ),
0, 0, m_pImage[WINUI_CENTERLEFT]->GetWidth(), m_pImage[WINUI_CENTERLEFT]->GetHeight(), UnitPixel );
}

//画右部竖条
nStart = m_pImage[WINUI_TOPRIGHT]->GetHeight();
nEnd = rc.Height() - m_pImage[WINUI_BOTTOMRIGHT]->GetHeight();
height = m_pImage[WINUI_CENTERRIGHT]->GetHeight();
int left = rc.Width() - m_pImage[WINUI_CENTERRIGHT]->GetWidth();
for( int y = nStart; y < nEnd ; y += height )
{
if( ( nEnd - y ) < height )
height = nEnd - y;

graph.DrawImage( m_pImage[WINUI_CENTERRIGHT], Rect( left, y, m_pImage[WINUI_CENTERRIGHT]->GetWidth(), height ),
0, 0, m_pImage[WINUI_CENTERRIGHT]->GetWidth(), m_pImage[WINUI_CENTERRIGHT]->GetHeight(), UnitPixel );
}

//画4个角
graph.DrawImage( m_pImage[WINUI_TOPLEFT], Rect( 0, 0, m_pImage[WINUI_TOPLEFT]->GetWidth(),
m_pImage[WINUI_TOPLEFT]->GetHeight() ),
0, 0, m_pImage[WINUI_TOPLEFT]->GetWidth(), m_pImage[WINUI_TOPLEFT]->GetHeight(), UnitPixel );
graph.DrawImage( m_pImage[WINUI_TOPRIGHT], Rect( rc.Width() - m_pImage[WINUI_TOPRIGHT]->GetWidth(),
0, m_pImage[WINUI_TOPRIGHT]->GetWidth(), m_pImage[WINUI_TOPRIGHT]->GetHeight() ),
0, 0, m_pImage[WINUI_TOPRIGHT]->GetWidth(), m_pImage[WINUI_TOPRIGHT]->GetHeight(), UnitPixel );
graph.DrawImage( m_pImage[WINUI_BOTTOMLEFT], Rect( 0, rc.Height()-m_pImage[WINUI_BOTTOMLEFT]->GetHeight(),
m_pImage[WINUI_BOTTOMLEFT]->GetWidth(), m_pImage[WINUI_BOTTOMLEFT]->GetHeight() ),
0, 0, m_pImage[WINUI_BOTTOMLEFT]->GetWidth(), m_pImage[WINUI_BOTTOMLEFT]->GetHeight(), UnitPixel );
graph.DrawImage( m_pImage[WINUI_BOTTOMRIGHT], Rect( rc.Width() - m_pImage[WINUI_BOTTOMRIGHT]->GetWidth(),
rc.Height()-m_pImage[WINUI_BOTTOMRIGHT]->GetHeight(), m_pImage[WINUI_BOTTOMRIGHT]->GetWidth(),
m_pImage[WINUI_BOTTOMRIGHT]->GetHeight() ),
0, 0, m_pImage[WINUI_BOTTOMRIGHT]->GetWidth(), m_pImage[WINUI_BOTTOMRIGHT]->GetHeight(), UnitPixel );

return TRUE;
}

public:
typedef enum
{
CTRL_BUTTON = 0, //按钮控件
CTRL_CHECKBOX, //CHECKBOX
CTRL_COMBOBOX, //COMBOBOX
CTRL_EDIT, //EDIT
CTRL_PROGRESS, //进度条
CTRL_RADIOBOX, //单选按钮
CTRL_STATIC, //静态标签
CTRL_SCROLLBAR, //滚动条
CTRL_TABCTRL, //属性页
}CTRLTYPE;

protected:
CSimpleArray< CQsButton * > m_ctlButtons; //界面上的所有按钮控件列表
CSimpleArray< CQsCheckBox * > m_ctlCheckBoxs; //界面上的所有按钮控件列表
CSimpleArray< CQsRadioBox * > m_ctlRadioBoxs; //界面上的所有按钮控件列表
CSimpleArray< CQsComboBox * > m_ctlComboBoxs; //界面上的所有下列选择控件列表
CSimpleArray< CQsEdit * > m_ctlEdits; //界面上的所有下列选择控件列表
CSimpleArray< CQSProgressBar * > m_ctlProgs; //界面上的所有进度条控件列表
CSimpleArray< CQsStatic * > m_ctlStaCtrls; //界面上的所有Static控件列表
std::vector< HWND > m_vtUnSubclass; //不需要自动绑定的控件句柄
private:

/**
*@method GetCustomObjectEx
*@brief 获得对象实例
*
*@param HWND hwnd 根据窗口句柄获得自定义控件对象
*@return CCtrlImageMgr * 如果存在,返回对象地址否则返回NULL
*/
CCtrlImageMgr *GetCustomObjectEx( HWND hwnd )
{
CCtrlImageMgr *pcim = NULL;
for( int i = 0; ( i < m_ctlButtons.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsButton *p = m_ctlButtons[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

for( int i = 0; ( i < m_ctlCheckBoxs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsCheckBox *p = m_ctlCheckBoxs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

for( int i = 0; ( i < m_ctlRadioBoxs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsRadioBox *p = m_ctlRadioBoxs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

for( int i = 0; ( i < m_ctlComboBoxs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsComboBox *p = m_ctlComboBoxs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

for( int i = 0; ( i < m_ctlEdits.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsEdit *p = m_ctlEdits[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

for( int i = 0; ( i < m_ctlProgs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQSProgressBar *p = m_ctlProgs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

for( int i = 0; ( i < m_ctlStaCtrls.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsStatic *p = m_ctlStaCtrls[i];
if( p->m_hWnd == hwnd )
{
pcim = (CCtrlImageMgr*)p;
break;
}
}

return pcim;
}


protected:

/**
*@method GetCustomObject
*@brief 获得对象实例
*
*@param HWND hwnd 根据窗口句柄获得自定义控件对象
*@return void * 如果存则,返回对象地址否则返回NULL
*/
void *GetCustomObject( HWND hwnd )
{
void *pcim = NULL;
for( int i = 0; ( i < m_ctlButtons.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsButton *p = m_ctlButtons[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQsButton*)p;
break;
}
}

for( int i = 0; ( i < m_ctlCheckBoxs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsCheckBox *p = m_ctlCheckBoxs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQsCheckBox*)p;
break;
}
}

for( int i = 0; ( i < m_ctlRadioBoxs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsRadioBox *p = m_ctlRadioBoxs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQsRadioBox*)p;
break;
}
}

for( int i = 0; ( i < m_ctlComboBoxs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsComboBox *p = m_ctlComboBoxs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQsComboBox*)p;
break;
}
}

for( int i = 0; ( i < m_ctlEdits.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsEdit *p = m_ctlEdits[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQsEdit*)p;
break;
}
}

for( int i = 0; ( i < m_ctlProgs.GetSize() ) && ( NULL == pcim ); i++ )
{
CQSProgressBar *p = m_ctlProgs[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQSProgressBar*)p;
break;
}
}

for( int i = 0; ( i < m_ctlStaCtrls.GetSize() ) && ( NULL == pcim ); i++ )
{
CQsStatic *p = m_ctlStaCtrls[i];
if( p->m_hWnd == hwnd )
{
pcim = (CQsStatic*)p;
break;
}
}

return pcim;
}

/**
*@method GetCustomObject
*@brief 获得对象实例
*
*@param UINT uID
*@return void * 如果存则,返回对象地址否则返回NULL
*/
void *GetCustomObject( UINT uID )
{
T *pT = static_cast< T* >( this );
return GetCustomObject( pT->GetDlgItem( uID ) );
}

/**
*@method SetImage
*@brief 设置控件图像
*
*@param HWND hwnd
*@param UINT nState 详见CTRL_STATE_IMG定义
*@param Image *pImage 图片对象
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetImage( HWND hwnd, UINT nState, Image *pImage, int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
CCtrlImageMgr *pcim = GetCustomObjectEx( hwnd );

if( NULL != pcim )
{
return pcim->SetImage( nState, pImage, nx, ny, nWidth, nHeight );
}

return FALSE;
}

/**
*@method SetImage
*@brief 设置控件图像
*
*@param HWND hwnd
*@param UINT nState 详见CTRL_STATE_IMG定义
*@param UINT uID 图片在资源中存放的ID
*@param LPCTSTR sTR 图片在资源中存放的资源标签
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetImage( HWND hwnd, UINT nState, UINT uID, LPCTSTR sTR, int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
Image *pImage = ImageFromIDResourceEx( uID, sTR );
if( pImage )
{
SetImage( hwnd, nState, pImage, nx, ny, nWidth, nHeight );
delete pImage;
}
return TRUE;
}

/**
*@method SetCtrlIcon
*@brief 设置控件图标
*
*@param HWND hwnd
*@param UINT nState 详见CTRL_STATE_IMG定义
*@param Image *pImage 图片对象
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetCtrlIcon( HWND hwnd, UINT nState, Image *pImage, int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
CCtrlImageMgr *pcim = GetCustomObjectEx( hwnd );

if( NULL != pcim )
{
return pcim->SetCtrlIcon( nState, pImage, nx, ny, nWidth, nHeight );
}

return FALSE;
}

/**
*@method SetCtrlIcon
*@brief 设置控件图标
*
*@param HWND hwnd
*@param UINT nState 详见CTRL_STATE_IMG定义
*@param UINT uID 图片在资源中存放的ID
*@param LPCTSTR sTR 图片在资源中存放的资源标签
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetCtrlIcon( HWND hwnd, UINT nState, UINT uID, LPCTSTR sTR, int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
Image *pImage = ImageFromIDResourceEx( uID, sTR );
if( pImage )
{
SetCtrlIcon( hwnd, nState, pImage, nx, ny, nWidth, nHeight );
delete pImage;
}
return TRUE;
}

private:
typedef struct _STATEIMAGE
{
HWND hWnd; //控件句柄
CTRLTYPE ct; //控件类型
UINT uState; //状态
Image *pImage;//显示图片

_STATEIMAGE():pImage( NULL )
{
}

~_STATEIMAGE()
{
delete pImage;
}

}STATEIMAGE;

CSimpleArray< STATEIMAGE * > m_stImages; //控件状态图片列表

private:

/**
*@method GetControlImage
*@brief 获得控件在指定状态下的图片
*
*@param CTRLTYPE ct 控件类型
*@param UINT uState 控件状态
*@param HWND hwnd 控件句柄,如果该值为NULL,则返回该控件类型对应状态下的图片
*@return Image * 成功返回对应的图片对象,否则返回NULL
*/
Image *GetControlImage( CTRLTYPE ct, UINT uState, HWND hwnd )
{
Image *pImage = NULL;
int nSize = m_stImages.GetSize();
for( int i = 0; i < nSize; i++ )
{
STATEIMAGE *p = m_stImages[i];

//如果获得控件类型对应状态下的图片
if( ( ct == p->ct ) && ( uState == p->uState ) )
{
pImage = p->pImage;
}

if( ( ct == p->ct ) && ( uState == p->uState ) && ( hwnd == p->hWnd ) )
{
return p->pImage;
}
}

return pImage;
}

public:

/**
*@method SetControlImage
*@brief 设置控件在指定状态下的图片
*
*@param CTRLTYPE ct 控件类型
*@param UINT uState 控件状态
*@param Image *pImage 图片对象
*@param HWND hwnd = NULL
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetControlImage( CTRLTYPE ct, UINT uState, Image *pImage, HWND hwnd = NULL,
int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
int nSize = m_stImages.GetSize();
for( int i = 0; i < nSize; i++ )
{
STATEIMAGE *p = m_stImages[i];
if( ( ct == p->ct ) && ( uState == p->uState ) && ( hwnd == p->hWnd ) )
{
delete p;
m_stImages.RemoveAt( i );
break;
}
}

STATEIMAGE *p = new STATEIMAGE;
p->hWnd = hwnd;
p->ct = ct;
p->uState = uState;

//复制图片
int width = nWidth==0?pImage->GetWidth():nWidth;
int height = nHeight==0?pImage->GetHeight():nHeight;

Bitmap bmp( width, height );
Graphics graph( &bmp );

graph.DrawImage( pImage, Rect( 0, 0, width, height ), nx, ny, width, height, UnitPixel );
bmp.Clone(0, 0, width, height, bmp.GetPixelFormat() );
p->pImage = bmp.Clone( 0, 0, width, height, bmp.GetPixelFormat() );

m_stImages.Add( p );

return TRUE;
}

/**
*@method SetControlImage
*@brief 设置控件在指定状态下的图片
*
*@param CTRLTYPE ct 控件类型
*@param UINT uState 控件状态
*@param UINT uID 图片在资源中存放的ID
*@param LPCTSTR sTR 图片在资源中存放的资源标签
*@param HWND hwnd = NULL
*@param int nx = 0 图像范围--左上点的X坐标,默认为0
*@param int ny = 0 图像范围--左上点的Y坐标,默认为0
*@param int nWidth = 0 图像范围--宽度,默认为0,此时为图像的宽度
*@param int nHeight = 0 图像范围--高度,默认为0,此时为图像的高度
*@return BOOL
*/
BOOL SetControlImage( CTRLTYPE ct, UINT uState, UINT uID, LPCTSTR sTR, HWND hwnd = NULL,
int nx = 0, int ny = 0, int nWidth = 0, int nHeight = 0 )
{
Image *pImage = ImageFromIDResourceEx( uID, sTR );
if( NULL == pImage )
return FALSE;

return SetControlImage( ct, uState, pImage, hwnd, nx, ny, nWidth, nHeight );
}

/**
*@method SubclassAllControls
*@brief 将窗口上的所有控件进行关联
*
*@param void
*@return BOOL
*/
BOOL SubclassAllControls( void )
{
T* pT = static_cast< T* > ( this );
return ::EnumChildWindows( pT->m_hWnd, EnumChildProc, ( LPARAM ) this );
}

/**
*@method UnSubclassControl
*@brief 根据控件类型对控件进行关联
*
*@param HWND hwnd hwnd 控件句柄
*@return void
*/
void UnSubclassControl( HWND hwnd )
{
m_vtUnSubclass.push_back( hwnd );
}

/**
*@method SubclassWindow
*@brief 根据控件类型对控件进行关联
*
*@param HWND hwnd 控件句柄
*@param CTRLTYPE ct 控件类型
*@return BOOL
*/
virtual BOOL SubclassWindow( HWND hwnd, CTRLTYPE ct )
{
//判断该句柄是否在不邦定列表中
for( size_t i = 0; i < m_vtUnSubclass.size(); i++ )
{
if( m_vtUnSubclass[i] == hwnd )
{
return TRUE;
}
}

T *pT = static_cast< T * > ( this );
ATL::CWindow cw( hwnd );
if( cw.GetParent().m_hWnd != pT->m_hWnd )
return TRUE;

Image* pImg = NULL;
switch( ct )
{
case CTRL_BUTTON:
{
CQsButton *pCtrl = new CQsButton;
pCtrl->SubclassWindow( hwnd );
m_ctlButtons.Add( pCtrl );

break;
}
case CTRL_CHECKBOX:
{
CQsCheckBox *pCtrl = new CQsCheckBox;
pCtrl->SubclassWindow( hwnd );
m_ctlCheckBoxs.Add( pCtrl );

break;
}
case CTRL_RADIOBOX:
{
CQsRadioBox *pCtrl = new CQsRadioBox;
pCtrl->SubclassWindow( hwnd );
m_ctlRadioBoxs.Add( pCtrl );
break;
}
case CTRL_COMBOBOX:
{
CQsComboBox *pCtrl = new CQsComboBox;
pCtrl->SubclassWindow( hwnd );
m_ctlComboBoxs.Add( pCtrl );
break;
}
case CTRL_EDIT:
{
CQsEdit *pCtrl = new CQsEdit;
pCtrl->SubclassWindow( hwnd );
m_ctlEdits.Add( pCtrl );
break;
}
case CTRL_PROGRESS:
{
CQSProgressBar *pCtrl = new CQSProgressBar;
pCtrl->SubclassWindow( hwnd );

m_ctlProgs.Add( pCtrl );
break;
}
case CTRL_STATIC:
{
CQsStatic *pCtrl = new CQsStatic;
pCtrl->SubclassWindow( hwnd );

m_ctlStaCtrls.Add( pCtrl );
break;
}
}

return TRUE;
}

/**
*@method EnumChildProc
*@brief 控件遍历回调函数
*
*@param HWND hwnd
*@param LPARAM lParam
*@return BOOL CALLBACK
*/
static BOOL CALLBACK EnumChildProc( HWND hwnd, LPARAM lParam )
{
CQsSkinWindowUI< T, _bIsChildWnd > *pThis = ( CQsSkinWindowUI< T, _bIsChildWnd > * )lParam;

CString strClass;
GetClassName( hwnd, strClass.GetBuffer( 64 ), 64 );

strClass.MakeUpper();

if( strClass == _T("BUTTON") )
{
LONG lStyle = GetWindowLong( hwnd, GWL_STYLE );

if( ( lStyle & BS_CHECKBOX ) == BS_CHECKBOX )
{
return pThis->SubclassWindow( hwnd, CTRL_CHECKBOX );
}
else if( ( lStyle & BS_AUTOCHECKBOX ) == BS_AUTOCHECKBOX )
{
return pThis->SubclassWindow( hwnd, CTRL_CHECKBOX );
}
else if( ( lStyle & BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON )
{
return pThis->SubclassWindow( hwnd, CTRL_RADIOBOX );
}
else if( ( lStyle & BS_GROUPBOX ) == BS_GROUPBOX )
{

}
else if( ( lStyle & BS_RADIOBUTTON ) == BS_RADIOBUTTON )
{
return pThis->SubclassWindow( hwnd, CTRL_RADIOBOX );
}
else
{
return pThis->SubclassWindow( hwnd, CTRL_BUTTON );
}

}
else if( strClass == _T( "COMBOBOX" ) )
{
return pThis->SubclassWindow( hwnd, CTRL_COMBOBOX );
}
else if( strClass == _T( "EDIT" ) )
{
return pThis->SubclassWindow( hwnd, CTRL_EDIT );
}
else if( strClass == _T( "MSCTLS_PROGRESS32" ) )
{
return pThis->SubclassWindow( hwnd, CTRL_PROGRESS );
}
else if( strClass == _T( "SCROLLBAR" ) )
{
return pThis->SubclassWindow( hwnd, CTRL_SCROLLBAR );
}
else if( strClass == _T( "SYSTABCONTROL32" ) )
{
return pThis->SubclassWindow( hwnd, CTRL_TABCTRL );
}
else if( strClass == _T( "STATIC" ) )
{
return pThis->SubclassWindow( hwnd, CTRL_STATIC );
}

return TRUE;
}

/**
*@method ImageFromIDResourceEx
*@brief 从资源中读取图像
*
*@param UINT nID 资源ID
*@param LPCTSTR sTR 资源标签名
*@return Image * 成功返回读取到的图片对象,否则返回NULL
*/
Image *ImageFromIDResourceEx(UINT nID, LPCTSTR sTR)
{
Image *pImage;
HINSTANCE hIns = _AtlBaseModule.GetResourceInstance();
HRSRC hRsrc = ::FindResource (hIns,MAKEINTRESOURCE(nID),sTR); // type
if (!hRsrc)
return NULL;

// load resource into memory
DWORD len = SizeofResource(hIns, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hIns, hRsrc);
if (!lpRsrc)
return NULL;

// Allocate global memory on which to create stream
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
IStream* pstm;

memcpy(pmem,lpRsrc,len);
if(CreateStreamOnHGlobal(m_hMem,FALSE,&pstm) != S_OK)
return NULL;

// load from stream
pImage=Gdiplus::Image::FromStream(pstm);

GlobalUnlock(m_hMem);
pstm->Release();
FreeResource(lpRsrc);

GlobalFree(m_hMem);

return pImage;
}

/**
*@method SetCtrlText
*@brief 设置控件显示文字
*
*@param int nCtrlID 控件ID
*@param LPCTSTR strText 要设置的文字
*@return BOOL
*/
BOOL SetCtrlText( int nCtrlID, LPCTSTR strText )
{
T *pT = static_cast< T* >( this );
ATL::CWindow cw = pT->GetDlgItem( nCtrlID );
if( !cw.IsWindow() )
return FALSE;

WTL::CString strClass;
GetClassName( cw.m_hWnd, strClass.GetBuffer( 64 ), 64 );
strClass.MakeUpper();

if( strClass == _T( "COMBOBOX" ) )
{
DWORD dwStyle = cw.GetWindowLong( GWL_STYLE );
if( ( dwStyle & CBS_DROPDOWNLIST ) )
{
WTL::CComboBox cb = cw.m_hWnd;
for( int i = 0; i < cb.GetCount(); i++ )
{
WTL::CString strTemp;
cb.GetLBText( i, strTemp );
if( strTemp == strText )
{
cb.SetCurSel( i );
break;
}
}
}
else
{
cw.SetWindowText( strText );

CRect rc;
cw.GetWindowRect( rc );
pT->ScreenToClient( rc );
pT->InvalidateRect( rc, TRUE );

}
}
else
{
cw.SetWindowText( strText );

CRect rc;
cw.GetWindowRect( rc );
pT->ScreenToClient( rc );
pT->InvalidateRect( rc, TRUE );
}


return TRUE;
}

/**
*@method SetCtrlText
*@brief 设置控件显示文字
*
*@param int nCtrlID 控件ID
*@param int nTextID 要设置的文字在资源中的ID
*@return BOOL
*/
BOOL SetCtrlText( int nCtrlID, int nTextID )
{
CString strText;
strText.LoadString( nTextID );

return SetCtrlText( nCtrlID, strText );
}

/**
*@method GetCtrlText
*@brief 获得控件文字
*
*@param int nCtrlID 控件ID
*@return WTL::CString 控件文字
*/
CString GetCtrlText( int nCtrlID )
{
CString strText;

T* pT = static_cast< T* >( this );
ATL::CWindow cw = pT->GetDlgItem( nCtrlID );
if( !cw.IsWindow() )
return strText;

int len = cw.GetWindowTextLength() + 1;
cw.GetWindowText( strText.GetBuffer( len ), len );
strText.ReleaseBuffer();

return strText;
}

/**
*@method SetCtrlFont
*@brief 设置控件制定状态下文字字体
*
*@param int nCtrlID 控件ID
*@param UINT uState = 0 状态ID
*@param LPCTSTR lpszFaceName = _T("宋体") 字体
*@param int nHeight = 12 字体高度
*@param int fnWeight = FW_NORMAL
*@param BYTE bItalic = FALSE 斜体字
*@param BYTE bUnderline = FALSE 下划线
*@param BYTE bStrikeOut = FALSE 删除线
*@return BOOL
*/
BOOL SetCtrlFont( int nCtrlID, UINT uState = 0, LPCTSTR lpszFaceName = _T( "宋体" ),
int nHeight = 12, int fnWeight = FW_NORMAL, BYTE bItalic = FALSE,
BYTE bUnderline = FALSE, BYTE bStrikeOut = FALSE )
{
T *pT = static_cast< T* >( this );
HWND hwnd = pT->GetDlgItem( nCtrlID );

CCtrlImageMgr *pcim = ( CCtrlImageMgr* )GetCustomObjectEx( hwnd );
if( pcim )
{
pcim->SetStateFont( uState, lpszFaceName, nHeight, fnWeight, bItalic, bUnderline, bStrikeOut );
return TRUE;
}
else
{
return FALSE;
}

}

/**
*@method SetFontColor
*@brief 设置指定状态下字体的颜色
*
*@param HWND hwnd 控件句柄
*@param UINT uState 状态值
*@param COLORREF rgb 字体颜色
*@return BOOL
*/
BOOL SetFontColor( HWND hwnd, UINT uState, COLORREF rgb )
{
CCtrlImageMgr *pcim = ( CCtrlImageMgr* )GetCustomObjectEx( hwnd );
if( pcim )
{
pcim->SetFontColor( uState, rgb );
return TRUE;
}
else
{
return FALSE;
}

}

/**
*@method SetFontColor
*@brief 设置指定状态下字体的颜色
*
*@param int nCtrlID 控件ID
*@param UINT uState 状态值
*@param COLORREF rgb 字体颜色
*@return BOOL
*/
BOOL SetFontColor( int nCtrlID, UINT uState, COLORREF rgb )
{
T *pT = static_cast< T* >( this );
HWND hwnd = pT->GetDlgItem( nCtrlID );

return SetFontColor( hwnd, uState, rgb );
}

void ReDraw( )
{
delete m_pBKImage;
m_pBKImage = NULL;

T *pT = static_cast< T* >( this );
if ( pT->IsWindow())
{
pT->Invalidate( );

HWND hChild = FindWindowEx( pT->m_hWnd, NULL, NULL, NULL );
while ( NULL != hChild )
{
::SendMessage( hChild, WM_REDRAWBKGND, 0, 0 );
hChild = FindWindowEx( pT->m_hWnd, hChild, NULL, NULL );
}
}
}
};