template< class Func >
void draw_with_brush_and_pen(CDC& dc, const COLORREF& col, const COLORREF& col2, const int line_width, Func draw_func)
{
	CBrush myBrush(col);
	CBrush* oldBrush = dc.SelectObject(&myBrush);
	CPen myPen(PS_SOLID, line_width, col2);
	CPen* oldPen = dc.SelectObject(&myPen);
	draw_func(dc);
	dc.SelectObject(oldBrush);
	dc.SelectObject(oldPen);
	return;
}
void enmergin(CRect& rect, const int mergin)
{
	rect.top -= mergin;
	rect.bottom += mergin;
	rect.left -= mergin;
	rect.right += mergin;
	return;
}
template< class Func >
void draw_with_font(CDC& dc, const char* face, Func draw_func)
{
	HFONT hFont = CreateFont(
		36,       //フォント高さ
		0,                      //文字幅(高さと同じ)
		0,                  //テキストの角度
		0,                      //ベースラインとx軸との角度
		FW_REGULAR,             //フォントの重さ(太さ)
		FALSE,                  //イタリック体
		FALSE,                  //アンダーライン
		FALSE,                  //打ち消し線
		SHIFTJIS_CHARSET,       //文字セット
		OUT_DEFAULT_PRECIS,     //出力精度
		CLIP_DEFAULT_PRECIS,    //クリッピング精度
		PROOF_QUALITY,          //出力品質
		FIXED_PITCH | FF_MODERN,  //ピッチとファミリー
		face);                  //書体名
	HFONT hFontOld = (HFONT)SelectObject(dc, hFont);
	draw_func(dc);
	SelectObject(dc, hFontOld);
	DeleteObject(hFont);
	return;
}
void MyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);     //Get device context object
	Graphics grp(dc);

	dc.SetBkMode(TRANSPARENT);

	CRect rt;
	rt = lpDrawItemStruct->rcItem;        //Get button rect

	{
		// リージョン指定
		CRgn rgn;
		rgn.CreateRoundRectRgn(0, 0, rt.Width(), rt.Height(), 18, 18);
		SetWindowRgn(rgn, TRUE);
	}
	UINT state = lpDrawItemStruct->itemState; //Get state of the button
	if ((state & ODS_SELECTED))            // If it is pressed
	{
		auto rt2 = rt;
		enmergin(rt2, -4);
		auto func = [&rt2](CDC& dc) { dc.RoundRect(rt2, CPoint(20, 20)); };
		draw_with_brush_and_pen(dc, RGB(88, 128, 88), RGB(0,255,0), 3, func);
		dc.SetTextColor(RGB(0, 255, 20));
	}
	else if ((state & ODS_FOCUS))            // If it is pressed
	{
		auto rt2 = rt;
		enmergin(rt2, -4);
		auto func = [&rt2](CDC& dc) { dc.RoundRect(rt2, CPoint(20, 20)); };
		draw_with_brush_and_pen(dc, RGB(180, 190, 180), RGB(0, 188, 0), 3, func);
		dc.SetTextColor(RGB(0, 122, 20));
	}
	else
	{		
		auto rt2 = rt;
		enmergin(rt2, -3);
		auto func = [&rt2](CDC& dc) { dc.RoundRect(rt2, CPoint(20, 20)); };
		if (_yes_hover)
		{
			draw_with_brush_and_pen(dc, RGB(255, 180, 250), RGB(180, 23, 255), 1, func);
			dc.SetTextColor(RGB(255, 20, 220));
		}
		else
		{
			draw_with_brush_and_pen(dc, RGB(180, 180, 180), RGB(0, 23, 255), 1, func);
			dc.SetTextColor(RGB(0, 20, 120));
		}
	}

	// text color
	CString strTemp;
	GetWindowText(strTemp);
	// Get the caption which have been set
	if ((state & ODS_FOCUS))       // If the button is focused
	{
		// Draw a focus rect which indicates the user 
		// that the button is focused
		enmergin(rt, -12);
		dc.DrawFocusRect(rt);
	}
	else
	{

	}
	// draw text
	{
		auto func = [&rt, &strTemp](CDC& dc) {
			dc.DrawText(strTemp, rt, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		};
		draw_with_font(dc, "Meiryo UI", func);
	}
	// Draw out the caption


	dc.Detach();

	return;
}


BOOL MyButton::OnEraseBkgnd(CDC* pDC)
{
	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
	return true;
	//return CButton::OnEraseBkgnd(pDC);
}


void MyButton::OnNcMouseMove(UINT nHitTest, CPoint point)
{
	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。

	_yes_hover = true;
	// each time a WM_MOUSEHOVER is generated it cancels previous calls to TrackMouseEvent()
	// so we must recall it everytime a WM_MOUSEHOVER or WM_MOUSELEAVE is generated.The
	// logic that calls it in WM_MOUSELEAVE is actually in WM_MOUSEMOVE. When the cursor
	// is detected as moving back into our window TrackMouseEvent() gets called.
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(tme);
	tme.dwFlags = TME_HOVER | TME_LEAVE;
	tme.hwndTrack = m_hWnd;
	tme.dwHoverTime = HOVER_DEFAULT;
	::TrackMouseEvent(&tme);
	CButton::OnNcMouseMove(nHitTest, point);
}


void MyButton::OnNcMouseLeave()
{
	// この機能は Windows 2000 かそれ以降のバージョンを必要とします。
	// シンボル _WIN32_WINNTと WINVER は >= 0x0500 にならなければなりません。
	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。

	_yes_hover = false;
	CButton::OnNcMouseLeave();
}


void MyButton::OnMouseHover(UINT nFlags, CPoint point)
{
	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
	_yes_hover = true;
	CButton::OnMouseHover(nFlags, point);
	// each time a WM_MOUSEHOVER is generated it cancels previous calls to TrackMouseEvent()
	// so we must recall it everytime a WM_MOUSEHOVER or WM_MOUSELEAVE is generated.The
	// logic that calls it in WM_MOUSELEAVE is actually in WM_MOUSEMOVE. When the cursor
	// is detected as moving back into our window TrackMouseEvent() gets called.
	//if (!_yes_hover)
	//{
	//	TRACKMOUSEEVENT tme;
	//	tme.cbSize = sizeof(tme);
	//	tme.dwFlags = TME_HOVER | TME_LEAVE;
	//	tme.hwndTrack = m_hWnd;
	//	tme.dwHoverTime = 5;/*HOVER_DEFAULT*/;
	//	::TrackMouseEvent(&tme);
	//}
	this->Invalidate();
}


void MyButton::OnMouseLeave()
{
	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
	_yes_hover = false;
	Invalidate();
	CButton::OnMouseLeave();
}


void MyButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: ここにメッセージ ハンドラー コードを追加するか、既定の処理を呼び出します。
	// each time a WM_MOUSEHOVER is generated it cancels previous calls to TrackMouseEvent()
	// so we must recall it everytime a WM_MOUSEHOVER or WM_MOUSELEAVE is generated.The
	// logic that calls it in WM_MOUSELEAVE is actually in WM_MOUSEMOVE. When the cursor
	// is detected as moving back into our window TrackMouseEvent() gets called.
	static bool done = false;
	if (!_yes_hover)
	{
		_yes_hover= true;
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.dwFlags = TME_HOVER | TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		tme.dwHoverTime = 5;
		::TrackMouseEvent(&tme);
	}
	CButton::OnMouseMove(nFlags, point);
}