VC++ CDialog自绘

 CSWDialog头文件声明(CSWDialog.h)

#pragma once
#include <afxwin.h>

class CSWDialog :
	public CDialog
{
	DECLARE_DYNAMIC(CSWDialog)
public:
	CSWDialog();
	CSWDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);
	CSWDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
	virtual ~CSWDialog();

protected:
	void CommonConstruct(); // 初始化

public:
	enum BackgroundLocation
	{		
		BACKGR_TOPLEFT,
		BACKGR_TOPCENTER,
		BACKGR_TOPRIGHT,
		BACKGR_MIDDLELEFT,
		BACKGR_MIDDLECENTER,
		BACKGR_MIDDLERIGHT,
		BACKGR_BOTTOMLEFT,
		BACKGR_BOTTOMCENTER,
		BACKGR_BOTTOMRIGHT,
		BACKGR_COUNT,
	};

	enum BackgroundShow
	{
		BACKGR_TILE,	// 平铺
		BACKGR_STRETCH,	// 拉伸
		BACKGR_AUTOFIT,	// 自适应
	};

	enum SystemMenu
	{
		SYSMNU_MIN,
		SYSMNU_MAX,
		SYSMNU_CLOSE,
		SYSMNU_COUNT,
	};

protected:
	RECT m_rcImageWindow;		// 背景图片相对于源图片文件中裁剪下来的区域
	RECT m_rcImageClient;		// 9宫格中心客户区相对于源图片文件中的裁剪区域

	Gdiplus::Bitmap*		m_pBkgrBitmap;
	Gdiplus::Bitmap*		m_pSysMinBitmap;
	Gdiplus::Bitmap*		m_pSysMaxBitmap;
	Gdiplus::Bitmap*		m_pSysCloseBitmap;
	RECT				m_rcMin;
	RECT				m_rcMax;
	RECT				m_rcClose;
	CSize				m_sizeBkgrBitmap;
	CBrush				m_brBkgr;
	BOOL				m_bSysMnu[SYSMNU_COUNT];
	BOOL				m_bHasTitleBar;
	int					m_nSysMnuHover;
	BOOL				m_bTracking;
	std::string			m_sWindowText;

protected:
	afx_msg void OnPaint();
	afx_msg void OnNcPaint();
	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
	afx_msg BOOL OnNcActivate(BOOL bActive);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp);
	afx_msg LRESULT OnNcHitTest(CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnKillFocus(CWnd* pNewWnd);
	afx_msg void OnMouseHover(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnMouseLeave();
	afx_msg void OnNcLButtonDblClk(UINT nHitTest, CPoint point);
	afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
	afx_msg void OnNcLButtonUp(UINT nHitTest, CPoint point);
	afx_msg void OnNcMouseHover(UINT nFlags, CPoint point);
	afx_msg void OnNcMouseLeave();
	afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
	afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
	DECLARE_MESSAGE_MAP()

protected:
	virtual BOOL OnInitDialog();
	virtual BOOL PreTranslateMessage(MSG* pMsg);

public:
	// 设置窗口背景图片
	void SetBackgroundColor(COLORREF clrBkgr, BOOL bRepaint = TRUE);
	
	/*
	lpszImageName: 背景图片句柄
	rcWindow: 窗口区域
	rcClient:客户区区域
	*/
	void SetBackgroundImage(HBITMAP hBitmap, RECT* rcWindow = NULL, RECT* rcClient = NULL, BOOL bRepaint = TRUE);
	
	/*
	lpszImageName: 背景图片资源ID
	rcWindow: 窗口区域
	rcClient:客户区区域
	*/
	void SetBackgroundImage(UINT uiBmpResId, RECT* rcWindow = NULL, RECT* rcClient = NULL, BOOL bRepaint = TRUE);

	/*
		lpszImageName: 背景图片名称
		rcWindow: 窗口区域
		rcClient:客户区区域
	*/
	void SetBackgroundImage(LPCTSTR lpszImageName, RECT* rcWindow = NULL, RECT* rcClient = NULL, BOOL bRepaint = TRUE);

	// 设置最小化、最小化、恢复、关闭按钮图标
	void SetMinImage(LPCTSTR lpszImageName)
	{
		m_pSysMinBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(lpszImageName);
	}
	void SetMaxImage(LPCTSTR lpszImageName)
	{
		m_pSysMaxBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(lpszImageName);
	}
	void SetCloseImage(LPCTSTR lpszImageName)
	{
		m_pSysCloseBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(lpszImageName);
	}

	void SetBackgroundMaskImage(LPCTSTR lpszImageName);

private:
	void DoPaint();
	void DoNcPaint();
	void DrawSysMenu(Gdiplus::Graphics& g);
	void DrawWindowText(Gdiplus::Graphics& g);
};

CSWDialog源文件定义(CSWDialog.cpp):

#include "stdafx.h"
#include "CSWDialog.h"

IMPLEMENT_DYNAMIC(CSWDialog, CDialog)

CSWDialog::CSWDialog()
{
	CommonConstruct();
}

CSWDialog::CSWDialog(UINT nIDTemplate, CWnd* pParentWnd/* = NULL*/)
	: CDialog(nIDTemplate, pParentWnd)
{
	CommonConstruct();
}

CSWDialog::CSWDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd/* = NULL*/)
	: CDialog(lpszTemplateName, pParentWnd)
{
	CommonConstruct();
}

CSWDialog::~CSWDialog()
{
}

#define RIGHT_EDGE	5
#define TOP_EDGE	0
#define SYSMENU_WIDTH	40
#define SYSMENU_HEIGHT	32
void CSWDialog::CommonConstruct()
{
	m_pBkgrBitmap = NULL;
	m_pSysMinBitmap = NULL;
	m_pSysMaxBitmap = NULL;
	m_pSysCloseBitmap = NULL;
	m_sizeBkgrBitmap = CSize(0, 0);
	m_rcImageWindow = CRect(0, 0, 0, 0);
	m_rcImageClient = CRect(0, 0, 0, 0);
	memset(&m_bSysMnu, 0, SYSMNU_COUNT);
	m_bHasTitleBar = FALSE;
	m_nSysMnuHover = -1;
	m_brBkgr.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
}

BEGIN_MESSAGE_MAP(CSWDialog, CDialog)
	ON_WM_PAINT()
	ON_WM_NCPAINT()
	ON_WM_ACTIVATE()
	ON_WM_ERASEBKGND()
	ON_WM_NCACTIVATE()
	ON_WM_SIZE()
	ON_WM_NCCALCSIZE()
	ON_WM_NCHITTEST()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_KILLFOCUS()
	ON_WM_MOUSEHOVER()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSELEAVE()
	ON_WM_NCLBUTTONDBLCLK()
	ON_WM_NCLBUTTONDOWN()
	ON_WM_NCLBUTTONUP()
	ON_WM_NCMOUSEHOVER()
	ON_WM_NCMOUSELEAVE()
	ON_WM_NCMOUSEMOVE()
	ON_WM_SYSCOMMAND()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CTLCOLOR()
END_MESSAGE_MAP()

BOOL CSWDialog::OnInitDialog()
{
	DWORD dwStyle = (DWORD)GetWindowLong(m_hWnd, GWL_STYLE);;//获取样式
	if (dwStyle&WS_MAXIMIZEBOX)
		m_bSysMnu[SYSMNU_MAX] = TRUE;
	if (dwStyle&WS_MINIMIZEBOX)
		m_bSysMnu[SYSMNU_MIN] = TRUE;
	if (dwStyle&WS_SYSMENU)
		m_bSysMnu[SYSMNU_CLOSE] = TRUE;
	//if (dwStyle&WS_CAPTION)
	//	m_bHasTitleBar = TRUE;
	
	CString strText;
	int nLen = ::GetWindowTextLength(m_hWnd);
	::GetWindowText(m_hWnd, strText.GetBufferSetLength(nLen), nLen + 1);
	strText.ReleaseBuffer(); m_sWindowText = strText;

	// 去掉标题栏
	ModifyStyle(WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_MODALFRAME, 0);
	ModifyStyleEx(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE, 0);

	return CDialog::OnInitDialog();
}

void CSWDialog::OnPaint()
{
	if (!IsIconic())
		DoPaint();

	CDialog::OnPaint();
}

void CSWDialog::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
	CDialog::OnActivate(nState, pWndOther, bMinimized);

	// TODO: 在此处添加消息处理程序代码
	//DoNcPaint();
}

BOOL CALLBACK EnumChildWindowsProc(HWND hWnd, LPARAM lParam)
{
	//UINT nType = *(UINT*)lParam;
	if (::IsWindow(hWnd))
	{
		CWnd* pWnd = CWnd::FromHandle(hWnd);
		char szClassName[_MAX_PATH] = { 0 };
		::GetClassName(hWnd, szClassName, _MAX_PATH);
		std::string sClassName = pWnd->GetRuntimeClass()->m_lpszClassName;
		if (sClassName == _T("CSWButton"))
		{
			((CSWButton*)pWnd)->NoticeBkgrRefresh();
		}
		else if (sClassName == _T("CSWSwitchButton"))
		{
			((CSWSwitchButton*)pWnd)->NoticeBkgrRefresh();
		}
		else if (sClassName == _T("CSWStatic"))
		{
			((CSWStatic*)pWnd)->NoticeBkgrRefresh();
		}
		else if (sClassName == _T("CSWEdit"))
		{
			((CSWEdit*)pWnd)->NoticeBkgrRefresh();
		}
	}

	return TRUE;
}

void CSWDialog::SetBackgroundColor(COLORREF clrBkgr, BOOL bRepaint)
{
	if (m_brBkgr.GetSafeHandle() != NULL)
	{
		m_brBkgr.DeleteObject();
	}

	if (clrBkgr != (COLORREF)-1)
	{
		m_brBkgr.CreateSolidBrush(clrBkgr);
	}

	if (bRepaint && GetSafeHwnd() != NULL)
	{
		Invalidate();
		UpdateWindow();
		EnumChildWindows(m_hWnd, EnumChildWindowsProc, NULL);
	}
}

void CSWDialog::SetBackgroundImage(HBITMAP hBitmap, RECT* rcWindow, RECT* rcClient, BOOL bRepaint)
{
	m_pBkgrBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(hBitmap);
	m_rcImageWindow = *rcWindow;
	m_rcImageClient = *rcClient;
	if (m_pBkgrBitmap)
	{
		if (rcWindow == NULL)
			m_rcImageWindow = CRect(0, 0, m_pBkgrBitmap->GetWidth(), m_pBkgrBitmap->GetHeight());
		if (rcClient == NULL)
			m_rcImageClient = m_rcImageWindow;
		m_sizeBkgrBitmap = CSize(m_pBkgrBitmap->GetWidth(), m_pBkgrBitmap->GetHeight());
		if (bRepaint && GetSafeHwnd() != NULL)
		{
			Invalidate();
			UpdateWindow();
			EnumChildWindows(m_hWnd, EnumChildWindowsProc, NULL);
		}
	}
}

void CSWDialog::SetBackgroundImage(UINT uiBmpResId, RECT* rcWindow, RECT* rcClient, BOOL bRepaint)
{
	m_pBkgrBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(uiBmpResId, RT_BITMAP);
	m_rcImageWindow = *rcWindow;
	m_rcImageClient = *rcClient;
	if (m_pBkgrBitmap)
	{
		if (rcWindow == NULL)
			m_rcImageWindow = CRect(0, 0, m_pBkgrBitmap->GetWidth(), m_pBkgrBitmap->GetHeight());
		if (rcClient == NULL)
			m_rcImageClient = m_rcImageWindow;
		m_sizeBkgrBitmap = CSize(m_pBkgrBitmap->GetWidth(), m_pBkgrBitmap->GetHeight());
		if (bRepaint && GetSafeHwnd() != NULL)
		{
			Invalidate();
			UpdateWindow();
			EnumChildWindows(m_hWnd, EnumChildWindowsProc, NULL);
		}
	}
}

void CSWDialog::SetBackgroundImage(LPCTSTR lpszImageName, RECT* rcWindow, RECT* rcClient, BOOL bRepaint)
{
	m_pBkgrBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(lpszImageName);		
	if (m_pBkgrBitmap)
	{
		m_rcImageWindow = (rcWindow == NULL) ? CRect(0, 0, m_pBkgrBitmap->GetWidth(), m_pBkgrBitmap->GetHeight()) : *rcWindow;
		if (rcClient == NULL)
			m_rcImageClient = m_rcImageWindow;
		else
			m_rcImageClient = *rcClient;
		m_sizeBkgrBitmap = CSize(m_pBkgrBitmap->GetWidth(), m_pBkgrBitmap->GetHeight());
		if (bRepaint && GetSafeHwnd() != NULL)
		{
			Invalidate();
			UpdateWindow();
			EnumChildWindows(m_hWnd, EnumChildWindowsProc, NULL);
		}
	}
}


BOOL CSWDialog::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return FALSE;
}


void CSWDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnGetMinMaxInfo(lpMMI);
}


BOOL CSWDialog::OnNcActivate(BOOL bActive)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//DoNcPaint();
	return TRUE;
	//return CDialog::OnNcActivate(bActive);
}


void CSWDialog::OnNcPaint()
{
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 CDialog::OnNcPaint()
	//DoNcPaint();
}


void CSWDialog::OnSize(UINT nType, int cx, int cy)
{
	CDialog::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
	if (m_pSysCloseBitmap && m_pSysMaxBitmap && m_pSysMinBitmap)
	{
		CRect rcClient; GetClientRect(rcClient);
		m_rcClose.left = rcClient.right - m_pSysCloseBitmap->GetWidth() / 3 - RIGHT_EDGE;
		m_rcClose.right = m_rcClose.left + m_pSysCloseBitmap->GetWidth() / 3;
		m_rcClose.top = TOP_EDGE;
		m_rcClose.bottom = m_rcClose.top + m_pSysCloseBitmap->GetHeight();

		m_rcMax.left = m_rcClose.left - m_pSysMaxBitmap->GetWidth() / 3;
		m_rcMax.right = m_rcMax.left + m_pSysMaxBitmap->GetWidth() / 3;
		m_rcMax.top = TOP_EDGE;
		m_rcMax.bottom = m_rcMax.top + m_pSysMaxBitmap->GetHeight() / 2;

		m_rcMin.left = m_rcMax.left - m_pSysMinBitmap->GetWidth() / 3;
		m_rcMin.right = m_rcMin.left + m_pSysMinBitmap->GetWidth() / 3;
		m_rcMin.top = TOP_EDGE;
		m_rcMin.bottom = m_rcMin.top + m_pSysMinBitmap->GetHeight();
	}
	else
	{
		CRect rcClient; GetClientRect(rcClient);
		m_rcClose.left = rcClient.right - SYSMENU_WIDTH - RIGHT_EDGE;
		m_rcClose.right = m_rcClose.left + SYSMENU_WIDTH;
		m_rcClose.top = TOP_EDGE;
		m_rcClose.bottom = m_rcClose.top + SYSMENU_HEIGHT;

		m_rcMax.left = m_rcClose.left - SYSMENU_WIDTH;
		m_rcMax.right = m_rcMax.left + SYSMENU_WIDTH;
		m_rcMax.top = TOP_EDGE;
		m_rcMax.bottom = m_rcMax.top + SYSMENU_HEIGHT;

		m_rcMin.left = m_rcMax.left - SYSMENU_WIDTH;
		m_rcMin.right = m_rcMin.left + SYSMENU_WIDTH;
		m_rcMin.top = TOP_EDGE;
		m_rcMin.bottom = m_rcMin.top + SYSMENU_HEIGHT;
	}

	if (nType == SIZE_MAXIMIZED || nType == SIZE_RESTORED)
	{
		DoNcPaint();
		InvalidateRect(NULL, TRUE);
		//::RedrawWindow(m_hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);// 通知窗口和所有子窗口重绘
		
		EnumChildWindows(m_hWnd, EnumChildWindowsProc, (LPARAM)&nType);
	}
}


void CSWDialog::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (m_bHasTitleBar && bCalcValidRects && !::IsRectEmpty(&m_rcImageClient) && !::IsRectEmpty(&m_rcImageWindow))
	{
		int cx = ::GetSystemMetrics(SM_CXFRAME);
		int cy = ::GetSystemMetrics(SM_CYFRAME);
		lpncsp->rgrc[0].top += m_rcImageClient.top - m_rcImageWindow.top + cy;
	}
	else
	{
		CDialog::OnNcCalcSize(bCalcValidRects, lpncsp);
	}
}

#define RESIZE_REGION_SIZE 5
LRESULT CSWDialog::OnNcHitTest(CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	RECT rcWindow;
	::GetWindowRect(m_hWnd, &rcWindow);

	// 最好将四个角的判断放在前面
	if (point.x <= rcWindow.left + RESIZE_REGION_SIZE && point.y <= rcWindow.top + RESIZE_REGION_SIZE)
		return HTTOPLEFT;
	else if (point.x >= rcWindow.right - RESIZE_REGION_SIZE && point.y <= rcWindow.top + RESIZE_REGION_SIZE)
		return HTTOPRIGHT;
	else if (point.x <= rcWindow.left + RESIZE_REGION_SIZE && point.y >= rcWindow.bottom - RESIZE_REGION_SIZE)
		return HTBOTTOMLEFT;
	else if (point.x >= rcWindow.right - RESIZE_REGION_SIZE && point.y >= rcWindow.bottom - RESIZE_REGION_SIZE)
		return HTBOTTOMRIGHT;
	else if (point.x <= rcWindow.left + RESIZE_REGION_SIZE)
		return HTLEFT;
	else if (point.x >= rcWindow.right - RESIZE_REGION_SIZE)
		return HTRIGHT;
	else if (point.y <= rcWindow.top + RESIZE_REGION_SIZE)
		return HTTOP;
	else if (point.y >= rcWindow.bottom - RESIZE_REGION_SIZE)
		return HTBOTTOM;

	//return HTCAPTION;
	return CDialog::OnNcHitTest(point);
}


void CSWDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (!m_bHasTitleBar && m_nSysMnuHover == -1)
	{
		CRect rcClient; 
		GetClientRect(rcClient);
		CRect rcDrag = CRect(0, 0, rcClient.Width(), m_rcImageClient.top - m_rcImageWindow.top);
		if (rcDrag.IsRectEmpty())
			rcDrag = rcClient;
		ClientToScreen(rcDrag);
		CPoint point; GetCursorPos(&point);
		if (PtInRect(rcDrag, point))
			::PostMessage(m_hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0L);
	}

	CDialog::OnLButtonDown(nFlags, point);
}


void CSWDialog::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (m_nSysMnuHover!=-1)
	{
		if (PtInRect(&m_rcMin, point))
			::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
		else if (PtInRect(&m_rcMax, point))
		{
			if (::IsZoomed(m_hWnd))
				::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
			else
				::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
		}
		else if (PtInRect(&m_rcClose, point))
			::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
	}	

	CDialog::OnLButtonUp(nFlags, point);
}


void CSWDialog::OnKillFocus(CWnd* pNewWnd)
{
	CDialog::OnKillFocus(pNewWnd);

	// TODO: 在此处添加消息处理程序代码
}


void CSWDialog::OnMouseHover(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnMouseHover(nFlags, point);
}


void CSWDialog::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE;
		tme.dwHoverTime = 1;
		m_bTracking = _TrackMouseEvent(&tme);
	}

	int nOldSysMnuHover = m_nSysMnuHover;
	if (PtInRect(&m_rcMin, point))
		m_nSysMnuHover = SYSMNU_MIN;
	else if (PtInRect(&m_rcMax, point))
		m_nSysMnuHover = SYSMNU_MAX;
	else if (PtInRect(&m_rcClose, point))
		m_nSysMnuHover = SYSMNU_CLOSE;
	else
		m_nSysMnuHover = -1;
	
	if (m_nSysMnuHover != nOldSysMnuHover)
	{
		InvalidateRect(&m_rcMin, FALSE);
		InvalidateRect(&m_rcMax, FALSE);
		InvalidateRect(&m_rcClose, FALSE);
	}

	CDialog::OnMouseMove(nFlags, point);
}


void CSWDialog::OnMouseLeave()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_bTracking = FALSE;
	if (m_nSysMnuHover != -1)
	{
		InvalidateRect(NULL, FALSE);
		m_nSysMnuHover = -1;
	}

	CDialog::OnMouseLeave();
}


void CSWDialog::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnNcLButtonDblClk(nHitTest, point);
}


void CSWDialog::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	switch (nHitTest)
	{
	case HTTOP:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOP, MAKELPARAM(point.x, point.y));
		break;
	case HTBOTTOM:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOM, MAKELPARAM(point.x, point.y));
		break;
	case HTLEFT:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_LEFT, MAKELPARAM(point.x, point.y));
		break;
	case HTRIGHT:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_RIGHT, MAKELPARAM(point.x, point.y));
		break;
	case HTTOPLEFT:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPLEFT, MAKELPARAM(point.x, point.y));
		break;
	case HTTOPRIGHT:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_TOPRIGHT, MAKELPARAM(point.x, point.y));
		break;
	case HTBOTTOMLEFT:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMLEFT, MAKELPARAM(point.x, point.y));
		break;
	case HTBOTTOMRIGHT:
		SendMessage(WM_SYSCOMMAND, SC_SIZE | WMSZ_BOTTOMRIGHT, MAKELPARAM(point.x, point.y));
		break;
	default:
		CDialog::OnNcLButtonDown(nHitTest, point);
	}
}


void CSWDialog::OnNcLButtonUp(UINT nHitTest, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnNcLButtonUp(nHitTest, point);
}


void CSWDialog::OnNcMouseHover(UINT nFlags, CPoint point)
{
	// 该功能要求使用 Windows 2000 或更高版本。
	// 符号 _WIN32_WINNT 和 WINVER 必须 >= 0x0500。
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnNcMouseHover(nFlags, point);
}


void CSWDialog::OnNcMouseLeave()
{
	// 该功能要求使用 Windows 2000 或更高版本。
	// 符号 _WIN32_WINNT 和 WINVER 必须 >= 0x0500。
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnNcMouseLeave();
}


void CSWDialog::OnNcMouseMove(UINT nHitTest, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialog::OnNcMouseMove(nHitTest, point);
}


void CSWDialog::OnSysCommand(UINT nID, LPARAM lParam)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (nID != SC_CLOSE)
		DoNcPaint();

	CDialog::OnSysCommand(nID, lParam);
}


BOOL CSWDialog::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_UNINITMENUPOPUP)
		DoNcPaint();

	if (pMsg->message == 0x00AE ||	//WM_NCUAHDRAWCAPTION
		pMsg->message == 0x00AF)	//WM_NCUAHDRAWFRAME)
	{
		DoNcPaint();
		return TRUE;
	}

	return CDialog::PreTranslateMessage(pMsg);
}


void CSWDialog::DoPaint()
{
	TRACE("%s::DoPaint(%d)\n", this->GetRuntimeClass()->m_lpszClassName, GetTickCount());
	CPaintDC dc(this);
	if (m_brBkgr.GetSafeHandle() == NULL && m_pBkgrBitmap == NULL)
		return ;

	CRect rcClient;
	GetClientRect(rcClient);

	if (m_pBkgrBitmap == NULL)
	{
		if (m_brBkgr.GetSafeHandle() != NULL)
			dc.FillRect(rcClient, &m_brBkgr);
		
		return;
	}

	ASSERT(m_sizeBkgrBitmap != CSize(0, 0));
	sw::CMemDC dcMem(dc, this); 
	Gdiplus::Graphics g(dcMem);

	// 左上
	{
		if (!m_bHasTitleBar)
		{
			CRect rcClipImage = m_rcImageWindow;
			rcClipImage.right = m_rcImageClient.left;
			rcClipImage.bottom = m_rcImageClient.top;
			CRect rcShowImage = rcClipImage;
			if (!rcShowImage.IsRectEmpty())
				g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
		}
	}
	// 左中
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.top = m_rcImageClient.top;
		rcClipImage.right = m_rcImageClient.left;
		rcClipImage.bottom = m_rcImageClient.bottom;
		CRect rcShowImage = rcClipImage;
		if (m_bHasTitleBar)
			rcShowImage.top = 0;
		else
			rcShowImage.top = m_rcImageClient.top - m_rcImageWindow.top;
		rcShowImage.bottom = rcClient.bottom - (m_rcImageWindow.bottom - m_rcImageClient.bottom);
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 左下
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.top = m_rcImageClient.bottom;
		rcClipImage.right = m_rcImageClient.left;
		rcClipImage.bottom = m_rcImageWindow.bottom;
		CRect rcShowImage = rcClipImage;
		rcShowImage.top = rcClient.bottom - (m_rcImageWindow.bottom - m_rcImageClient.bottom);
		rcShowImage.bottom = rcClient.bottom;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}

	// 右上
	{
		if (!m_bHasTitleBar)
		{
			CRect rcClipImage = m_rcImageWindow;
			rcClipImage.top = 0;// m_rcImageClient.top - m_rcImageWindow.top;
			rcClipImage.left = m_rcImageClient.right;
			rcClipImage.bottom = m_rcImageClient.top;
			CRect rcShowImage = rcClipImage;
			rcShowImage.left = rcClient.right - (m_rcImageWindow.right - m_rcImageClient.right);
			rcShowImage.right = rcClient.right;
			rcShowImage.bottom = m_rcImageClient.top;
			if (!rcShowImage.IsRectEmpty())
				g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
		}
	}
	// 右中
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.top = m_rcImageClient.top;
		rcClipImage.left = m_rcImageClient.right;
		rcClipImage.bottom = m_rcImageClient.bottom;
		CRect rcShowImage = rcClipImage;
		if (m_bHasTitleBar)
			rcShowImage.top = 0;
		else
			rcShowImage.top = m_rcImageClient.top - m_rcImageWindow.top;
		rcShowImage.left = rcClient.right - (m_rcImageWindow.right - m_rcImageClient.right);
		rcShowImage.right = rcClient.right;
		rcShowImage.bottom = rcClient.bottom - (m_rcImageWindow.bottom - m_rcImageClient.bottom);
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 右下
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.left = m_rcImageClient.right;
		rcClipImage.top = m_rcImageClient.bottom;
		rcClipImage.bottom = m_rcImageWindow.bottom;
		CRect rcShowImage = rcClipImage;
		rcShowImage.left = rcClient.right - (m_rcImageWindow.right - m_rcImageClient.right);
		rcShowImage.right = rcClient.right;
		rcShowImage.top = rcClient.bottom - (m_rcImageWindow.bottom - m_rcImageClient.bottom);
		rcShowImage.bottom = rcClient.bottom;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}

	// 中上
	{
		if (!m_bHasTitleBar)
		{
			CRect rcClipImage = m_rcImageWindow;
			rcClipImage.top = 0;// m_rcImageClient.top - m_rcImageWindow.top;
			rcClipImage.left = m_rcImageClient.left;
			rcClipImage.right = m_rcImageClient.right;
			rcClipImage.bottom = m_rcImageClient.top;
			CRect rcShowImage = rcClipImage;
			rcShowImage.right = rcClient.right - (m_rcImageWindow.right - m_rcImageClient.right);
			rcShowImage.bottom = m_rcImageClient.top;
			if (!rcShowImage.IsRectEmpty())
				g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
		}
	}
	// 中中
	{
		CRect rcClipImage = m_rcImageClient;
		CRect rcShowImage = rcClipImage;
		if (m_bHasTitleBar)
			rcShowImage.top = 0;
		else
			rcShowImage.top = m_rcImageClient.top - m_rcImageWindow.top;
		rcShowImage.right = rcClient.right - (m_rcImageWindow.right - m_rcImageClient.right);
		rcShowImage.bottom = rcClient.bottom - (m_rcImageWindow.bottom - m_rcImageClient.bottom);
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 中下
	{
		CRect rcClipImage = m_rcImageClient;
		rcClipImage.top = m_rcImageClient.bottom;
		rcClipImage.bottom = m_rcImageWindow.bottom;
		CRect rcShowImage = rcClipImage;
		rcShowImage.right = rcClient.right - (m_rcImageWindow.right - m_rcImageClient.right);
		rcShowImage.top = rcClient.bottom - (m_rcImageWindow.bottom - m_rcImageClient.bottom);
		rcShowImage.bottom = rcClient.bottom;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}

	if (!m_bHasTitleBar)
	{
		/*
		 *	绘制标题栏图标
		 *	绘制标题栏文本
		*/
		DrawWindowText(g);
		DrawSysMenu(g);
	}

	// 平铺
	for (int x = rcClient.left; x < rcClient.Width(); x += m_sizeBkgrBitmap.cx)
	{
		for (int y = rcClient.top; y < rcClient.Height(); y += m_sizeBkgrBitmap.cy)
		{
			//pDC->DrawState(CPoint(x, y), m_sizeBkgrBitmap, m_hBkgrBitmap, DSS_NORMAL);
		}
	}
}

void CSWDialog::DoNcPaint()
{
	if ((!m_bHasTitleBar) || (m_brBkgr.GetSafeHandle() == NULL && m_pBkgrBitmap == NULL))
	{
		//CDialog::OnNcPaint();
		return;
	}

	if (::IsRectEmpty(&m_rcImageClient) || ::IsRectEmpty(&m_rcImageWindow))
	{
		//CDialog::OnNcPaint();
		return;
	}

	CDC* pDC = GetWindowDC();
	ASSERT_VALID(pDC);

	CRect rcClient;
	GetClientRect(rcClient);

	// 获取位置
	CRect rcWindow;
	GetWindowRect(&rcWindow);
	rcWindow.OffsetRect(-rcWindow.left, -rcWindow.top);

	// 剪除掉客户区
	int cx = ::GetSystemMetrics(SM_CXFRAME);
	int cy = ::GetSystemMetrics(SM_CYFRAME);
	int ret = pDC->ExcludeClipRect(cx, m_rcImageClient.top - m_rcImageWindow.top, rcWindow.right - cx, rcWindow.bottom - cy);

	if (m_pBkgrBitmap == NULL)
	{
		if (m_brBkgr.GetSafeHandle() != NULL)
		{
			pDC->FillRect(rcWindow, &m_brBkgr);
		}

		return;
	}

	ASSERT(m_sizeBkgrBitmap != CSize(0, 0));
	sw::CMemDC dc(*pDC, rcWindow);
	Gdiplus::Graphics g(dc);

	// 左上
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.right = m_rcImageClient.left;
		rcClipImage.bottom = m_rcImageClient.top;
		CRect rcShowImage = rcClipImage;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 右上
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.left = m_rcImageClient.right;
		rcClipImage.bottom = m_rcImageClient.top;
		CRect rcShowImage = rcClipImage;
		rcShowImage.left = rcWindow.right - (m_rcImageWindow.right - m_rcImageClient.right);
		rcShowImage.right = rcWindow.right;
		rcShowImage.bottom = m_rcImageClient.top;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 中上
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.left = m_rcImageClient.left;
		rcClipImage.right = m_rcImageClient.right;
		rcClipImage.bottom = m_rcImageClient.top;
		CRect rcShowImage = rcClipImage;
		rcShowImage.right = rcWindow.right - (m_rcImageWindow.right - m_rcImageClient.right);
		rcShowImage.bottom = m_rcImageClient.top;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}

	// 左边框
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.right = rcClipImage.left + cx;
		rcClipImage.bottom = m_rcImageClient.top;
		CRect rcShowImage = rcClipImage;
		rcShowImage.top = m_rcImageClient.top - m_rcImageWindow.top;
		rcShowImage.bottom = rcWindow.bottom + 100;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 右边框
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.left = m_rcImageWindow.right - cx;
		rcClipImage.bottom = m_rcImageClient.top;
		CRect rcShowImage = rcClipImage;
		rcShowImage.top = m_rcImageClient.top - m_rcImageWindow.top;
		rcShowImage.left = rcWindow.right - cx;
		rcShowImage.bottom = rcWindow.bottom;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}
	// 下边框
	{
		CRect rcClipImage = m_rcImageWindow;
		rcClipImage.top = m_rcImageWindow.bottom - cy;
		rcClipImage.bottom = m_rcImageClient.top;
		CRect rcShowImage = rcClipImage;
		rcShowImage.right = rcWindow.right;
		rcShowImage.bottom = rcWindow.bottom;
		if (!rcShowImage.IsRectEmpty())
			g.DrawImage(m_pBkgrBitmap, RectF(rcShowImage.left, rcShowImage.top, rcShowImage.Width(), rcShowImage.Height()), rcClipImage.left, rcClipImage.top, rcClipImage.Width(), rcClipImage.Height(), UnitPixel, NULL, NULL, NULL);
	}

	//
	/*
	 *	绘制标题栏图标
	*/

	//
	/*
	 *	绘制标题栏文本
	*/
	DrawWindowText(g);

	//
	/*
	 *	绘制系统功能按钮
	*/
	DrawSysMenu(g);

	// 平铺
	for (int x = rcWindow.left; x < rcWindow.Width(); x += m_sizeBkgrBitmap.cx)
	{
		for (int y = rcWindow.top; y < rcWindow.Height(); y += m_sizeBkgrBitmap.cy)
		{
			//pDC->DrawState(CPoint(x, y), m_sizeBkgrBitmap, m_hBkgrBitmap, DSS_NORMAL);
		}
	}
}

void CSWDialog::DrawSysMenu(Gdiplus::Graphics& g)
{
	CRect rcClient; GetClientRect(rcClient);
	g.SetSmoothingMode(Gdiplus::/*SmoothingModeAntiAlias*/SmoothingModeHighQuality);
	if (m_bSysMnu[SYSMNU_CLOSE])
	{
		if (m_pSysCloseBitmap)
		{
			CRect rcClip = CRect(0, 0, m_pSysCloseBitmap->GetWidth() / 3, m_pSysCloseBitmap->GetHeight());
			if (m_nSysMnuHover == SYSMNU_CLOSE)
				rcClip.OffsetRect(m_pSysCloseBitmap->GetWidth() / 3, 0);
			CRect rcShow(m_rcClose);
			g.DrawImage(m_pSysCloseBitmap, RectF(rcShow.left, rcShow.top, rcShow.Width(), rcShow.Height()), rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), UnitPixel, NULL, NULL, NULL);
		}
		else
		{
			CRect rcShow(m_rcClose);

			//
			if (m_nSysMnuHover == SYSMNU_CLOSE)			{
				
				BYTE byAlpha = 128;
				Color colors[] =
				{
					Color(byAlpha, 255, 255, 255),
					Color(byAlpha, 0, 255, 0),
				};
				float positions[] = { 0.0f, 1.0f };
				LinearGradientBrush linGrBrush(RectF(0, 0, 80, 80), Color::White, Color::Green, LinearGradientModeVertical);
				//linGrBrush.SetInterpolationColors(colors, positions, 2);
				g.FillRectangle(&linGrBrush, rcShow.left, rcShow.top, rcShow.Width(), rcShow.Height());
			}

			{
				rcShow.DeflateRect(14, 10);
				g.TranslateTransform(rcShow.left, rcShow.top);
				Gdiplus::Pen pen(Color(240, 0, 0, 0), 3);
				pen.SetStartCap(Gdiplus::LineCapRound);
				pen.SetEndCap(Gdiplus::LineCapRound);
				pen.SetLineJoin(Gdiplus::LineJoinRound);
				Point points[] = { Point(0, 0), Point(rcShow.Width(), rcShow.Height()), Point(0, rcShow.Height()), Point(rcShow.Width(), 0) };
				g.DrawLine(&pen, points[0], points[1]);
				g.DrawLine(&pen, points[2], points[3]);
				g.ResetTransform();
			}
			//
		}
	}

	if (m_bSysMnu[SYSMNU_MAX])
	{
		if (m_pSysMaxBitmap)
		{
			CRect rcClip = CRect(0, 0, m_pSysMaxBitmap->GetWidth() / 3, m_pSysMaxBitmap->GetHeight() / 2);
			if (IsZoomed())
				rcClip.OffsetRect(0, m_pSysMaxBitmap->GetHeight() / 2);

			if (m_nSysMnuHover == SYSMNU_MAX)
				rcClip.OffsetRect(m_pSysMaxBitmap->GetWidth() / 3, 0);

			CRect rcShow(m_rcMax);
			g.DrawImage(m_pSysMaxBitmap, RectF(rcShow.left, rcShow.top, rcShow.Width(), rcShow.Height()), rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), UnitPixel, NULL, NULL, NULL);
		}
		else
		{
			CRect rcShow(m_rcMax);

			//
			if (m_nSysMnuHover == SYSMNU_MAX) {

				BYTE byAlpha = 128;
				Color colors[] =
				{
					Color(byAlpha, 255, 255, 255),
					Color(byAlpha, 0, 255, 0),
				};
				float positions[] = { 0.0f, 1.0f };
				LinearGradientBrush linGrBrush(RectF(0, 0, 80, 80), Color::White, Color::Green, LinearGradientModeVertical);
				//linGrBrush.SetInterpolationColors(colors, positions, 2);
				g.FillRectangle(&linGrBrush, rcShow.left, rcShow.top, rcShow.Width(), rcShow.Height());
			}

			{
				rcShow.DeflateRect(14, 10);
				Gdiplus::Pen pen(Color(255, 0, 0, 0), 2);
				if (IsZoomed())
				{
					rcShow.top += 4;
					rcShow.right -= 4;
					g.TranslateTransform(rcShow.left, rcShow.top);
					g.DrawRectangle(&pen, 0, 0, rcShow.Width(), rcShow.Height());
					Point points[] = { Point(0, 2), Point(rcShow.Width(), 2) };
					g.DrawLine(&pen, points[0], points[1]);

					rcShow.OffsetRect(4, -4);
					{
						g.ResetTransform();
						g.TranslateTransform(rcShow.left, rcShow.top);
						g.DrawRectangle(&pen, 0, 0, rcShow.Width(), 2);
						//g.DrawLine(&pen, Point(0, 0), Point(rcShow.Width(), 0));
						//g.DrawLine(&pen, Point(0, 1), Point(rcShow.Width(), 1));
						g.DrawLine(&pen, Point(0, 0), Point(0, rcShow.Height() - 5));
						g.DrawLine(&pen, Point(rcShow.Width(), 0), Point(rcShow.Width(), rcShow.Height()));
						g.DrawLine(&pen, Point(5, rcShow.Height()), Point(rcShow.Width(), rcShow.Height()));
					}
				}
				else
				{
					g.TranslateTransform(rcShow.left, rcShow.top);
					g.DrawRectangle(&pen, 0, 0, rcShow.Width(), rcShow.Height());
					Point points[] = { Point(0, 2), Point(rcShow.Width(), 2) };
					g.DrawLine(&pen, points[0], points[1]);
				}
				g.ResetTransform();
			}
			//
		}
	}

	if (m_bSysMnu[SYSMNU_MIN])
	{
		if (m_pSysMinBitmap)
		{
			CRect rcClip = CRect(0, 0, m_pSysMinBitmap->GetWidth() / 3, m_pSysMinBitmap->GetHeight());
			if (m_nSysMnuHover == SYSMNU_MIN)
				rcClip.OffsetRect(m_pSysMinBitmap->GetWidth() / 3, 0);
			CRect rcShow(m_rcMin);
			g.DrawImage(m_pSysMinBitmap, RectF(rcShow.left, rcShow.top, rcShow.Width(), rcShow.Height()), rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), UnitPixel, NULL, NULL, NULL);
		}
		else
		{
			CRect rcShow(m_rcMin);

			//
			if (m_nSysMnuHover == SYSMNU_MIN) {

				BYTE byAlpha = 128;				
				Color colors[] =
				{
					Color(byAlpha, 255, 255, 255),
					Color(byAlpha, 0, 255, 0),
				};
				float positions[] = { 0.0f, 1.0f };
				LinearGradientBrush linGrBrush(RectF(0, 0, 80, 80), Color::White, Color::Green, LinearGradientModeVertical);
				//linGrBrush.SetInterpolationColors(colors, positions, 2);
				g.FillRectangle(&linGrBrush, rcShow.left, rcShow.top, rcShow.Width(), rcShow.Height());
			}

			{
				rcShow.DeflateRect(14, 10);
				rcShow.OffsetRect(0, 10);
				g.TranslateTransform(rcShow.left, rcShow.top);
				Gdiplus::SolidBrush brush(Color(255, 0, 0, 0));
				g.FillRectangle(&brush, 0, 0, rcShow.Width(), 3);
				g.ResetTransform();
			}
			//
		}
	}
}

BOOL CSWDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	switch (nHitTest)
	{
	case HTTOP:
	case HTBOTTOM:
		SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENS)));
		return TRUE;

	case HTLEFT:
	case HTRIGHT:
		SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
		return TRUE;

	case HTTOPLEFT:
	case HTBOTTOMRIGHT:
		SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
		return TRUE;

	case HTTOPRIGHT:
	case HTBOTTOMLEFT:
		SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
		return TRUE;
	}

	return CDialog::OnSetCursor(pWnd, nHitTest, message);
}


void CSWDialog::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (!m_bHasTitleBar)
	{
		CRect rcClient;
		GetClientRect(rcClient);
		CRect rcDrag = CRect(0, 0, rcClient.Width(), m_rcImageClient.top - m_rcImageWindow.top);
		if (rcDrag.IsRectEmpty())
			rcDrag = rcClient;
		ClientToScreen(rcDrag);
		CPoint point; GetCursorPos(&point);
		if (PtInRect(rcDrag, point))
		{
			if (IsZoomed())
			{
				::PostMessage(m_hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L);
			}
			else
			{
				if (!m_bSysMnu[SYSMNU_MAX])
					return ;

				::PostMessage(m_hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0L);
			}
		}
	}

	CDialog::OnLButtonDblClk(nFlags, point);
}

void CSWDialog::DrawWindowText(Gdiplus::Graphics& g)
{
	int xPos = 10;
	int yPos = 10;
	HICON hIcon = (HICON)::SendMessage(m_hWnd, WM_GETICON, FALSE, 0);
	if (hIcon)
	{
		Gdiplus::Bitmap* pBitmap = Gdiplus::Bitmap::FromHICON(hIcon);
		g.DrawImage(pBitmap, RectF(xPos, yPos, pBitmap->GetWidth(), pBitmap->GetHeight()/*GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)*/), 0, 0, pBitmap->GetWidth(), pBitmap->GetHeight(), UnitPixel, NULL, NULL, NULL);
		xPos += pBitmap->GetWidth();
		xPos += 5;
		delete pBitmap;
		pBitmap = NULL;
	}

	if (m_sWindowText.size() > 0)
	{
		Gdiplus::Font font(L"微软雅黑", 12, FontStyleBold);
		StringFormat stringFormat;
		stringFormat.SetFormatFlags(StringFormatFlagsNoWrap);
		stringFormat.SetAlignment(StringAlignmentNear);
		stringFormat.SetLineAlignment(StringAlignmentNear);
		std::wstring wsTitle = sw::CSWStrConverter::GBKToUnicode(m_sWindowText.c_str());
		SolidBrush brush((ARGB)Color::White);
		PointF point;
		point.X = (Gdiplus::REAL)xPos;
		point.Y = (Gdiplus::REAL)yPos - 4;
		g.SetTextRenderingHint(TextRenderingHintAntiAlias);
		g.DrawString(wsTitle.c_str(), wsTitle.size(), &font, point, &stringFormat, &brush);
	}
}

HBRUSH CSWDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何特性
	if (nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_BTN)
	{
		return HBRUSH(GetStockObject(HOLLOW_BRUSH)); //CreateSolidBrush(m_crKey);
	}

	if (nCtlColor == CTLCOLOR_STATIC)
	{
		//pDC->SetBkMode(TRANSPARENT);
		//pDC->SetTextColor(RGB(0, 0, 0));
		return HBRUSH(GetStockObject(HOLLOW_BRUSH));
	}

	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor/* = 0*/, COLORREF cTolerance/* = 0x101010*/)
{
	HRGN hRgn = NULL;
	if (hBmp)
	{
		HDC hMemDC = CreateCompatibleDC(NULL);
		if (hMemDC)
		{
			BITMAP bm;
			GetObject(hBmp, sizeof(bm), &bm);
			BITMAPINFOHEADER RGB32BITSBITMAPINFO = {
				sizeof(BITMAPINFOHEADER),	// biSize 
				bm.bmWidth,					// biWidth; 
				bm.bmHeight,				// biHeight; 
				1,							// biPlanes; 
				32,							// biBitCount 
				BI_RGB,						// biCompression; 
				0,							// biSizeImage; 
				0,							// biXPelsPerMeter; 
				0,							// biYPelsPerMeter; 
				0,							// biClrUsed; 
				0							// biClrImportant; 
			};
			VOID * pbits32;
			HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, NULL, 0);
			if (hbm32)
			{
				HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
				HDC hDC = CreateCompatibleDC(hMemDC);
				if (hDC)
				{
					BITMAP bm32;
					GetObject(hbm32, sizeof(bm32), &bm32);
					while (bm32.bmWidthBytes % 4)
						bm32.bmWidthBytes++;
					HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
					BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
					DWORD maxRects = 200;
					HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
					RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
					pData->rdh.dwSize = sizeof(RGNDATAHEADER);
					pData->rdh.iType = RDH_RECTANGLES;
					pData->rdh.nCount = pData->rdh.nRgnSize = 0;
					SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);

					BYTE lr = GetRValue(cTransparentColor);
					BYTE lg = GetGValue(cTransparentColor);
					BYTE lb = GetBValue(cTransparentColor);
					BYTE hr = min(0xff, lr + GetRValue(cTolerance));
					BYTE hg = min(0xff, lg + GetGValue(cTolerance));
					BYTE hb = min(0xff, lb + GetBValue(cTolerance));

					BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
					for (int y = 0; y < bm.bmHeight; y++)
					{
						for (int x = 0; x < bm.bmWidth; x++)
						{
							int x0 = x;
							LONG *p = (LONG *)p32 + x;
							while (x < bm.bmWidth)
							{
								BYTE b = GetRValue(*p);
								if (b >= lr && b <= hr)
								{
									b = GetGValue(*p);
									if (b >= lg && b <= hg)
									{
										b = GetBValue(*p);
										if (b >= lb && b <= hb)
											break;
									}
								}
								p++;
								x++;
							}

							if (x > x0)
							{
								if (pData->rdh.nCount >= maxRects)
								{
									GlobalUnlock(hData);
									maxRects += 200;
									hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
									pData = (RGNDATA *)GlobalLock(hData);
								}
								RECT *pr = (RECT *)&pData->Buffer;
								SetRect(&pr[pData->rdh.nCount], x0, y, x, y + 1);
								if (x0 < pData->rdh.rcBound.left)
									pData->rdh.rcBound.left = x0;
								if (y < pData->rdh.rcBound.top)
									pData->rdh.rcBound.top = y;
								if (x > pData->rdh.rcBound.right)
									pData->rdh.rcBound.right = x;
								if (y + 1 > pData->rdh.rcBound.bottom)
									pData->rdh.rcBound.bottom = y + 1;
								pData->rdh.nCount++;

								if (pData->rdh.nCount == 2000)
								{
									HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
									if (hRgn)
									{
										CombineRgn(hRgn, hRgn, h, RGN_OR);
										DeleteObject(h);
									}
									else
										hRgn = h;
									pData->rdh.nCount = 0;
									SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
								}
							}
						}
						p32 -= bm32.bmWidthBytes;
					}

					HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
					if (hRgn)
					{
						CombineRgn(hRgn, hRgn, h, RGN_OR);
						DeleteObject(h);
					}
					else
						hRgn = h;

					GlobalFree(hData);
					SelectObject(hDC, holdBmp);
					DeleteDC(hDC);
				}
				DeleteObject(SelectObject(hMemDC, holdBmp));
			}
			DeleteDC(hMemDC);
		}
	}

	return hRgn;
}

void CSWDialog::SetBackgroundMaskImage(LPCTSTR lpszImageName)
{
#if 1
	COLORREF crAlpha = RGB(255, 0, 0);
	CImage img; img.Load(lpszImageName);

	if (img.IsNull())
		return;

	struct PixelData
	{
		BYTE B;
		BYTE G;
		BYTE R;
		BYTE A;
	};

	HRGN hRgn = NULL;
	DWORD maxRects = 200;
	HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
	RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
	pData->rdh.dwSize = sizeof(RGNDATAHEADER);
	pData->rdh.iType = RDH_RECTANGLES;
	pData->rdh.nCount = pData->rdh.nRgnSize = 0;
	SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
	for (int y = 0; y < img.GetHeight(); y++)
	{
		for (int x = 0; x < img.GetWidth(); x++)
		{
			int x0 = x;
			while (x < img.GetWidth())
			{
				PixelData* pPixel = (PixelData*)img.GetPixelAddress(x, y);
				if (pPixel->R != GetRValue(crAlpha) || pPixel->G != GetGValue(crAlpha) || pPixel->B != GetBValue(crAlpha))
					//if (pPixel->A == 0)
					break;

				x++;
			}

			if (x > x0)
			{
				if (pData->rdh.nCount >= maxRects)
				{
					GlobalUnlock(hData);
					maxRects += 200;
					hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
					pData = (RGNDATA *)GlobalLock(hData);
				}

				RECT *pRc = (RECT *)&pData->Buffer;
				SetRect(&pRc[pData->rdh.nCount], x0, y, x, y + 1);
				if (x0 < pData->rdh.rcBound.left)
					pData->rdh.rcBound.left = x0;
				if (y < pData->rdh.rcBound.top)
					pData->rdh.rcBound.top = y;
				if (x > pData->rdh.rcBound.right)
					pData->rdh.rcBound.right = x;
				if (y + 1 > pData->rdh.rcBound.bottom)
					pData->rdh.rcBound.bottom = y + 1;
				pData->rdh.nCount++;

				if (pData->rdh.nCount == 500)
				{
					HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
					if (hRgn)
					{
						CombineRgn(hRgn, hRgn, h, RGN_OR);
						DeleteObject(h);
					}
					else
						hRgn = h;
					pData->rdh.nCount = 0;
					SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
				}
			}
		}
	}

	HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
	if (hRgn)
	{
		CombineRgn(hRgn, hRgn, h, RGN_OR);
		DeleteObject(h);
	}
	else
		hRgn = h;
	pData->rdh.nCount = 0;
	GlobalUnlock(hData);
	GlobalFree(hData);

#else
	COLORREF crAlpha = RGB(255, 0, 0);
	Gdiplus::Bitmap* pBkgrMaskBitmap = CImageFactory::getSingletonPtr()->GetSkinItemImage(lpszImageName);

	struct PixelData
	{
		BYTE B;
		BYTE G;
		BYTE R;
		BYTE A;
	};

	HRGN hRgn = NULL;
	if (pBkgrMaskBitmap)
	{
		//if (Gdiplus::IsAlphaPixelFormat((Gdiplus::PixelFormat)pBkgrMaskBitmap->GetPixelFormat()))
		{
			Gdiplus::BitmapData bitmapData;
			Gdiplus::Rect rcBitmap(0, 0, pBkgrMaskBitmap->GetWidth(), pBkgrMaskBitmap->GetHeight());
			Gdiplus::Status status = pBkgrMaskBitmap->LockBits(&rcBitmap, Gdiplus::ImageLockModeRead, pBkgrMaskBitmap->GetPixelFormat(), &bitmapData);
			if (status == Gdiplus::Ok)
			{
				#define ALLOC_UNIT	200
				DWORD maxRects = ALLOC_UNIT;
				HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
				RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
				pData->rdh.dwSize = sizeof(RGNDATAHEADER);
				pData->rdh.iType = RDH_RECTANGLES;
				pData->rdh.nCount = pData->rdh.nRgnSize = 0;
				SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
				int nBitsPixel = GetPixelFormatSize(pBkgrMaskBitmap->GetPixelFormat()) >> 3;
				int nLinesize = pBkgrMaskBitmap->GetWidth() * nBitsPixel;
				int nOffset = bitmapData.Stride - bitmapData.Width * nBitsPixel;
				PixelData* pPixel = (PixelData*)bitmapData.Scan0;
				for (int y = 0; y < bitmapData.Height; y++)
				{
					for (int x = 0; x < bitmapData.Width; x++)
					{
						int x0 = x;
						while (x < bitmapData.Width)
						{
							//if (pPixel->R==GetRValue(crAlpha) && pPixel->G == GetGValue(crAlpha) && pPixel->B == GetBValue(crAlpha))
							if (pPixel->R != GetRValue(crAlpha) || pPixel->G != GetGValue(crAlpha) || pPixel->B != GetBValue(crAlpha))
							//if (pPixel->A == 0)
								break;						

							x++;
							pPixel++;
							if (!Gdiplus::IsAlphaPixelFormat((Gdiplus::PixelFormat)pBkgrMaskBitmap->GetPixelFormat()))
								pPixel -= 1;
						}

						if (x < bitmapData.Width)
						{
							pPixel++;
							if (!Gdiplus::IsAlphaPixelFormat((Gdiplus::PixelFormat)pBkgrMaskBitmap->GetPixelFormat()))
								pPixel -= 1;
						}

						if (x > x0)
						{
							if (pData->rdh.nCount >= maxRects)
							{
								GlobalUnlock(hData);
								maxRects += ALLOC_UNIT;
								hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
								pData = (RGNDATA *)GlobalLock(hData);
							}

							RECT *pRc = (RECT *)&pData->Buffer;
							SetRect(&pRc[pData->rdh.nCount], x0, y, x, y + 1);
							if (x0 < pData->rdh.rcBound.left)
								pData->rdh.rcBound.left = x0;
							if (y < pData->rdh.rcBound.top)
								pData->rdh.rcBound.top = y;
							if (x > pData->rdh.rcBound.right)
								pData->rdh.rcBound.right = x;
							if (y + 1 > pData->rdh.rcBound.bottom)
								pData->rdh.rcBound.bottom = y + 1;
							pData->rdh.nCount++;

							if (pData->rdh.nCount == 500)
							{
								HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
								if (hRgn)
								{
									CombineRgn(hRgn, hRgn, h, RGN_OR);
									DeleteObject(h);
								}
								else
									hRgn = h;
								pData->rdh.nCount = 0;
								SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
							}
						}
					}

					pPixel += bitmapData.Stride - (bitmapData.Width * nBitsPixel);
				}

				HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
				if (hRgn)
				{
					CombineRgn(hRgn, hRgn, h, RGN_OR);
					DeleteObject(h);
				}
				else
					hRgn = h;
				pData->rdh.nCount = 0;
				GlobalUnlock(hData);
				GlobalFree(hData);
				pBkgrMaskBitmap->UnlockBits(&bitmapData);
			}
		}
	}
#endif

	::SetWindowRgn(m_hWnd, hRgn, TRUE);
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值