리스트 박스는 컨트롤을 오버라이드 하지 않고 할만한게 없어서..
간단하게 Owner Draw Fixed를 이용하여 셀 높이 조절과 문자열에 여백넣는
샘플을 만들어 보았습니다.
우선 리스트 박스를 하나 올리고, 속성을 위와 같이 준다.
위의 그림은 셀의 높이를 20픽셀로 준것이고, 왼쪽에 여백을 5픽셀 준것이다.
이러한 기능을 구현하는것은 컨트롤의 내부를 건드리지 않고서는 사실상 불가능하지만
구현 자체가 그리 어려운것은 아니다.
우선 CListBox를 상속한 CCustomListBox 클래스를 하나 생성한다.
class CCustomListBox : public CListBox
{
// Construction
public:
CCustomListBox();
// Attributes
public:
COLORREF m_rgbText, m_rgbBack; // 글자색과 배경색
UINT m_nHeight; // 셀의 높이
CRect m_szMargin; // 글자의 마진
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCustomListBox)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CCustomListBox();
// 가상함수를 아래 처럼 추가한다.
// 요건 아이템을 로우 단위로 그려주는넘.
virtual void DrawItem(LPDRAWITEMSTRUCT pDIStruct);
// 요건 아이템의 높낮이를 조절하는 놈
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
// Generated message map functions
protected:
//{{AFX_MSG(CCustomListBox)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
아래의 코드들을 실제로 구현되는 내용들이다.
추가적인 코드가 들어가는 함수만을 추려서 설명을 넣는다.
[사실 이게 코드의 90%이다.]
// 생성자로 필요한 초기값을 넣는다.
CCustomListBox::CCustomListBox()
{
m_rgbText = RGB(255, 0, 0);
m_rgbBack = RGB(255, 255, 0);
m_nHeight = 20;
m_szMargin = CRect(5, 0, 0, 0);
}
// 아이템을 그려주는 가상함수이다.
// Owner Draw속성을 주면 사용자가 재정의한 함수를 자동으로 호출해준다.
void CCustomListBox::DrawItem(LPDRAWITEMSTRUCT pDIStruct)
{
CDC dc;
// 코드를 간결하게 하기 위하여 전달된 HDC를 CDC에 어태치한다.
if( !dc.Attach( pDIStruct -> hDC ) )
return;
// 현재 전달된 아이템이 선택되어진 넘인이 확인한다.
if( pDIStruct -> itemState & ODS_SELECTED )
{
// 속성에 맞게 글자색, 배경색상을 지정한다.
dc.SetTextColor((0x00FFFFFF & ~(GetSysColor(COLOR_WINDOWTEXT))));
dc.SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
dc.FillSolidRect(&pDIStruct->rcItem, GetSysColor(COLOR_HIGHLIGHT));
}
else
{
dc.SetTextColor(m_rgbText);
dc.SetBkColor(m_rgbBack);
dc.FillSolidRect(&pDIStruct->rcItem, m_rgbBack);
}
// 아이템의 인덱스가 -1이 아니면
if(pDIStruct->itemID != -1)
{
// 선택된 아이템의 문자열을 읽어온다.
CString m_SelText;
GetText(pDIStruct->itemID, m_SelText);
// 만약 선택된 아이템이 디저블 속성이면 글자 색상을 회색으로
if(pDIStruct->itemState & ODS_DISABLED)
dc.SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
// 배경은 투명 속성으로
dc.SetBkMode(TRANSPARENT);
// 글자를 그릴 영역의 여백을 조절한다..
CRect rcText = pDIStruct->rcItem;
rcText.left += m_szMargin.left;
rcText.top += m_szMargin.top;
rcText.right -= m_szMargin.right;
rcText.bottom -= m_szMargin.bottom;
dc.DrawText(m_SelText, rcText, DT_VCENTER | DT_SINGLELINE);
}
dc.Detach();
return;
}
// 아이템의 높이를 설정한다.
void CCustomListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
lpMeasureItemStruct->itemHeight = m_nHeight;
}
차츰 컨트롤을 다뤄가다 보면 나름대로 이것 저것 해볼 욕심이 생길때가 있는데..
이 때 컨트롤의 Owner Draw를 이용하면 대부분의 구현이 가능합니다..
유명한 코드그루나 코드프로젝트 같은 사이트의 샘플들도 대략 이런식으로 구현되어
클래스로 잘 꾸며놓았다가 필요할 때 쓰면 되는것이죠.