본문 바로가기
Program/C++ MFC

[C++ MFC] Dialog RadioButton Item 배경 투명하게 만들기

by 냠만 2024. 6. 21.

[개요]

MFC를 접한 지 얼마 안 되었습니다. 당장 UIUX를 구현해야 하는 상황이 되어 급하게 공부를 하면서 구성중입니다. 근데 라디오버튼이 네모지게 Backcolor가 유지되는 게 border와 함께 굉장히 거슬리더군요.

단순히 속성에서 제어가 가능할 줄 알았는데 생각보다 요구하는 시퀀스가 복잡해서 추후에 또 참고할 자료 정리가 필요할 것 같았습니다. 그래서 직접 지우는 방법을 정리해봤습니다.

[순서 정리]

전체적인 순서는 아래와 같습니다.

1. 라디오 버튼 생성

2. Resource.h 확인해서 라디오버튼 넘버링 독립적으로 픽스

3. .h 파일에 CButton 배열 변수 선언

4. .cpp 파일에 DDX_Control 선언해서 CButton 변수와 1번에서 생성한 라디오버튼 바인딩

 

5. 라디오버튼 속성옵션에서 Transparent = true로 변경 및 Group Number 설정

6. WM 시스템 메시지 Color선언

7. OnCtlColor 함수 세팅 (필요 컨트롤만 설정될 수 있도록)

8. 클래스뷰에서 OnInitDialog 재 정의 (오버로딩)

9. 오버로드된 OnInitDialog 함수에서 SetWindowTheme 핸들 설정

10. stdafx.h 헤더 파일에 #pragma comment(lib, "UxTheme.lib") 선언

 

[순서 해석]

순서를 대략적으로 해석해 드립니다. 위의 정리와 정확하게 일치하진 않습니다. 전반적인 순서는 위에껄 참고하시면 되고 디테일이 필요하신 경우 아래를 참고하시면 될 것 같습니다.

라디오버튼 선언

1. 라디오버튼을 생성하면 됩니다.

Panel위에 배경색을 지정했을 경우 그 위에 올라간 라디오버튼은 배경색이 보기 싫게 적용되어 있습니다. 동일한 색상으로 변경해도 잘 가려지지 않습니다. 그래서 투명옵션을 적용해야 합니다.

클래스뷰 열기

2. OnInitDialog 함수를 오버로딩하기 위해 클래스뷰를 열어줍니다. C# 할 때는 건들지도 않아 봤는데 참 여러모로 불편한 언어입니다.

폼 함수 오버로딩

3. 2번에서 열린 클래스뷰에 접근하고 Dialog를 붙인 Form에 접근하여 OnInitDialog를 오버로딩 할 수 있습니다.

 

오버로딩 및 변수설정

4. Header파일에서 CButton 배열 변수를 선언해 줍니다. MAX_RADIO_COUNT는 단순 디파인해줬습니다.

 

컨트롤과 변수 묶기

5. cpp파일에 접근해서 DDX_Control를 선언하여 Resource.h에 나와있는 라디오버튼의 네임을 참조하여 4번에서 선언한 CButton 배열 변수를 바인딩합니다.

 

컨트롤 ID 확인

6. 참고로 Resource.h는 이렇게 생겼고 모든 Dialog의 컨트롤 ID가 디파인됩니다. 여기서 동일 폼에서 불러오는 경우 컨트롤 ID가 같으면 변수 및 컨트롤의 바인딩이 정상적으로 이루어지지 않고 이상현상이 발생될 수 있으니 반드시 컨트롤 ID는 KEY값으로 겹치지 않게 관리되어야 합니다.

 

큰 프로젝트를 진행하는 경우 Dialog가 수십 개가 넘어갈 수 있기 때문에 그런 경우에서는 반드시 DDX_Control처럼 직접 변수이름과 컨트롤변수를 정의하여 사용해야 합니다. 그렇게 하면 컨트롤 ID가 변경되거나 다른 Dialog와 중복되어도 컴파일러가 혼동하지 않고 값을 적용하거나 가져올 수 있습니다.

 

버튼 속성 변경

7. 다시 Dialog로 접근해서 Transparent 속성값을 True로 변경해 줍니다. 해당 옵션은 컨트롤에 투명한 배경을 적용합니다.

버튼 그룹화

8. 속성 변경 이후 그룹을 지정해 줍니다. 그룹 속성은 True에서 다음 True를 만나기 전까지를 그룹으로 인정합니다. RadioButton을 그룹으로 묶는 경우 그룹 A에서 1개 선택, 그룹 B에서 1개 선택이 가능합니다.

만약 1 ~ 6번을 한 개의 그룹으로 묶는 경우 6개의 버튼 중 한 개만 선택이 가능합니다.

 

좀 더 풀어서 설명하자면 그룹 속성은 True와 False로 구분할 수 있는데, Radio버튼 1, 2, 3번을 A그룹으로 묶고 4, 5, 6번을 B그룹으로 묶고 싶은 경우 그룹의 시작버튼인 1번과 4번 Group속성을 True로 변경해 주면 됩니다.

클래스 마법사 실행

9. 해당 Dialog에서 클래스마법사에 진입합니다. Dialog 창에서 우클릭으로 진입하거나 속성창에서 설정할 수 있습니다.

 

메시지함수 설정

10. 메시지탭에서 WM_CTLCOLOR를 선택하고 처리기 추가를 선택합니다. 그럼 기존 처리기에 메시지함수가 추가된 걸 확인할 수 있습니다.

이제 해당 Dialog를 관장하는 cpp파일에서 메시지 컨트롤 함수 설정이 가능합니다.

 

메시지함수 수정

11. 메시지 내용입니다. HBRUSH를 선언하고 Dialog와 도우 핸들러를 연결한 다음 컨트롤의 형식이 CTLCOLOR_STATIC인 케이스만 배경을 투명으로 변경하는 내용입니다.

 

아래 주석처리를 참고하시면 Resource.h에서 참고했던 버튼의 ID를 가지고 컨트롤의 속성을 변경할 수 있습니다.

 

디파인 확인

12. CTLCOLOR_STATIC은 WinUser.h 헤더파일에 디파인 되어 있으며 각 속성값에 해당되는 컨트롤만 골라내서 속성을 다르게 설정할 수 있습니다.

 

 

코멘트 추가

13. stdafx.h 헤더파일에 마지막으로 해당 라인을 추가해 주시면 됩니다. 해당 명령어가 누락된 경우 속성값과 메시지 함수를 세팅해도 정상적으로 적용이 되지 않습니다.

[결론]

투명화 완료

결과적으로 투명화가 완료되었습니다. 확실히 시인성과 디자인적으로 효과가 있지만 여전히 스타일은 구립니다. 괜히 MFC에서 수많은 ActiveX를 끌어와서 사용하는 게 아니라는 느낌이 듭니다. 기본적으로 제공되는 Control의 디자인과 기능이 너무 무력해서 상업용으로 개발을 진행할 때에는 어쩔 수 없을 것 같습니다.

 

그래도 기본 로직은 비슷하니 참고가 되시면 좋겠습니다.