제 9 장고급컨트롤과리본 9.1 MFC Feature 컨트롤실습 9-1 간단한명함제작프로그램만들기 9.2 리본실습 9.2 리본메뉴및각종리본컨트롤사용하기
MFC Feature 컨트롤 MFC 버튼컨트롤 MFC Button 은기본적으로 CButton 과같은속성을갖고있음. 사용목적에따라 Radio, Check, Command 버튼으로스타일을변경할수있다. CButton 클래스를출력면에서다양하게보완한것으로, 다양한 Flat 스타일, 배경및텍스트색상의변경, 커서모양, Tool Tip, 아이콘, 그림출력등의제어할수있다.
MFC Feature 컨트롤 MFC 셀리스트와셀트리컨트롤 각각 CListCtrl, CTreeCtrl 클래스를윈도우상의폴더구조를출력하고쉽게접근할수있도록특성화시켜놓은컨트롤
MFC Feature 컨트롤 MFC 프로퍼티그리드컨트롤 다량의정보와속성을직관적으로표현할수있으며, 속성설정을위한콤보상자, 에디트상자, 칼라상자, 폰트상자등다양한아이템컨트롤을통해매우쉽게속성을변경할수있는컨트롤 또한유사한정보끼리그룹을생성할수있으며, 항목별또는사전순으로정렬할수있음. 대표적인사용예시가 Visual Studio 의 [ 속성 ] 창이다.
MFC Feature 컨트롤 MFC VS 리스트박스컨트롤 여러개의항목을출력한다는측면에서리스트상자와매우흡사하지만, CListBox 클래스의기능을상속받은것은아님. 기본적으로추가, 삭제, 위로이동, 아래로이동을위한 4 가지표준버튼을제공
MFC Feature 컨트롤 MFC 에디트브라우저컨트롤 윈도우상의폴더또는파일의위치를입력하기위한것으로, 맨오른쪽 Browse 버튼을누르면 [ 파일열기 ] 대화상자가출력되어해당위치를선택하게하는컨트롤
MFC Feature 컨트롤 MFC 마스크에디트컨트롤 Input Mask 를특정문자를세팅함으로써특정형식을사용자에게보여주어형식에맞게입력할수있게하는컨트롤
MFC Feature 컨트롤 MFC 폰트콤보박스 기본적으로현재윈도우에설치된폰트의목록을보여주고선택을하기위한컨트롤 폰트의크기나색상은지원하지않음
실습 9-1 간단한명함제작프로그램만들기 이번실습은간단한명함출력프로그램을작성하는것으로 CVSListBox 를이용하여명함을추가, 삭제를하고, MFC PropertyGrid 컨트롤을이용하여명함의정보를자세히출력하도록할것이다
실습 9-1 프로그램의기능 CVSListBox 컨트롤을이용하여명함데이터를추가및삭제하도록한다. MFC PropertyGrid 컨트롤을이용하여명함의정보를출력한다. 대화상자의컨트롤과 MFC PropertyGrid 컨트롤의속성변경에따라명함을출력한다.
실습 9-1 프로그램작성순서 1) 대화상자기반의프로젝트를생성한다 2) 대화상자에컨트롤을배치하고속성을설정한다. Picture 컨트롤 3 개, MFC ColorButton 컨트롤 2 개, MFC FontComboBox 컨트롤등 3) 명함을저장하기위한구조체선언과클래스에변수를추가한다. 4) 각컨트롤들을멤버변수에연결하고, 명함데이터처리함수를추가한다.
실습 9-1 프로그램작성순서 5) 명함을추가, 삭제하고목록과선택된명함의속성을출력한다. 6) 각컨트롤들을초기화하고명함출력함수를추가한다. OnInitDialog() 함수에서각컨트롤들을초기화한다. 7) 명함의배경색, 연락처텍스트색상, 글꼴을변경한다. 8)MFC Property Grid 아이템변경에대한핸들러함수를만든다. 9) 프로그램을실행시킨다.
실습 9-1 실행결과
리본사용자인터페이스 리본 Microsoft 는오피스 2007 의 유연한사용자인터페이스 의일부로리본을도입 명령버튼과아이콘이있는패널로이루어져있으며명령어들은탭으로모아구성 탭안의임의의영역에있는동안마우스스크롤휠을움직이면리본이탭을통해순환
리본사용자인터페이스 리본메뉴의구성 Ribbon Bar 모든구성요소들을가지고있는전역객체 Application Button 파일메뉴를별도로구성하고있음 Quick Access Toolbar 사용자가자주사용하는기능을등록하여사용할수있는도구상자 우측의화살표를눌러나오는메뉴를통하여제어
리본사용자인터페이스 리본메뉴의구성 ( 계속 ) Category 소프트웨어에서제공하는기능을독립적으로분류해놓은것 Panel 해당기능을수행하기위한액션들을분류해놓은것 Panel 내부는각종유용한컨트롤들이배치되어사용자와인터페이스하도록설계되어있음
리본사용자인터페이스 구성요소별구현된클래스 구성요소 Ribbon Bar Application Button Quick Access Toolbar Category Panel Base Element 구현클래스 CMFCRibbonBar CMFCRibbonApplicationButton CMFCRibbonQuickAccessToolBar CMFCRibbonCategory CMFCRibbonPanel CMFCRibbonBaseElement
리본사용자인터페이스 리본컨트롤클래스 리본컨트롤은일반적인컨트롤과 MFC Feature 컨트롤의기능을리본메뉴상에서동일하게사용할수있도록여러종류로구현되어있음 버튼형태컨트롤 버튼, 체크박스, 칼라버튼, 에디트박스, 콤보상자, 폰트콤보상자등 비 - 버튼형태컨트롤 슬라이더, 탭, 프로그레스바등
실습 9-2리본메뉴및각종리본컨트롤사용하기 이번실습은리본디자이너 (Ribbon Designer) 를통하여그리기명령, 그리기객체의선택, 텍스트의글꼴, 크기, 색상등을설정하기위한리본메뉴를편집하고, 리본메뉴의각컨트롤에대한이벤트처리를한다.
실습 9-2 프로그램의기능 그리기객체의선택, 속성설정을위한리본메뉴를구성하도록한다. 리본메뉴를통하여그리기명령과색상, 제어점출력여부등의기능을구현한다. 리본메뉴를통하여텍스트의입력, 글꼴및크기, 색상을설정하도록한다. 리본컨트롤의슬라이더를이용하여뷰영역의확대 / 축소를조절한다.
실습 9-2 프로그램작성순서 1) Office 스타일의단일문서기반의프로젝트를생성한다. 2) 리본디자이너를사용하여리본메뉴를구성한다.. 3) 객체그리기를위한필요한변수를선언한다. 정점의좌표를저장하는멤버변수 정점의개수를저장하는멤버변수 윈도우에출력될문자열을저장하는멤버변수
실습 9-2 프로그램작성순서 4) 윈도우에그리기객체와텍스트출력을위한함수를추가한다.. 직선, 사각형, 원, 다각형을그리는함수 확대 / 축소를초기화하는함수 5) 러버밴드를위한함수를추가한다. 6) 각리본메뉴의컴포넌트에대한이벤트처리를추가한다. 7) 프로그램을실행시킨다.
실습 9-2 실행화면
실습 9-2 실행화면
연습문제 9-1MFC Property Grid 컨트롤을이용한회원정보관리프로그램만들기 List 컨트롤을이용하여회원리스트를출력하고, 버튼을통해서회원추가 / 삭제를수행한다. MFC Property Grid 컨트롤은현재선택된회원정보를출력하고, 정보를수정한다.
BOOL CExercise9_1Dlg::OnInitDialog() m_listmembers.insertcolumn(0, _T(" 회원번호 "), LVCF_WIDTH, 60); m_listmembers.insertcolumn(1, _T(" 이름 "), LVCF_WIDTH, 80); m_listmembers.insertcolumn(2, _T(" 성별 "), LVCF_WIDTH, 40); m_listmembers.insertcolumn(3, _T(" 연락처 "), LVCF_WIDTH, 120); // 명함 Property Grid 를생성하고초기화한다. CRect rectdummy, rc; rectdummy.setrectempty(); if (!m_propmember.create(ws_visible WS_CHILD, rectdummy, this, 2)) { TRACE0(" 속성표를만들지못했습니다. \n"); return -1; // 만들지못했습니다. } GetDlgItem(IDC_STATIC_PROPGRID)->GetWindowRect(&rc); ScreenToClient(&rc); m_propmember.movewindow(&rc); UpdateMemberInfo(Member()); ((CButton*) GetDlgItem(IDC_RADIO_MALE))->SetCheck(TRUE); return TRUE; // 포커스를컨트롤에설정하지않으면 TRUE를반환합니다.
void CExercise9_1Dlg::UpdateMemberInfo(Member m) m_propmember.removeall(); m_propmember.enableheaderctrl(false); m_propmember.setvsdotnetlook(); m_propmember.enabledescriptionarea(); // 1. 개인신상정보 CMFCPropertyGridProperty* pgroupinfo = new CMFCPropertyGridProperty(_T(" 회원정보 ")); pgroupinfo->addsubitem(new CMFCPropertyGridProperty(_T(" 이름 "), m.strname, _T(" 이름을입력하세요."), 0)); CMFCPropertyGridProperty* psex = new CMFCPropertyGridProperty(_T(" 성별 "), m.bsex? _T(" 남 "):_T(" 여 "), _T(" 성별을선택하세요."), 1); psex->addoption(_t(" 남 ")); psex->addoption(_t(" 여 ")); psex->allowedit(false); pgroupinfo->addsubitem(psex);
void CExercise9_1Dlg::UpdateMemberInfo(Member m) pgroupinfo->addsubitem(new CMFCPropertyGridProperty(_T(" 연락처 "), m.strphone, _T(" 연락처를입력하세요."), 2)); m_propmember.addproperty(pgroupinfo); // 2. 출력양식정보 CMFCPropertyGridProperty* pgroupprint = new CMFCPropertyGridProperty(_T(" 보기 ")); CMFCPropertyGridProperty* pview = new CMFCPropertyGridProperty(_T(" 리스트뷰 "), _T("Detail"), _T(" 리스트컨트롤보기 "), 3); pview->addoption(_t("detail")); pview->addoption(_t("list")); pview->addoption(_t("tile")); pview->allowedit(false); pgroupprint->addsubitem(pview); m_propmember.addproperty(pgroupprint); m_propmember.updatedata(false);}
void CExercise9_1Dlg::OnClickedButtonAdd() UpdateData(TRUE); Member m; m.nid = m_ncount!=0? m_members[m_ncount-1].nid+1 : 1; m.strname = m_strname; m.bsex = m_bsex; m.strphone = _T("010-123-4567"); m_members[m_ncount++] = m; UpdateMembers(); UpdateMemberInfo(m_Members[m_nCount-1]); m_strname.empty(); m_nselectedmember = m_ncount-1; UpdateData(FALSE);}
void CExercise9_1Dlg::UpdateMembers(void) m_listmembers.deleteallitems(); { CString str; for(int i=0; i<m_ncount; i++) str.format(_t("%d"), m_members[i].nid); m_listmembers.insertitem(i, str); m_listmembers.setitem(i, 1, LVIF_TEXT, m_members[i].strname, -1, 0, 0, 0); str = m_members[i].bsex? _T(" 남 ") : _T(" 여 "); m_listmembers.setitem(i, 2, LVIF_TEXT, str, -1, 0, 0, 0); m_listmembers.setitem(i, 3, LVIF_TEXT, m_members[i].strphone, -1, 0, 0, 0); }}
void CExercise9_1Dlg::OnRadioFemale() { // TODO: 여기에명령처리기코드를추가합니다. m_bsex = false; }
void CExercise9_1Dlg::OnRadioMale() { // TODO: 여기에명령처리기코드를추가합니다. m_bsex = true; }
void CExercise9_1Dlg::OnItemchangedListMembers(NMHDR *pnmhdr, LRESULT *presult) LPNMLISTVIEW pnmlv = reinterpret_cast<lpnmlistview>(pnmhdr); // TODO: 여기에컨트롤알림처리기코드를추가합니다. m_nselectedmember = pnmlv->iitem; UpdateMemberInfo(m_Members[m_nSelectedMember]); *presult = 0;
void CExercise9_1Dlg::OnClickedButtonRemove() if( m_nselectedmember<0 ) return; if( MessageBox(_T(" 정말로삭제하시겠습니까?"), _T(" 확인 "), MB_YESNO MB_ICONQUESTION)!= IDYES ) return; if( m_nselectedmember< (m_ncount-1) ) memcpy( &m_members[m_nselectedmember], &m_members[m_nselectedmember+1], sizeof(member)*(m_ncount-m_nselectedmember-1)); m_ncount--; UpdateMembers();
LRESULT CExercise9_1Dlg::OnPropertyChanged(WPARAM wparam, LPARAM lparam) CMFCPropertyGridProperty* pproperty = (CMFCPropertyGridProperty*)lParam; { { switch(pproperty->getdata()) case 0 :// 이름 m_members[m_nselectedmember].strname = pproperty->getvalue(); break; case 1 :// 성별 if( (CString)pProperty->GetValue() == _T(" 남 ") ) m_members[m_nselectedmember].bsex = true; else m_members[m_nselectedmember].bsex = false; } break; case 2:// 연락처 m_members[m_nselectedmember].strphone = pproperty->getvalue(); break; case 3 :// 리스트뷰보기 if( ((CString)pProperty->GetValue())== _T("Detail") ) m_listmembers.setview(lv_view_details); else if( ((CString)pProperty->GetValue())== _T("List") ) m_listmembers.setview(lv_view_list); else m_listmembers.setview(lv_view_tile); } break; UpdateMembers(); return 0L;
연습문제 9-1MFC Property Grid 컨트롤을이용한회원정보관리프로그램만들기 실행결과