티스토리 뷰
목차
MFC, 동적 버튼 생성, 색을 입히고 클릭 이벤트 설정
MFC에서 동적으로 버튼을 생성하고 클릭 이벤트를 설정합니다. 동적 버튼이란 동적으로 색상을 변경하는 것을 의미합니다. 아래 그림처럼 색상이 다양합니다.
위의 첨부 파일을 다운 받으셔서 실행하시면 확인이 됩니다.
[MFC, 동적 버튼 생성, 색을 입히고 클릭 이벤트 설정]
프로그램 개요
- 버튼의 동적 생성.
- 버튼 클릭 시, 색상이 변하며 메시지 박스가 생성.
달랑 두 가지 기능이 있습니다. 버튼을 동적으로 생성하고 색을 입히고, 클릭 이벤트도 설정합니다.
우선, 아래와 같이 4개의 함수와 1개의 변수를 설정합니다.
1 2 3 4 5 6 | virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); void addButton(CButton* createButton); void ClearButton(); CArray<CButton*> m_arrButton; | cs |
간단하게 설명하면 이렇습니다.
- OnCommand : 클릭 이벤트
- OnDrawItem : 색상 입히기
- addButton : 동적 버튼 생성 함수
- ClearButton : 메모리 해제
- CArray : 동적 버튼 저장소
프로그램은 버튼을 클릭함으로써 시작됩니다. 별로 어렵지 않죠?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | void CTest_DynamicCreation_ButtonDlg::OnBnClickedButton1() { UpdateData(TRUE); if(m_nBtnNumber > 20) { MessageBox(_T("20 미만으로 설정하세요")); return; } if(m_arrButton.GetSize() > 0) ClearButton(); for(int i = 0; i <= m_nBtnNumber; i++) { int left = 10 + (i * 30) + i * 2; int top = 40; int right = 10 + (i * 30) + (i * 2) + 30; int bottom = 65; CButton* createButton = new CButton; createButton->Create(NULL, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, CRect(left, top, right, bottom), this, 2000 + i); addButton(createButton); } Invalidate(TRUE); } | cs |
위의 소스에서 BS_OWNERDRAW 옵션을 주지 않으면 색을 입힐 수 없습니다. 그리고 맨 마지막에 2000 + i를 함으로써, nID도 구분해 줍니다.
addButton() 함수에선 단순히, CArray에 생성된 버튼을 저장합니다.
1 2 3 4 | void CTest_DynamicCreation_ButtonDlg::addButton(CButton* createButton) { m_arrButton.Add(createButton); } | cs |
버튼에 색을 입히기 위해선 OnDrawItem 함수를 반드시 다시 정의 해야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | void CTest_DynamicCreation_ButtonDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { UINT uStyle = DFCS_BUTTONPUSH; ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON); if (lpDrawItemStruct->itemState & ODS_SELECTED) uStyle |= DFCS_PUSHED; ::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle); CDC dc; dc.Attach(lpDrawItemStruct->hDC); RECT rect; rect = lpDrawItemStruct->rcItem; if(nIDCtl >= 2000 && nIDCtl < nIDCtl + m_arrButton.GetSize()) { for(int i = 0; i < m_arrButton.GetSize(); i++) { if(nIDCtl == 2000 + i) { dc.FillSolidRect(&rect, RGB(static_cast<unsigned int>(rand() % 254), static_cast<unsigned int>(rand() % 254), static_cast<unsigned int>(rand() % 254))); break; } } } //CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); } | cs |
24번 줄의 dc.FillSolidRect를 통해서 다이얼로그에 버튼을 그립니다.
[MFC, 동적 버튼 생성, 색을 입히고 클릭 이벤트 설정]
OnCommand에선 nID를 기준으로 버튼을 식별할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | BOOL CTest_DynamicCreation_ButtonDlg::OnCommand(WPARAM wParam, LPARAM lParam) { if(wParam >= 2000 && wParam < 2000 + m_arrButton.GetSize()) { for(int i = 0; i < m_arrButton.GetSize(); i++) { if(2000 + i == wParam) { CString strTmp; strTmp.Format("%d번 버튼", i + 1); MessageBox(strTmp); } } } return CDialog::OnCommand(wParam, lParam); } | cs |
메모리 해제 시엔, 버튼 객체를 하나씩 만들어 해제해 줍니다.
1 2 3 4 5 6 7 8 9 10 11 | void CTest_DynamicCreation_ButtonDlg::ClearButton() { for(int i = 0; i < m_arrButton.GetSize(); i++) { CButton* deleteButton = m_arrButton.GetAt(i); delete deleteButton; deleteButton = NULL; } m_arrButton.RemoveAll(); m_arrButton.FreeExtra(); } | cs |
RemoveAll()은 모든 객체를 지우겠다는 의미이고, FreeExtra()는 사용하지 않는 메모리를 반납하겠다는 의미입니다. 당연히, 함께 써줘야 합니다.
ps. MFC는 사람을 바보 만드는데 재주가 있는 듯.
MFC, 동적 버튼 생성, 색을 입히고 클릭 이벤트 설정