#include "stdafx.h"
#include "testcbx.h"
#include "WzComboBox.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CWzComboBox::CWzComboBox()
{
m_crBkGnd = ::GetSysColor(COLOR_WINDOW);
m_crHiLightBkGnd = ::GetSysColor(COLOR_HIGHLIGHT);
m_crText = ::GetSysColor(COLOR_WINDOWTEXT);
m_crHiLightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_crHiLightFrame = RGB(0,0,0);
VERIFY(m_ImgList.Create(16,16,ILC_COLOR8|ILC_MASK,2,1));
}
CWzComboBox::~CWzComboBox()
{
if(m_ImgList.GetSafeHandle() != NULL)
m_ImgList.DeleteImageList();
}
BEGIN_MESSAGE_MAP(CWzComboBox, CComboBox)
ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)
ON_WM_PAINT()
ON_WM_SYSCOLORCHANGE()
END_MESSAGE_MAP()
void CWzComboBox::OnDropdown()
{
RecalcDropWidth();
}
void CWzComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct != NULL);
ASSERT(lpDrawItemStruct->CtlType == ODT_COMBOBOX);
if(int(lpDrawItemStruct->itemID) < 0)
return;
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
if (!IsWindowEnabled())
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem,RGB(192,192,192));
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
DrawIconString(lpDrawItemStruct, FALSE);
return;
}
if ((lpDrawItemStruct->itemState & ODS_SELECTED) && (lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem,m_crBkGnd);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(m_crHiLightText);
DrawIconString(lpDrawItemStruct, TRUE);
}
if (!(lpDrawItemStruct->itemState & ODS_SELECTED) && (lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
{
pDC->FillSolidRect(&lpDrawItemStruct->rcItem,m_crBkGnd);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(m_crText);
DrawIconString(lpDrawItemStruct, FALSE);
}
}
void CWzComboBox::DrawIconString(LPDRAWITEMSTRUCT lpDIS, BOOL bselected)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
LPITEMDATA pData= (LPITEMDATA)GetItemData(lpDIS->itemID);
CRect rcText(lpDIS->rcItem);
rcText.right -= 1;
if (m_ImgList.GetImageCount() > 0)
{
POINT pt;
CRect rcIcon;
TRACE(_T("itemState = %d, itemAction = %d\n"),lpDIS->itemState,lpDIS->itemAction);
if((lpDIS->itemState & ODS_COMBOBOXEDIT) && lpDIS->itemAction == ODA_DRAWENTIRE)
rcIcon.left = rcText.left + 2;
else
rcIcon.left = rcText.left + pData->cLevel * 20;
rcIcon.top = rcText.top;
rcIcon.bottom = rcText.bottom;
rcIcon.right = rcIcon.left + 18;
pt.x = rcIcon.left + 2;
pt.y = rcIcon.top;
m_ImgList.Draw(pDC,pData->cType,pt,ILD_TRANSPARENT);
if(bselected)
{
rcIcon.InflateRect(0,0,1,0);
pDC->Draw3dRect(rcIcon,RGB(255,128,128),RGB(0,0,255));
}
rcText.left = rcIcon.right+2;
}
CString string = _T("");
if (lpDIS->itemID != -1)
GetLBText(lpDIS->itemID, string);
if(bselected)
{
pDC->FillSolidRect(&rcText,m_crHiLightBkGnd);
CPen penFrame(PS_SOLID, 1, m_crHiLightFrame);
CPen *pOP = pDC->SelectObject(&penFrame);
pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(&rcText);
pDC->SelectObject(pOP);
penFrame.DeleteObject();
}
rcText.DeflateRect(3,1,2,1);
pDC->DrawText(string, rcText, DT_SINGLELINE |DT_VCENTER );
}
void CWzComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
ASSERT(lpMeasureItemStruct->CtlType == ODT_COMBOBOX);
lpMeasureItemStruct->itemHeight = 18;
}
void CWzComboBox::DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
{
ASSERT(lpDeleteItemStruct->CtlType == ODT_COMBOBOX);
LPITEMDATA pData = (LPITEMDATA)GetItemData(lpDeleteItemStruct->itemID);
delete pData;
CComboBox::DeleteItem(lpDeleteItemStruct);
}
void CWzComboBox::PreSubclassWindow()
{
CComboBox::PreSubclassWindow();
::SendMessage(m_hWnd, CB_SETITEMHEIGHT, (WPARAM)-1, 16L);
}
int CWzComboBox::AddIcon(HICON hIcon)
{
ASSERT(hIcon != NULL);
return m_ImgList.Add(hIcon);
}
WORD CWzComboBox::AddCTString(WORD wParentIdx,BYTE cType,LPCTSTR lpszString)
{
int idx = -1;
if(wParentIdx == nRootIndex)
{
idx = CComboBox::AddString(lpszString);
LPITEMDATA pData = new ITEMDATA;
ASSERT(pData != NULL);
pData->cLevel = 0;
pData->cType = cType;
pData->wOriginIdx = (WORD)idx;
pData->wParantOriginIdx = wParentIdx;
SetItemData(idx,(DWORD)pData);
}
else
{
int ParentCurrentIdx = CurrentIdxFromOriginIdx((int)wParentIdx);
LPITEMDATA pParentData = (LPITEMDATA)GetItemData(ParentCurrentIdx);
int count = GetChildCount(pParentData->wOriginIdx);
int pos = wParentIdx + count + 1;
idx = CComboBox::InsertString(pos,lpszString);
LPITEMDATA pData = new ITEMDATA;
ASSERT(pData != NULL);
pData->cLevel = pParentData->cLevel + 1;
pData->cType = cType;
pData->wOriginIdx = (WORD)idx;
pData->wParantOriginIdx = pParentData->wOriginIdx;
SetItemData(idx,(DWORD)pData);
}
return (WORD)idx;
}
int CWzComboBox::DeleteCTString(int index)
{
LPITEMDATA pdata = (LPITEMDATA)GetItemData(index);
BOOL bFind = TRUE;
while(bFind)
{
bFind = FALSE;
int count = GetCount();
for(int i = index + 1; i < count; i++)
{
LPITEMDATA p = (LPITEMDATA)GetItemData(i);
if(p->cLevel > pdata->cLevel)
{
bFind = TRUE;
CComboBox::DeleteString(i);
break;
}
}
}
CComboBox::DeleteString(index);
return GetCount();
}
int CWzComboBox::GetChildCount(WORD wParentIdx)
{
LPITEMDATA pdata = (LPITEMDATA)GetItemData(wParentIdx);
int nTotalCount = GetCount();
int wChildCount = 0;
for(int i = wParentIdx+1; i < nTotalCount; i++)
{
LPITEMDATA p = (LPITEMDATA)GetItemData(i);
if(p->cLevel > pdata->cLevel)
wChildCount++;
else
break;
}
return wChildCount;
}
int CWzComboBox::CurrentIdxFromOriginIdx(int wOriginIdx)
{
int nRtn = -1;
int count = GetCount();
for(int i = 0; i < count; i++)
{
LPITEMDATA pData = (LPITEMDATA)GetItemData(i);
if(wOriginIdx == (int)pData->wOriginIdx)
{
nRtn = i;
break;
}
}
return nRtn;
}
void CWzComboBox::RecalcDropWidth()
{
int nNumEntries = GetCount();
int nWidth = 0;
CString str;
CDC *pDC = GetDC();
int nScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL);
for (int i = 0; i < nNumEntries; i++)
{
GetLBText(i, str);
LPITEMDATA pData = (LPITEMDATA)GetItemData(i);
int nLength = 20 + pData->cLevel * 8 + pDC->GetTextExtent(str).cx + nScrollWidth + 30;
nWidth = max(nWidth, nLength);
}
nWidth += pDC->GetTextExtent("0").cx;
ReleaseDC(pDC);
SetDroppedWidth(nWidth);
}
void CWzComboBox::DrawCombo(DWORD dwStyle, COLORREF clrTopLeft, COLORREF clrBottomRight)
{
CRect rcItem;
GetClientRect(&rcItem);
CDC* pDC = GetDC();
pDC->Draw3dRect(rcItem, clrTopLeft, clrBottomRight);
rcItem.DeflateRect(1,1);
if (!IsWindowEnabled())
{
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNHIGHLIGHT),::GetSysColor(COLOR_BTNHIGHLIGHT));
}
else
{
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNFACE),::GetSysColor(COLOR_BTNFACE));
}
rcItem.DeflateRect(1,1);
rcItem.left = rcItem.right-::GetSystemMetrics(SM_CXHTHUMB);
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNFACE),::GetSysColor(COLOR_BTNFACE));
rcItem.DeflateRect(1,1);
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNFACE),::GetSysColor(COLOR_BTNFACE));
if (!IsWindowEnabled())
{
return;
}
switch (dwStyle)
{
case FC_DRAWNORMAL:
rcItem.top -= 1;
rcItem.bottom += 1;
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNHIGHLIGHT),::GetSysColor(COLOR_BTNHIGHLIGHT));
rcItem.left -= 1;
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNHIGHLIGHT),::GetSysColor(COLOR_BTNHIGHLIGHT));
break;
case FC_DRAWRAISED:
rcItem.top -= 1;
rcItem.bottom += 1;
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNHIGHLIGHT),::GetSysColor(COLOR_BTNSHADOW));
break;
case FC_DRAWPRESSD:
rcItem.top -= 1;
rcItem.bottom += 1;
rcItem.OffsetRect(1,1);
pDC->Draw3dRect(rcItem, ::GetSysColor(COLOR_BTNSHADOW),::GetSysColor(COLOR_BTNHIGHLIGHT));
break;
}
ReleaseDC(pDC);
}
void CWzComboBox::OnPaint()
{
Default();
DrawCombo(FC_DRAWRAISED, ::GetSysColor(COLOR_BTNSHADOW),::GetSysColor(COLOR_BTNHIGHLIGHT));
}
void CWzComboBox::OnSysColorChange()
{
CComboBox::OnSysColorChange();
m_crBkGnd = ::GetSysColor(COLOR_WINDOW);
m_crHiLightBkGnd = ::GetSysColor(COLOR_HIGHLIGHT);
m_crText = ::GetSysColor(COLOR_WINDOWTEXT);
m_crHiLightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
}