//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// // ListBoxEx.cpp : implementation file // #include "stdafx.h" #include "hammer.h" #include "ListBoxEx.h" // memdbgon must be the last include file in a .cpp file!!! #include ///////////////////////////////////////////////////////////////////////////// // CListBoxEx CListBoxEx::CListBoxEx() { Items.SetSize(16); nItems = 0; iItemHeight = -1; dwStyle = 0; bControlActive = FALSE; bIgnoreChange = FALSE; } CListBoxEx::~CListBoxEx() { } BEGIN_MESSAGE_MAP(CListBoxEx, CListBox) //{{AFX_MSG_MAP(CListBoxEx) ON_WM_LBUTTONDOWN() ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelchange) ON_WM_LBUTTONUP() ON_WM_CHAR() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CListBoxEx message handlers void CListBoxEx::SetStyle(DWORD dwStyle_) { this->dwStyle = dwStyle_; } void CListBoxEx::AddItem(char *pszCaption, int iEditType, PVOID pData, int iRangeMin, int iRangeMax, const char * pszHelp) { LBEXTITEMSTRUCT lbis; memset(&lbis, 0, sizeof lbis); strcpy(lbis.szCaption, pszCaption); lbis.pszSaveCaption = pszCaption; lbis.iEditType = iEditType; switch(iEditType) { case lbeYesNo: case lbeOnOff: lbis.iDataType = lbdBool; lbis.iDataValue = PINT(pData)[0]; break; case lbeInteger: lbis.iDataType = lbdInteger; lbis.iDataValue = PINT(pData)[0]; break; case lbeTexture: case lbeString: lbis.iDataType = lbdString; strcpy(lbis.szDataString, LPCTSTR(pData)); break; case lbeChoices: lbis.iDataType = lbdString; lbis.pChoices = NULL; break; } lbis.pSaveTo = pData; lbis.iRangeMin = iRangeMin; lbis.iRangeMax = iRangeMax; lbis.pszHelp = pszHelp; Items[nItems++] = lbis; AddString(""); // trick windows! muahaha } void CListBoxEx::SetItemChoices(int iItem, CStringArray * pChoices, int iDefaultChoice) { LBEXTITEMSTRUCT& lbis = Items[iItem]; lbis.pChoices = pChoices; lbis.iDataValue = iDefaultChoice; V_strcpy_safe( lbis.szDataString, pChoices->GetAt( iDefaultChoice ) ); } void CListBoxEx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { if(iItemHeight == -1) { CDC *pDC = GetDC(); TEXTMETRIC tm; pDC->GetOutputTextMetrics(&tm); iItemHeight = tm.tmHeight + 4; CRect r; GetClientRect(r); iCaptionWidthPixels = r.Width() / 2; ReleaseDC(pDC); } lpMeasureItemStruct->itemHeight = iItemHeight; } void CListBoxEx::GetItemText(int iItem, char *pszText) { LBEXTITEMSTRUCT& lbis = Items[iItem]; switch(lbis.iDataType) { case lbdBool: if(lbis.iEditType == lbeYesNo) strcpy(pszText, lbis.iDataValue ? "Yes" : "No"); else strcpy(pszText, lbis.iDataValue ? "On" : "Off"); break; case lbdString: strcpy(pszText, lbis.szDataString); break; case lbdInteger: ltoa(lbis.iDataValue, pszText, 10); break; } } void CListBoxEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC dc; dc.Attach(lpDrawItemStruct->hDC); dc.SaveDC(); RECT& r = lpDrawItemStruct->rcItem; if(lpDrawItemStruct->itemID != -1 && (lpDrawItemStruct->itemAction == ODA_DRAWENTIRE || lpDrawItemStruct->itemAction == ODA_SELECT)) { LBEXTITEMSTRUCT& item = Items[lpDrawItemStruct->itemID]; dc.SetROP2(R2_COPYPEN); int iBackIndex = COLOR_WINDOW; int iForeIndex = COLOR_WINDOWTEXT; BOOL bDrawCaptionOnly = FALSE; if(lpDrawItemStruct->itemAction == ODA_SELECT && (lpDrawItemStruct->itemState & ODS_SELECTED)) { iBackIndex = COLOR_HIGHLIGHT; iForeIndex = COLOR_HIGHLIGHTTEXT; bDrawCaptionOnly = item.iDataType != lbdBool ? TRUE : FALSE; } // draw background CBrush brush; brush.CreateSolidBrush(GetSysColor(iBackIndex)); if(0)//!bDrawCaptionOnly) dc.FillRect(&r, &brush); else { CRect r2(&r); r2.right = iCaptionWidthPixels; dc.FillRect(r2, &brush); } // first, draw text dc.SetTextColor(GetSysColor(iForeIndex)); dc.SetBkColor(GetSysColor(iBackIndex)); dc.TextOut(r.left + 1, r.top+ 1, item.szCaption, strlen(item.szCaption)); if(!bDrawCaptionOnly) { // draw value .. char szText[128]; GetItemText(lpDrawItemStruct->itemID, szText); dc.TextOut(r.left + iCaptionWidthPixels + 1, r.top + 1, szText, strlen(szText)); } // draw border. CPen pen(PS_SOLID, 1, RGB(200, 200, 200)); dc.SelectObject(pen); dc.MoveTo(r.left, r.bottom-1); dc.LineTo(r.right, r.bottom-1); dc.MoveTo(r.left + iCaptionWidthPixels, r.top); dc.LineTo(r.left + iCaptionWidthPixels, r.bottom-1); } else if(lpDrawItemStruct->itemAction == ODA_FOCUS) { dc.DrawFocusRect(&r); } dc.RestoreDC(-1); } void CListBoxEx::OnLButtonDown(UINT nFlags, CPoint point) { BOOL bOutside; int iItem = ItemFromPoint(point, bOutside); LBEXTITEMSTRUCT& lbis = Items[iItem]; if(lbis.iDataType == lbdBool) { // toggle bool field lbis.iDataValue = !lbis.iDataValue; } CListBox::OnLButtonDown(nFlags, point); } int CListBoxEx::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct) { return 0; } void CListBoxEx::CreateEditControl() { if(IsWindow(EditCtrl.m_hWnd)) return; // create edit control int iItem = GetCurSel(); if(iItem == LB_ERR) return; LBEXTITEMSTRUCT& lbis = Items[iItem]; if(lbis.iEditType != lbeString && lbis.iEditType != lbeInteger && lbis.iEditType != lbeTexture) return; CRect r; GetItemRect(iItem, r); r.InflateRect(-1, -1); r.left += iCaptionWidthPixels; // create edit ctrl EditCtrl.Create(ES_LEFT | ES_LOWERCASE | WS_VISIBLE | WS_TABSTOP, r, this, IDC_EDITPARAMETER); // set font HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); if (hFont == NULL) hFont = (HFONT)GetStockObject(ANSI_VAR_FONT); EditCtrl.SendMessage(WM_SETFONT, (WPARAM)hFont); // set current text in edit ctrl char szBuf[128]; GetItemText(iItem, szBuf); EditCtrl.SetWindowText(szBuf); EditCtrl.SetForegroundWindow(); EditCtrl.SetSel(0, -1); bControlActive = TRUE; iControlItem = iItem; } void CListBoxEx::CreateComboControl() { if(IsWindow(ComboCtrl.m_hWnd)) return; // create edit control int iItem = GetCurSel(); if(iItem == LB_ERR) return; LBEXTITEMSTRUCT& lbis = Items[iItem]; if(lbis.iEditType != lbeChoices) return; CRect r; GetItemRect(iItem, r); r.left += iCaptionWidthPixels; r.bottom += 80; // create combo ctrl ComboCtrl.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST | WS_TABSTOP, r, this, IDC_EDITPARAMETER); // set font HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); if (hFont == NULL) hFont = (HFONT)GetStockObject(ANSI_VAR_FONT); ComboCtrl.SendMessage(WM_SETFONT, (WPARAM)hFont); // add strings to combo ctrl CStringArray * pChoices = lbis.pChoices; Assert(pChoices); for(int i = 0; i < pChoices->GetSize(); i++) ComboCtrl.AddString(pChoices->GetAt(i)); // set current selection in combo ctrl ComboCtrl.SetCurSel(lbis.iDataValue); ComboCtrl.SetForegroundWindow(); bControlActive = TRUE; iControlItem = iItem; } void CListBoxEx::DestroyControls() { // get rid of window if there is one if(::IsWindow(EditCtrl.m_hWnd)) { EditCtrl.DestroyWindow(); } if(::IsWindow(ComboCtrl.m_hWnd)) { ComboCtrl.DestroyWindow(); } bControlActive = FALSE; } void CListBoxEx::OnSelchange() { if(bControlActive) { // on combobox/edit controls, save string back to data LBEXTITEMSTRUCT& lbis = Items[iControlItem]; if(lbis.iEditType == lbeChoices) { ComboCtrl.GetLBText(ComboCtrl.GetCurSel(), lbis.szDataString); lbis.iDataValue = ComboCtrl.GetCurSel(); } else if(lbis.iDataType == lbdString) { EditCtrl.GetWindowText(lbis.szDataString, 128); } else if(lbis.iDataType == lbdInteger) { EditCtrl.GetWindowText(lbis.szDataString, 128); lbis.iDataValue = atoi(lbis.szDataString); } } DestroyControls(); int iCurItem = GetCurSel(); LBEXTITEMSTRUCT& lbis = Items[iCurItem]; if(lbis.iEditType == lbeChoices) { CreateComboControl(); } else { CreateEditControl(); } } void CListBoxEx::OnLButtonUp(UINT nFlags, CPoint point) { CListBox::OnLButtonUp(nFlags, point); int iItem = GetCurSel(); if(iItem == LB_ERR) return; LBEXTITEMSTRUCT& lbis = Items[iItem]; if(lbis.iDataType == lbdBool) { lbis.iDataValue = !lbis.iDataValue; Invalidate(); } } void CListBoxEx::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CListBox::OnChar(nChar, nRepCnt, nFlags); return; int iItem = GetCurSel(); if(iItem == LB_ERR) return; LBEXTITEMSTRUCT& lbis = Items[iItem]; switch(nChar) { case VK_RETURN: if(!(nFlags & 0x8000)) break; if(lbis.iDataType == lbdBool) { // toggle bool field lbis.iDataValue = !lbis.iDataValue; Invalidate(); } else if(lbis.iEditType == lbeChoices) { CreateComboControl(); } else if(lbis.iEditType == lbeString || lbis.iEditType == lbeInteger || lbis.iEditType == lbeTexture) { CreateEditControl(); } break; } }