첵크와 라디오는 상당히 많이 사용되지만 그 직관적인 인터페이스 만큼 사용도 단순하다.
지금까지 사용해오면서도 특별하게 다뤄본 기억이 없을만큼... 흠..
먼가 응용할만한 자료가 없을까 검색 하다보니, 코드프로젝트에 첵크그룹박스라는 자료가 있었다.
이를 응용하여 간단한 참고자료를 만들어 보았다.
위 화면은 별로 볼건 없지만 다음과 같은 기능을 제공한다.
1. 첵크박스를 선택하면 해당 그루박스 내부의 컨트롤들이 자동으로 Enable/Disable토글된다.
2. 첵크박스 그룹은 해당 첵크박스의 동작에 영향을 받는다.
3. 라디오버튼은 여러 그룹중에 선택되어진 하나만 활성화 되고, 나머지는 자동으로 Disable된다.
즉, 라디오의 특성처럼 하나의 그룹만 선택가능하다.
그림 처럼 첵크는 여러그룹이 선택가능하지만 라디오는 오직 한 그룹만 선택가능하다.
그럼 핵심 함수부를 살펴보자.
이 함수는 해당 버튼(첵크 or 라디오)과 그를 둘러싼 그룹박스 아이디, 그리고 부모 윈도우를
인자로 가지는 함수이다.
기능은 해당 버튼의 상태에 따라 그룹박스 내부 컨트롤을 Enable 혹은 Disable 시킨다.
void CheckGroup(INT CheckID, INT GroupID, CWnd* pWndParent)
{
// 일단 버튼의 첵크 상태를 읽어온다.
// 이게 첵크던 라디오던 상관없다. 다 CButton을 상속한 컨트롤이기 때문이다.
BOOL bCheck = pWndParent->IsDlgButtonChecked(CheckID);
// 영역의 사각정보를 저장할 임시 변수들
CRect rcGroup, rcChild;
// 그룹박스의 영역 정보를 읽어온다.
pWndParent->GetDlgItem(GroupID)->GetWindowRect(rcGroup);
// 현재 다이알로그의 차일드 윈도우중 첫번째 것을 가져온다.
CWnd* pWnd = pWndParent->GetWindow(GW_CHILD);
while (pWnd)
{
// 해당 그룹과, 버튼을 제외한 차일드 윈도우.
if(pWnd->GetDlgCtrlID() != CheckID && pWnd->GetDlgCtrlID() != GroupID)
{
// 차일드 윈도우의 영역 정보를 읽어온다.
pWnd->GetWindowRect(rcChild);
// 만약 차일드 윈도우가 그룹박스 내부에 존재하면, bCheck 상태에 따라
// 인에이블 정보를 토글한다.
if (rcChild.IntersectRect(rcGroup, rcChild))
pWnd->EnableWindow(bCheck);
}
pWnd = pWnd->GetWindow(GW_HWNDNEXT);
}
}
그리고, 아래 4개의 멤버 함수는 각각의 첵크 박스와 라디오 버튼을 눌렀을 때
인자를 어떻게 전달했는지를 보여준다.
void CSssDlg::OnCheckUser()
{
CheckGroup(IDC_CHECK1, IDC_STATIC1, this);
}
void CSssDlg::OnCheckSub()
{
CheckGroup(IDC_CHECK2, IDC_STATIC5, this);
}
void CSssDlg::OnRadioUser()
{
CheckGroup(IDC_RADIO1, IDC_STATIC9, this);
CheckGroup(IDC_RADIO2, IDC_STATIC13, this);
}
void CSssDlg::OnRadioSub()
{
CheckGroup(IDC_RADIO1, IDC_STATIC9, this);
CheckGroup(IDC_RADIO2, IDC_STATIC13, this);
}
화면 구성에 비하여 상당히 깔끔하고, 단촐한 코드로 구성되어 사용하기도 쉬울것이다.
처음에는 위에서 처럼 처리하는것이 아니라, Tab Order 와 Group 속성을 이용하면
해당 그룹을 묶어서 처리할 수 있지 않을까 하는 생각을 가져보기도 했었는데..
아쉽게도 Group 속성에 대한 이해가 모자라 일반적인 꽁수로 해결을 보았다.
첵크와 라디오를 어떻게 응용해 볼 수 있을까?