/*
* CMultilineList custom control
* Copyright (C) 2006 Dave Calkins (coder1024@gmail.com)
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
*/
#include "stdafx.h"
#include "MultilineList.h"
using namespace std;
// Win32 class name used for the window; if you're using the VS dialog editor you need
// to put this string in the Class property of the custom control
#define MULTILINELIST_CLASSNAME _T("CMultilineList")
// width of the internal borders used between cells/cols/rows
#define GRID_WIDTH 1
// spacing inside cells between the text and the cell borders
#define INNER_PADDING 2
// control IDs for child controls
#define CHILD_ID_HEADERCTRL 101
#define CHILD_ID_SCROLLBAR 102
#define CHILD_ID_SCROLLBARHORZ 103
// header control height is set to be the font height plus the below
#define HEADERCTRL_HEIGHT_EXTRA 6
// # pixels to scroll horizontally when using arrows
#define HORZSCROLL_PIXELS 25
IMPLEMENT_DYNAMIC(CMultilineList, CWnd)
BEGIN_MESSAGE_MAP(CMultilineList, CWnd)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_VSCROLL()
ON_WM_MOUSEWHEEL()
ON_WM_HSCROLL()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////////
// PUBLIC
////////////////////////////////////////////////////////////////////////////////
CMultilineList::CMultilineList()
: m_nCols(0),
m_nRows(0),
m_viewYPos(0),
m_viewXPos(0),
m_curSelRow(-1)
{
RegisterWindowClass();
}
CMultilineList::~CMultilineList()
{
}
BOOL CMultilineList::Create(CWnd* pParentWnd, const RECT& rect, UINT nID,
DWORD dwStyle /*=WS_VISIBLE*/)
{
return CWnd::Create(MULTILINELIST_CLASSNAME, _T(""), dwStyle, rect,
pParentWnd, nID);
}
void CMultilineList::SetSize(int nCols, int nRows)
{
ASSERT(nCols >= 0);
ASSERT(nRows >= 0);
// if no change, do nothing
if ((nCols == m_nCols) &&
(nRows == m_nRows))
{
return;
}
// if the # cols or # rows is being reduced
if ((nCols < m_nCols) ||
(nRows < m_nRows))
{
// walk through all cells
map<pair<int,int>,Cell>::iterator i;
for (i = m_cells.begin(); i != m_cells.end(); )
{
int col = i->first.first;
int row = i->first.second;
// remove any cells outside the new dimensions
if ((col >= nCols) ||
(row >= nRows))
{
i = m_cells.erase(i);
}
else
{
++i;
}
}
}
// if the # cols is being reduced
if (nCols < m_nCols)
{
// walk through all columns
map<int,Column>::iterator j;
for (j = m_columns.begin(); j != m_columns.end(); )
{
int col = j->first;
// remove any columns outside the new dimensions
if (col >= nCols)
{
j = m_columns.erase(j);
}
else
{
++j;
}
}
// invalidate all row heights
m_rowHeights.clear();
}
// if the # rows is being reduced but # cols is not being reduced
// (since if the # cols was reduced all row heights would have been
// invalidated anyway)
if ((nRows < m_nRows) &&
(nCols >= m_nCols))
{
// walk through the calculated row heights
map<int,int>::iterator k;
for (k = m_rowHeights.begin(); k != m_rowHeights.end(); )
{
int row = k->first;
// remove (invalidate) calculated row heights corresponding to rows which are outside the new dimensions
if (row >= nRows)
{
k = m_rowHeights.erase(k);
}
else
{
++k;
}
}
}
// store new size
m_nCols = nCols;
m_nRows = nRows;
// update
Invalidate(FALSE);
CalculateRowHeights();
UpdateChildControls();
}
void CMultilineList::GetSize(int & nCols, int & nRows)
{
// return current size of the list
nCols = m_nCols;
nRows = m_nRows;
}
void CMultilineList::SetColHeading(int col, LPCTSTR heading)
{
ASSERT(col >= 0);
ASSERT(col < m_nCols);
ASSERT(heading != NULL);
// use existing column object (if there is one) or a new one
Column column;
map<int,Column>::iterator i = m_columns.find(col);
if (i != m_columns.end())
{
column = i->second;
// abort if no change
if (column.m_heading == CString(heading))
return;
}
// set column heading
column.m_heading = heading;
// store the column object back in the map
m_columns[col] = column;
// update
Invalidate(FALSE);
UpdateChildControls();
}
void CMultilineList::SetColWidth(int col, int width)
{
ASSERT(col >= 0);
ASSERT(col < m_nCols);
ASSERT(width >= 0);
// use existing column object (if there is one) or use default
Column column;
map<int,Column>::iterator i = m_columns.find(col);
if (i != m_columns.end())
{
column = i->second;
// abort if no change
if (column.m_width == width)
return;
}
// set column width
column.m_width = width;
// store the column object back in the map
m_columns[col] = column;
// invalidate all row heights
m_rowHeights.clear();
// update
Invalidate(FALSE);
CalculateRowHeights();
UpdateChildControls();
}
void CMultilineList::SetCellText(int col, int row, LPCTSTR text)
{
ASSERT(col >= 0);
ASSERT(row >= 0);
ASSERT(col < m_nCols);
ASSERT(row < m_nRows);
ASSERT(text != NULL);
// use existing cell object (if there is one) or a new one
Cell cell;
pair<int,int> coord = make_pair(col,row);
map<pair<int,int>,Cell>::iterator i = m_cells.find(coord);
if (i != m_cells.end())
{
cell = i->second;
// abort if no change
if (cell.m_text == CString(text))
return;
}
// set cell text
cell.m_text = text;
// store the cell object back in the map
m_cells[coord] = cell;
// invalidate this row's height
m_rowHeights.erase(row);
// update
Invalidate(FALSE);
CalculateRowHeights();
UpdateChildControls();
}
CString CMultilineList::GetCellText(int col, int row)
{
ASSERT(col >= 0);
ASSERT(row >= 0);
ASSERT(col < m_nCols);
ASSERT(row < m_nRows);
CString result;
// use existing cell object (if there is one) or use default
Cell cell;
map<pair<int,int>,Cell>::iterator i = m_cells.find(make_pair(col,row));
if (i != m_cells.end())
{
cell = i->second;
}
// return the cell text
result = cell.m_text;
return result;
}
void CMultilineList::SetSelRow(int row)
{
ASSERT(row >= 0);
ASSERT(row < m_nRows);
// force selected row to the specified value
m_curSelRow = row;
// update
Invalidate(FALSE);
UpdateChildControls();
}
int CMultilineList::GetSelRow()
{
// return currently selected row
return m_curSelRow;
}
int CMultilineList::GetRowFromPoint
- 1
- 2
- 3
- 4
前往页