1. 참고링크 [Bottom] [Top]

2. MFC 주요 클래스 참조 방법 [Bottom] [Top]

3. 메뉴 [Bottom] [Top]

3.1. Context Menu 처리 [Bottom] [Top]

마우스 오른쪽 버튼을 클릭했을 때 메뉴 출력을 하는 소스 코드.

  1. WM_CONTEXTMENU 메세지에 대한 핸들러를 추가한다.

  2. CMenu 클래스 변수를 선언한다.
    CMenu menu, *pMenu;
    
  3. CMenu 클래스 변수에 메뉴를 적재한다.
    menu.LoadMenu( ... );
    pMenu = menu.GetSubMenu( ... );
    
  4. 메뉴를 출력한다.
    pMenu->TrackPopupMenu( ... );
    

4. 대화상자 [Bottom] [Top]

4.1. Enter 키 처리 [Bottom] [Top]

Enter 키 입력시 대화상자가 닫기도록 처리하는 소스 코드.

  1. PreTranslateMessage() 함수(가상) 를 재정의 한다.

  2. Enter 키 처리 코드를 추가한다.
       1 BOOL CExampleDlg::PreTranslateMessage( MSG * pMsg )
       2 {
       3         if( ( pMsg->message == WM_KEYDOWN ) && ( pMsg->wParam == VK_RETURN ) )
       4         {
       5                 ...
       6         }
       7 
       8         return CDialog::PreTranslateMessage( pMsg );
       9 }
      10 
    

참고> Eating returns in a single line edit

4.2. 유용한 CWnd 멤버 함수 [Bottom] [Top]

유용하지만 간혹 기억나지 않아 찾느라 고생하는 일이 있어서 몇가지를 정리한다.

위의 멤버 함수에 해당하는 WIN32 API 는 아래와 같다.

4.3. DDX/DDV 함수 [Bottom] [Top]

매번 헷갈리는 DDX/DDV 함수의 사용법이다.

4.4. CDialogBar 를 CDialog 처럼 사용하기 [Bottom] [Top]

4.5. 대화상자 드래그 이동하기 [Bottom] [Top]

일반 창이나 대화상자에서 윈도우 타이틀(창의 제목 표시줄) 이 없을 경우, 또는 윈도우의 아무 곳이나 클릭하여 드래그할 때 윈도우를 이동시키고 싶다면 WM_NCHITTEST 메세지 핸들러를 추가하여 처리한다.

4.6. 액셀러레이터 키 (바로 가기 키) 처리 [Bottom] [Top]

대화상자에서 액셀러레이터 키 처리를 추가하는 순서와 소스 코드.

  1. 액셀러레이터 키 테이블 변수 추가
    // 대화상자 클래스에 변수 추가
    HACCEL  m_hAccelTable;
    
  2. 리소스 편집기에서 액셀러레이터 키 테이블 추가 (예: 리소스ID = IDR_ACCELERATOR )

  3. 액셀러레이터 키 처리 코드 추가
       1 // STEP 1: 액셀러레이터 키 테이블 로딩 (가상 함수 재정의)
       2 BOOL CExampleDlg::OnInitDialog()
       3 {
       4         CDialog::OnInitDialog();
       5 
       6         // 리소스ID IDR_ACCELERATOR 의 액셀러레이터 키 테이블 로딩
       7         m_hAccelTable = ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_ACCELERATOR ) );
       8 
       9         return TRUE;
      10 }
      11 
      12 // STEP 2: 액셀러레이터 키 처리 코드 추가 (가상 함수 재정의)
      13 BOOL CExampleDlg::PreTranslateMessage( MSG * pMsg )
      14 {
      15         if( WM_KEYDOWN == pMsg->message )
      16         {
      17                 if( NULL != m_hAccelTable )
      18                 {
      19                         if( ::TranslateAccelerator( m_hWnd, m_hAccelTable, pMsg ) )
      20                         {
      21                                 return TRUE;
      22                         }
      23                 }
      24         }
      25 
      26         return CDialog::PreTranslateMessage(pMsg);
      27 }
      28 
    

4.7. ToolBar 와 StatusBar 추가하기 [Bottom] [Top]

4.8. 메뉴 기능 추가 [Bottom] [Top]

대화상자에서 기본으로 제공되지 않는 메뉴 기능을 추가한다. 대화상자의 속성에서 간단한 추가로 쉽게 사용할 수 있지만 명령 사용자 인터페이스(UPDATE_COMMAND_UI) 가 처리되지 않기 때문에 추가적인 작업이 필요하다.

  1. [리소스 뷰] 에서 [Menu] 를 추가한다. (메뉴 리소스 ID 지정 - 필수)

  2. [리소스 뷰] 에서 대화상자의 속성 창으로 열고 [Menu] 속성에 메뉴 리소스 ID 를 설정한다.

  3. 대화상자 클래스(CDialog 를 상속받은 클래스) 에서 각 메뉴의 메시지 핸들러(COMMAND) 를 추가한다.

하지만, 메뉴의 명령 사용자 인터페이스(UPDATE_COMMAND_UI) 가 처리되지 않는다.

따라서 필요한 경우 다음과 같은 추가 구현이 필요하다.

  1. 대화상자 클래스에 WM_INITMENUPOPUP 메시지 핸들러 추가한다. (OnInitMenuPopup() 멤버 함수가 추가됨)

  2. OnInitMenuPopup() 함수를 다음과 같이 구현한다.

       1 // File: MFC/Dlg_OnInitMenuPopup.cpp
       2 
       3 void CTestDlg::OnInitMenuPopup( CMenu * pPopupMenu, UINT nIndex, BOOL bSysMenu )
       4 {
       5     ASSERT( pPopupMenu != NULL );
       6     // Check the enabled state of various menu items.
       7 
       8     CCmdUI state;
       9     state.m_pMenu = pPopupMenu;
      10     ASSERT( state.m_pOther == NULL );
      11     ASSERT( state.m_pParentMenu == NULL );
      12 
      13     // Determine if menu is popup in top-level menu and set m_pOther to
      14     // it if so (m_pParentMenu == NULL indicates that it is secondary popup).
      15     HMENU hParentMenu;
      16     if( AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu )
      17         state.m_pParentMenu = pPopupMenu;       // Parent == child for tracking popup.
      18     else if( ( hParentMenu = ::GetMenu( m_hWnd ) ) != NULL )
      19     {
      20         CWnd * pParent = this;
      21         // Child windows don't have menus--need to go to the top!
      22         if( ( pParent != NULL )
      23             && ( ( hParentMenu = ::GetMenu( pParent->m_hWnd ) ) != NULL ) )
      24         {
      25             int nIndexMax = ::GetMenuItemCount( hParentMenu );
      26             for( int nIndex = 0; nIndex < nIndexMax; ++nIndex )
      27             {
      28                 if( ::GetSubMenu( hParentMenu, nIndex ) == pPopupMenu->m_hMenu )
      29                 {
      30                     // When popup is found, m_pParentMenu is containing menu.
      31                     state.m_pParentMenu = CMenu::FromHandle( hParentMenu );
      32                     break;
      33                 }
      34             }
      35         }
      36     }
      37 
      38     state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
      39     for( state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; ++state.m_nIndex )
      40     {
      41         state.m_nID = pPopupMenu->GetMenuItemID( state.m_nIndex );
      42         if( state.m_nID == 0 )
      43             continue;       // Menu separator or invalid cmd - ignore it.
      44 
      45         ASSERT( state.m_pOther == NULL );
      46         ASSERT( state.m_pMenu != NULL );
      47         if( state.m_nID == (UINT)-1 )
      48         {
      49             // Possibly a popup menu, route to first item of that popup.
      50             state.m_pSubMenu = pPopupMenu->GetSubMenu( state.m_nIndex );
      51             if( ( state.m_pSubMenu == NULL )
      52                 || ( ( state.m_nID = state.m_pSubMenu->GetMenuItemID( 0 ) ) == 0 )
      53                 || ( state.m_nID == (UINT)-1 ) )
      54             {
      55                 continue;       // First item of popup can't be routed to.
      56             }
      57             state.DoUpdate( this, TRUE );   // Popups are never auto disabled.
      58         }
      59         else
      60         {
      61             // Normal menu item.
      62             // Auto enable/disable if frame window has m_bAutoMenuEnable
      63             // set and command is _not_ a system command.
      64             state.m_pSubMenu = NULL;
      65             state.DoUpdate( this, FALSE );
      66         }
      67 
      68         // Adjust for menu deletions and additions.
      69         UINT nCount = pPopupMenu->GetMenuItemCount();
      70         if( nCount < state.m_nIndexMax )
      71         {
      72             state.m_nIndex -= ( state.m_nIndexMax - nCount );
      73             while( ( state.m_nIndex < nCount )
      74                 && ( pPopupMenu->GetMenuItemID( state.m_nIndex ) == state.m_nID ) )
      75             {
      76                 ++state.m_nIndex;
      77             }
      78         }
      79         state.m_nIndexMax = nCount;
      80     }
      81 }
    

5. 문자열 [Bottom] [Top]

5.1. CString 객체를 C-Style Null-Terminated 문자열로 변환하기 [Bottom] [Top]

표준 런타임 라이브러리를 사용하기 위해서 C-Style 문자열이 필요할 때 사용.

6. 글꼴 [Bottom] [Top]

6.1. 속성 바꾸기 [Bottom] [Top]

CWnd 를 상속받은 객체에서 현재 사용중인 글꼴의 속성(크기)를 바꾸는 소스 코드.

6.2. 글꼴 크기 계산 [Bottom] [Top]

일반적으로 많이 쓰는 포인트(pt) 크기와 논리 크기 사이에는 크기 변환을 다음과 같은 식으로 계산한다.

6.3. DC 에서 GDI 글꼴 크기 계산하기 [Bottom] [Top]

DC (device-context) 에서 표시될 GDI 글꼴 크기를 계산하는 소스 코드. 아래의 소스 코드는 한글 1자의 크기, 영문 1자의 크기를 계산하는 코드.

7. 컨트롤 [Bottom] [Top]

7.1. 8 비트 이상의 이미지 사용하기 [Bottom] [Top]

Tree 컨트롤에서 8 비트 (256색) 이상의 이미지를 사용하기 위한 코드로 ToolBar 에서도 사용 가능하다.

참고> Very simple true color toolbar (It's true!) - Code Project

7.2. CBitmapButton 사용하기 [Bottom] [Top]

버튼 모양을 마음대로 만들 수 있는 CBitmapButton 을 생성하는 소스 코드.

7.3. CListCtrl 사용하기 [Bottom] [Top]

7.4. 컨트롤의 문자색/배경색 바꾸기 [Bottom] [Top]

특정 타입의 컨트롤이나 지정된 하나의 컨트롤에 글자색, 배경색, 배경 모드(예: 혼합 모드) 등을 설정하는 소스 코드.

7.5. 컨트롤 내부 스크롤하기 [Bottom] [Top]

CListBox 와 같은 컨트롤에서 내부 영역을 스크롤하는 방법. 특히 문자열을 추가할 때마다 자동으로 스크롤되어야 할 경우 유용하다.

8. 파일 처리 [Bottom] [Top]

8.1. 파일 대화상자 - 파일이름 얻기 [Bottom] [Top]

8.2. 파일 열기 [Bottom] [Top]

8.3. Serialize() 함수 구현 [Bottom] [Top]

8.4. INI 파일 사용하기 [Bottom] [Top]

8.4.1. ToolBar 정보 읽기/쓰기 [Bottom] [Top]

CMainFrame 객체에 등록되어 있는 ToolBar 정보(상태)를 읽기/쓰기 위한 방법.

CWinApp 객체에서 정보를 저장하는 방식(ini 파일 / 레지스트리) 에 따라 lpszProfileName 변수는 다음과 같이 사용된다.

ini 파일을 사용할 경우 CWinApp 객체에서 지정된 ini 파일(CWinApp::m_pszProfileName)에 저장된다.

9. 윈도우즈 메시지 처리 [Bottom] [Top]

9.1. 사용자 정의 메시지 처리하기 [Bottom] [Top]

사용자 정의 메시지 처리에 대하여 수동으로 추가하는 방법(MS 에서는 자동으로 추가하는 방법을 제공하지 않음).

MFC 프로그래밍 2 (last edited 2011-09-18 09:26:10 by viper)