이 노트에서는 명령 라우팅 및 디스패치 건축 뿐만 아니라 일반 창 메시지 라우팅에 고급 주제。
설명서 를 참조 하십시오 Visual c + + 프로그래머의 일반에 대 한 내용은 여기에서 설명한 아키텍처 특히 Windows 메시지, 컨트롤 알림 및 명령 사이의 구별 합니다. 인쇄 된 문서에서 설명 하는 문제에 매우 익숙한 하 고만 매우 고급 주제를 해결이 참고 가정 합니다.
명령 라우팅 및 디스패치 MFC 1.0 기능 진화 MFC 2.0 아키텍처
Windows는 WM_COMMAND 메시지 알림 메뉴 명령 액셀러레이터 키, 대화 상자 컨트롤 알림을 제공 하는 오버 로드는。
CWnd 에 명령 처리기 (예를 들어, "OnFileNew")를 허용 하 여 조금에 내장 된 MFC 1.0 특정 WM_COMMAND에 대 한 응답에서 호출 하는 클래스 파생. 이 메시지 맵에 라고 하는 데이터 구조와 함께 붙어있다 그리고 매우 공간 효율적인 명령 메커니즘에 결과。
MFC 1.0는 또한 명령 메시지에서 컨트롤 알림을 분리에 대 한 추가 기능을 제공 합니다. 명령 id입니다. 명령 라고도 하는 16 비트 ID로 표시 됩니다. 명령 CFrameWnd 에서 일반적으로 시작 (예: 메뉴 선택 또는 번역된 가속기) 다양 한 다른 창에 전달 받을。
다중 문서 인터페이스 (MDI)의 구현에 대 한 제한 된 의미에서 명령 라우팅을 사용 하는 MFC 1.0. (MDI 프레임 창 명령을 활성 MDI 자식 창에 위임 합니다.)
이 기능은 일반화 되었으며, 명령 개체 (뿐 아니라 window 개체)의 넓은 범위에 의해 처리 될 수 있도록 MFC 2.0에서 확장 합니다. 그것은 더 많은 공식 제공 및 라우팅에 대 한 확장 가능한 아키텍처 메시지 뿐만 아니라 명령 처리를 위한 뿐만 아니라 명령의 현재 가용성을 반영 하도록 UI 개체 (예: 메뉴 항목 및 도구 모음 단추)를 업데이트 하기 위한 명령 대상 라우팅 재사용。
명령 Id
명령 라우팅 및 바인딩 프로세스에 대 한 설명은 Visual c + + 프로그래머 가이드 를 참조 하십시오. 기술 참고 20 ID 명명에 대 한 정보를 포함。
우리는 명령 Id에 대 한 일반적인 접두사 "ID_"를 사용합니다. 명령 Id는 gt; 0x8000 =. 메시지 줄 또는 상태 표시줄 명령 설명 문자열 명령 ID와 동일한 Id 사용 하 여 STRINGTABLE 리소스 인지 표시 됩니다(&G).
응용 프로그램의 리소스 ID 수 명령 여러 장소에 나타납니다.:
응용 프로그램의 소스 코드에서 명령 ID 수 여러 장소에 나타납니다.:
현재 mfc 명령 Id를 필요로 하는 유일한 구현 될 gt; = 0x8000는 GOSUB 대화/명령 구현(&G)。
GOSUB 명령, 대화 상자에서 명령 아키텍처를 사용 하 여
라우팅 및 활성화 명령을 명령 아키텍처 프레임 창, 메뉴 항목, 도구 모음 단추, 대화 상자 모음 단추, 기타 컨트롤 막대 및 기타 사용자 인터페이스 요소 수요와 경로 명령에 업데이트 하거나 기본 명령 대상 (일반적으로 주 프레임 창)에 Id를 제어 하도록 설계와 함께 잘 작동 합니다. 그 주요 명령 대상 적절 한 다른 명령 대상 개체에 명령 또는 컨트롤 알림을 라우팅할 수 있습니다.
적절 한 명령 id 대화 컨트롤의 컨트롤 ID를 할당 하는 경우 명령 아키텍처의 특징 중의 일부 로부터 이점을 얻을 수 있습니다 (모달 또는 모덜리스) 대화 상자 대화 상자에 대 한 지원 아니므로 자동으로, 몇 가지 추가 코드를 작성 해야 할 수 있습니다.
이러한 모든 기능이 제대로 작동 하려면에 대 한 명령 Id 여야 합니다 gt; 0x8000 =. 때문에 많은 대화 상자 같은 프레임 전달 얻을 수 있는, 공유 명령 해야 한다 >는 비공유 IDC의 특정 대화에 있어야 하는 반면, 0x8000 = < 0x7FFF =。
적절 한 명령 ID로 설정 하는 버튼의 IDC와 일반적인 모달 대화 상자에서 일반 단추를 배치할 수 있습니다. 사용자가 단추를 선택 하는 경우 대화 (일반적으로 주 프레임 창)의 소유자 처럼 다른 명령 명령을 가져옵니다. 이 때문에 일반적으로 사용 하는 다른 대화 상자 (첫 번째 대화 GOSUB) GOSUB 명령 라고。
또한 당신의 대화에 CWnd::UpdateDialogControls 함수를 호출 하 고 주 프레임 창의 주소를 전달할 수 있습니다. 이 함수는 사용 또는 사용 안 함 대화 상자 컨트롤 프레임에 명령 처리기를 있는지 여부에 따라. 이 함수는 호출 자동으로 당신을 위해 응용 프로그램의 유휴 루프에서 컨트롤 막대에 대 한 하지만이 기능을가지고 하고자 하는 일반 대화 상자에 대 한 직접 호출 해야 합니다.
ON_UPDATE_COMMAND_UI 라고
모든 시간 프로그램의 모든 메뉴 항목의 활성화 체크 상태를 유지 하는 계산 비용이 문제가 될 수 있습니다. 일반적인 방법은 사용/확인 메뉴 항목 팝업을 선택 하는 경우에 하는 것입니다. CFrameWnd MFC 2.0 구현 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를 사용 하 여 전체 팝업을 참조 하는 우리. 이 경우 CCmdUI 개체의 m_pSubMenu 멤버 변수에 NULL이 아닌 것 하 고 팝업 메뉴를 가리킵니다.
두 번째 팝업 메뉴 항목은 그려야 하기 바로 전에 호출 됩니다. 이 경우 ID 단지 첫 번째 메뉴 항목을 참조 하 고 CCmdUI 개체의 m_pSubMenu 멤버 변수는 NULL이 될 것입니다.
이 팝업 메뉴 항목에 구분을 사용 하면 하지만 일부 메뉴 인식 코드를 작성 해야 합니다. 예를 들어, 다음과 같은 구조를 가진 중첩된 메뉴에서:
Filegt;
?? 새로운 >
?????? 시트 (ID_NEW_SHEET)
?????? 차트 (ID_NEW_CHART)
ID_NEW_SHEET 및 ID_NEW_CHART 명령은 수 있습니다 독립적으로 활성화 또는 비활성화. 둘 중 하나를 사용 하는 경우 "New" 팝업 메뉴를 사용 해야。
ID_NEW_SHEET (팝업에서 첫 번째 명령)에 대 한 명령 처리기 처럼 생겼을 것:
void CMyApp::OnUpdateNewSheet (CCmdUI * pCmdUI)
{
nbsp;? 경우 (pCmdUI-> m_pSubMenu! = NULL)
?? {
?????? / / "새로 만들기" 시트와 차트에 대 한 전체 팝업 활성화
?????? BOOL bEnable m_bCanCreateSheet = | | m_bCanCreateChart;
/ / Ccmdui::enable이 경우 아니요 op 그래서 우리
?????? / / 그것 어떻게 했을 수행 해야 합니다.
?????? pCmdUI-> m_pMenu-> EnableMenuItem (pCmdUI-> m_nIndex,
?????????? MF_BYPOSITION |
?????????????? (bEnable? MF_ENABLED: (MF_DISABLED (KO) | MF_GRAYED)));
?????? 반환;
?? }
?? / / 그렇지 않으면 그냥 새 시트 명령
?? pCmdUI-> Enable(m_bCanCreateSheet);
}
일반 업데이트 명령 처리기와 비슷해 보이는 것이 ID_NEW_CHART에 대 한 명령 처리기:
void CMyApp::OnUpdateNewChart (CCmdUI * pCmdUI)
{
nbsp;? pCmdUI-> Enable(m_bCanCreateChart);
}
ON_COMMAND 및 ON_BN_CLICKED
ON_COMMAND 및 ON_BN_CLICKED 에 대 한 메시지 맵 매크로 동일합니다. MFC 명령 및 제어 알림 라우팅 메커니즘만 명령 ID를 사용 하 여 라우팅할 위치를 결정 합니다. 0 (BN_CLICKED)의 컨트롤 알림 코드를 사용 하 여 컨트롤 알림은 명령으로 해석 하는。
고급 참고: 실제 사실에서 모든 컨트롤 알림 메시지 명령 처리기 체인을 통해 이동 합니다. 따라서 문서 클래스에서 EN_CHANGE 말에 대 한 컨트롤 알림 처리기를 작성 하는 당신을 위해 기술적으로 가능 하다. 이후이 기능은의 실용적인 응용 프로그램 몇 가지, 마법사, 기능을 지원 하지 않습니다 기능 깨지기 쉬운 코드에서 발생할 수 있습니다 이것은 일반적으로 권장 하지。
Button 컨트롤의 자동 해제 사용 안 함
대화 상자 표시줄에서 또는 어디에서 호출할 때는 CWnd::UpdateDialogControls 자신만 사용 대화 상자에서 단추 컨트롤을 배치 하는 경우는 단추 ON_COMMAND 또는 ON_UPDATE_COMMAND_UI 처리기는 없습니다 자동으로 비활성화 됩니다 당신을 위해 프레임 워크에 의해 통보 됩니다. 어떤 경우에 당신이 것입니다 필요가 없습니다 처리기, 하지만 계속 사용 하려면 단추를 원할 것입니다. 이것을 달성 하는 가장 쉬운 방법은 (쉽게 ClassWizard 할) 더미 명령 처리기를 추가 하는 그것에서 아무것도 하지 않고。
창 메시지 라우팅
다음 MFC 클래스 및 Windows 메시지 라우팅 및 다른 주제 미치는 그들에 몇 가지 더 고급 주제를 설명. 여기에 정보를 간략하게 설명만 합니다. 공용 Api에 대 한 자세한 내용은 클래스 라이브러리 참조 를 참조 하십시오. 구현 세부 사항에 대 한 자세한 내용은 MFC 라이브러리 소스 코드를 참조 하십시오。
참조 하십시오 기술 노트 17 창 정리에 매우 중요 한 주제에 대 한 모든 CWnd-파생 클래스。
CWnd 문제
구현 멤버 함수 CWnd::OnChildNotify 연결 또는 메시지, 명령, 및 그들의 부모 (또는 "소유자") 이동 하는 컨트롤 알림 통보 그렇지 않으면 자식 창 (컨트롤)에 대 한 강력 하 고 확장 가능한 아키텍처를 제공 합니다. 만약 자식 창 (/) 자체를 OnChildNotify 라고 먼저 매개 변수 원본 메시지 ( MSG 구조)에서 가상 함수는 c + + CWnd 개체입니다. 자식 창 메시지를 내버려 두고, 그것을 먹고 하거나 수정할 수 있습니다 메시지 (희귀) 부모에 대 한。
기본 CWnd 구현 다음 메시지를 처리 하 고 OnChildNotify 후크를 사용 하 여 자식 창 (컨트롤)를 먼저 메시지에서 균열을 허용합니다:
OnChildNotify 후크 self-draw 메시지를 소유자 그리기 메시지를 변경 하는 것에 대 한 사용 하는 것을 알 수。
OnChildNotify 후크 외에 스크롤 메시지 추가 라우팅 동작이 있다. 스크롤 막대 및 WM_HSCROLL 및 WM_VSCROLL 메시지의 소스에 대 한 자세한 내용은 아래 참조 하십시오。
CFrameWnd 문제
대부분의 명령 라우팅 및 사용자 인터페이스를 제공 하는 CFrameWnd 클래스 구현 업데이트 합니다. 이것은 주로 응용 프로그램 (CWinApp::m_pMainWnd)의 주 프레임 창에 대 한 사용 하지만 모든 프레임 창에 적용 됩니다.
주 프레임 창의 메뉴 표시줄 창을 이며 상태 표시줄의 부모 또는 라인 메시지. 명령 라우팅에 대 한 위의 논의를 참조 하십시오 및 WM_INITMENUPOPUP.
CFrameWnd 클래스는 현재 보기의 관리를 제공합니다. 현재 보기를 통해 다음 메시지를 라우팅할:
CMDIFrameWnd/CMDIChildWnd 문제
MDI 프레임 창 클래스는 CFrameWnd 에서 파생 및 따라서 둘 다의 명령 라우팅 및 사용자 인터페이스 업데이트 CFrameWnd에서 제공 하는 동일한 종류에 대해 사용할 수 있습니다. 일반적인 MDI 응용 프로그램에서 주 프레임 창 ( CMDIFrameWnd 개체)만 메뉴 모음 및 상태 표시줄을 보유 하 고 따라서 명령 라우팅 구현의 주요 소스입니다.
일반 라우팅 구성표는 활성 MDI 자식 창 명령에서 첫 번째 균열을 가져옵니다. 기본 PreTranslateMessage 함수 처리 두 MDI 자식 창에 대 한 액셀러레이터 테이블 (첫 번째) 및 MDI 프레임 뿐만 아니라, 일반적으로 TranslateMDISysAccel (마지막) 의해 처리 표준 MDI 시스템 명령 단축키 (2)。
스크롤 막대 문제
스크롤 메시지를 처리 하는 경우 (WM_HSCROLL/OnHScroll 및 WM_VSCROLL/OnVScroll ), 그래서 어디에서 온 스크롤 막대 메시지에 의존 하지 않는 처리기 코드를 작성 하려고 한다. 이것은 단지 일반적인 Windows 문제, 또는 WS_HSCROLL진정한 스크롤 막대 컨트롤에서에서 스크롤 메시지 올 수 있으므로 / 하지 않은WS_VSCROLL 스크롤 막대 스크롤 막대 컨트롤。
MFC 자식 또는 형제 (사실 스크롤 막대와 스크롤 되 고 창 사이의 부모/자식 관계는 아무것도 될 수 있다) 스크롤 되는 윈도우의 스크롤 막대 컨트롤에 대 한 허용을 확장 합니다. 이것은 분할 창 함께 공유 스크롤 막대에 대 한 특히 중요 합니다. CSplitterWnd 공유 스크롤 막대 문제에 대 한 더 많은 정보를 포함 한 구현에 대 한 내용은 기술 참고 29 를 참조 하십시오。
메모 측면에서 두 CWnd 파생된 클래스 어디에서 지정 된 스크롤 막대 스타일 만들기 시간 갇혀 있고 Windows에 전달 되지 있습니다. 생성 루틴에 전달 하는 경우 WS_HSCROLL 및 WS_VSCROLL 독립적으로 설정할 수 없는, 하지만 후에 창조를 변경할 수 없습니다. 물론, 당신이 직접 테스트 해야 하거나 합니다 WS_ 설정?그들이 만든 창 스타일 비트를 스크롤。
CMDIFrameWnd 에 대 한 스크롤 막대 스타일 만들기 또는 LoadFrame 에 전달 된 MDICLIENT를 만드는 데 사용 됩니다. 설정 해야 합니다. 스크롤 MDICLIENT 영역 (같은 Windows 프로그램 관리자) 하고자 하는 경우 두 스크롤 막대 스타일 (WS_HSCROLL (ko) | WS_VSCROLL) CMDIFrameWnd 생성 하는 데 사용 하는 스타일에 대 한。
CSplitterWnd 스크롤 막대 스타일 분할 영역에 대 한 특별 한 공유 스크롤 막대에 적용 됩니다. 정적 분할 창 스크롤 막대 스타일 중 하나를 설정 하지 일반적으로 것입니다. 동적 분할 창에 대 한 일반적으로 당신은 것입니다 스크롤 방향 분할 것입니다 즉, WS_HSCROLL 열을 분할 하는 경우 행을 WS_VSCROLL 를 분할할 수 하는 경우에 대 한 스타일 설정 막대。
기술 노트 번호로 |nbsp; 카테고리별 기술 노트(&N)