첵크와 라디오는 상당히 많이 사용되지만 그 직관적인 인터페이스 만큼 사용도 단순하다.
지금까지 사용해오면서도 특별하게 다뤄본 기억이 없을만큼... 흠..

먼가 응용할만한 자료가 없을까 검색 하다보니, 코드프로젝트에 첵크그룹박스라는 자료가 있었다.
이를 응용하여 간단한 참고자료를 만들어 보았다.

위 화면은 별로 볼건 없지만 다음과 같은 기능을 제공한다.
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 속성에 대한 이해가 모자라 일반적인 꽁수로 해결을 보았다.

첵크와 라디오를 어떻게 응용해 볼 수 있을까?

59.zip
0.15MB



첵크 박스의 Tri State는 라디오에는 없는 단독 속성이라 따로 설명을 하였다.
저 속성은 옵션 다이알로그를 만들거나 복합 옵션들을 구현할 때 사용되는, 상당히 직관적인 속성이다.

다음은, 첵크와 라디오가 가지는 공통속성 중에서 특별하게 다루어야할 만한 것들 을 골라보았다.
머 그래봤자 남는거라고는 멀티라인, 아이콘, 이미지 정도이다.

그림의 아래쪽에 보이는 색상 변경 부분은 그동안 다루었던 에디트와 스태틱 컨트로에서 사용되었던 배경 투명화와 색상 변경하기 기법을 적용하였다.
매 컨트롤마다 써먹으면 식상(?)하니 한군데 몰아부처 이렇게도 사용할 수 있음을 예시한다.

1.
아이콘 로딩.
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Icon 속성을 첵크한다.

//
첫번째 첵크박스의 포인터를 얻은 후 CButton으로 형변환한다.
CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK1);
//
아이콘을 로딩한 후 SetIcon 메서드를 이용하여 아이콘을 넣어준다.
pButton->SetIcon(::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME)));

2.
비트맵 로딩.
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Bitmap 속성을 첵크한다.
//
첫번째 첵크박스의 포인터를 얻은 후 CButton으로 형변환한다.
CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK1);
//
비트맵을 로딩한 후 SetBitmap 메서드를 이용하여 비트맵을 넣어준다.
pButton->SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP3)));

3. Pushlike
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Pushlike속성을 첵크한다.
이 속성은 별거 없어보이지만, 이걸 이용하면 버튼을 2가지 상태로 (눌린상태, 아닌상태)로 아주 쉽게 구분하여 하나의 버튼을 다양하게 이용할 수 있다.

만약 파워버튼이라고 가정하면..
1.
튀어 나와있을 때 - 캡션 파워오프
2.
눌려져 있을 때 - 캡션 파워온
.. 상태를 표현할 경우는 그냥 CButton보다 쉽게 접근하여 사용이 가능하다.

4. Multiline
첵크 박스나 라디오 버튼에서 Styles 페이지에서 Multiline 속성을 첵크한다.
표현 해주고자 하는 캡션이 길 때 사용한다.

5.
배경의 투명화와 색상 변경.
//
아래 코드는 이제 설명하지 쉽게 이해할 수 있을 것이다.
HBRUSH CSssDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
    if(pWnd->GetDlgCtrlID() == IDC_CHECK8 || pWnd->GetDlgCtrlID() == IDC_RADIO9)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
        pDC->SetBkColor(RGB(0, 255, 0));
    }
    else if(pWnd->GetDlgCtrlID() == IDC_CHECK9 || pWnd->GetDlgCtrlID() == IDC_RADIO10)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
        pDC->SetBkColor(RGB(0, 255, 0));
        return m_brh;
    }
    else if(pWnd->GetDlgCtrlID() == IDC_CHECK10 || pWnd->GetDlgCtrlID() == IDC_RADIO11)
    {
        pDC->SetTextColor(RGB(255, 0, 0));
        pDC->SetBkMode(TRANSPARENT);
        return (HBRUSH)GetStockObject(NULL_BRUSH);
    }
 
    // TODO: Return a different brush if the default is not desired
    return hbr;
}

76.zip
0.09MB

첵크 박스와 라디오 버튼은 CButton 에서 기능이 특화된 두 부류이다.
이전 강좌에서 CStatic를 Text와 Picture로 나누어 특화시킨것과 마찬가지이고...
물론 CButton 컨트롤을 동적생성해서 위 두 속성을 주어 변경하는 것도 당연히 가능하다..

위 그림은 첵크 박스의 사용 목적을 일목 요연하게 보여줄 수 있는 것이라 생각하고 캡처해 보았다.
그림에서 처럼 다양한 어떤 기능이나 옵션을 제공할 때 원하는 것을 하나 혹은 여러개를 선택할 수 있도록 사용자 인터페이스를 제공해 주는 목적을 가진다.
( 물론 위 그림처럼 트리와 첵크박스를 저렇게 이뿌게 조합할려면 노가다가 필수다 -_-;;;)
( 필자 생각으로는 UI는 노가다의 산물이 아닐까 라고 가끔 생각해 본다.. ㅎㅎ)

위의 그림은 곰플레이어의 옵션 다이알로그의 한 페이지를 캡처한 화면이다.
[자동으로 계속하기 설정]이라고 써있는 부분을 보면 3가지 기능이 나열되어 있고, 그 중에 하나를
선택할 수 있도록 되어있다.
위 처럼 하나의 주요한 기능를 여러가지 관점에서 바라 볼 수 있고, 사용자가 그 중에 하나를 선택하여 동작하도록 제공해주는 인터페이스가 라디오 버튼이다.

비슷하면서도 큰 차이점이..

첵크박스는 여러가지 옵션을 다양하게 선택할 수 있도록 해주는 반면
라디오 버튼은 하나의 관점에서 특화된 옵션을 다양한 각도로 선택할 수 있도록 제공해준다.

이제부터 리소스 편집창을 살펴보자.

왼쪽의 빨강 똥그라미는 첵크박스, 오른쪽의 파랑 똥그라미는 라디오 버튼이다.

이제 부터 각 컨트롤의 속성 페이지를 살펴보자.

우선 첵크박스의 프로퍼티중 스타일을 살펴본다. 나머지 탭들은 기존의 설명과 중복되어 생략한다.

1. Auto - 사용자가 마우스로 첵크박스의 사각형 부분을 선택하면 상태가 자동으로 토글된다.
  이 옵션을 꺼놓으면 사용자가 직접 상태를 모두 변경시켜주어야한다.
2. Left Text - 글자가 왼쪽으로 가고 첵크박스가 오른쪽으로 간다.
3. Tri State - 첵크/언첵크 외에 첵크된 상태에서 배경이 회색으로 바뀐다. 즉 3가지 상태를 가진다.

4. Push Like - 일반적인 푸쉬버튼과 같은 형태를 가진다.

5. Multiline - 글자를 다중 라인으로 작성할 수 있다.

6. Notify - 상태 변경등의 정보를 부모윈도우로 전달해준다.
7. Flat - 플랫한 모양으로 바뀐다.

8. Icon - 글자대신 아이콘을 넣을 수 있다.

9. Bitmap - 글자대신 비트맵을 넣을 수 있다.

10. Horizontal alignment - 수평 글자 정렬
11. Vertical alignment - 수직 글자 정렬

라디오 버튼의 속성을 살펴보자.

첵크박스의 속성과 대부분 같고, Tri State만 없는 것을 볼 수 있을 것이다.
모든 속성의 설명은 첵크박스와 같다..
당연한가? 모두 버튼이니까..
그렇다면? ...
...
그렇다 리소스상의 버튼의 속성중에 위와 중복되는 속성은 모두 동일하게 사용할 수 있다.

여기까지는 그냥 기본 속성의 설명이었을 뿐이고, 라디오 버튼은 General 페이지에 있는
Group라는 옵션에 지대한 영향을 받는다...

지금까지 다룬 다른 컨트롤들은 저 속성을 거의 그냥 무시하고 지나갔다.

[사실 필자도 다른 컨트롤에서 저 그룹 속성이 어떤 동작 특성을 가지는지는 잘 모른다 -_-]

지금까지 이해해온 대로라면 라디오 버튼은 비슷한 기능을 가진 옵션들을 모아놓고 그중에 하나를 선택하는 기능을 제공해준다고 하였다.

또한 Ctrl+D를 눌러 라디오 버튼을 순서대로 정렬해 놓으면 실행시킨 후에 선택할 수 있는 라이오 버튼 항목은 단 1개이다.

그렇다면 하나의 다이알로그 폼에 그런 선택속성을 가진 그룹이 여러개 존재한다면???

위의 빨간 글중에 파랑색으로 표기한 그룹이라는 단어가 눈에 띄일것이다....

그렇다, 저걸 첵크 해놓으면 저걸 첵크해놓은 라디오 버튼 중에 탭 오더가 낮은 것들은 자동으로 하나의 선택그룹으로 묶이게 된다.

여러개의 라디오 버튼을 여러개의 그룹으로 묶으려면? 중간에 특성이 갈라지는 놈의 속성 페이지를 열어서 저걸 첵크해놓으면 된다..

이렇게 첵크박스와 라디오 버튼의 속성을 간단하게 살펴보았다.
다음에는 우선 저 속성을 설명하면서 나타난 화면을 직접 구현해 보는 시간을 가져보고자 한다..

+ Recent posts