로그인

검색

조회 수 5119 추천 수 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 5723
    28 LLM [번역]거대언어모델(LLM) 가이드 OBG 2023.07.20 396
    27 Deeplearning Top 3 most used Pytorch Ecosystem Libraries you should Know about OBG 2023.08.02 1148
    26 Deeplearning LSTM-AE를 이용한 시퀀스 데이터 이상 탐지 OBG 2023.08.14 454
    25 Deeplearning 내 마음대로 선정한 머신러닝/딥러닝 학습 추천 서적 OBG 2023.08.14 1025
    24 Deeplearning 마이크로소프트가 공개한 무료 AI 코스들 OBG 2023.11.28 906
    23 Site 모든 개발자를위한 10 가지 특별한 GitHub 리포지토리 OBG 2023.12.28 659
    22 Site 10 Useful/Fun/Weird Github Repos You Have to Play Around With OBG 2023.12.28 940
    21 Tool/etc How to stop programmers to copy the code from GitHub when they leave the company? OBG 2024.01.02 720
    20 Deeplearning [ifkakao] 추천 시스템: 맥락과 취향 사이 줄타 OBG 2024.01.10 404
    19 서버 멀티-플레이어 게임 서버와 레이턴시 보상 테크닉 OBG 2024.01.16 489
    18 Deeplearning Using Machine Learning to Predict Customers’ Next Purchase Day OBG 2024.02.27 389
    17 LLM [12월 1주] 떠오르는 '미스트랄 7B'...'라마 2' 이어 한국어 모델 세대교체 주도 OBG 2024.03.05 656
    16 LLM A Beginner's Guide to Prompt Engineering with GitHub Copilot OBG 2024.04.04 346
    15 LLM 만능 프롬프트 OBG 2024.04.07 796
    14 LLM How LLMs Work ? Explained in 9 Steps — Transformer Architecture OBG 2024.04.11 363
    13 LLM Getting Started with Sentiment Analysis using Python OBG 2024.04.11 375
    12 LLM Real-Time Stock News Sentiment Prediction with Python OBG 2024.04.11 599
    11 LLM ChatGPT의 강력한 경쟁 언어모델 등장!, Mixtral 8x7B OBG 2024.04.14 589
    10 LLM Mixture of Experts - Part 2 OBG 2024.04.14 355
    9 LLM The difference between quantization methods for the same bits OBG 2024.04.14 366
    Board Pagination Prev 1 ... 6 7 8 9 10 11 12 13 14 15 Next
    / 15