mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
31b63bb79f
Generated using script: for file in \$(find ./legacy -type f | \grep -E "\.cpp|\.h") do mv $file temp.xxx cp gplheader $file cat temp.xxx >> $file done
473 lines
11 KiB
C++
473 lines
11 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
// ListVwEx.cpp : implementation of the CListViewEx class
|
|
//
|
|
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1997 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
#include "ListVwEx.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CListViewEx
|
|
|
|
IMPLEMENT_DYNCREATE(CListViewEx, CListView)
|
|
|
|
BEGIN_MESSAGE_MAP(CListViewEx, CListView)
|
|
//{{AFX_MSG_MAP(CListViewEx)
|
|
ON_WM_SIZE()
|
|
ON_WM_PAINT()
|
|
ON_WM_SETFOCUS()
|
|
ON_WM_KILLFOCUS()
|
|
//}}AFX_MSG_MAP
|
|
ON_MESSAGE(LVM_SETIMAGELIST, OnSetImageList)
|
|
ON_MESSAGE(LVM_SETTEXTCOLOR, OnSetTextColor)
|
|
ON_MESSAGE(LVM_SETTEXTBKCOLOR, OnSetTextBkColor)
|
|
ON_MESSAGE(LVM_SETBKCOLOR, OnSetBkColor)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CListViewEx construction/destruction
|
|
|
|
CListViewEx::CListViewEx()
|
|
{
|
|
m_bFullRowSel = TRUE;
|
|
m_bClientWidthSel = TRUE;
|
|
|
|
m_cxClient = 0;
|
|
m_cxStateImageOffset = 0;
|
|
|
|
m_clrText = ::GetSysColor(COLOR_WINDOWTEXT);
|
|
m_clrTextBk = ::GetSysColor(COLOR_WINDOW);
|
|
m_clrBkgnd = ::GetSysColor(COLOR_WINDOW);
|
|
}
|
|
|
|
CListViewEx::~CListViewEx()
|
|
{
|
|
}
|
|
|
|
BOOL CListViewEx::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
// default is report view and full row selection
|
|
cs.style &= ~LVS_TYPEMASK;
|
|
cs.style |= LVS_REPORT | LVS_OWNERDRAWFIXED;
|
|
m_bFullRowSel = TRUE;
|
|
|
|
return(CListView::PreCreateWindow(cs));
|
|
}
|
|
|
|
BOOL CListViewEx::SetFullRowSel(BOOL bFullRowSel)
|
|
{
|
|
// no painting during change
|
|
LockWindowUpdate();
|
|
|
|
m_bFullRowSel = bFullRowSel;
|
|
|
|
BOOL bRet;
|
|
|
|
if (m_bFullRowSel)
|
|
bRet = ModifyStyle(0L, LVS_OWNERDRAWFIXED);
|
|
else
|
|
bRet = ModifyStyle(LVS_OWNERDRAWFIXED, 0L);
|
|
|
|
// repaint window if we are not changing view type
|
|
if (bRet && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
|
|
Invalidate();
|
|
|
|
// repaint changes
|
|
UnlockWindowUpdate();
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
BOOL CListViewEx::GetFullRowSel()
|
|
{
|
|
return(m_bFullRowSel);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CListViewEx drawing
|
|
|
|
// offsets for first and other columns
|
|
#define OFFSET_FIRST 2
|
|
#define OFFSET_OTHER 6
|
|
|
|
void CListViewEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
CListCtrl& ListCtrl=GetListCtrl();
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
|
CRect rcItem(lpDrawItemStruct->rcItem);
|
|
UINT uiFlags = ILD_TRANSPARENT;
|
|
CImageList* pImageList;
|
|
int nItem = lpDrawItemStruct->itemID;
|
|
BOOL bFocus = (GetFocus() == this);
|
|
COLORREF clrTextSave, clrBkSave;
|
|
COLORREF clrImage = m_clrBkgnd;
|
|
static _TCHAR szBuff[MAX_PATH];
|
|
LPCTSTR pszText;
|
|
|
|
// get item data
|
|
|
|
LV_ITEM lvi;
|
|
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
|
|
lvi.iItem = nItem;
|
|
lvi.iSubItem = 0;
|
|
lvi.pszText = szBuff;
|
|
lvi.cchTextMax = sizeof(szBuff);
|
|
lvi.stateMask = 0xFFFF; // get all state flags
|
|
ListCtrl.GetItem(&lvi);
|
|
|
|
BOOL bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
|
|
bSelected = bSelected || (lvi.state & LVIS_DROPHILITED);
|
|
|
|
// set colors if item is selected
|
|
|
|
CRect rcAllLabels;
|
|
ListCtrl.GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);
|
|
|
|
CRect rcLabel;
|
|
ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);
|
|
|
|
rcAllLabels.left = rcLabel.left;
|
|
if (m_bClientWidthSel && rcAllLabels.right<m_cxClient)
|
|
rcAllLabels.right = m_cxClient;
|
|
|
|
if (bSelected)
|
|
{
|
|
clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
|
|
|
|
pDC->FillRect(rcAllLabels, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
|
|
}
|
|
else
|
|
pDC->FillRect(rcAllLabels, &CBrush(m_clrTextBk));
|
|
|
|
// set color and mask for the icon
|
|
|
|
if (lvi.state & LVIS_CUT)
|
|
{
|
|
clrImage = m_clrBkgnd;
|
|
uiFlags |= ILD_BLEND50;
|
|
}
|
|
else if (bSelected)
|
|
{
|
|
clrImage = ::GetSysColor(COLOR_HIGHLIGHT);
|
|
uiFlags |= ILD_BLEND50;
|
|
}
|
|
|
|
// draw state icon
|
|
|
|
UINT nStateImageMask = lvi.state & LVIS_STATEIMAGEMASK;
|
|
if (nStateImageMask)
|
|
{
|
|
int nImage = (nStateImageMask>>12) - 1;
|
|
pImageList = ListCtrl.GetImageList(LVSIL_STATE);
|
|
if (pImageList)
|
|
{
|
|
pImageList->Draw(pDC, nImage,
|
|
CPoint(rcItem.left, rcItem.top), ILD_TRANSPARENT);
|
|
}
|
|
}
|
|
|
|
// draw normal and overlay icon
|
|
|
|
CRect rcIcon;
|
|
ListCtrl.GetItemRect(nItem, rcIcon, LVIR_ICON);
|
|
|
|
pImageList = ListCtrl.GetImageList(LVSIL_SMALL);
|
|
if (pImageList)
|
|
{
|
|
UINT nOvlImageMask=lvi.state & LVIS_OVERLAYMASK;
|
|
if (rcItem.left<rcItem.right-1)
|
|
{
|
|
ImageList_DrawEx(pImageList->m_hImageList, lvi.iImage,
|
|
pDC->m_hDC,rcIcon.left,rcIcon.top, 16, 16,
|
|
m_clrBkgnd, clrImage, uiFlags | nOvlImageMask);
|
|
}
|
|
}
|
|
|
|
// draw item label
|
|
|
|
ListCtrl.GetItemRect(nItem, rcItem, LVIR_LABEL);
|
|
rcItem.right -= m_cxStateImageOffset;
|
|
|
|
pszText = MakeShortString(pDC, szBuff,
|
|
rcItem.right-rcItem.left, 2*OFFSET_FIRST);
|
|
|
|
rcLabel = rcItem;
|
|
rcLabel.left += OFFSET_FIRST;
|
|
rcLabel.right -= OFFSET_FIRST;
|
|
|
|
pDC->DrawText(pszText,-1,rcLabel,DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
|
|
|
|
// draw labels for extra columns
|
|
|
|
LV_COLUMN lvc;
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH;
|
|
|
|
for(int nColumn = 1; ListCtrl.GetColumn(nColumn, &lvc); nColumn++)
|
|
{
|
|
rcItem.left = rcItem.right;
|
|
rcItem.right += lvc.cx;
|
|
|
|
int nRetLen = ListCtrl.GetItemText(nItem, nColumn,
|
|
szBuff, sizeof(szBuff));
|
|
if (nRetLen == 0)
|
|
continue;
|
|
|
|
pszText = MakeShortString(pDC, szBuff,
|
|
rcItem.right - rcItem.left, 2*OFFSET_OTHER);
|
|
|
|
UINT nJustify = DT_LEFT;
|
|
|
|
if(pszText == szBuff)
|
|
{
|
|
switch(lvc.fmt & LVCFMT_JUSTIFYMASK)
|
|
{
|
|
case LVCFMT_RIGHT:
|
|
nJustify = DT_RIGHT;
|
|
break;
|
|
case LVCFMT_CENTER:
|
|
nJustify = DT_CENTER;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
rcLabel = rcItem;
|
|
rcLabel.left += OFFSET_OTHER;
|
|
rcLabel.right -= OFFSET_OTHER;
|
|
|
|
pDC->DrawText(pszText, -1, rcLabel,
|
|
nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
|
|
}
|
|
|
|
// draw focus rectangle if item has focus
|
|
|
|
if (lvi.state & LVIS_FOCUSED && bFocus)
|
|
pDC->DrawFocusRect(rcAllLabels);
|
|
|
|
// set original colors if item was selected
|
|
|
|
if (bSelected)
|
|
{
|
|
pDC->SetTextColor(clrTextSave);
|
|
pDC->SetBkColor(clrBkSave);
|
|
}
|
|
}
|
|
|
|
LPCTSTR CListViewEx::MakeShortString(CDC* pDC, LPCTSTR lpszLong, int nColumnLen, int nOffset)
|
|
{
|
|
static const _TCHAR szThreeDots[] = _T("...");
|
|
|
|
int nStringLen = lstrlen(lpszLong);
|
|
|
|
if(nStringLen == 0 ||
|
|
(pDC->GetTextExtent(lpszLong, nStringLen).cx + nOffset) <= nColumnLen)
|
|
{
|
|
return(lpszLong);
|
|
}
|
|
|
|
static _TCHAR szShort[MAX_PATH];
|
|
|
|
lstrcpy(szShort,lpszLong);
|
|
int nAddLen = pDC->GetTextExtent(szThreeDots,sizeof(szThreeDots)).cx;
|
|
|
|
for(int i = nStringLen-1; i > 0; i--)
|
|
{
|
|
szShort[i] = 0;
|
|
if((pDC->GetTextExtent(szShort, i).cx + nOffset + nAddLen)
|
|
<= nColumnLen)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
lstrcat(szShort, szThreeDots);
|
|
return(szShort);
|
|
}
|
|
|
|
void CListViewEx::RepaintSelectedItems()
|
|
{
|
|
CListCtrl& ListCtrl = GetListCtrl();
|
|
CRect rcItem, rcLabel;
|
|
|
|
// invalidate focused item so it can repaint properly
|
|
|
|
int nItem = ListCtrl.GetNextItem(-1, LVNI_FOCUSED);
|
|
|
|
if(nItem != -1)
|
|
{
|
|
ListCtrl.GetItemRect(nItem, rcItem, LVIR_BOUNDS);
|
|
ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);
|
|
rcItem.left = rcLabel.left;
|
|
|
|
InvalidateRect(rcItem, FALSE);
|
|
}
|
|
|
|
// if selected items should not be preserved, invalidate them
|
|
|
|
if(!(GetStyle() & LVS_SHOWSELALWAYS))
|
|
{
|
|
for(nItem = ListCtrl.GetNextItem(-1, LVNI_SELECTED);
|
|
nItem != -1; nItem = ListCtrl.GetNextItem(nItem, LVNI_SELECTED))
|
|
{
|
|
ListCtrl.GetItemRect(nItem, rcItem, LVIR_BOUNDS);
|
|
ListCtrl.GetItemRect(nItem, rcLabel, LVIR_LABEL);
|
|
rcItem.left = rcLabel.left;
|
|
|
|
InvalidateRect(rcItem, FALSE);
|
|
}
|
|
}
|
|
|
|
// update changes
|
|
|
|
UpdateWindow();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CListViewEx diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
|
|
void CListViewEx::Dump(CDumpContext& dc) const
|
|
{
|
|
CListView::Dump(dc);
|
|
|
|
dc << "m_bFullRowSel = " << (UINT)m_bFullRowSel;
|
|
dc << "\n";
|
|
dc << "m_cxStateImageOffset = " << m_cxStateImageOffset;
|
|
dc << "\n";
|
|
}
|
|
|
|
#endif //_DEBUG
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CListViewEx message handlers
|
|
|
|
LRESULT CListViewEx::OnSetImageList(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if( (int) wParam == LVSIL_STATE)
|
|
{
|
|
int cx, cy;
|
|
|
|
if(::ImageList_GetIconSize((HIMAGELIST)lParam, &cx, &cy))
|
|
m_cxStateImageOffset = cx;
|
|
else
|
|
m_cxStateImageOffset = 0;
|
|
}
|
|
|
|
return(Default());
|
|
}
|
|
|
|
LRESULT CListViewEx::OnSetTextColor(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_clrText = (COLORREF)lParam;
|
|
return(Default());
|
|
}
|
|
|
|
LRESULT CListViewEx::OnSetTextBkColor(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_clrTextBk = (COLORREF)lParam;
|
|
return(Default());
|
|
}
|
|
|
|
LRESULT CListViewEx::OnSetBkColor(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
m_clrBkgnd = (COLORREF)lParam;
|
|
return(Default());
|
|
}
|
|
|
|
void CListViewEx::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
m_cxClient = cx;
|
|
CListView::OnSize(nType, cx, cy);
|
|
}
|
|
|
|
void CListViewEx::OnPaint()
|
|
{
|
|
// in full row select mode, we need to extend the clipping region
|
|
// so we can paint a selection all the way to the right
|
|
if (m_bClientWidthSel &&
|
|
(GetStyle() & LVS_TYPEMASK) == LVS_REPORT &&
|
|
GetFullRowSel())
|
|
{
|
|
CRect rcAllLabels;
|
|
GetListCtrl().GetItemRect(0, rcAllLabels, LVIR_BOUNDS);
|
|
|
|
if(rcAllLabels.right < m_cxClient)
|
|
{
|
|
// need to call BeginPaint (in CPaintDC c-tor)
|
|
// to get correct clipping rect
|
|
CPaintDC dc(this);
|
|
|
|
CRect rcClip;
|
|
dc.GetClipBox(rcClip);
|
|
|
|
rcClip.left = min(rcAllLabels.right-1, rcClip.left);
|
|
rcClip.right = m_cxClient;
|
|
|
|
InvalidateRect(rcClip, FALSE);
|
|
// EndPaint will be called in CPaintDC d-tor
|
|
}
|
|
}
|
|
|
|
CListView::OnPaint();
|
|
}
|
|
|
|
void CListViewEx::OnSetFocus(CWnd* pOldWnd)
|
|
{
|
|
CListView::OnSetFocus(pOldWnd);
|
|
|
|
// check if we are getting focus from label edit box
|
|
if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
|
|
return;
|
|
|
|
// repaint items that should change appearance
|
|
if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
|
|
RepaintSelectedItems();
|
|
}
|
|
|
|
void CListViewEx::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
CListView::OnKillFocus(pNewWnd);
|
|
|
|
// check if we are losing focus to label edit box
|
|
if(pNewWnd != NULL && pNewWnd->GetParent() == this)
|
|
return;
|
|
|
|
// repaint items that should change appearance
|
|
if(m_bFullRowSel && (GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
|
|
RepaintSelectedItems();
|
|
}
|