글 작성자: HEROHJK

네이버 지식인 활동을 하다가 괜찮은 질문을 발견했습니다.


"mfc 체크박스를 에디트컨트롤로 입력받은 수만큼 체크하고 나머지를 비활성화시키고 싶은데

어떻게 코딩해야 할까요?"


그래서 답변을 다음과같이 달아드렸습니다.


"여러가지 방법이 있겠습니다만 이렇게 해보세요


우선 에디트컨트롤의 값을 숫자로 바꿔서 클래스의 멤버 변수에 저장시키세요.

이 값을 maxCheckCount라고 하겠습니다.

그리고 제한을 하고싶으시니 현재 체크되어있는 수를 변수로 둬야겠죠?

그 값을 checkCount라고 하겠습니다.(이 값은 0으로 초기화가 되어있어야 하겠죠?)

마지막으로 maxCheckCount에 도달하게되면, 나머지를 비활성화 시키고 싶다고하셨으니

그것들을 일괄적으로 활성화/비활성화 시키는 함수가 필요하겠네요.

그 함수는 CheckBoxEnable(BOOL isMaxCheck) 이런식으로 이름을 정하겠습니다.

그리고 각 체크박스의 조건을 이렇게 바꿔보세요.

체크 되었을때 ->

checkCount++
if(checkCount>=maxCheckCount) CheckBoxEnable(FALSE)


체크를 풀었을때 ->

checkCount--
if(checkCount<maxCheckCount) CheckBoxEnable(TRUE)


그리고 CheckBoxEnable의 처리 내용은 다음과 같습니다.

1
2
3
void CheckBoxEnable(BOOL isEnable){ 
   체크박스이름.EnableWindow(isEnable); //<-이것들은체크박스 숫자대로 넣어주시면 됩니다 
cs


그러자 댓글로 다른 질문을 하셨습니다.


"체크박스를 70개 넘게 사용할건데 일일이 조건을 바꿔줘야 하나요?"


그래서 방법을 찾아보았습니다.


문제는 세가지정도가 있네요.


1. 다수의 체크박스를 등록할때

2. 다수의 체크박스를 눌렀을때

3. 다수의 체크박스를 ON/OFF시킬때


저는 이렇게 해결하였습니다.


1. 다수의 체크박스를 등록할때

-> 


resource.h를 열어 체크박스들의 ID숫자값들을 연속된 값으로 변경해주었습니다.


1
2
3
4
5
6
7
8
9
10
11
//resource.h
 
#define IDC_CHECK1                      2001
#define IDC_CHECK2                      2002
#define IDC_CHECK3                      2003
#define IDC_CHECK4                      2004
#define IDC_CHECK5                      2005
.
.
.
#define IDC_CHECK90                     2090
cs


그 후에 DDX_Control에 다음처럼 등록을 해주었습니다.


1
2
3
4
5
6
7
8
9
void CMFCCheckBoxExamDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
 
    for (int i = 0; i < CHECKCOUNT - 1; i++) {//배열의 수만큼 반복한다
        DDX_Control(pDX, IDC_CHECK1+i, checkBoxes[i]);//IDC_CHECK1+i번째값을 체크박스들의 i번째에 담는다
    }
 
}
cs




2. 다수의 체크박스를 눌렀을때

->


체크박스를 눌렀을때, 컨트롤들을 통합하는 방법은


"ON_COMMAND_RANGE"를 메세지맵에 등록하여 일정 범위를 하나의 함수에 처리하게끔 하는것 입니다.

비긴 메세지맵에 들어가는 코드는 다음과 같습니다


1
2
3
4
5
6
7
8
9
BEGIN_MESSAGE_MAP(CMFCCheckBoxExamDlg, CDialog)
    .
    .
    .
    ON_COMMAND_RANGE(IDC_CHECK1, IDC_CHECK90, CMFCCheckBoxExamDlg::OnCheckBtnClick)//IDC_CHECK1부터 90까지 범위처리
    .
    .
    .
END_MESSAGE_MAP()
cs


그 후 OnCheckBtnClick 함수를 다음과 같이 작성해줍니다.


1
2
3
4
5
6
7
8
9
10
11
void CMFCCheckBoxExamDlg::OnCheckBtnClick(UINT uiID)
{
    if (((CButton*)GetDlgItem(uiID))->GetCheck() == TRUE) {//체크버튼이 눌려있다면
        count++;//카운트를 센다
        if (count >= maxCount) AllCheckBoxEnable(FALSE);//카운트가 최대값까지 도달했다면 컨트롤들을 끈다
    }
    else if (((CButton*)GetDlgItem(uiID))->GetCheck() == FALSE) {//체크버튼이 눌려있지 않다면
        count--;//카운트를 뺀다
        if (count < maxCount) AllCheckBoxEnable(TRUE);//최대값이 더 크다면 컨트롤들을 켠다
    }
}
cs


해당 ID값의 체크상태를 확인하여 연산을 하는방식입니다.




3. 다수의 체크박스를 ON/OFF시킬때

->


이제 다 정리가 되었으니 2번에 나온 AllCheckBoxEnable 함수만 구현해주면 되겠죠?


1
2
3
4
5
6
7
8
void CMFCCheckBoxExamDlg::AllCheckBoxEnable(BOOL isEnable)
{
    for(int i=0;i<CHECKCOUNT-1;i++){//컨트롤의 수만큼 반복한다
        checkBoxes[i].EnableWindow(isEnable);//컨트롤들을 ON/OFF한다
        if(!isEnable && checkBoxes[i].GetCheck() == TRUE) //컨트롤을 OFF할때, 체크되어있는 컨트롤들은 다시 켜준다
            checkBoxes[i].EnableWindow(TRUE);
    }
}
cs


저는 이렇게 구현하였습니다.


물론 On/Off를 두번씩(특정조건에서는 Enable이 두번씩 쓰입니다)쓰는건 좋지않습니다.


단순히 예제를 보여드린것이니 나중에 비슷한 상황이 실제로 생길때 조금더 논리적인 코딩을 하시길 바랍니다.


MFCCheckBoxExam.zip


반응형