TN021: 명령 및 메시지 라우팅
[!참고]
온라인 설명서의을 처음 포함 되었습니다 때문 다음 기술 참고 업데이트 되지 않았습니다.따라서 일부 절차 및 항목 오래 되었거나 잘못 된 수 있습니다.최신 정보는 온라인 설명서 색인에서 관심 있는 주제에 대해 검색 하는 것이 좋습니다.
이 참고가 명령 라우팅 및 디스패치 아키텍처 뿐만 아니라 일반 창 메시지 라우팅에 대 한 고급 항목에 설명합니다.
Visual C++에 대 한 일반적인 내용은 여기에서 설명 하는 아키텍처 Windows 메시지, 컨트롤 알림 및 명령 사이의 구별 특히 참조 하십시오.이 참고가 설명서에서 설명 하는 문제에 정통한 이며만 매우 고급 항목을 다룹니다 가정 합니다.
MFC 2.0에 발전 1.0 MFC 명령 라우팅 및 발송 기능 아키텍처
Windows는 WM_COMMAND 메시지 알림 메뉴 명령을 액셀러레이터 키, 대화 상자 컨트롤 알림을 제공 하도록 오버 로드 됩니다.
MFC 1.0 내장에 약간 있으므로 명령 처리기 (예: "OnFileNew")는 CWnd 파생 클래스에 대 한 응답으로 특정 호출에 WM_COMMAND.이 메시지 맵 이라는 데이터 구조와 함께 붙이고 공간-효율적인 명령을 메커니즘의 결과.
MFC 1.0도 컨트롤 알림 메시지 명령에서에서 분리 하는 추가 기능을 제공 합니다.명령은 명령 ID로 라고도 하는 16 비트 ID가 표시 됩니다.명령을 정상적으로 시작는 CFrameWnd (메뉴 선택 또는 번역된 된 가속기)와 다양 한 다른 창에 라우팅할 수 있습니다.
MFC 1.0 명령 다중 문서 인터페이스 (MDI)의 구현에 대 한 제한 된 점에서 라우팅을 사용 합니다.(MDI 프레임 창 대리자 명령을 해당 활성 MDI 자식 창입니다.)
이 기능은 일반화 하 명령을 더 넓은 범위의 개체 (뿐 아니라 window 개체)에서 처리 될 수 있도록 MFC 2.0에서 확장 했습니다.더 공식적인 제공 및 라우팅에 대 한 확장 가능한 아키텍처 메시지 및 명령 대상 뿐 아니라 명령으로 처리 하지만 UI 개체 (예: 메뉴 항목 및 도구 모음 단추) 현재 사용 가능한 명령 반영 하도록 업데이트에 대 한 회람을 재사용.
명령 Id
Visual C++의 명령 라우팅 및 바인딩 프로세스에 대 한 설명은 참조 하십시오.기술 참고 20 ID 명명에 대 한 정보가 포함 되어 있습니다.
우리는 명령 Id에 대 한 일반 "ID_" 접두사가 있습니다.명령 Id는 > = 0x8000.메시지 줄 또는 상태 표시줄 명령 ID와 동일한 Id로는 STRINGTABLE 리소스 인지 명령 설명 문자열이 표시 됩니다.
응용 프로그램의 리소스를, 명령 ID 수 있습니다 여러 곳에 나타납니다.
메시지 줄 프롬프트와 같은 ID를 가진 한 STRINGTABLE 리소스에 있습니다.
동일한 명령을 호출 하는 메뉴 항목에 연결 된 수 많은 메뉴 리소스에.
(GOSUB 명령을 대화 단추에서 고급).
응용 프로그램의 소스 코드에서 ID 수 있습니다 명령을 여러 위치에서 나타납니다.
리소스에서.H 또는 다른 주 기호 헤더 파일 응용 프로그램별 명령 Id를 정의 합니다.
도구 모음을 만드는 데 아마도 ID 배열.
에 ON_COMMAND 매크로.
아마에 있는 ON_UPDATE_COMMAND_UI 매크로.
현재, 유일한 명령 Id를 필요로 하는 MFC에서 구현 될 > = 0x8000 GOSUB 대화 상자/명령을 구현 됩니다.
GOSUB 명령, 대화 상자에서 명령 아키텍처를 사용 하 여
명령 및 명령 라우팅의 아키텍처 프레임 창, 메뉴 항목, 도구 모음 단추, 대화 상자 모음 단추, 기타 컨트롤 막대 및 명령을 요구 및 경로 업데이트 하거나 기본 명령 대상 (일반적으로 주 프레임 창)에 Id를 제어 하도록 설계 된 다른 사용자 인터페이스 요소와 함께 사용할 수 있습니다.기본 명령 대상 명령 또는 컨트롤 알림 다른 명령 대상 개체를 적절 하 게 라우팅할 수 있습니다.
(모달 또는 모덜리스) 대화 상자가 적절 한 명령 ID에 대화 컨트롤의 컨트롤 ID를 지정할 경우 명령은 아키텍처의 기능 중 일부를 활용할 수 있습니다.일부 추가 코드를 작성 해야 할 경우 대화 상자에 대 한 지원은 자동으로 아니므로.
제대로 작동 하려면 모든 이러한 기능에 대 한 명령 Id를 해야 합니다 > 0x8000 =.많은 대화 상자 같은 프레임에 라우팅된 얻을 수 있으므로 공유 명령이 있어야 > 비공유 IDCs 특정 대화 상자에서 해야 하지만, 0x8000 = < 0x7FFF =.
IDC의 적절 한 명령 ID로 설정 하는 단추와 일반적인 모달 대화 상자에서 표준 단추를 배치할 수 있습니다.사용자가 단추를 선택 하면 모든 다른 명령과 마찬가지로 방금 명령을 (일반적으로 주 프레임 창) 대화 상자의 소유자를 가져옵니다.(첫 번째 대화 상자의 GOSUB) 다른 대화 상자를 표시 하려면 대개 사용 하므로 GOSUB 명령을 이라고 합니다.
함수를 호출할 수도 있습니다 CWnd::UpdateDialogControls 대화 상자에서 고 주 프레임 창의 주소를 전달 합니다.이 함수 사용 또는 이러한 명령 처리기 프레임에 있는지 여부 따라 대화 상자 컨트롤을 사용 하지 않도록 설정 됩니다.자동으로 응용 프로그램의 유휴 루프에서 컨트롤 막대에 대 한 호출 되는이 함수 있지만 사용자는이 기능을 사용 하려는 정상적인 대화에 대 한 직접 호출 해야 합니다.
ON_UPDATE_COMMAND_UI 호출 되 면
활성화 체크 프로그램의 모든 메뉴 항목의 상태를 항상 유지 비용이 계산 상 문제가 될 수 있습니다.일반적인 방법만 사용자 팝업을 선택 하면 메뉴 항목이 활성화 체크 것입니다.MFC 2.0 구현의 CFrameWnd 핸들의 WM_INITMENUPOPUP 메시지 및 명령 라우팅 아키텍처를 사용 하 여 메뉴를 통해 상태를 확인할 수 ON_UPDATE_COMMAND_UI 처리기입니다.
CFrameWnd 도 처리는 WM_ENTERIDLE 메시지 상태 표시줄 (메시지 줄 라고도 함)에서 선택한 항목에서 현재 메뉴에 설명 합니다.
Visual C++에서 편집할 응용 프로그램의 메뉴 구조를 잠재적인 명령에서 사용할 수를 나타내는 데 사용 WM_INITMENUPOPUP 시간.ON_UPDATE_COMMAND_UI 상태 또는 텍스트 메뉴를 처리기를 수정할 수 있습니다 또는 실제로 파일 MRU 목록 또는 OLE 동사 팝업 메뉴와 같은 고급 기능을 사용을 수정 하기 전에 메뉴 구조에 대 한 메뉴 그려집니다.
동일한 정렬의 ON_UPDATE_COMMAND_UI 도구 모음과 기타 컨트롤 막대에 대 한 처리가 수행 되는 응용 프로그램의 유휴 루프를 입력할 때.참조는 클래스 라이브러리 참조 및 기술 참고 31 컨트롤 막대에 대 한 자세한 내용은.
중첩 된 팝업 메뉴
중첩 된 메뉴 구조를 사용 하는 경우에 확인할 수 있는 ON_UPDATE_COMMAND_UI 두 가지 서로 다른 경우에 팝업 메뉴의 첫 번째 메뉴 항목에 대 한 처리기를 호출 합니다.
팝업 메뉴를 먼저 호출 됩니다.팝업 메뉴 Id가 없는 우리 팝업 메뉴의 첫 번째 메뉴 항목의 ID는 전체 팝업 메뉴로 참조할 수 있기 때문에 필요 합니다.이 경우는 m_pSubMenu 의 멤버 변수는 CCmdUI 개체는 NULL이 아니어야 하 고에 팝업 메뉴.
둘째, 그릴 팝업 메뉴에서 메뉴 항목을 방금 되기 전에 호출 됩니다.이 경우 방금 첫 번째 메뉴 항목에 ID를 참조 및 m_pSubMenu 의 멤버 변수는 CCmdUI 개체는 NULL 이어야 합니다.
이 팝업 메뉴에서 해당 메뉴 항목을 구분을 사용할 수 있습니다. 일부 메뉴 인식 코드를 작성 해야 합니다.예를 들어, 중첩 된 메뉴에는 다음과 같은 구조를 갖는.
File>
New>
Sheet (ID_NEW_SHEET)
Chart (ID_NEW_CHART)
ID_NEW_SHEET 및 ID_NEW_CHART 명령은 개별적으로 설정 하거나 해제할 수 있습니다.New 둘 중 하나를 사용 하는 경우 팝업 메뉴를 사용 해야 합니다.
ID_NEW_SHEET (팝업 첫 번째 명령)에 대 한 명령 처리기는 다음과 같습니다.
void CMyApp::OnUpdateNewSheet(CCmdUI* pCmdUI)
{
if (pCmdUI->m_pSubMenu != NULL)
{
// enable entire pop-up for "New" sheet and chart
BOOL bEnable = m_bCanCreateSheet || m_bCanCreateChart;
// CCmdUI::Enable is a no-op for this case, so we
// must do what it would have done.
pCmdUI->m_pMenu->EnableMenuItem(pCmdUI->m_nIndex,
MF_BYPOSITION |
(bEnable ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
return;
}
// otherwise just the New Sheet command
pCmdUI->Enable(m_bCanCreateSheet);
}
ID_NEW_CHART에 대 한 명령 처리기는 표준 업데이트 명령 처리기와 같습니다 모양이 됩니다.
void CMyApp::OnUpdateNewChart(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bCanCreateChart);
}
ON_COMMAND 및 ON_BN_CLICKED
메시지 맵 매크로 대 한 ON_COMMAND 및 ON_BN_CLICKED 같습니다.MFC 명령 및 컨트롤 알림 라우팅 메커니즘만 명령 ID를 사용 하 여를 라우팅할 위치를 결정 합니다.0 컨트롤 알림 코드를 사용 하 여 알림을 제어 (BN_CLICKED) 명령으로 해석 됩니다.
[!참고]
사실, 모든 컨트롤 알림 메시지는 명령 처리기 체인을 통해 이동합니다.예를 들어, 기술적으로 가능한 컨트롤 알림 처리기를 작성할 수 있습니다 EN_CHANGE 의 문서 클래스입니다.이 응용이 기능의 몇 가지, 기능, 클래스 마법사에서 지원 되지 않습니다 고 기능이 취약 코드에서 발생할 수 있습니다 때문에 일반적으로 권장 되지 않습니다.
단추 컨트롤의 자동 해제 사용 안 함
대화 상자 표시줄에서 단추 컨트롤을 배치 하거나 대화 상자에서 위치를 사용 하 여 호출 하는 경우 CWnd::UpdateDialogControls 것을 사용자가 직접가지고 있지 않은 해당 단추가 확인할 수 ON_COMMAND 또는 ON_UPDATE_COMMAND_UI 처리기가 자동으로 비활성화 됩니다 자동으로 프레임 워크에 의해.어떤 경우에 처리기가 필요 합니다 있지만 단추를 활성화 합니다.이 작업을 수행 하는 가장 쉬운 방법은 더미 명령 처리기 (클래스 마법사를 쉽게 할 수)를 추가 하는 것과 그 안에서 아무것도 하지.
창 메시지 라우팅
다음은 MFC 클래스와 어떻게 Windows 메시지 라우팅 및 다른 항목에 영향을 주는 일부 고급 항목을입니다.여기에 정보만 간략하게 설명 되어 있습니다.참조는 클래스 라이브러리 참조 공용 Api에 대 한 자세한 내용은.구현 세부 사항에 대 한 자세한 내용은 MFC 라이브러리 소스 코드를 참조 하십시오.
참조 하십시오 기술 노트 17 창 정리에 대 한 자세한 내용은, 모두에 대 한 매우 중요 한 주제에 대 한 CWnd-클래스를 파생 합니다.
CWnd 문제
구현 멤버 함수 CWnd::OnChildNotify 후크 하거나 그렇지 않으면 메시지, 명령, 및 해당 부모 (또는 "소유자") 이동 컨트롤 알림 통보 자식 창 (컨트롤이 라고도 함)에 대 한 강력 하 고 확장 가능한 아키텍처를 제공 합니다.경우 자식 창 (/)는 C++ CWnd 자체 가상 함수 개체 OnChildNotify 매개 변수와 함께 원본 메시지를 먼저 라고 (즉, 한 MSG 구조).자식 창 메시지를 내버려 둬, 먹을 하거나 (희귀) 부모에 대 한 메시지를 수정할 수 있습니다.
기본 CWnd 구현 다음 메시지를 처리 하 고 사용 하는 OnChildNotify windows 메시지에 대 한 첫 번째 액세스 (컨트롤) 자식 수 있도록 후크:
WM_MEASUREITEM 및 WM_DRAWITEM (에 대 한 self-draw)
WM_COMPAREITEM 및 WM_DELETEITEM (에 대 한 self-draw)
WM_HSCROLL 및 WM_VSCROLL
WM_CTLCOLOR
WM_PARENTNOTIFY
알 수 있는 OnChildNotify 후크 self-draw 메시지로 소유자 그리기 메시지를 변경 하는 데 사용 됩니다.
이외에 OnChildNotify 후크를 스크롤 메시지가 더 이상 동작을 라우팅 합니다.아래에 스크롤 막대와 소스에 대 한 자세한 내용은 참조 하십시오 WM_HSCROLL 및 WM_VSCROLL 메시지입니다.
CFrameWnd 문제
CFrameWnd 클래스는 대부분의 명령 라우팅 및 사용자 인터페이스를 제공 구현 업데이트 합니다.이 응용 프로그램의 주 프레임 창에 주로 사용 됩니다 (CWinApp::m_pMainWnd) 하지만 모든 프레임 창에 적용 됩니다.
주 프레임 창의 메뉴 모음을 사용 하 여 창 이며 상태 표시줄의 부모 또는 메시지 줄.위 토론에서 명령 라우팅을 참조 하십시오 및 WM_INITMENUPOPUP.
CFrameWnd 은 현재 보기의 관리 클래스를 제공 합니다.다음 메시지는 활성 뷰를 통해 라우팅됩니다.
(현재 보기 첫 번째 액세스를 가져옵니다) 모든 명령 메시지입니다.
WM_HSCROLL 및 WM_VSCROLL 메시지에서 형제 스크롤 막대 (아래 참조).
WM_ACTIVATE (및 WM_MDIACTIVATE MDI를)에 대 한 가상 함수 호출 설정 가져오기 CView::OnActivateView.
CMDIChildWnd CMDIFrameWnd/문제
두 MDI 프레임 창 클래스에서 파생 하 여 CFrameWnd 따라서 모두 동일한 명령 라우팅 정렬 하기 위해 사용 되 고 제공 된 사용자 인터페이스를 업데이트 합니다. CFrameWnd.일반적인 MDI 응용 프로그램에는 주 프레임 창에 (즉, 해당 CMDIFrameWnd 개체) 메뉴 모음 및 상태 표시줄을 보유 하 고 따라서 명령 라우팅 구현의 주요 소스입니다.
일반 라우팅 구성표 활성 MDI 자식 창 명령에 대 한 첫 번째 액세스를 갖는 것입니다.기본 PreTranslateMessage 함수는 액셀러레이터 키 테이블 두 MDI 자식 창에 대 한 처리 (먼저)와 MDI 프레임 뿐만 아니라 표준 MDI 시스템 명령 액셀러레이터 정상적으로 처리 (둘째) TranslateMDISysAccel (마지막).
스크롤 막대 문제
스크롤 메시지를 처리할 때 (WM_HSCROLL/OnHScroll 또는 WM_VSCROLL/OnVScroll), 스크롤 막대 메시지의 출처 의존 하지 않는 있도록 처리기 코드를 작성 하려고 합니다.True 이면 스크롤 막대 컨트롤 또는 스크롤 메시지 로부터 수 있으므로이은 일반 Windows 문제가 되지 않습니다 WS_HSCROLL/WS_VSCROLL 스크롤 스크롤 막대 컨트롤에는 없는 막대 합니다.
MFC 확장 스크롤 막대 컨트롤 창의 스크롤 되 형제 또는 자식으로 허용 하는 (사실, 스크롤 막대 및 창 스크롤 되는 부모/자식 관계 아무것도 될 수 있습니다).분할자 창은 공유 스크롤 막대에 대 한 특히 중요합니다.참조 하십시오 기술 참고 29 의 구현에 대 한 자세한 내용은 CSplitterWnd 에서 자세한 정보를 비롯 하 여 스크롤 막대 문제를 공유 합니다.
측면 메모에서 두 가지 CWnd 파생된 클래스에 지정 된 스크롤 막대 스타일 작성 시간을 트랩 및 Windows에 전달지 않습니다.생성 루틴으로 전달 하는 경우 WS_HSCROLL 및 WS_VSCROLL 독립적으로 설정할 수 있습니다, 후에 작성을 변경할 수 없습니다.물론 테스트 나는 WS_ 설정 해야 직접?자신이 만든 창 스타일 비트를 스크롤하십시오.
에 대 한 CMDIFrameWnd 스크롤 막대 스타일에 전달 만들기 또는 LoadFrame 의 MDICLIENT 만드는 데 사용 됩니다.설정 해야 스크롤 가능한 MDICLIENT 영역 (같은 Windows 프로그램 관리자) 하려는 경우에 모두 막대 스타일 스크롤 (WS_HSCROLL | WS_VSCROLL)를 만드는 데 사용 되는 스타일은 CMDIFrameWnd.
에 대 한 CSplitterWnd 분할 영역에 대 한 특별 한 공유 스크롤 막대 스크롤 막대 스타일을 적용 합니다.정적 분할 창에서 두 스크롤 막대 스타일을 설정 합니다 정상적으로 않습니다.동적 분할자 창, 일반적으로 스크롤 막대 방향 됩니다 분할 하 여, 즉,에 대 한 스타일 설정 해야 합니다 WS_HSCROLL 행을 분할 하 여 경우 WS_VSCROLL 열을 제대로 구분할 수 있습니다 경우.