[kaze's test] プログラミングメモ →目次

楕円形ボタン(VC++)

リージョンでボタンの操作範囲と描画範囲を設定すれば、どんな色んな形状のボタンでも作れます。今回のメモは、MFC楕円形のボタンを作る手順を記述します。

1.リソース編集で、ボタン(IDC_BUTTON1)をダイアログに貼り付けて、「オーナー描画」を設定します。

2.CButtonからCBtn1を派生します。ClassWizardでボタン(IDC_BUTTON1)と関連付けるCBtn1型の変数m_btnを追加します。



3.ダイアログ クラスのOnInitDialog()の中で、ボタンの操作範囲を設定します。

	CRect r;
	m_btn.GetClientRect(&r);
	HRGN hRgn = CreateEllipticRgn(r.left, r.top, r.right-1, r.bottom-1);
	m_btn.SetWindowRgn(hRgn, TRUE);
	DeleteObject(hRgn);

4.オーナー描画を実装する為に、CBtn1のDrawItem()関数をオーバーライドして、実装します。

void CBtn1::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
	CRect rct = lpDrawItemStruct->rcItem;

	CRgn rgnClip;
	rgnClip.CreateEllipticRgn(rct.left, rct.top, rct.right-1, rct.bottom-1);
	pDC->SelectClipRgn(&rgnClip);

	pDC->FillSolidRect(&rct, ::GetSysColor(COLOR_BTNFACE));

	rct.DeflateRect(1,1);
	
	CPen penWhite(PS_SOLID, 2, (COLORREF)0x00ffffff);
	CPen penBlack(PS_SOLID, 2, (COLORREF)0x00404040);

	if(lpDrawItemStruct->itemState & ODS_SELECTED)  
		pDC->SelectObject(&penBlack);
	else
		pDC->SelectObject(&penWhite);

	pDC->Arc(rct.left, rct.top, rct.right-1, rct.bottom-1, 
			rct.CenterPoint().x + rct.Width() / 2 /pow(2,0.5),
			rct.CenterPoint().y - rct.Height() / 2 /pow(2,0.5),
			rct.CenterPoint().x - rct.Width() / 2 /pow(2,0.5),
			rct.CenterPoint().y + rct.Height() / 2 /pow(2,0.5));
	
	if(lpDrawItemStruct->itemState & ODS_SELECTED)  
		pDC->SelectObject(&penWhite);
	else
		pDC->SelectObject(&penBlack);

	pDC->Arc(rct.left, rct.top, rct.right-1, rct.bottom-1, 
			rct.CenterPoint().x - rct.Width() / 2 /pow(2,0.5),
			rct.CenterPoint().y + rct.Height() / 2 /pow(2,0.5),
			rct.CenterPoint().x + rct.Width() / 2 /pow(2,0.5),
			rct.CenterPoint().y - rct.Height() / 2 /pow(2,0.5));

	CString strWindowText;
	GetWindowText(strWindowText);
	int nBkMode = pDC->SetBkMode(TRANSPARENT);
	COLORREF colorref = pDC->SetTextColor(RGB(255,0,0));
	if(lpDrawItemStruct->itemState & ODS_SELECTED)  
		rct.OffsetRect(1,1);
	pDC->DrawText(strWindowText, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
	pDC->SetTextColor(colorref);
	pDC->SelectClipRgn(NULL);
	rgnClip.DeleteObject();
}