비고
다음 기술 정보는 온라인 설명서에 처음 포함되었으므로 업데이트되지 않았습니다. 따라서 일부 절차와 항목이 만료되거나 올바르지 않을 수 있습니다. 최신 정보는 온라인 설명서 인덱스의 관심 항목을 검색하는 것이 좋습니다.
이 기술 참고에서는 MFC 4.0의 새로운 기능인 메시지 리플렉션에 대해 설명합니다. 또한 메시지 리플렉션을 사용하는 간단한 재사용 가능한 컨트롤을 만들기 위한 지침도 포함되어 있습니다.
이 기술 참고 사항은 ActiveX 컨트롤(이전의 OLE 컨트롤)에 적용되므로 메시지 리플렉션에 대해 설명하지 않습니다. ActiveX 컨트롤: Windows 컨트롤 서브클래싱 문서를 참조하세요.
메시지 리플렉션이란?
Windows 컨트롤은 부모 창에 알림 메시지를 자주 보냅니다. 예를 들어 많은 컨트롤은 부모가 컨트롤의 배경을 그리기 위한 브러시를 제공할 수 있도록 컨트롤 색 알림 메시지(WM_CTLCOLOR 또는 변형 중 하나)를 부모에 보냅니다.
Windows 및 버전 4.0 이전의 MFC에서는 종종 대화 상자인 부모 창에서 이러한 메시지를 처리합니다. 즉, 메시지 처리를 위한 코드는 부모 창의 클래스에 있어야 하며 해당 메시지를 처리해야 하는 모든 클래스에서 중복되어야 합니다. 위의 경우 사용자 지정 배경이 있는 컨트롤을 원하는 모든 대화 상자에서 컨트롤 색 알림 메시지를 처리해야 합니다. 자체 배경색을 처리하는 컨트롤 클래스를 작성할 수 있는 경우 코드를 다시 사용하는 것이 훨씬 쉽습니다.
MFC 4.0에서는 이전 메커니즘이 계속 작동합니다. 부모 창에서 알림 메시지를 처리할 수 있습니다. 그러나 MFC 4.0은 자식 제어 창 또는 부모 창 또는 둘 다에서 이러한 알림 메시지를 처리할 수 있는 "메시지 리플렉션"이라는 기능을 제공하여 재사용을 용이하게 합니다. 이제 컨트롤 배경색 예제에서 부모에 의존하지 않고 반사된 WM_CTLCOLOR 메시지를 처리하여 자체 배경색을 설정하는 컨트롤 클래스를 작성할 수 있습니다. (메시지 리플렉션은 Windows가 아닌 MFC에 의해 구현되므로 메시지 리플렉션이 작동하려면 부모 창 클래스가 CWnd
파생되어야 합니다.)
이전 버전의 MFC는 소유자가 그린 목록 상자(WM_DRAWITEM 등)에 대한 메시지와 같은 몇 가지 메시지에 대한 가상 함수를 제공하여 메시지 리플렉션과 비슷한 작업을 수행했습니다. 새 메시지 리플렉션 메커니즘은 일반화되고 일관됩니다.
메시지 리플렉션은 MFC 4.0 이전 버전용으로 작성된 코드와 역호환됩니다.
부모 창의 클래스에서 특정 메시지나 메시지의 범위에 대해 처리기를 제공한 경우, 사용자 고유의 처리기에서 기본 클래스의 처리기 함수를 호출하지 않으면 동일한 메시지에 대한 반영된 메시지 처리기를 재정의하게 됩니다. 예를 들어, 당신의 대화 상자 클래스에서 WM_CTLCOLOR를 처리하는 경우, 이 처리는 반영된 모든 메시지 처리기를 재정의하게 됩니다.
부모 창 클래스에서 특정 WM_NOTIFY 메시지 또는 WM_NOTIFY 메시지 범위에 대한 처리기를 제공하는 경우, 해당 메시지를 보내는 자식 컨트롤에 반영된 메시지 처리기가 없을 때에만 처리기가 ON_NOTIFY_REFLECT()
호출됩니다. 메시지 맵에서 사용하는 ON_NOTIFY_REFLECT_EX()
경우 메시지 처리기가 부모 창에서 메시지를 처리하도록 허용할 수도 있고 허용하지 않을 수도 있습니다. 처리기가 FALSE를 반환하는 경우 메시지는 부모도 처리하지만 TRUE 를 반환하는 호출은 부모가 처리할 수 없습니다. 반영된 메시지는 알림 메시지 전에 처리됩니다.
WM_NOTIFY 메시지를 보내면 컨트롤에서 메시지를 처리할 수 있는 첫 번째 기회가 제공됩니다. 다른 반영된 메시지가 전송되면 부모 창에서 해당 메시지를 처리할 수 있는 첫 번째 기회가 있으며 컨트롤은 반영된 메시지를 받습니다. 이렇게 하려면 처리기 함수와 컨트롤의 클래스 메시지 맵에 적절한 항목이 필요합니다.
반영된 메시지에 대한 메시지 맵 매크로는 일반 알림과 약간 다릅니다. 일반적인 이름에 _REFLECT 추가되었습니다. 예를 들어 부모에서 WM_NOTIFY 메시지를 처리하려면 부모 메시지 맵에서 매크로 ON_NOTIFY 사용합니다. 자식 컨트롤에서 반영된 메시지를 처리하려면 자식 컨트롤의 메시지 맵에서 ON_NOTIFY_REFLECT 매크로를 사용합니다. 경우에 따라 매개 변수도 다릅니다. ClassWizard는 일반적으로 메시지 맵 항목을 추가하고 올바른 매개 변수를 사용하여 기본 함수 구현을 제공할 수 있습니다.
새 WM_NOTIFY 메시지에 대한 자세한 내용은 TN061: ON_NOTIFY 및 WM_NOTIFY 메시지를 참조하세요.
반영된 메시지에 대한Message-Map 항목 및 처리기 함수 프로토타입
반영된 컨트롤 알림 메시지를 처리하려면 아래 표에 나열된 메시지 맵 매크로 및 함수 프로토타입을 사용합니다.
ClassWizard는 일반적으로 이러한 메시지 맵 항목을 추가하고 기본 함수 구현을 제공할 수 있습니다. 반영된 메시지에 대한 처리기를 정의하는 방법에 대한 자세한 내용은 반영된 메시지에 대한 메시지 처리기 정의를 참조하세요.
메시지 이름에서 반영된 매크로 이름으로 변환하려면 앞에 ON_ 추가하고 _REFLECT 추가합니다. 예를 들어, WM_CTLCOLOR는 ON_WM_CTLCOLOR_REFLECT로 변경됩니다. (반영할 수 있는 메시지를 보려면 아래 표의 매크로 항목에서 반대 변환을 수행합니다.)
위의 규칙에 대한 세 가지 예외는 다음과 같습니다.
WM_COMMAND 알림에 대한 매크로가 ON_CONTROL_REFLECT.
WM_NOTIFY 리플렉션에 대한 매크로는 ON_NOTIFY_REFLECT.
ON_UPDATE_COMMAND_UI 리플렉션에 대한 매크로는 ON_UPDATE_COMMAND_UI_REFLECT라는 것입니다.
위의 각 특수 사례에서 처리기 멤버 함수의 이름을 지정해야 합니다. 다른 경우에는 처리기 함수에 표준 이름을 사용해야 합니다.
매개 변수의 의미와 함수의 반환 값은 함수 이름 또는 On 앞에 추가된 함수 이름 아래에 설명되어 있습니다. 예를 들어, CtlColor
가 OnCtlColor
에 문서화되어 있습니다. 여러 개의 반영된 메시지 처리기는 부모 창의 유사한 처리기보다 더 적은 매개 변수가 필요합니다. 아래 표의 이름과 설명서의 정식 매개 변수 이름과 일치하기만 하면됩니다.
지도 항목 | 함수 프로토타입 |
---|---|
ON_CONTROL_REFLECT(wNotifyCode ,memberFxn ) |
afx_msg voidmemberFxn ( ); |
ON_NOTIFY_REFLECT(wNotifyCode ,memberFxn ) |
afx_msg voidmemberFxn ( NMHDR*pNotifyStruct , LRESULT*result); |
ON_UPDATE_COMMAND_UI_REFLECT(memberFxn ) |
afx_msg voidmemberFxn ( CCmdUI*pCmdUI ); |
ON_WM_CTLCOLOR_REFLECT( ) |
afx_msg HBRUSH CtlColor(CDC*pDC ), UINTnCtlColor ); |
ON_WM_DRAWITEM_REFLECT( ) |
afx_msg void DrawItem(LPDRAWITEMSTRUCTlpDrawItemStruct ); |
ON_WM_MEASUREITEM_REFLECT( ) |
afx_msg void MeasureItem(LPMEASUREITEMSTRUCTlpMeasureItemStruct ); |
ON_WM_DELETEITEM_REFLECT( ) |
afx_msg void DeleteItem(LPDELETEITEMSTRUCTlpDeleteItemStruct ); |
ON_WM_COMPAREITEM_REFLECT( ) |
afx_msg int CompareItem(LPCOMPAREITEMSTRUCTlpCompareItemStruct ); |
ON_WM_CHARTOITEM_REFLECT( ) |
afx_msg int CharToItem (UINTnKey , UINTnIndex ); |
ON_WM_VKEYTOITEM_REFLECT( ) |
afx_msg int VKeyToItem(UINTnKey , UINTnIndex ); |
ON_WM_HSCROLL_REFLECT( ) |
afx_msg void HScroll (UINTnSBCode , UINTnPos ); |
ON_WM_VSCROLL_REFLECT( ) |
afx_msg void VScroll (UINTnSBCode , UINTnPos ); |
ON_WM_PARENTNOTIFY_REFLECT( ) |
afx_msg void ParentNotify(UINTmessage , LPARAMlParam ); |
ON_NOTIFY_REFLECT 및 ON_CONTROL_REFLECT 매크로에는 두 개 이상의 개체(예: 컨트롤 및 부모)가 지정된 메시지를 처리할 수 있는 변형이 있습니다.
지도 항목 | 함수 프로토타입 |
---|---|
ON_NOTIFY_REFLECT_EX(wNotifyCode ,memberFxn ) |
afx_msg BOOLmemberFxn ( NMHDR*pNotifyStruct , LRESULT*result); |
ON_CONTROL_REFLECT_EX(wNotifyCode ,memberFxn ) |
afx_msg BOOLmemberFxn ( ); |
반영된 메시지 처리: 재사용 가능한 컨트롤의 예
이 간단한 예제에서는 다시 사용할 수 있는 컨트롤을 CYellowEdit
만듭니다. 컨트롤은 노란색 배경에 검은색 텍스트를 표시한다는 점을 제외하고 일반 편집 컨트롤과 동일하게 작동합니다. 컨트롤이 다른 색을 표시할 수 있도록 하는 멤버 함수를 CYellowEdit
쉽게 추가할 수 있습니다.
재사용 가능한 컨트롤을 만드는 예제를 시도하려면
기존 애플리케이션에서 새 대화 상자를 만듭니다. 자세한 내용은 대화 편집 기 항목을 참조하세요.
재사용 가능한 컨트롤을 개발할 애플리케이션이 있어야 합니다. 사용할 기존 애플리케이션이 없는 경우 AppWizard를 사용하여 대화 상자 기반 애플리케이션을 만듭니다.
Visual C++에 프로젝트를 로드한 상태에서 ClassWizard를 사용하여
CYellowEdit
을(를) 기반으로 한 새 클래스CEdit
을(를) 만듭니다.클래스에 세 개의 멤버 변수를 추가합니다
CYellowEdit
. 처음 두 가지는 텍스트 색과 배경색을 보유하는 COLORREF 변수입니다. 세 번째는 배경을 칠할 브러시를 담고 있는CBrush
개체입니다. 개체CBrush
를 사용하면 브러시를 한 번 만들고, 그 후에만 참조하고, 컨트롤이 제거되면 브러시를CYellowEdit
자동으로 삭제할 수 있습니다.다음과 같이 생성자를 작성하여 멤버 변수를 초기화합니다.
CYellowEdit::CYellowEdit() { m_clrText = RGB(0, 0, 0); m_clrBkgnd = RGB(255, 255, 0); m_brBkgnd.CreateSolidBrush(m_clrBkgnd); }
ClassWizard를 사용하여 반영된 WM_CTLCOLOR 메시지에 대한 처리기를 클래스에 추가합니다
CYellowEdit
. 처리할 수 있는 메시지 목록의 메시지 이름 앞에 있는 등호는 메시지가 반영됨을 나타냅니다. 이는 반영된 메시지에 대한 메시지 처리기 정의에 설명되어 있습니다.ClassWizard는 다음과 같은 메시지 맵 매크로 및 기본 함수를 추가합니다.
ON_WM_CTLCOLOR_REFLECT() // Note: other code will be in between.... HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) { // TODO: Change any attributes of the DC here // TODO: Return a non-NULL brush if the // parent's handler should not be called return NULL; }
함수 본문을 다음 코드로 바꿉다. 이 코드는 컨트롤의 나머지 부분에 대한 텍스트 색, 텍스트 배경색 및 배경색을 지정합니다.
pDC->SetTextColor(m_clrText); // text pDC->SetBkColor(m_clrBkgnd); // text bkgnd return m_brBkgnd; // ctl bkgnd
대화 상자에서 편집 컨트롤을 만든 다음 컨트롤 키를 누른 상태에서 편집 컨트롤을 두 번 클릭하여 멤버 변수에 연결합니다. 멤버 변수 추가 대화 상자에서 변수 이름을 완료하고 범주에 대해 "Control"을 선택한 다음 변수 형식에 대해 "CYellowEdit"를 선택합니다. 대화 상자에서 탭 순서를 설정하는 것을 잊지 마세요. 또한 대화 상자의 헤더 파일에 컨트롤의
CYellowEdit
헤더 파일을 포함해야 합니다.애플리케이션을 빌드하고 실행합니다. 편집 컨트롤에는 노란색 배경이 있습니다.
참고하십시오
숫자로 된 기술 노트
범주별 기술 정보