WTL 界面设计篇(CSkinDialog)

头文件声明(CSkinDialog.h):

#pragma once

#include <gdiplus.h>
#include "SkinManager.h"

class CSkinDialog : public CWindowImpl<CSkinDialog, CWindow>
{
public:
	CSkinDialog(void);
	~CSkinDialog(void);

	BEGIN_MSG_MAP_EX(CSkinDialog)
		MSG_WM_CREATE(OnCreate)
		MSG_WM_NCCREATE(OnNcCreate)
		MSG_WM_INITDIALOG(OnInitDialog)
		MSG_WM_NCHITTEST(OnNcHitTest)
		MSG_WM_NCCALCSIZE(OnNcCalcSize)
		MSG_WM_NCACTIVATE(OnNcActivate)
		MSG_WM_NCPAINT(OnNcPaint)
		MSG_WM_ERASEBKGND(OnEraseBkgnd)
		MSG_WM_PAINT(OnPaint)
		MSG_WM_LBUTTONDOWN(OnLButtonDown)
		MSG_WM_LBUTTONUP(OnLButtonUp)
		MSG_WM_MOUSEMOVE(OnMouseMove)
		MSG_WM_MOUSELEAVE(OnMouseLeave)
		MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
		MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
		MSG_WM_SIZE(OnSize)
		MSG_WM_DESTROY(OnDestroy)
	END_MSG_MAP()

public:
	void SetBgColor(COLORREF clrBg);
	BOOL SetBgPic(LPCTSTR lpFileName);
	BOOL SetBgPic(LPCTSTR lpFileName, const CRect& rcNinePart);
	BOOL SetTitleBarBgPic(LPCTSTR lpFileName);
	BOOL SetTitleBarBgPic(LPCTSTR lpFileName, const CRect& rcNinePart);
	BOOL SetMinSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown);
	BOOL SetMaxSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown);
	BOOL SetRestoreSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown);
	BOOL SetCloseSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown);
	BOOL SetTitleText(LPCTSTR lpszText);
	CString GetTitleText();
	HDC GetBgDC();
	
	BOOL SubclassWindow(HWND hWnd);

private:
	BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct);
	int OnCreate(LPCREATESTRUCT lpCreateStruct);
	BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
	BOOL OnNcActivate(BOOL bActive);
	UINT OnNcHitTest(CPoint point);
	LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam);
	void OnNcPaint(CRgnHandle rgn);
	BOOL OnEraseBkgnd(CDCHandle dc);
	void OnPaint(CDCHandle dc);
	void OnLButtonDown(UINT nFlags, CPoint point);
	void OnLButtonUp(UINT nFlags, CPoint point);
	void OnMouseMove(UINT nFlags, CPoint point);
	void OnMouseLeave();
	void OnLButtonDblClk(UINT nFlags, CPoint point);
	void OnGetMinMaxInfo(LPMINMAXINFO lpMMI);
	void OnSize(UINT nType, CSize size);
	void OnDestroy();

	void CalcTitleBarRect();
	int HitTest(POINT pt);
	BOOL StartTrackMouseLeave();

private:
	BOOL m_bHasTitleBar;
	BOOL m_bHasMinBtn, m_bHasMaxBtn, m_bHasCloseBtn;
	BOOL m_bSizeBox;

	CRect m_rcTitleBar;
	CRect m_rcMinBtn, m_rcMaxBtn, m_rcCloseBtn;

	BOOL m_bMouseTracking;
	BOOL m_bMinBtnPress, m_bMinBtnHover;
	BOOL m_bMaxBtnPress, m_bMaxBtnHover;
	BOOL m_bCloseBtnPress, m_bCloseBtnHover;

	COLORREF m_clrBg;
	CImageEx * m_lpBgImg;
	CImageEx * m_lpTitleBarBgImg;
	CImageEx * m_lpMinSysBtnImgN, * m_lpMinSysBtnImgH, * m_lpMinSysBtnImgD;
	CImageEx * m_lpMaxSysBtnImgN, * m_lpMaxSysBtnImgH, * m_lpMaxSysBtnImgD;
	CImageEx * m_lpRestoreSysBtnImgN, * m_lpRestoreSysBtnImgH, * m_lpRestoreSysBtnImgD;
	CImageEx * m_lpCloseSysBtnImgN, * m_lpCloseSysBtnImgH, * m_lpCloseSysBtnImgD;

	CString m_strTitleText;

	HDC m_hMemDC;
	HBITMAP m_hMemBmp, m_hOldBmp;
};

源码实现(CSkinDialog.cpp):

#include "StdAfx.h"
#include "SkinDialog.h"


#ifdef DrawEclosionText

// 绘制羽化文字
void DrawEclosionText(HDC hDC, LPCTSTR lpszText, LPCTSTR lpszFontName, int nFontSize)
{
	int nWidth = 56, nHeight = 16;

	Gdiplus::Bitmap bmp(nWidth, nHeight, 0, PixelFormat32bppARGB, NULL);
	Gdiplus::Graphics graphics(&bmp);
	Gdiplus::GraphicsPath path(Gdiplus::FillModeAlternate);
	Gdiplus::FontFamily fontFamily(lpszFontName, NULL);
	Gdiplus::StringFormat strFmt(0, 0);

	Gdiplus::RectF rc(0.0f, 0.0f, nWidth, nHeight);
	path.AddString(lpszText, -1, &fontFamily, Gdiplus::FontStyleBold, nFontSize, rc, &strFmt);

	Gdiplus::Matrix matrix(1.0f/* / 5.0f*/, 0.0f, 0.0f, 1.0f/* / 5.0f*/, -1.0f/* / 5.0f*/, -1.0f/* / 5.0f*/);
	
	graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
	graphics.SetTransform(&matrix);

	Gdiplus::Color color((Gdiplus::ARGB)0x55CCE0EE);
	Gdiplus::Pen pen(color, 3);

	graphics.DrawPath(&pen, &path);

	Gdiplus::Color color2((Gdiplus::ARGB)0x55CCE0EE);
	Gdiplus::SolidBrush brush(color2);

	graphics.FillPath(&brush, &path);

 	Gdiplus::Bitmap bmp2(300, 40, 0, PixelFormat32bppARGB, NULL);
 	Gdiplus::Graphics graphics2(&bmp2);
 
 	graphics2.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
 	graphics2.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
 	graphics2.DrawImage(&bmp, 0, 0, nWidth, nHeight);
 
 	Gdiplus::Color color3((Gdiplus::ARGB)0xFF000000);
 	Gdiplus::SolidBrush brush2(color3);
 
 	graphics2.FillPath(&brush2, &path);

	CLSID clsid;
	::CLSIDFromString(_T("{557CF406-1A04-11D3-9A73-0000F81EF32E}"), &clsid);
	bmp2.Save(_T("c:\\CoolText.png"), &clsid, NULL);

	Gdiplus::Graphics graphics3(hDC);

	graphics3.DrawImage(&bmp2, 8, 4);
}
#endif

CSkinDialog::CSkinDialog(void)
{
	m_bHasTitleBar = TRUE;
	m_bHasMinBtn = m_bHasMaxBtn = m_bHasCloseBtn = TRUE;
	m_bSizeBox = TRUE;

	m_rcTitleBar = CRect(0,0,0,0);
	m_rcMinBtn = m_rcMaxBtn = m_rcCloseBtn = CRect(0,0,0,0);

	m_bMouseTracking = FALSE;
	m_bMinBtnPress = m_bMinBtnHover = FALSE;
	m_bMaxBtnPress = m_bMaxBtnHover = FALSE;
	m_bCloseBtnPress = m_bCloseBtnHover = FALSE;

	m_clrBg = ::GetSysColor(COLOR_BTNFACE);

	m_lpBgImg = NULL;
	m_lpTitleBarBgImg = NULL;
	m_lpMinSysBtnImgN = m_lpMinSysBtnImgH = m_lpMinSysBtnImgD = NULL;
	m_lpMaxSysBtnImgN = m_lpMaxSysBtnImgH = m_lpMaxSysBtnImgD = NULL;
	m_lpRestoreSysBtnImgN = m_lpRestoreSysBtnImgH = m_lpRestoreSysBtnImgD = NULL;
	m_lpCloseSysBtnImgN = m_lpCloseSysBtnImgH = m_lpCloseSysBtnImgD = NULL;

	m_hMemDC = NULL;
	m_hMemBmp = m_hOldBmp = NULL;
}

CSkinDialog::~CSkinDialog(void)
{
}

void CSkinDialog::SetBgColor(COLORREF clrBg)
{
	m_clrBg = clrBg;
}

BOOL CSkinDialog::SetBgPic(LPCTSTR lpFileName)
{
	return SetBgPic(lpFileName, CRect(0,0,0,0));
}

BOOL CSkinDialog::SetBgPic(LPCTSTR lpFileName, const CRect& rcNinePart)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpBgImg);

	m_lpBgImg = CSkinManager::GetInstance()->GetImage(lpFileName);

	if (m_lpBgImg != NULL)
		m_lpBgImg->SetNinePart(rcNinePart);

	return (NULL == m_lpBgImg) ? FALSE : TRUE;
}

BOOL CSkinDialog::SetTitleBarBgPic(LPCTSTR lpFileName)
{
	return SetTitleBarBgPic(lpFileName, CRect(0,0,0,0));
}

BOOL CSkinDialog::SetTitleBarBgPic(LPCTSTR lpFileName, const CRect& rcNinePart)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpTitleBarBgImg);

	m_lpTitleBarBgImg = CSkinManager::GetInstance()->GetImage(lpFileName);

	if (m_lpTitleBarBgImg != NULL)
		m_lpTitleBarBgImg->SetNinePart(rcNinePart);

	return (NULL == m_lpTitleBarBgImg) ? FALSE : TRUE;
}

BOOL CSkinDialog::SetMinSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpMinSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMinSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMinSysBtnImgD);

	m_lpMinSysBtnImgN = CSkinManager::GetInstance()->GetImage(lpNormal);
	m_lpMinSysBtnImgH = CSkinManager::GetInstance()->GetImage(lpHighlight);
	m_lpMinSysBtnImgD = CSkinManager::GetInstance()->GetImage(lpDown);

	if (NULL == m_lpMinSysBtnImgN || 
		NULL == m_lpMinSysBtnImgH || NULL == m_lpMinSysBtnImgD)
		return FALSE;
	else
		return TRUE;
}

BOOL CSkinDialog::SetMaxSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpMaxSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMaxSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMaxSysBtnImgD);

	m_lpMaxSysBtnImgN = CSkinManager::GetInstance()->GetImage(lpNormal);
	m_lpMaxSysBtnImgH = CSkinManager::GetInstance()->GetImage(lpHighlight);
	m_lpMaxSysBtnImgD = CSkinManager::GetInstance()->GetImage(lpDown);

	if (NULL == m_lpMaxSysBtnImgN || 
		NULL == m_lpMaxSysBtnImgH || NULL == m_lpMaxSysBtnImgD)
		return FALSE;
	else
		return TRUE;
}

BOOL CSkinDialog::SetRestoreSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpRestoreSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpRestoreSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpRestoreSysBtnImgD);

	m_lpRestoreSysBtnImgN = CSkinManager::GetInstance()->GetImage(lpNormal);
	m_lpRestoreSysBtnImgH = CSkinManager::GetInstance()->GetImage(lpHighlight);
	m_lpRestoreSysBtnImgD = CSkinManager::GetInstance()->GetImage(lpDown);

	if (NULL == m_lpRestoreSysBtnImgN || 
		NULL == m_lpRestoreSysBtnImgH || NULL == m_lpRestoreSysBtnImgD)
		return FALSE;
	else
		return TRUE;
}

BOOL CSkinDialog::SetCloseSysBtnPic(LPCTSTR lpNormal, LPCTSTR lpHighlight, LPCTSTR lpDown)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpCloseSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpCloseSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpCloseSysBtnImgD);

	m_lpCloseSysBtnImgN = CSkinManager::GetInstance()->GetImage(lpNormal);
	m_lpCloseSysBtnImgH = CSkinManager::GetInstance()->GetImage(lpHighlight);
	m_lpCloseSysBtnImgD = CSkinManager::GetInstance()->GetImage(lpDown);

	if (NULL == m_lpCloseSysBtnImgN || 
		NULL == m_lpCloseSysBtnImgH || NULL == m_lpCloseSysBtnImgD)
		return FALSE;
	else
		return TRUE;
}

BOOL CSkinDialog::SetTitleText(LPCTSTR lpszText)
{
	m_strTitleText = lpszText;
	SetWindowText(lpszText);
	if (IsWindowVisible())
		Invalidate();
	return TRUE;
}

CString CSkinDialog::GetTitleText()
{
	return m_strTitleText;
}

HDC CSkinDialog::GetBgDC()
{
	return m_hMemDC;
}

BOOL CSkinDialog::SubclassWindow(HWND hWnd)
{
	__super::SubclassWindow(hWnd);

	DWORD dwStyle = GetStyle();

	m_bHasMinBtn = dwStyle & WS_MINIMIZEBOX;
	m_bHasMaxBtn = dwStyle & WS_MAXIMIZEBOX;
	m_bHasCloseBtn = dwStyle & WS_CAPTION;
	m_bSizeBox = dwStyle & WS_SIZEBOX;

	dwStyle &= ~WS_CAPTION;
	dwStyle &= ~DS_3DLOOK;
	dwStyle &= ~DS_FIXEDSYS;
	dwStyle &= ~WS_CLIPCHILDREN;	// WS_CLIPCHILDREN:裁剪子窗口样式,如果设置了该样式,在父窗口重绘时就不会绘制子窗口区域
//	dwStyle |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
	SetWindowLong(GWL_STYLE, dwStyle);

	DWORD dwStyleEx = GetExStyle();
	dwStyleEx = WS_EX_STATICEDGE | WS_EX_APPWINDOW;
	SetWindowLong(GWL_EXSTYLE, dwStyleEx);

	SetWindowPos(NULL, 0, 0, 0, 0, 
		SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

	m_bMouseTracking = FALSE;
	m_bMinBtnPress = m_bMinBtnHover = FALSE;
	m_bMaxBtnPress = m_bMaxBtnHover = FALSE;
	m_bCloseBtnPress = m_bCloseBtnHover = FALSE;

	CalcTitleBarRect();

	CRect rcClient;
	GetClientRect(&rcClient);

	HDC hDC = ::GetDC(m_hWnd);
	m_hMemDC = ::CreateCompatibleDC(hDC);
	m_hMemBmp = ::CreateCompatibleBitmap(hDC, rcClient.Width(), rcClient.Height());
	m_hOldBmp = (HBITMAP)::SelectObject(m_hMemDC, m_hMemBmp);
	::ReleaseDC(m_hWnd, hDC);

	return TRUE;
}

BOOL CSkinDialog::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
	return 1;
}

int CSkinDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	DWORD dwStyle = GetStyle();

	m_bHasMinBtn = dwStyle & WS_MINIMIZEBOX;
	m_bHasMaxBtn = dwStyle & WS_MAXIMIZEBOX;
	m_bHasCloseBtn = dwStyle & WS_CAPTION;
	m_bSizeBox = dwStyle & WS_SIZEBOX;

	dwStyle &= ~WS_CAPTION;
	dwStyle &= ~DS_3DLOOK;
	dwStyle &= ~DS_FIXEDSYS;
	dwStyle |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
	SetWindowLong(GWL_STYLE, dwStyle);

	DWORD dwStyleEx = GetExStyle();
	dwStyleEx = WS_EX_STATICEDGE | WS_EX_APPWINDOW;
	SetWindowLong(GWL_EXSTYLE, dwStyleEx);

	SetWindowPos(NULL, 0, 0, 0, 0, 
		SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

	CalcTitleBarRect();

	return TRUE;
}

BOOL CSkinDialog::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
	DWORD dwStyle = GetStyle();

	m_bHasMinBtn = dwStyle & WS_MINIMIZEBOX;
	m_bHasMaxBtn = dwStyle & WS_MAXIMIZEBOX;
	m_bHasCloseBtn = dwStyle & WS_CAPTION;
	m_bSizeBox = dwStyle & WS_SIZEBOX;

	dwStyle &= ~WS_CAPTION;
	dwStyle &= ~DS_3DLOOK;
	dwStyle &= ~DS_FIXEDSYS;
	dwStyle |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
	SetWindowLong(GWL_STYLE, dwStyle);

	DWORD dwStyleEx = GetExStyle();
	dwStyleEx = WS_EX_STATICEDGE | WS_EX_APPWINDOW;
	SetWindowLong(GWL_EXSTYLE, dwStyleEx);

	SetWindowPos(NULL, 0, 0, 0, 0, 
		SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

	CalcTitleBarRect();

	return TRUE;
}

BOOL CSkinDialog::OnNcActivate(BOOL bActive)
{
	if (IsIconic())
		SetMsgHandled(FALSE);
	return (bActive == FALSE) ? TRUE : FALSE;
}

UINT CSkinDialog::OnNcHitTest(CPoint point)
{
	ScreenToClient(&point);

	int nHitTest = HitTest(point);
	if (nHitTest != HTMINBUTTON && nHitTest != HTMAXBUTTON
		&& nHitTest != HTCLOSE && nHitTest != HTCAPTION)
		return nHitTest;
	else
		return HTCLIENT;
}

LRESULT CSkinDialog::OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
{
	if (bCalcValidRects)
	{
		CRect rcWindow;

		GetWindowRect(rcWindow);

		LPNCCALCSIZE_PARAMS pParam = (LPNCCALCSIZE_PARAMS)lParam;

		if (SWP_NOSIZE == (SWP_NOSIZE & pParam->lppos->flags))
			return 0;

		if (0 == (SWP_NOMOVE & pParam->lppos->flags))
		{
			rcWindow.left = pParam->lppos->x;
			rcWindow.top = pParam->lppos->y;
		}

		rcWindow.right = rcWindow.left + pParam->lppos->cx;
		rcWindow.bottom = rcWindow.top + pParam->lppos->cy;
		pParam->rgrc[0] = rcWindow;
		pParam->rgrc[1] = pParam->rgrc[0];
	}

	return 0;
}

void CSkinDialog::OnNcPaint(CRgnHandle rgn)
{
	return;
}

BOOL CSkinDialog::OnEraseBkgnd(CDCHandle dc)
{
	return TRUE;
}

void CSkinDialog::OnPaint(CDCHandle dc)
{
	CPaintDC PaintDC(m_hWnd);

	CRect rcClient;
	GetClientRect(&rcClient);

	int cx = 0, cy = 0;

	if (m_hMemBmp != NULL)
	{
		BITMAP bmpInfo = {0};
		::GetObject(m_hMemBmp, sizeof(BITMAP), &bmpInfo);
		cx = bmpInfo.bmWidth;
		cy = bmpInfo.bmHeight;
	}

	if (rcClient.Width() != cx || rcClient.Height() != cy)
	{
		if (m_hMemDC != NULL && m_hMemBmp != NULL)
		{
			::SelectObject(m_hMemDC, m_hOldBmp);
			::DeleteObject(m_hMemBmp);
		}

		m_hMemBmp = ::CreateCompatibleBitmap(PaintDC.m_hDC, rcClient.Width(), rcClient.Height());
		m_hOldBmp = (HBITMAP)::SelectObject(m_hMemDC, m_hMemBmp);
	}

	CDCHandle MemDC(m_hMemDC);

	if (m_lpBgImg != NULL && !m_lpBgImg->IsNull())	// 填充背景图片
	{
		m_lpBgImg->Draw2(MemDC.m_hDC, rcClient);
	}
	else	// 填充背景颜色
	{
		MemDC.FillSolidRect(&rcClient, m_clrBg);
	}

	if (m_lpTitleBarBgImg != NULL && !m_lpTitleBarBgImg->IsNull())	// 填充标题栏背景图片
	{
		m_lpTitleBarBgImg->Draw2(MemDC.m_hDC, m_rcTitleBar);
	}

// 	HPEN hPen = ::CreatePen(PS_SOLID | PS_INSIDEFRAME, 1, RGB(62, 114, 132));
// 	HPEN hOldPen = MemDC.SelectPen(hPen);
// 	HBRUSH hOldBrush = MemDC.SelectBrush((HBRUSH)::GetStockObject(NULL_BRUSH));
// 	MemDC.RoundRect(rcClient.left, rcClient.top, 
// 		rcClient.right, rcClient.bottom, 4, 4);
// 	MemDC.SelectPen(hOldPen);
// 	MemDC.SelectBrush(hOldBrush);
// 	::DeleteObject(hPen);

	if (m_bHasMinBtn)	// 绘制最小化按钮
	{
		if (m_bMinBtnPress)
		{
			if (m_lpMinSysBtnImgD != NULL && !m_lpMinSysBtnImgD->IsNull())
				m_lpMinSysBtnImgD->Draw(MemDC.m_hDC, m_rcMinBtn);
		}
		else if(m_bMinBtnHover)
		{
			if (m_lpMinSysBtnImgH != NULL && !m_lpMinSysBtnImgH->IsNull())
				m_lpMinSysBtnImgH->Draw(MemDC.m_hDC, m_rcMinBtn);
		}
		else
		{
			if (m_lpMinSysBtnImgN != NULL && !m_lpMinSysBtnImgN->IsNull())
				m_lpMinSysBtnImgN->Draw(MemDC.m_hDC, m_rcMinBtn);
		}
	}

	if (m_bHasMaxBtn)	// 绘制最大化按钮
	{
		if (IsZoomed())		// 窗口最大化标志
		{
			if (m_bMaxBtnPress)
			{
				if (m_lpRestoreSysBtnImgD != NULL && !m_lpRestoreSysBtnImgD->IsNull())
					m_lpRestoreSysBtnImgD->Draw(MemDC.m_hDC, m_rcMaxBtn);
			}
			else if(m_bMaxBtnHover)
			{
				if (m_lpRestoreSysBtnImgH != NULL && !m_lpRestoreSysBtnImgH->IsNull())
					m_lpRestoreSysBtnImgH->Draw(MemDC.m_hDC, m_rcMaxBtn);
			}
			else
			{
				if (m_lpRestoreSysBtnImgN != NULL && !m_lpRestoreSysBtnImgN->IsNull())
					m_lpRestoreSysBtnImgN->Draw(MemDC.m_hDC, m_rcMaxBtn);
			}
		}
		else
		{
			if (m_bMaxBtnPress)
			{
				if (m_lpMaxSysBtnImgD != NULL && !m_lpMaxSysBtnImgD->IsNull())
					m_lpMaxSysBtnImgD->Draw(MemDC.m_hDC, m_rcMaxBtn);
			}
			else if(m_bMaxBtnHover)
			{
				if (m_lpMaxSysBtnImgH != NULL && !m_lpMaxSysBtnImgH->IsNull())
					m_lpMaxSysBtnImgH->Draw(MemDC.m_hDC, m_rcMaxBtn);
			}
			else
			{
				if (m_lpMaxSysBtnImgN != NULL && !m_lpMaxSysBtnImgN->IsNull())
					m_lpMaxSysBtnImgN->Draw(MemDC.m_hDC, m_rcMaxBtn);
			}
		}
	}

	if (m_bHasCloseBtn)	// 绘制关闭按钮
	{
		if (m_bCloseBtnPress)
		{
			if (m_lpCloseSysBtnImgD != NULL && !m_lpCloseSysBtnImgD->IsNull())
				m_lpCloseSysBtnImgD->Draw(MemDC.m_hDC, m_rcCloseBtn);
		}
		else if(m_bCloseBtnHover)
		{
			if (m_lpCloseSysBtnImgH != NULL && !m_lpCloseSysBtnImgH->IsNull())
				m_lpCloseSysBtnImgH->Draw(MemDC.m_hDC, m_rcCloseBtn);
		}
		else
		{
			if (m_lpCloseSysBtnImgN != NULL && !m_lpCloseSysBtnImgN->IsNull())
				m_lpCloseSysBtnImgN->Draw(MemDC.m_hDC, m_rcCloseBtn);
		}
	}

	int nTitleTextLen = m_strTitleText.GetLength();
	if (nTitleTextLen > 0)
	{
		//DrawEclosionText(MemDC.m_hDC, m_strTitleText, _T("微软雅黑"), 12);

 		CRect rcText(m_rcTitleBar);
 		rcText.left += 8;
 
 		NONCLIENTMETRICS nif;						//创建标题栏字体对象
 		nif.cbSize = sizeof(nif);
 		::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nif, 0);
 		HFONT hFont = ::CreateFontIndirect(&nif.lfSmCaptionFont);
 
 		int nMode = ::SetBkMode(MemDC.m_hDC, TRANSPARENT);
 		HFONT hOldFont = (HFONT)::SelectObject(MemDC.m_hDC, hFont);
 		::DrawText(MemDC.m_hDC, m_strTitleText, nTitleTextLen, 
 			&rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS);
 		::SelectObject(MemDC.m_hDC, hOldFont);
 		::SetBkMode(MemDC.m_hDC, nMode);
 
 		::DeleteObject(hFont);
	}

	::BitBlt(PaintDC.m_hDC, 0, 0, rcClient.Width(), rcClient.Height(), m_hMemDC, 0, 0, SRCCOPY);
}

void CSkinDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
	int nHitTest = HitTest(point);

	if (nHitTest == HTMINBUTTON || nHitTest == HTMAXBUTTON
		|| nHitTest == HTCLOSE)
	{
		::SetCapture(m_hWnd);

		CRect rcSysBtn(0,0,0,0);
		rcSysBtn.UnionRect(&m_rcMinBtn, &m_rcMaxBtn);
		rcSysBtn.UnionRect(&rcSysBtn, &m_rcCloseBtn);
		
		if (nHitTest == HTMINBUTTON)
		{
			m_bMinBtnPress = TRUE;
			InvalidateRect(&rcSysBtn);
		}
		else if (nHitTest == HTMAXBUTTON)
		{
			m_bMaxBtnPress = TRUE;
			InvalidateRect(&rcSysBtn);
		}
		else if (nHitTest == HTCLOSE)
		{
			m_bCloseBtnPress = TRUE;
			InvalidateRect(&rcSysBtn);
		}
	}
	else if (nHitTest == HTCAPTION)
	{
		if (!IsZoomed())
			SendMessage(WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
	}

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnLButtonUp(UINT nFlags, CPoint point)
{
	int nHitTest = HitTest(point);

	HWND hWnd = ::GetCapture();
	if (m_hWnd == hWnd)
		::ReleaseCapture();

	CRect rcSysBtn(0,0,0,0);
	rcSysBtn.UnionRect(&m_rcMinBtn, &m_rcMaxBtn);
	rcSysBtn.UnionRect(&rcSysBtn, &m_rcCloseBtn);

	if (nHitTest == HTMINBUTTON && m_bMinBtnPress)
	{
		m_bMinBtnPress = FALSE;
		InvalidateRect(&rcSysBtn);
		SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
	}
	else if (nHitTest == HTMAXBUTTON && m_bMaxBtnPress)
	{
		m_bMaxBtnPress = FALSE;
		InvalidateRect(&rcSysBtn);

		if (IsZoomed())
			SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0);
		else
			SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
	}
	else if (nHitTest == HTCLOSE && m_bCloseBtnPress)
	{
		m_bCloseBtnPress = FALSE;
		InvalidateRect(&rcSysBtn);

		SendMessage(WM_SYSCOMMAND, SC_CLOSE, 0);
	}
	else
	{
		if (m_bMinBtnPress || m_bMaxBtnPress || m_bCloseBtnPress)
		{
			m_bMinBtnPress = FALSE;
			m_bMaxBtnPress = FALSE;
			m_bCloseBtnPress = FALSE;
			InvalidateRect(&rcSysBtn);
		}
	}

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnMouseMove(UINT nFlags, CPoint point)
{
	CRect rcSysBtn(0,0,0,0);
	rcSysBtn.UnionRect(&m_rcMinBtn, &m_rcMaxBtn);
	rcSysBtn.UnionRect(&rcSysBtn, &m_rcCloseBtn);

	int nHitTest = HitTest(point);
	if (nHitTest == HTMINBUTTON || nHitTest == HTMAXBUTTON
		|| nHitTest == HTCLOSE)
	{
		if (!(m_bMinBtnPress || m_bMaxBtnPress
			|| m_bCloseBtnPress))
		{
			if (!m_bMouseTracking)
			{
				StartTrackMouseLeave();
				m_bMouseTracking = TRUE;
			}

			if (nHitTest == HTMINBUTTON)
			{
				if (!m_bMinBtnHover)
				{
					m_bMinBtnHover = TRUE;
					m_bMaxBtnHover = FALSE;
					m_bCloseBtnHover = FALSE;
					InvalidateRect(&rcSysBtn);
				}
			}
			else if (nHitTest == HTMAXBUTTON)
			{
				if (!m_bMaxBtnHover)
				{
					m_bMinBtnHover = FALSE;
					m_bMaxBtnHover = TRUE;
					m_bCloseBtnHover = FALSE;
					InvalidateRect(&rcSysBtn);
				}
			}
			else if (nHitTest == HTCLOSE)
			{
				if (!m_bCloseBtnHover)
				{
					m_bMinBtnHover = FALSE;
					m_bMaxBtnHover = FALSE;
					m_bCloseBtnHover = TRUE;
					InvalidateRect(&rcSysBtn);
				}
			}
		}
	}
	else
	{
		if (m_bMinBtnHover || m_bMaxBtnHover || m_bCloseBtnHover)
		{
			m_bMinBtnHover = FALSE;
			m_bMaxBtnHover = FALSE;
			m_bCloseBtnHover = FALSE;
			InvalidateRect(&rcSysBtn);
		}
	}

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnMouseLeave()
{
	CRect rcSysBtn(0,0,0,0);
	rcSysBtn.UnionRect(&m_rcMinBtn, &m_rcMaxBtn);
	rcSysBtn.UnionRect(&rcSysBtn, &m_rcCloseBtn);

	if (m_bMinBtnHover || m_bMaxBtnHover || m_bCloseBtnHover)
	{
		m_bMinBtnHover = FALSE;
		m_bMaxBtnHover = FALSE;
		m_bCloseBtnHover = FALSE;
		InvalidateRect(&rcSysBtn);
	}

	m_bMouseTracking = FALSE;

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	if (m_bHasMaxBtn)
	{
		int nHitTest = HitTest(point);
		if (nHitTest == HTCAPTION)
		{
			if (IsZoomed())
				SendMessage(WM_SYSCOMMAND, SC_RESTORE | HTCAPTION, NULL);
			else
				SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE | HTCAPTION, NULL);
			Invalidate();
		}
	}

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnGetMinMaxInfo(LPMINMAXINFO lpMMI)
{
	HMONITOR hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY);

	MONITORINFO stMonitorInfo = {0};
	stMonitorInfo.cbSize = sizeof(stMonitorInfo);
	::GetMonitorInfo(hMonitor, &stMonitorInfo);
	RECT rcWork = stMonitorInfo.rcWork;
	::OffsetRect(&rcWork, -rcWork.left, -rcWork.top);

	lpMMI->ptMaxPosition.x = rcWork.left;
	lpMMI->ptMaxPosition.y = rcWork.top;
	lpMMI->ptMaxTrackSize.x = rcWork.right;
	lpMMI->ptMaxTrackSize.y = rcWork.bottom;

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnSize(UINT nType, CSize size)
{
	SIZE szRoundCorner = {4,4};
	if (!IsIconic()) 
	{
		if (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)
		{
			RECT rcWindow;
			::GetWindowRect(m_hWnd, &rcWindow);
			::OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
			rcWindow.right++;
			rcWindow.bottom++;
			HRGN hRgn = ::CreateRoundRectRgn(rcWindow.left, 
				rcWindow.top, rcWindow.right, rcWindow.bottom, 
				szRoundCorner.cx, szRoundCorner.cy);
			::SetWindowRgn(m_hWnd, hRgn, TRUE);
			::DeleteObject(hRgn);
		}

		CalcTitleBarRect();
		
		Invalidate();
	}

	SetMsgHandled(FALSE);
}

void CSkinDialog::OnDestroy()
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpBgImg);
	CSkinManager::GetInstance()->ReleaseImage(m_lpTitleBarBgImg);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMinSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMinSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMinSysBtnImgD);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMaxSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMaxSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpMaxSysBtnImgD);
	CSkinManager::GetInstance()->ReleaseImage(m_lpRestoreSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpRestoreSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpRestoreSysBtnImgD);
	CSkinManager::GetInstance()->ReleaseImage(m_lpCloseSysBtnImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpCloseSysBtnImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpCloseSysBtnImgD);

	if (m_hMemDC != NULL && m_hMemBmp != NULL)
	{
		::SelectObject(m_hMemDC, m_hOldBmp);
		::DeleteObject(m_hMemBmp);
		::DeleteDC(m_hMemDC);
	}
	m_hMemDC = NULL;
	m_hMemBmp = m_hOldBmp = NULL;

	SetMsgHandled(FALSE);
}

void CSkinDialog::CalcTitleBarRect()
{
	CRect rcClient;
	GetClientRect(&rcClient);

	m_rcTitleBar = CRect(0, 0, rcClient.Width(), 27);

	if (m_bHasCloseBtn)
	{
		m_rcCloseBtn = CRect(rcClient.Width() - 39, 0, rcClient.Width(), 20);

		if (m_bHasMaxBtn)
		{
			m_rcMaxBtn = CRect(rcClient.Width() - 39 - 28, 0, rcClient.Width() - 39, 20);
		}
	}

	if (m_bHasMinBtn)
	{
		if (!m_bHasMaxBtn)
		{
			m_rcMinBtn = CRect(rcClient.Width() - 39 - 28, 0, rcClient.Width() - 39, 20);
		}
		else
		{
			m_rcMinBtn = CRect(rcClient.Width() - 39 - 28 - 28, 0, rcClient.Width() - 39 - 28, 20);
		}
	}
}

int CSkinDialog::HitTest(POINT pt)
{
	if (!IsZoomed() && m_bSizeBox)
	{
		CRect rcClient;
		GetClientRect(&rcClient);

		RECT rcSizeBox = {4,4,4,4};
		if (pt.y < rcClient.top + rcSizeBox.top)
		{
			if (pt.x < rcClient.left + rcSizeBox.left)
				return HTTOPLEFT;
			if (pt.x > rcClient.right - rcSizeBox.right)
				return HTTOPRIGHT;
			return HTTOP;
		}
		else if (pt.y > rcClient.bottom - rcSizeBox.bottom)
		{
			if (pt.x < rcClient.left + rcSizeBox.left)
				return HTBOTTOMLEFT;
			if (pt.x > rcClient.right - rcSizeBox.right)
				return HTBOTTOMRIGHT;
			return HTBOTTOM;
		}
		if (pt.x < rcClient.left + rcSizeBox.left)
			return HTLEFT;
		if (pt.x > rcClient.right - rcSizeBox.right)
			return HTRIGHT;
	}

	if (m_bHasMinBtn && m_rcMinBtn.PtInRect(pt))
		return HTMINBUTTON;

	if (m_bHasMaxBtn && m_rcMaxBtn.PtInRect(pt))
		return HTMAXBUTTON;

	if (m_bHasCloseBtn && m_rcCloseBtn.PtInRect(pt))
		return HTCLOSE;

	if (m_bHasTitleBar && m_rcTitleBar.PtInRect(pt))
		return HTCAPTION;

	return HTCLIENT;
}

BOOL CSkinDialog::StartTrackMouseLeave()
{
	TRACKMOUSEEVENT tme = { 0 };
	tme.cbSize = sizeof(tme);
	tme.dwFlags = TME_LEAVE;
	tme.hwndTrack = m_hWnd;
	return _TrackMouseEvent(&tme);
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值