You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
431 lines
8.8 KiB
431 lines
8.8 KiB
//========= 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 <tier0/memdbgon.h> |
|
|
|
///////////////////////////////////////////////////////////////////////////// |
|
// 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; |
|
} |
|
}
|
|
|