1. msdn 참고
2. MFC의 Message Reflection 을 활용해서만든다.
In MFC 4.0, the old mechanism still works ? parent windows can handle notification messages. In addition, however, MFC 4.0 facilitates reuse by providing a feature called "message reflection" that allows these notification messages to be handled in either the child control window or the parent window, or in both.
3. 서브클리싱, 가상함수의 개념만 있다면 쉽게 이해 할 수 있다. 자식이 부모가 요청한 작업을 한다.
Windows controls frequently send notification messages to their parent windows. For instance, many controls send a control color notification message (WM_CTLCOLOR or one of its variants) to their parent to allow the parent to supply a brush for painting the background of the control.
예제 1. CEdit 클래스로 부터 상속받은 클래스로 에디트 박스의 배경색과 글자색을 정한다.
#include "afxwin.h"
class CColorEdit :public CEdit
{
public:
COLORREF m_clrText; // 글자색
COLORREF m_clrBkg; // 글자 배경색
CBrush m_hbrBkg; // 배경을 칠할 브러시
void SetColor( COLORREF clrText, COLORREF clrBkg)
{
m_clrText = clrText;
m_clrBkg = clrBkg;
if ( m_hbrBkg.m_hObject != 0 )
m_hbrBkg.DeleteObject();
m_hbrBkg.CreateSolidBrush( m_clrBkg);
}
// WM_CTLCOLOR
HBRUSH CtlColor(CDC* pDC, UINT /*nCtlColor*/)
{
// 이제 부모가 반사해준 메세지를 처리한다.
pDC->SetTextColor( m_clrText );
pDC->SetBkColor( m_clrBkg);
// 배경을 칠할 브러시를 리턴한다.
return (HBRUSH)m_hbrBkg.m_hObject;
}
};
예제 2. CListBox 로 상속받아은 클래스로 아이콘을 포함하는 리스트박스를 구현.
#include "afxwin.h"
struct LISTDATA
{
HICON hIcon;
CString text;
};
#include <vector>
using std::vector;
class CIconListBox : public CListBox
{
public:
vector<LISTDATA> m_vector;
void AddItem( HICON hIcon, CString text )
{
LISTDATA data = { hIcon, text };
m_vector.push_back( data );
// 일단 빈문자열로 채워 둔다.
int index = AddString("");
static int id = 0;
SetItemData( index, id );
}
void DrawItem(LPDRAWITEMSTRUCT p)
{
// 항목을 그린다.
HDC hdc = p->hDC;
CRect rc( p->rcItem );
// 이제 그린다. m_vector의 내용으로
int id = (int)p->itemID;
HICON hIcon = m_vector[id].hIcon;
CString text = m_vector[id].text;
DrawIcon( hdc, rc.left, rc.top, hIcon );
TextOut( hdc, rc.left + 35, rc.top, text, text.GetLength() );
}
void MeasureItem(LPMEASUREITEMSTRUCT p)
{
p->itemHeight = 32;
}
};
예제 3. CStatusBar 에 안에 다른 Control을 포함시키기.
1. WM_SIZE 에서 ProgressCtrl 의 위치를 꼭 정해주자.. 까먹으면 개고생-_-...
#include "afxext.h"
class CMyStatusBar : public CStatusBar
{
public:
// 프로그레스가 들어갈 pane의 ID
UINT m_index;
CProgressCtrl m_wndProgress;
void OnSize(UINT nType, int cx, int cy)
{
CStatusBar::OnSize(nType, cx, cy);
// 프로그레스바가 만들어 지면 실행하도록 조건을 건다.
if( m_wndProgress.GetSafeHwnd() )
{
CRect rc;
GetItemRect( m_index, &rc );
m_wndProgress.MoveWindow( rc );
}
}
void CreateProgress( UINT index, int width )
{
int w;
UINT id, style;
m_index = index;
// id pane 의 정보를 구한다.
GetPaneInfo( index, id, style, w );
// 이제 너비만 변경한다.
SetPaneInfo( index, id, style, width );
// 이제 해당 id pane의 정확한 크기를 구한다.
CRect rc(0, 0, 0, 0);
GetItemRect( index, &rc );
// 이제 프로그래스를 만든다.
m_wndProgress.Create( WS_CHILD | WS_VISIBLE | PBS_SMOOTH, rc,
this, 2001 );
m_wndProgress.SetRange( 0, 100 );
m_wndProgress.SetPos(55);
}