로그인

검색

조회 수 5055 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 게시글 수정 내역 댓글로 가기 인쇄

http://www.anycoding.com/bbs/board.php?bo_table=acProgram_Cpp&wr_id=3783&page=&sca=&sfl=mb_id%2C1&stx=winterer

 

이 글은 Furyheimdall 에 의해 furyheimdall.tistory.com 과 www.ac-plus.net 에서 작성되었습니다.

퍼가실 때는 이 박스를 함께 복사해주세요


 

Visual Studio 2008 Feature Pack 에서 도입된 MFC Next 에는 Ribbon Interface 가 추가되었습니다.
쉽게 말해 MFC 로 Office 2008 같은 UI 의 프로그래밍을 할 수 있게 되었지요.

특별히 자료가 필요할 만큼 어렵지는 않고 이런 혁신적으로 바뀐 UI를 몇 줄(?)의 코드만으로 변경할 수 있다는 데 놀랐습니다. UI가 다 그렇듯 노가다성이 좀 짙게 띄는 단점이 있습니다. 그리고 설계는 잘 되어있는 듯 보이지만 자잘한 버그들이 많이 보고 되고 있는 것 같네요.

어찌됬건 이번 포스팅에서는 프로젝트를 진행하면서 Ribbon 을 이용하여 프로그램을 제작하였던 경험을 바탕으로 처음 사용하시는 분들을 위해 사용법을 알려드릴까 합니다.

MFC Next 에서 추가된 점은 이전 포스팅 한 Visual C++ 2008 Feature Pack 정식판 를 참고하세요.




     

    사용자 삽입 이미지


     

    <Ribbon 메뉴의 구조>




     

    사용자 삽입 이미지


     

    <Ribbon 클래스 구조 - 출저: http://zeroone.tistory.com/>





     

    1. 리본 생성, 추가하기
    리본을 사용하게 되면 CMainFrame 를 주시하여야 합니다.
    실제 리본에 관련된 초기화 부터 설정까지 모든 작업이 CMainFrame 에서 이뤄지게 됩니다.
    OnCreate() 에서 리본바 생성및 초기화를 하고, InitializeRibbon() 에서 리본에 대한 설정을 하게 됩니다.

    InitializeRibbon() 내부를 보면 수 많은 코드들이 반복적으로 나열되어 있는데 바로 이 코드들이 리본을 설정하는 코드입니다.

    InitializeRibbon() 에서 리본 생성및 설정은 크게 다음과 같은 순서로 진행됩니다.


     

    1. 툴바 이미지 로드
    2. 메인 버튼 초기화&설정(메인 메뉴)
    3. 메인 메뉴 아이템 추가
    4. 카테고리 메뉴 추가(Category)
    5. 패널 추가(Panel)
    6. 아이템 추가(Base Element)


     

    실제로 가장 많이 사용되고 반복되는 코드가 4,5,6번에 해당됩니다.

    실제 사용되었던 4,5,6의 예제 코드입니다.





    1. // 4. Category insert
    2. bNameValid = strTemp.LoadString(IDS_RIBBON_CATEGORY_CAMERA);
    3. ASSERT(bNameValid);
    4. CMFCRibbonCategory* pCategoryCamera = m_wndRibbonBar.AddCategory(strTemp, IDB_WRITESMALL, IDB_WRITELARGE);
    5. // 5. Panel insert

    1. bNameValid = strTemp.LoadString(IDS_RIBBON_CAMERA_INTERFACE);
    2. ASSERT(bNameValid);
    3. CMFCRibbonPanel* pPanelClipboard = pCategoryCamera->AddPanel(strTemp, m_PanelImages.ExtractIcon(27));
    4. // 6. Item create & insert
    5. bNameValid = strTemp.LoadString(IDS_RIBBON_CAMERA_INTERFACE_1394);
    6. ASSERT(bNameValid);
    7. CMFCRibbonButton* pBtn1394 = new CMFCRibbonButton(ID_RIBBON_CAMERA_INTERFACE_1394, strTemp, 0,0);
    8. pPanelClipboard->Add(pBtn1394);


    개인적으로 리본메뉴는 깊이에 따라서 탭으로 구분하여 넣어주고 있습니다.
    코드가 길어질 경우 눈에 잘 들어오지 않아서 저렇게 넣어주게 되었네요.

    IDS 접두어로 시작하는 식별자들은 모두 VS에서 지원하는 스트링테이블에 등록된 문자열로 실제 패널이나 아이템, 카테고리의 표시되는 이름입니다.
    카테고리를 생성할 때는 AddCategory 를 호출하며 반환되는 녀석은 추가된 카테고리의 접근할 수 있는 포인터입니다. 이 포인터를 이용해서 패널을 등록하고, 그리고 이 등록된 패널 내부에 아이템을 등록하는 것입니다.
    6번의 경우 실제 아이템 타입이 결정되게 되는데 CMFCRibbonButton 타입으로 버튼을 생성했네요.

    실제 아이템 객체를 생성하는 부분 입니다.
    new CMFCRibbonButton(ID_RIBBON_CAMERA_INTERFACE_1394, strTemp, 0,0);

    첫번째 인자는 실제 메뉴의 ID (아래에 설명하겠습니다)
    두번째 인자는 메뉴 이름
    세번째 , 네번째 인자는 표시할 메뉴에 대한 아이콘입니다.
    4번항목에서 카테고리 등록시 IDB_WRITESMALL, IDB_WRITELARGE를 메뉴에 사용할 이미지 ID 로 설정하고,
    실제 아이템을 등록할때 몇번째 아이콘을 사용할 것인지 결정하게 됩니다.

    하나의 카테고리 안의 하나의 패널 안의 여러개의 아이템을 넣고 싶을 경우 위 상태에서 아이템 생성 및 추가에 해당하는 6번 코드 블럭을 밑에 추가적으로 나열하면 됩니다.



    2. 리본 메뉴와 실제 메뉴와의 관계
    리본을 사용함으로서 기존 메뉴는 사용하지 않을 듯 하지만 그렇지는 않습니다.
    리본 메뉴는 단순한 껍데기일 뿐이며 메뉴 핸들러와 메뉴에 대한 식별자는 모두 메뉴리소스에 의존합니다.
    리본버튼을 생성할때 넘겨주는 첫번째 인자의 ID가 바로 메뉴리소스의 메뉴ID 입니다.

    사용자 삽입 이미지

    <메뉴 리소스>

    위 이미지를 보시면 리본버튼을 생성할때 ID 값을 가지는 메뉴리소스의 메뉴입니다.
    위 메뉴에 대한 핸들러가 생성되지 않으면 리본버튼도 비활성화 되어있고, 핸들러가 생성되면 리본버튼이 활성화 되는 등 리본은 결국 껍데기에 불과합니다.



    3. 리본 메뉴의 아이콘 리소스 만들기
    사실 이 항목은 별도로 포스팅할 까 고민하던 내용이었습니다만 워낙 위의 내용이 부실해서 추가합니다. ㅡㅡ;

    PNG 를 통해서 만드는 방법도 있지만 32Bit BITMAP 파일을 이용하여 사용하는 방법이 차후 관리가 편하므로 이 방법을 통해서 아이콘을 만드는 방법을 알아보도록 하지요.

    일단 준비물은 Photoshop 입니다. 꼭 포토샵이 아니더라도 32Bit BITMAP 이미지를 제작하고 편집할 수 있는 환경이면 가능합니다.

    사용자 삽입 이미지

    진행중인 프로젝트를 기준으로 위의 첫번째 버튼인 IEEE1394 항목의 버튼을 바꿔보도록 하겠습니다.


    사용자 삽입 이미지

    우리가 넣을 리본바의 이미지는 32x32 픽셀의 사이즈를 가집니다.
    위 이미지는 웹에서 받은 이미지를 32x32 픽셀로 잘라서 포토샵으로 가져온 상태입니다.


    사용자 삽입 이미지

    위 이미지를 확대해서 배경 부분을 선택합니다. (Magic wand tool - 마법봉) 을 선택한 후 흰색을 클릭합니다.
    (복잡한 배경의 경우 조금 더 손이 더 갑니다만 이 포스트에서는 설명하지 않겠습니다.)


    사용자 삽입 이미지

    배경부분이 선택된 상태에서 마우스 오른쪽 버튼을 클릭후 [Select Inverse] 를 클릭합니다.


    사용자 삽입 이미지

    그러면 위와 같이 배경이 아닌 캐릭터 부분만 선택하게 됩니다.
    선택이 되면 하단 오른쪽(워크스페이스 설정에 따라 위치가 다를 수 있습니다) 에 [Channels] 탭을 선택 후 [Create new channel] 을 클릭합니다.


    사용자 삽입 이미지

    클릭하면 위와같이 화면이 검은색으로 변하며 알파채널이 추가되고 알파채널상태를 보게 됩니다.
    위 단계에서 선택한 영역이 남아있는데 이부분을 흰색으로 채워줍니다.
    (알파채널은 투명도입니다. 0(검은색)일때 완전한 투명 부터 255(흰색)일때 불투명까지 총 255단계로 표현합니다.
    즉 위 작업을 수행하면 배경부분은 투명하게, 캐릭터 부분은 불투명하게 하는 결과가 나옵니다.
    )

    사용자 삽입 이미지

    이제 아이콘 파일 작성은 완료되었습니다.
    아이콘 파일에 합치는 작업을 해봅시다. (이부분은 꼭 하지 않고 코드로 별도로 추가해도 되지만 번거롭습니다 :)
    프로젝트 리소스 파일의 writelarge.bmp 가 현재 우리가 추가하려는 규격의 아이콘들이 있는 파일입니다.
    포토샵으로 불러온 후 writelarge.bmp 가 선택된 상태에서 [Image -> Canvas size] 를 선택합니다.
    그러면 위 이미지 처럼 별도의 대화상자가 나오는데 위와같이 설정해준 후 OK 를 선택합니다.


    사용자 삽입 이미지

    OK 버튼을 누르면 writelarge.bmp 파일 오른쪽에 32x32px 의 빈공간이 생기게 되는데
    이 곳에 아이콘 이미지와 알파채널 이미지를 별도로 복사해서 넣어줍니다.
    Ctrl+A 를 누르시면 전체 선택 가능하니 전체를 복사하신 후 writelarge.bmp 에서 붙여넣어서 오른쪽에 넣습니다.

    알파채널 이미지도 마찬가지로 [Channel -> Alpha] 를 선택하면 흑백 이미지로 변하게 되는데
    아이콘 이미지처럼 똑같이 복사하면 됩니다.
    그리고 writelarge.bmp 파일의 레이어 병합 [Layer -> Patten Image] 을 하신 후 Save 를 합니다.

    사용자 삽입 이미지

    아이콘 파일밑에 숫자가 인덱스 번호입니다.
    아이템 생성시 이 번호를 인자로 넘기면 해당 인덱스의 아이콘이 보이게 됩니다.


    사용자 삽입 이미지

    MFC 리본 사용법이 어느덧 포토샵 강의로 변질되어가는 지점에서 드디어 결과물이 나왔네요. :)
    실행시키면 위와 같이 추가한 아이콘이 표시되는걸 볼 수 있습니다만...
    알파채널이 오른쪽으로 살짝 밀려서인지 ㅡㅡ; 보이는 부분이 조금 이상하군요.
    알파채널과 이미지는 정확하게 위치를 맞춰줘야 하기 때문에 주의하셔야 합니다.



    4. 그 외...
    많은 분들이 눈치채셨든 리본 관련으로 추가된 클래스는 모두 CMFC 라는 접두사를 붙이고 있습니다.
    사실 리본과 관련된 라이브러리는 MS 에서 제작한 것이 아닌 BCGSoft 라는 곳에서 판매하는 상용 라이브러리로 구성된 것입니다. BCGSoft 의 라이브러리는 CBCG 라는 접두사를 사용하는데 Find->"BCG"->Replace->"MFC" 인 듯 합니다. ㅡㅡ;; (거 참 성의 없네 MS)

    MFC Next 에서 CFrameWnd 클래스를 상속받는 SDI,MDI 관련 클래스들이 변경되었습니다.
    CMDIFrame-xWnd -> CMDIFrame-xWndEx , CMDIChildWnd -> CMDIChildWndEx 처럼 Ex 라는 접미어가 붙습니다.
    Ex 가 붙은 녀석들은 모두 각각의 기존 클래스에서 (CMDIFrame-xWnd, CMDIChildWnd, ETC) 상속 받아 MFC Next 의 새로운 기능들을 적용할 수 있게 추가된 클래스 입니다.

    MFC 툴바를 사용하려면 이전의 CToolBar 가 아닌 CMFCToolBar 를 사용하셔야 됩니다.

    버튼 외에 아이템 종류는 상단의 리본 클래스 구조도의 BaseElement 를 상속받는 요소들을 참고하시기 바랍니다.



    처음으로 상당히 긴 포스트를 작성해서인지 , 생각도 안하고 적어대서인지 참 복잡한 포스트가 되어버렸습니다.
    특히나 아이콘 제작부분의 분량이 절반이 넘어가서 이게 포토샵 강의인지 리본 설명인지 알 수 없을 정도로 정체성을 잃기 직전이네요. 어찌됬건 많은 분들에게 도움이 되었으면 합니다. :) 그럼 좋은 하루 되세요 ~
    ?

    List of Articles
    번호 분류 제목 글쓴이 날짜 조회 수
    공지 Tool/etc Programming 게시판 관련 2 MoA 2014.11.01 5193
    15 API/MFC Thread Programming Naya 2012.08.02 1411
    14 API/MFC MFC로 그림 그리기 Naya 2012.08.02 771
    13 API/MFC 메트로 스타일 앱개발을 위한 8가지 팁 너울 2012.05.14 1162
    12 API/MFC MFC, CHM파일 연동 (context help) 너울 2012.04.16 1595
    » API/MFC MFC 리본 사용하기 (아이콘 제작 포함) 너울 2012.02.09 5055
    10 API/MFC MFC Feature Pack: An Introduction 너울 2012.02.08 2266
    9 API/MFC 프로그램 배포용으로 만드는 과정 너울 2012.01.20 1591
    8 API/MFC Office 스타일의 리본바 만드는 법 너울 2012.01.12 841
    7 API/MFC CFormView 너울 2012.01.09 1307
    6 API/MFC MSCOMM32.OCX 등록 너울 2011.10.17 1791
    5 API/MFC 프로세스 - 생성과 종료 그리고 이것 저것 너울 2011.10.12 2161
    4 API/MFC Thread에서 Dialog의 UpdateData()사용하는 방법 너울 2011.09.26 1892
    3 API/MFC CreateThread와 AfxBeginThread의 차이 너울 2011.09.26 2443
    2 API/MFC 메시지 펌프 너울 2011.08.26 1492
    1 API/MFC Serial Communication in MFC 너울 2011.08.25 1626
    Board Pagination Prev 1 2 3 4 Next
    / 4