Files
envi-code/SourceCode/Code2026/HvacCmd/HListCtrl.cpp
T
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

611 lines
17 KiB
C++

// Author: SFr frydaysoft@gmx.de
#include "stdafx.h"
#include "HListCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CHListCtrl::CHListCtrl(int colSize)
{
m_columnSize=colSize; // number of columns
m_fullColumnLines=TRUE; // paint vert. lines | | |
m_withSingleRect=FALSE; // paint single rect for all sub-items
#ifdef _DEBUG
m_BigFocusRect=TRUE; // focus-rect with small/big dots
#endif
#ifndef _DEBUG
m_BigFocusRect=FALSE; // focus-rect with small/big dots
#endif
IsCreated=FALSE;
}
//***************************************************************
CHListCtrl::~CHListCtrl()
{
}
//***************************************************************
BEGIN_MESSAGE_MAP(CHListCtrl, CListCtrl)
//{{AFX_MSG_MAP(CHListCtrl)
ON_WM_PAINT()
ON_WM_DESTROY()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Behandlungsroutinen f黵 Nachrichten CHListCtrl
void CHListCtrl::OnDestroy()
{
DeleteAllItems();
CListCtrl::OnDestroy();
}
//***************************************************************
void CHListCtrl::SetColumnType(BOOL bNew)
{
m_fullColumnLines=bNew; // paint no/vert. lines | | |
if (IsCreated)
{
RedrawWindow();
}
}
void CHListCtrl::SetRectType(BOOL bNew)
{
m_withSingleRect=bNew; // paint no/single rect for all sub-items
if (IsCreated)
{
RedrawWindow();
}
}
void CHListCtrl::SetFocusType(BOOL bNew)
{
m_BigFocusRect=bNew; // focus-rect with small/big dots
if (IsCreated)
{
RedrawWindow();
}
}
//***************************************************************
CMyLParam* CHListCtrl::GetMyLParam(int Index)
{
LVITEM Item;
Item.mask = LVIF_PARAM;
Item.iItem = Index;
Item.iSubItem = 0;
CListCtrl::GetItem(&Item);
return (CMyLParam*)Item.lParam;
}
//***************************************************************
CRect CHListCtrl::GetFullCellRect(int nItem, BOOL outside)
{
static CRect rectCell;
CListCtrl::GetItemRect(nItem, rectCell, LVIR_BOUNDS);
if (!outside)
{ //decrease 1 pixel
rectCell.left++; rectCell.right--;
rectCell.top++; rectCell.bottom--;
}
return rectCell;
}
//***************************************************************
CRect CHListCtrl::GetCellRect(int nItem, int nColumn, BOOL outside)
{
static CRect rectCell;
// Get the height
CListCtrl::GetItemRect(nItem, rectCell, LVIR_BOUNDS);
LV_COLUMN column;
column.mask = LVCF_WIDTH; // Set the mask to only return the width
for (int x=0; x<nColumn; x++)
{
column.iSubItem=1;
CListCtrl::GetColumn(x, &column); // Get rect-edge (left/top)
rectCell.left+=column.cx;
}
column.iSubItem=1;
CListCtrl::GetColumn(nColumn, &column); // Get rect-edge (right/bottom)
rectCell.right = rectCell.left + column.cx;
if (!outside)
{ //decrease 1 pixel
rectCell.left++; rectCell.right--;
rectCell.top++; rectCell.bottom--;
}
return rectCell;
}
//***************************************************************
void CHListCtrl::InvalidateFullItem(int nItem, BOOL bErase)
{
CRect rcBounds=GetFullCellRect(nItem, TRUE);
InvalidateRect(rcBounds, bErase);
}
//***************************************************************
// create ListCtrl-head
int CHListCtrl::InitCtrl(CStringArray *phead, CByteArray *pProcent)
{
if ( (!phead)||(!pProcent)) return 1;
LV_COLUMN lvc;
int cx=0;
INT_PTR count = phead->GetSize();
if (count!=m_columnSize) return 2;
if (pProcent->GetSize() != count) return 3;
for (int x=0; x<count; x++) cx+=pProcent->GetAt(x);
if (cx!=100) return 4;
CRect rect_listbox;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
GetWindowRect( rect_listbox );
cx=int((rect_listbox.right-rect_listbox.left)-20); //some Pixel for Scrollbar
//set head-columns in ListBox
lvc.iSubItem = 0;
lvc.fmt = LVCFMT_LEFT ;
for (x=0; x<count; x++)
{
lvc.cx = int(cx*pProcent->GetAt(x)/100);
lvc.pszText = (LPTSTR)(LPCTSTR)(phead->GetAt(x));
CListCtrl::InsertColumn(x,&lvc);
}
return 0;
}
//***************************************************************
// add an item
int CHListCtrl::AddItem(CStringArray *line, int pos)
{
int ret_index=LISTCTRL_ERROR;
if (!line) return ret_index;
LV_ITEM lvi;
//set List-properties
lvi.mask = LVIF_TEXT ;
lvi.iSubItem = 0;
lvi.pszText = const_cast<LPTSTR>(_T(""));
int count=GetItemCount();
INT_PTR columns=line->GetSize();
if (m_columnSize!=columns) return ret_index;
if (DWORD(pos)<=DWORD(count)) count=pos;
lvi.iItem = count;
//lvi.lParam= count;
lvi.mask = LVIF_TEXT ;
lvi.iSubItem = 0; //refer to no Item
// insert an new line
ret_index=InsertItem(&lvi);
// set item text for additional columns
for (int x=0; x<columns; x++)
{
CListCtrl::SetItemText(count,x,(LPCTSTR)(line->GetAt(x)) );
}
lvi.mask = LVIF_STATE;
lvi.iSubItem = 1;
lvi.stateMask = 0xFFFFFFFF ;
lvi.state = 0;
if (CListCtrl::SetItem(&lvi))
{
CMyLParam *p=new CMyLParam(m_columnSize); //init with: DEF_BACKGROUND, def_text
#ifdef TESTCOLOR
// only for TEST
if (ret_index<3)
{
p->SetBackColor(ITEM_COLOR(ret_index+BLUE),0);
p->SetTextColor(ITEM_COLOR(ret_index+RED ),0);
}
else
if (ret_index<=6)
{
p->SetBackColor(ITEM_COLOR(ret_index+BLUE),1);
p->SetTextColor(ITEM_COLOR(ret_index+RED ),1);
}
else
{
p->SetBackColor(ITEM_COLOR((ret_index+BLUE)&0xF),2);
p->SetTextColor(ITEM_COLOR((ret_index+RED )&0xF),2);
}
// end: only for TEST
#endif
CListCtrl::SetItemData( ret_index, DWORD_PTR(p) );
return ret_index;
}
return LISTCTRL_ERROR;
}
//***************************************************************
BOOL CHListCtrl::DeleteAllItems()
{
while (CListCtrl::GetItemCount())
CHListCtrl::DeleteItem(0);
return TRUE;
}
//***************************************************************
BOOL CHListCtrl::DeleteItem(int nItem )
{
if (CListCtrl::GetItemCount()<=nItem) return FALSE;
CMyLParam *p=(CMyLParam*)CListCtrl::GetItemData(nItem);
if (p)
{
CListCtrl::SetItemData( nItem, p->GetData() );
delete p;
return CListCtrl::DeleteItem( nItem );
}
return TRUE;
}
//***************************************************************
DWORD CHListCtrl::GetItemData( int nItem ) const
{
CMyLParam *p=(CMyLParam*)CListCtrl::GetItemData(nItem);
if (p)
{
return p->GetData();
return TRUE;
}
return 0;
}
//***************************************************************
BOOL CHListCtrl::SetItemData( int nItem, DWORD dwData )
{
CMyLParam *p=(CMyLParam*)CListCtrl::GetItemData(nItem);
if (p)
{
p->SetData(dwData);
return TRUE;
}
return FALSE;
}
//***************************************************************
BOOL CHListCtrl::SetItemBackgndColor(ITEM_COLOR color, int Index, int iSub)
{
CMyLParam *p=GetMyLParam(Index);
if (!p) return FALSE;
if ( p->SetBackColor(color, iSub) )
{
RedrawItems( Index, Index );
return TRUE;
}
return FALSE;
}
//***************************************************************
BOOL CHListCtrl::SetItemTextColor(ITEM_COLOR color, int Index, int iSub)
{
CMyLParam *p=GetMyLParam(Index);
if (!p) return FALSE;
if ( p->SetTextColor(color, iSub) )
{
RedrawItems( Index, Index );
return TRUE;
}
return FALSE;
}
//***************************************************************
COLORREF CHListCtrl::GetItemBackgndColor(int Index, int iSub)
{
CMyLParam *p=GetMyLParam(Index);
if (!p) return 0;
return p->GetBackColor(iSub);
}
//***************************************************************
COLORREF CHListCtrl::GetItemTextColor(int Index, int iSub)
{
CMyLParam *p=GetMyLParam(Index);
if (!p) return 0;
return p->GetTextColor(iSub);
}
//***************************************************************
void CHListCtrl::OnPaint()
{
// First let the control do its default drawing.
const MSG *msg = GetCurrentMessage();
DefWindowProc( msg->message, msg->wParam, msg->lParam );
if (!m_fullColumnLines) return;
// Draw the lines only for LVS_REPORT mode
if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
{
// Get the number of columns
CClientDC dc(this );
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
// The bottom of the header corresponds to the top of the line
RECT rect;
pHeader->GetClientRect( &rect );
int top = rect.bottom;
// Now get the client rect so we know the line length and
// when to stop
GetClientRect( &rect );
// The border of the column is offset by the horz scroll
int borderx = 0 - GetScrollPos( SB_HORZ );
CPen *pOldPen;
CPen pen;
CGdiObject *pOldBrush;
pen.CreatePen( PS_SOLID, 0, GetColorRef(DEF_DESELTEXT) );
pOldPen =dc.SelectObject(&pen);
pOldBrush=dc.SelectStockObject(NULL_BRUSH);
for( int i = 0; i < nColumnCount; i++ )
{
// Get the next border
borderx += GetColumnWidth( i );
// if next border is outside client area, break out
if( borderx >= rect.right ) break;
// Draw the line.
dc.MoveTo( borderx-1, top);
dc.LineTo( borderx-1, rect.bottom );
}
dc.SelectObject(pOldPen);
dc.SelectObject(pOldBrush);
}
// Do not call CListCtrl::OnPaint() for painting messages
}
//***************************************************************
void CHListCtrl::RepaintSelectedItems()
{
// Invalidate focused item so it can repaint
int nItem = GetNextItem(-1, LVNI_FOCUSED);
if(nItem != -1)
{
InvalidateFullItem(nItem, FALSE);
}
// Invalidate selected items depending on LVS_SHOWSELALWAYS
if((GetStyle() & LVS_SHOWSELALWAYS))
{
for(nItem = GetNextItem(-1, LVNI_SELECTED);
nItem != -1; nItem = GetNextItem(nItem, LVNI_SELECTED))
{
InvalidateFullItem(nItem, FALSE);
}
}
UpdateWindow();
}
//***************************************************************
BOOL CHListCtrl::SetSel(int pos, BOOL bSelect)
{
// LVS_ES_FULLROWSELECT only works with newer version of Comctl32
// This style and some of the other new extended styles
// only work with version 4.72 (or higer) of COMCTL32.DLL
UINT nState=0;
if (bSelect) nState=LVIS_SELECTED|LVS_EX_FULLROWSELECT; else nState=0;
if (SetItemState(pos, nState, LVIS_SELECTED|LVS_EX_FULLROWSELECT))
{
if((GetStyle() & LVS_SHOWSELALWAYS))
{
InvalidateFullItem(pos, TRUE);
}
return TRUE;
}
return FALSE;
}
//***************************************************************
void CHListCtrl::OnKillFocus(CWnd* pNewWnd)
{
SendMessage(WM_PAINT);
CListCtrl::OnKillFocus(pNewWnd);
// check if we are losing focus
if(pNewWnd != NULL && pNewWnd->GetParent() == this)
return;
// repaint items that should change appearance
if((GetStyle() & LVS_TYPEMASK) == LVS_REPORT)
RepaintSelectedItems();
}
//***************************************************************
void CHListCtrl::OnSetFocus(CWnd* pOldWnd)
{
CListCtrl::OnSetFocus(pOldWnd);
// check if we are getting focus
if(pOldWnd!=NULL && pOldWnd->GetParent()==this)
return;
// repaint items that should change appearance
if((GetStyle() & LVS_TYPEMASK)==LVS_REPORT)
RepaintSelectedItems();
}
//***************************************************************
void CHListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (!lpDrawItemStruct) return;
IsCreated=TRUE;
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CMyLParam* pMyLParam = GetMyLParam(lpDrawItemStruct->itemID);
CRect rcItem;
if (!pMyLParam) return;
int x=0;
typedef enum {R_NOTHINGS=0, R_FOCUS, R_SELECT, R_NORMAL, R_SEL_NOFOCUS} redrawmode;
redrawmode redraw=R_NORMAL;
// Get item image and state info
LV_ITEM lvi;
lvi.mask = LVIF_IMAGE | LVIF_STATE;
lvi.iItem = lpDrawItemStruct->itemID;
lvi.iSubItem = 0;
lvi.stateMask = 0xFFFF; // get all state flags
GetItem(&lvi);
BOOL bHighlight = ( (lvi.state & LVIS_DROPHILITED)
||
(
(lvi.state & LVIS_SELECTED)
&&
( ( GetFocus() == this ) || ( GetStyle() & LVS_SHOWSELALWAYS ) )
)
);
BOOL bLostFocus=(GetFocus()!=this);
if ( (lpDrawItemStruct->itemAction&ODA_FOCUS)==ODA_FOCUS)
{ //the control gains or loses input focus
if (bLostFocus) redraw=R_SEL_NOFOCUS;
else
if ((lvi.state&LVIS_FOCUSED)==LVIS_FOCUSED) redraw=R_FOCUS;
else
{
if (bHighlight) redraw=R_SELECT;
else redraw=R_NORMAL;
}
}
else
if ((lpDrawItemStruct->itemAction&ODA_SELECT)==ODA_SELECT)
{ //the selection status has changed
if (bHighlight)
{
if (bLostFocus) redraw=R_SEL_NOFOCUS;
else redraw=R_SELECT;
}
else redraw=R_NORMAL;
}
else
{ //redraw the item
if (bLostFocus)
{
if (bHighlight) redraw=R_SEL_NOFOCUS;
else
redraw=R_NORMAL;
}
else
{
if ((lvi.state&LVIS_FOCUSED)==LVIS_FOCUSED) redraw=R_FOCUS;
else
{
if (bHighlight) redraw=R_SELECT;
else redraw=R_NORMAL;
}
}
}
CPen *pOldPen;
CPen pen;
CGdiObject *pOldBrush;
switch(redraw)
{
case R_FOCUS:
rcItem=GetFullCellRect(lpDrawItemStruct->itemID, TRUE);
pDC->FillSolidRect(rcItem, GetColorRef(DEF_SELBACKGROUND));
pDC->SetTextColor(GetColorRef(DEF_SELTEXT));
if (m_BigFocusRect)
{
pen.CreatePen( PS_SOLID, 0, GetColorRef(DEF_SELTEXT) );
pOldPen =pDC->SelectObject(&pen);
pOldBrush=pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(rcItem);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
else pDC->DrawFocusRect(rcItem);
for (x=0; x<m_columnSize; x++)
{
rcItem = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);
pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER );
}
break;
case R_SELECT:
rcItem=GetFullCellRect(lpDrawItemStruct->itemID, TRUE);
pDC->FillSolidRect(rcItem, GetColorRef(DEF_SELBACKGROUND));
pDC->SetTextColor(GetColorRef(DEF_SELTEXT));
for (x=0; x<m_columnSize; x++)
{
rcItem = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);
pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
}
break;
case R_SEL_NOFOCUS:
rcItem=GetFullCellRect(lpDrawItemStruct->itemID, TRUE);
pDC->FillSolidRect(rcItem, GetColorRef(DEF_DESELBACKGROUND));
pDC->SetTextColor(pMyLParam->GetTextColor(DEF_DESELTEXT));
pen.CreatePen( PS_SOLID, 0, GetColorRef(DEF_DESELBACKGROUND) );
pOldPen =pDC->SelectObject(&pen);
pOldBrush=pDC->SelectStockObject(NULL_BRUSH);
if (!m_withSingleRect)
pDC->Rectangle(rcItem);
for (x=0; x<m_columnSize; x++)
{
rcItem = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);
pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
}
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
break;
case R_NORMAL:
for (x=0; x<m_columnSize; x++)
{
rcItem = GetCellRect(lpDrawItemStruct->itemID, x, TRUE);
pDC->FillSolidRect(rcItem, pMyLParam->GetBackColor(x));
pDC->SetTextColor(pMyLParam->GetTextColor(x));
if (m_withSingleRect)
{
pOldBrush=pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(rcItem);
pDC->SelectObject(pOldBrush);
}
rcItem = GetCellRect(lpDrawItemStruct->itemID, x, FALSE);
pDC->DrawText(CListCtrl::GetItemText(lpDrawItemStruct->itemID,x), rcItem, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
}
break;
}
return;
}
void CHListCtrl::OnSize(UINT nType, int cx, int cy)
{
CListCtrl::OnSize(nType, cx, cy);
if (IsCreated)
{
RedrawWindow();
}
}