๋ฐ˜์‘ํ˜•

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Custom Button ๋งŒ๋“œ๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

(๋ณธ๋ฌธ ํ•˜๋‹จ์— ์ƒ˜ํ”Œ ์ฝ”๋“œ๊ฐ€ ์ฒจ๋ถ€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.)


๋จผ์ €, 'MyButton'์ด๋ผ๋Š” Dialog Base์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


๊ทธ๋ฆฌ๊ณ  GDI+๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

'์†”๋ฃจ์…˜ ํƒ์ƒ‰๊ธฐ'์—์„œ ํ”„๋กœ์ ํŠธ์— ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

('ํ”„๋กœ์ ํŠธ ์šฐํด๋ฆญ > Add > Class...' ๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.)


๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฐฝ์ด ์ƒ์„ฑ๋˜๋ฉด '์ถ”๊ฐ€(Add)' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.


ํด๋ž˜์Šค์— ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” 'CSkinButton'์ด๋ผ๊ณ  ์ด๋ฆ„์„ ์ง“๊ฒ ์Šต๋‹ˆ๋‹ค.


'Finish' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด 'SkinButton.cpp/h' ํŒŒ์ผ์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.


์•ž์œผ๋กœ ๋งŒ๋“ค SkinButton Class๋Š” CButton์„ ์ƒ์†๋ฐ›๋Š” ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋‹ˆ, 'CSkinButton.h'์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

//SkinButton.h 
 class CSkinButton : public CButton 
{
 public: 
	CSkinButton(); 
	~CSkinButton(); 
}; 


๊ทธ๋ฆฌ๊ณ , ๋ฒ„ํŠผ์˜ ๋ฐฐ๊ฒฝ / ์™ธ๊ณฝ์„  / ํ…์ŠคํŠธ์˜ ์ƒ‰์ƒ๊ณผ ํ…์ŠคํŠธ์˜ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

//SkinButton.h 
class CSkinButton : public CButton 
{
 public: 
	CSkinButton(); 
	~CSkinButton(); 
public : 
	void SetColorBackground(int a, int r, int g, int b); 
	void SetColorBorder(int a, int r, int g, int b); 
	void SetColorText(int a, int r, int g, int b); 
	void SetSizeText(float size); 
private : 
	Gdiplus::Color m_clrBackground; // ๋ฐฐ๊ฒฝ ์ƒ‰์ƒ. 
	Gdiplus::Color m_clrBorder; // ์™ธ๊ณฝ์„  ์ƒ‰์ƒ. 
	Gdiplus::Color m_clrText; // ํ…์ŠคํŠธ ์ƒ‰์ƒ. 
	float m_fSizeText; // ํ…์ŠคํŠธ ํฌ๊ธฐ. 
	CString m_strText; // ๋ฌธ์ž์—ด. 
};


'SkinButton.cpp'์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

์ž, ๋๋‚ฌ์Šต๋‹ˆ๋‹ค!











... ๋‹นํ™ฉ์Šค๋Ÿฝ์ฃ ?ใ…Žใ…Ž;

๋†๋‹ด์ด๊ตฌ์š”. ์ด์ œ ์•Œ๋งน์ด๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณผ๊นŒ์š”?

SkinButton Drawing ์ปจ์…‰์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.


๋จผ์ € Background ์˜์—ญ์„ ๊ทธ๋ฆฌ๊ณ  Border๋ฅผ ๊ทธ๋ฆฐ ๋‹ค์Œ Text๋ฅผ ๊ทธ๋ฆฌ๋ฉด ๋์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ, SetDlgItemText API๋ฅผ ์ด์šฉํ•œ ๋ฌธ์ž์—ด ์„ค์ •์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น API๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด ๊นœ๋นก์ž„ ํ˜„์ƒ์ด ๋‚˜ํƒ€๋‚˜ ๋ฌธ์ œ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ CString ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฌธ์ž์—ด์„ ์„ค์ •ํ•˜๊ณ  ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜๋„ ์ •์˜ํ•ด ๋ณผ๊ฒŒ์š”.

//SkinButton.h 
class CSkinButton : public CButton
{
public:
	CSkinButton();
	~CSkinButton();

public :
	void SetColorBackground(int a, int r, int g, int b);
	void SetColorBorder(int a, int r, int g, int b);
	void SetColorText(int a, int r, int g, int b);
	void SetSizeText(float size);

private :
	Gdiplus::Color m_clrBackground;
	Gdiplus::Color m_clrBorder;
	Gdiplus::Color m_clrText;
	float m_fSizeText;
	CString m_strText;

	void DrawBackground(Gdiplus::Graphics *pG); // ๋ฐฐ๊ฒฝ ๊ทธ๋ฆฌ๊ธฐ.
	void DrawBorder(Gdiplus::Graphics *pG); // ์™ธ๊ณฝ์„  ๊ทธ๋ฆฌ๊ธฐ.
	void DrawText(Gdiplus::Graphics *pG); // ํ…์ŠคํŠธ ๊ทธ๋ฆฌ๊ธฐ.
};
//SkinButton.cpp
void CSkinButton::DrawBackground(Graphics *pG)
{
	CRect rect;
	GetClientRect(&rect);

	Gdiplus::SolidBrush brush(m_clrBackground);

	pG->FillRectangle(&brush, rect.left, rect.top, rect.right, rect.bottom);
}

void CSkinButton::DrawBorder(Graphics *pG)
{
	CRect rect;
	GetClientRect(&rect);

	Gdiplus::Pen pen(m_clrBorder, 1);
	pG->DrawRectangle(&pen, rect.left, rect.top, rect.Width(), rect.Height());
}

void CSkinButton::DrawText(Graphics *pG)
{
	CRect rect;
	GetClientRect(&rect);

	Gdiplus::FontFamily fontfam(_T("Arial"));
	Gdiplus::Font font(&fontfam, m_fSizeText, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel);

	Gdiplus::StringFormat stringAlign;
	stringAlign.SetAlignment(Gdiplus::StringAlignmentCenter);
	stringAlign.SetLineAlignment(Gdiplus::StringAlignmentCenter);

	Gdiplus::SolidBrush brush(m_clrText);

	pG->DrawString(m_strText, m_strText.GetLength(), &font, 
		Gdiplus::RectF((float)rect.left, (float)rect.top, (float)rect.Width(), (float)rect.Height()), &stringAlign, &brush);
}

์—ฌ๊ธฐ๊นŒ์ง€ ๊ฐ ์š”์†Œ๋ฅผ ๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜์™€ ์ƒ‰์ƒ ๋ฐ ํฌ๊ธฐ๋ฅผ ์ •์˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ–ˆ๋Š”๋ฐ์š”.

๋ฒ„ํŠผ ์ปจํŠธ๋กค์„ '๊ทธ๋ฆฌ๋Š” ์ˆœ๊ฐ„'์€ ์–ธ์ œ์ผ๊นŒ์š”? ์–ด๋””์—์„œ ๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ ๊นŒ์š”?

๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ 'OnPaint()'์ž…๋‹ˆ๋‹ค.

OnPaint ํ•จ์ˆ˜๋Š” ์ปจํŠธ๋กค์ด ๊ทธ๋ ค์งˆ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ์ด๋ฒคํŠธ ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค.

OnPaint ํ•จ์ˆ˜์— ๊ทธ๋ƒฅ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋”๋ธ” ๋ฒ„ํผ๋ง(double buffering)์„ ์ ์šฉํ•˜์—ฌ ๊ทธ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๋จผ์ € OnPaint() ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ณผ๊นŒ์š”?

๋‹จ์ถ•ํ‚ค 'Ctrl+Shift+x' ๋˜๋Š” 'Class Wizard'๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

'Class name: CSkinButton'์„ ์„ ํƒํ•˜๊ณ , 'Messages'์—์„œ 'WM_PAINT'๋ฅผ 'Add Handler'๋ฅผ ํด๋ฆญํ•˜์—ฌ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

'OK'๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

void CSkinButton::OnPaint() 
{ 
	CPaintDC dc(this); // device context for painting 	
				 // TODO: Add your message handler code here 	
				 // Do not call CButton::OnPaint() for painting messages 
}

์ด์ œ OnPaint()๋ฅผ ์•„๋ž˜ ์ฒ˜๋Ÿผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

//SkinButton.cpp 
void CSkinButton::OnPaint()
{
	CPaintDC dc(this);

	CRect rect;
	GetClientRect(&rect);

	Graphics mainG(dc.GetSafeHdc());

	Bitmap bmp(rect.Width(), rect.Height());

	Graphics memG(&bmp);

	SolidBrush brush(m_clrBackground);
	memG.FillRectangle(&brush, 0, 0, rect.Width(), rect.Height());

	DrawBackground(&memG);
	DrawBorder(&memG);
	DrawText(&memG);

	mainG.DrawImage(&bmp, 0, 0);
}


์ด์ œ SkinButton ๊ตฌํ˜„์€ ๋๋‚ฌ์Šต๋‹ˆ๋‹ค.

Main Dialog์—์„œ SkinButton์„ ์ ์šฉํ•ด ๋ณผ๊นŒ์š”? ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ SkinButton.h์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

//SkinButton.h 
#include "SkinButton.h"

๊ทธ๋ฆฌ๊ณ  CMyButtonDlg์— ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

//MyButtonDlg.h
CSkinButton m_skinBtn;

๋ฆฌ์†Œ์Šค ํŽธ์ง‘๊ธฐ์—์„œ Button Control์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

Button์˜ ID๋Š” ๊ธฐ๋ณธ ๊ฐ’์ธ IDC_BUTTON1์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์†Œ์Šค ํŽธ์ง‘๊ธฐ์— ์ถ”๊ฐ€ํ•œ ๋ฒ„ํŠผ๊ณผ SkinButton ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ฅผ ์—ฐ๋™ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

//MyButtonDlg.cpp
void CMyButtonDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialogEx::DoDataExchange(pDX); 
	DDX_Control(pDX, IDC_BUTTON1, m_skinBtn); // ์ฝ”๋“œ ์ถ”๊ฐ€. 
} 


์ด์ œ ์‹คํ–‰ํ•ด ๋ณผ๊นŒ์š”?

๊ฒ€์€์ƒ‰๋งŒ ๋‚˜์˜ค์ฃ ? ์™œ๊ทธ๋Ÿด๊นŒ์š”?

์ƒ‰์ƒ ๋ณ€์ˆ˜๋ฅผ ์ •์˜๋Š” ํ–ˆ์ง€๋งŒ ์ดˆ๊ธฐํ™” ๋˜๋Š” ์„ค์ •์„ ์•ˆํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

CSkinButton() ์ƒ์„ฑ์ž์— ์•„๋ž˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ดˆ๊ธฐ ๊ฐ’์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

CSkinButton::CSkinButton()
{
	m_clrBackground = Gdiplus::Color(255, 64, 64, 64);
	m_clrBorder = Gdiplus::Color(255, 128, 128, 128);
	m_clrText = Gdiplus::Color(255, 255, 255, 255);
	m_strText = _T("Button");
	m_fSizeText = 15;
}


๋นŒ๋“œ ํ›„ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


์ด์ œ ์ƒ‰์ƒ ์„ค์ • ํ•จ์ˆ˜์™€ ๊ธ€์ž ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋งˆ์Œ๋Œ€๋กœ ๊พธ๋ฐ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

๊ทธ๋Ÿฐ๋ฐ ๋™์ž‘์€ ํ• ๊นŒ์š”?

๋ฆฌ์†Œ์Šค ํŽธ์ง‘๊ธฐ์—์„œ ๋ฒ„ํŠผ ์ปจํŠธ๋กค์„ ๋”๋ธ”ํด๋ฆญ ํ•˜๊ณ , ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

//MyButtonDlg.cpp
void CMyButtonDlg::OnBnClickedButton1()	 
{ 
	AfxMessageBox(_T("SkinButton!")); 
}

๊ทธ๋ฆฌ๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ณ  ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


์—ฌ๊ธฐ๊นŒ์ง€ SkinButton ๋งŒ๋“œ๋Š” ๊ณผ์ •์„ ์ง„ํ–‰ํ•ด ๋ณด์•˜๋Š”๋ฐ์š”. ์‚ฌ์‹ค ์–ด๋ ค์šด ๋ถ€๋ถ„์€ ์—†์Šต๋‹ˆ๋‹ค.

๋‹จ์ง€ ์ถ”๊ฐ€ํ•ด์•ผ ํ•  ๊ธฐ๋Šฅ์ ์ธ ๋ถ€๋ถ„์ด ๋งŽ์„ ๋ฟ์ด์ฃ .

์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฒ„ํŠผ์„ ๋ˆŒ๋ ธ์„ ๋•Œ ๋ˆŒ๋ฆฌ๋Š” ํšจ๊ณผ๋ผ๋“ ๊ฐ€, ๋งˆ์šฐ์Šค๊ฐ€ ๋ฒ„ํŠผ ์œ„์— ์žˆ์„ ๋•Œ ๋‹ค๋ฅธ ์ƒ‰์ƒ์„ ํ‘œํ˜„ํ•œ๋‹ค๋“ ๊ฐ€ ๋“ฑ ๋ง์ด์ฃ .


๋ณธ๋ฌธ ์˜ˆ์ œ๋Š” ์•„๋ž˜ ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ ํ™•์ธํ•ด๋ณด์„ธ์š”.

MyButton.zip
๋ฐ˜์‘ํ˜•