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.
955 lines
24 KiB
955 lines
24 KiB
/*++
|
|
|
|
© 1998 Seagate Software, Inc. All rights reserved
|
|
|
|
Module Name:
|
|
|
|
IeList.cpp
|
|
|
|
Abstract:
|
|
|
|
CIeList is a subclassed (owner-draw) list control that groups items into
|
|
a 3D panel that have the same information in the indicated
|
|
sortColumn.
|
|
|
|
The panels are created from tiles. Each tile corresponds to one subitem
|
|
in the list, and has the appropriate 3D edges so that the tiles together
|
|
make up a panel.
|
|
|
|
NOTE: The control must be initialized with the number of columns and the
|
|
sort column. The parent dialog must implement OnMeasureItem and call
|
|
GetItemHeight to set the row height for the control.
|
|
|
|
Author:
|
|
|
|
Art Bragg [artb] 01-DEC-1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "stdafx.h"
|
|
#include "IeList.h"
|
|
|
|
// Position of a tile in it's panel
|
|
#define POS_LEFT 100
|
|
#define POS_RIGHT 101
|
|
#define POS_TOP 102
|
|
#define POS_BOTTOM 103
|
|
#define POS_MIDDLE 104
|
|
#define POS_SINGLE 105
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CIeList
|
|
|
|
BEGIN_MESSAGE_MAP(CIeList, CListCtrl)
|
|
//{{AFX_MSG_MAP(CIeList)
|
|
ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
|
|
ON_WM_SETFOCUS()
|
|
ON_WM_KILLFOCUS()
|
|
//}}AFX_MSG_MAP
|
|
ON_WM_SYSCOLORCHANGE()
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
CIeList::CIeList()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets default dimensions for the control.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Initializations
|
|
//
|
|
m_ColCount = 0;
|
|
m_SortCol = 0;
|
|
m_pVertPos = NULL;
|
|
//
|
|
// Drawing dimensions
|
|
//
|
|
// If these are altered, the visual aspects of the control
|
|
// should be checked (especially the focus rectangle),
|
|
// as some minor adjustments may need to be made.
|
|
//
|
|
m_VertRaisedSpace = 1;
|
|
m_BorderThickness = 2;
|
|
m_VerticalTextOffsetTop = 1;
|
|
|
|
// The text height will be set later (based on the font size)
|
|
m_Textheight = 0;
|
|
m_VerticalTextOffsetBottom = 1;
|
|
|
|
// Total height will be set later
|
|
m_TotalHeight = 0;
|
|
m_HorzRaisedSpace = 1;
|
|
m_HorzTextOffset = 3;
|
|
|
|
}
|
|
|
|
CIeList::~CIeList()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleanup.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
// Cleanup the array of vertical positions
|
|
if( m_pVertPos ) free ( m_pVertPos );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CIeList message handlers
|
|
|
|
void CIeList::Initialize(
|
|
IN int colCount,
|
|
IN int sortCol
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the number of columns (not easily available from MFC) and
|
|
the sort column.
|
|
|
|
Arguments:
|
|
|
|
colCount - number of columns to display
|
|
sortCol - column to sort on
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
|
|
m_ColCount = colCount;
|
|
m_SortCol = sortCol;
|
|
}
|
|
|
|
void CIeList::DrawItem(
|
|
IN LPDRAWITEMSTRUCT lpDrawItemStruct
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the callback for an owner draw control.
|
|
Draws the appropriate text and/or 3D lines depending on the
|
|
item number and clipping rectangle supplied by MFC in lpDrawItemStruct
|
|
|
|
Arguments:
|
|
|
|
lpDrawItemStruct - MFC structure that tells us what and where to draw
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
CDC dc;
|
|
int saveDc;
|
|
|
|
int colWidth = 0; // Width of current column
|
|
int horzPos = POS_MIDDLE; // Horz position in the panel
|
|
int vertPos = POS_SINGLE; // Vert position in the panel
|
|
BOOL bSelected = FALSE; // Is this item selected
|
|
CRect rcAllLabels; // Used to find left position of focus rectangle
|
|
CRect itemRect; // Rectangle supplied in lpDrawItemStruct
|
|
CRect textRect; // Rectangle for text
|
|
CRect boxRect; // Rectangle for 3D box (the panel)
|
|
CRect clipRect; // Current clipping rectangle
|
|
LPTSTR pszText; // Text to display
|
|
COLORREF clrTextSave = 0; // Save the current color
|
|
COLORREF clrBkSave = 0; // Save the background color
|
|
int leftStart = 0; // Left edge of where we're currently drawing
|
|
BOOL bFocus = (GetFocus() == this); // Do we have focus?
|
|
|
|
//
|
|
// Get the current scroll position
|
|
//
|
|
int nHScrollPos = GetScrollPos( SB_HORZ );
|
|
|
|
//
|
|
// Get the item ID from the list for the item we're drawing
|
|
//
|
|
int itemID = lpDrawItemStruct->itemID;
|
|
|
|
//
|
|
// Get item data for the item we're drawing
|
|
//
|
|
LV_ITEM lvi;
|
|
lvi.mask = LVIF_IMAGE | LVIF_STATE;
|
|
lvi.iItem = itemID;
|
|
lvi.iSubItem = 0;
|
|
lvi.stateMask = 0xFFFF; // get all state flags
|
|
GetItem(&lvi);
|
|
|
|
//
|
|
// Determine focus and selected states
|
|
//
|
|
bSelected = (bFocus || (GetStyle() & LVS_SHOWSELALWAYS)) && lvi.state & LVIS_SELECTED;
|
|
|
|
//
|
|
// Get the rectangle to draw in
|
|
//
|
|
itemRect = lpDrawItemStruct->rcItem;
|
|
|
|
dc.Attach( lpDrawItemStruct->hDC );
|
|
saveDc = dc.SaveDC();
|
|
//
|
|
// Get the clipping rectangle - we use it's vertical edges
|
|
// to optimize what we draw
|
|
//
|
|
dc.GetClipBox( &clipRect );
|
|
boxRect = clipRect;
|
|
|
|
//
|
|
// For each column, paint it's text and the section of the 3D panel
|
|
//
|
|
for ( int col = 0; col < m_ColCount; col++ ) {
|
|
|
|
colWidth = GetColumnWidth( col );
|
|
//
|
|
// Only paint this column if it's in the clipping rectangle
|
|
//
|
|
if( ( ( leftStart + colWidth ) > clipRect.left ) || ( leftStart < clipRect.right ) ) {
|
|
|
|
//
|
|
// Determine the horizontal position based on the column
|
|
//
|
|
horzPos = POS_MIDDLE;
|
|
if( col == 0 ) horzPos = POS_LEFT;
|
|
if( col == m_ColCount - 1 ) horzPos = POS_RIGHT;
|
|
|
|
//
|
|
// Calculate the rectangle for this tile
|
|
//
|
|
boxRect.top = itemRect.top;
|
|
boxRect.bottom = itemRect.bottom;
|
|
boxRect.left = itemRect.left + leftStart;
|
|
boxRect.right = itemRect.left + leftStart + colWidth;
|
|
|
|
//
|
|
// Get the vertical position from the array. It was saved there
|
|
// during SortItem for performance reasons.
|
|
//
|
|
if( m_pVertPos ) {
|
|
|
|
vertPos = m_pVertPos[ itemID ];
|
|
|
|
}
|
|
|
|
//
|
|
// Draw the tile for this item.
|
|
//
|
|
Draw3dRectx ( &dc, boxRect, horzPos, vertPos, bSelected );
|
|
|
|
//
|
|
// If this item is selected, change the text colors
|
|
//
|
|
if( bSelected ) {
|
|
|
|
clrTextSave = dc.SetTextColor( m_clrHighlightText );
|
|
clrBkSave = dc.SetBkColor( m_clrHighlight );
|
|
|
|
}
|
|
|
|
//
|
|
// Calculate the text rectangle
|
|
//
|
|
textRect.top = itemRect.top + m_VertRaisedSpace + m_BorderThickness + m_VerticalTextOffsetTop;
|
|
textRect.bottom = itemRect.bottom; // Text is top justified, no need to adjust bottom
|
|
textRect.left = leftStart - nHScrollPos + m_HorzRaisedSpace + m_BorderThickness + m_HorzTextOffset;
|
|
textRect.right = itemRect.right;
|
|
|
|
//
|
|
// Get the text and put in the "..." if we need them
|
|
//
|
|
CString pszLongText = GetItemText( itemID, col );
|
|
pszText = NULL;
|
|
MakeShortString(&dc, (LPCTSTR) pszLongText,
|
|
textRect.right - textRect.left, 4, &pszText);
|
|
BOOL bFree = TRUE;
|
|
if (pszText == NULL) {
|
|
// Failure of some kind...
|
|
pszText = (LPTSTR)(LPCTSTR)pszLongText;
|
|
bFree = FALSE;
|
|
}
|
|
|
|
//
|
|
// Now draw the text using the correct color
|
|
//
|
|
COLORREF saveTextColor;
|
|
if( bSelected ) {
|
|
|
|
saveTextColor = dc.SetTextColor( m_clrHighlightText );
|
|
|
|
} else {
|
|
|
|
saveTextColor = dc.SetTextColor( m_clrText );
|
|
|
|
}
|
|
int textheight = dc.DrawText( pszText, textRect, DT_NOCLIP | DT_LEFT | DT_TOP | DT_SINGLELINE );
|
|
dc.SetTextColor( saveTextColor );
|
|
|
|
if (pszText && bFree) {
|
|
free(pszText);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Move to the next column
|
|
//
|
|
leftStart += colWidth;
|
|
}
|
|
//
|
|
// draw focus rectangle if item has focus. Use LVIR_BOUNDS rectangle
|
|
// to bound it.
|
|
//
|
|
GetItemRect(itemID, rcAllLabels, LVIR_BOUNDS);
|
|
if( lvi.state & LVIS_FOCUSED && bFocus ) {
|
|
|
|
CRect focusRect;
|
|
focusRect.left = rcAllLabels.left + m_HorzRaisedSpace + m_BorderThickness;
|
|
focusRect.right = min( rcAllLabels.right, (itemRect.right - m_HorzRaisedSpace * 2 - 3) );
|
|
focusRect.top = boxRect.top + m_VertRaisedSpace + m_BorderThickness;
|
|
focusRect.bottom = boxRect.top + m_TotalHeight - m_BorderThickness + 1;
|
|
|
|
dc.DrawFocusRect( focusRect );
|
|
|
|
}
|
|
|
|
// Restore colors
|
|
if( bSelected ) {
|
|
|
|
dc.SetTextColor( clrTextSave );
|
|
dc.SetBkColor( clrBkSave );
|
|
|
|
}
|
|
|
|
dc.RestoreDC( saveDc );
|
|
dc.Detach();
|
|
}
|
|
|
|
|
|
void CIeList::MakeShortString(
|
|
IN CDC* pDC,
|
|
IN LPCTSTR lpszLong,
|
|
IN int nColumnLen,
|
|
IN int nDotOffset,
|
|
OUT LPTSTR *ppszShort
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines it the supplied string fits in it's column. If not truncates
|
|
it and adds "...". From MS sample code.
|
|
|
|
Arguments:
|
|
|
|
pDC - Device context
|
|
lpszLong - Original String
|
|
nColumnLen - Width of column
|
|
nDotOffset - Space before dots
|
|
|
|
Return Value:
|
|
|
|
Shortened string
|
|
|
|
--*/
|
|
{
|
|
static const _TCHAR szThreeDots[] = _T("...");
|
|
|
|
int nStringLen = lstrlen(lpszLong);
|
|
|
|
*ppszShort = (_TCHAR *)malloc((nStringLen + 1) * sizeof(_TCHAR) + sizeof(szThreeDots));
|
|
if (*ppszShort == NULL)
|
|
return;
|
|
|
|
_TCHAR *szShort = *ppszShort;
|
|
if(nStringLen == 0) {
|
|
lstrcpy(szShort, _T(""));
|
|
} else {
|
|
lstrcpy(szShort, lpszLong);
|
|
}
|
|
|
|
if(nStringLen == 0 ||
|
|
(pDC->GetTextExtent(lpszLong, nStringLen).cx + nDotOffset) <= nColumnLen)
|
|
{
|
|
// return long format
|
|
return;
|
|
}
|
|
|
|
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 + nDotOffset + nAddLen)
|
|
<= nColumnLen)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
lstrcat(szShort, szThreeDots);
|
|
return;
|
|
}
|
|
|
|
void CIeList::Draw3dRectx (
|
|
IN CDC *pDc,
|
|
IN CRect &rect,
|
|
IN int horzPos,
|
|
IN int vertPos,
|
|
IN BOOL bSelected
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Draws the appropriate portion (tile) of a panel for a given cell in the
|
|
list. The edges of the panel portion are determined by the horzPos
|
|
and vertPos parameters.
|
|
|
|
Arguments:
|
|
|
|
pDc - Device context
|
|
rect - Rectangle to draw the panel portion in
|
|
horzPos - Where the portion is horizontally
|
|
vertPos - Where the portion is vertically
|
|
bSelected - Is the item selected
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
CPen *pSavePen;
|
|
int topOffset = 0;
|
|
int rightOffset = 0;
|
|
int leftOffset = 0;
|
|
|
|
//
|
|
// If a given edge of the tile is to be drawn, set an offset to that
|
|
// edge. If we don't draw a given edge, the offset is 0.
|
|
//
|
|
switch ( horzPos )
|
|
{
|
|
case POS_LEFT:
|
|
leftOffset = m_HorzRaisedSpace;
|
|
rightOffset = 0;
|
|
break;
|
|
case POS_MIDDLE:
|
|
leftOffset = 0;
|
|
rightOffset = 0;
|
|
break;
|
|
case POS_RIGHT:
|
|
leftOffset = 0;
|
|
rightOffset = m_HorzRaisedSpace + 3;
|
|
break;
|
|
}
|
|
|
|
switch ( vertPos )
|
|
{
|
|
|
|
case POS_TOP:
|
|
topOffset = m_VertRaisedSpace;
|
|
break;
|
|
case POS_MIDDLE:
|
|
topOffset = 0;
|
|
break;
|
|
case POS_BOTTOM:
|
|
topOffset = 0;
|
|
break;
|
|
case POS_SINGLE:
|
|
topOffset = m_VertRaisedSpace;
|
|
break;
|
|
|
|
}
|
|
//
|
|
// Erase
|
|
//
|
|
if( !bSelected ) pDc->FillSolidRect( rect, m_clrBkgnd );
|
|
//
|
|
// Highlight the selected area
|
|
//
|
|
if (bSelected)
|
|
{
|
|
CRect selectRect;
|
|
if (leftOffset == 0)
|
|
selectRect.left = rect.left;
|
|
else
|
|
selectRect.left = rect.left + leftOffset + m_BorderThickness;
|
|
if (rightOffset == 0)
|
|
selectRect.right = rect.right;
|
|
else
|
|
selectRect.right = rect.right - rightOffset - m_BorderThickness + 1;
|
|
selectRect.top = rect.top + m_VertRaisedSpace + m_BorderThickness;
|
|
selectRect.bottom = rect.top + m_TotalHeight - m_BorderThickness + 1;
|
|
|
|
pDc->FillSolidRect( selectRect, m_clrHighlight );
|
|
}
|
|
|
|
// Select a pen to save the original pen
|
|
pSavePen = pDc->SelectObject( &m_ShadowPen );
|
|
|
|
// left edge
|
|
if( horzPos == POS_LEFT ) {
|
|
// Outside lighter line
|
|
pDc->SelectObject( &m_ShadowPen );
|
|
pDc->MoveTo( rect.left + leftOffset, rect.top + topOffset );
|
|
pDc->LineTo( rect.left + leftOffset, rect.top + m_TotalHeight + 1);
|
|
// Inside edge - darker line
|
|
pDc->SelectObject( &m_DarkShadowPen );
|
|
pDc->MoveTo( rect.left + leftOffset + 1, rect.top + topOffset);
|
|
pDc->LineTo( rect.left + leftOffset + 1, rect.top + m_TotalHeight + 1);
|
|
}
|
|
// right edge
|
|
if( horzPos == POS_RIGHT ) {
|
|
// Outside line
|
|
pDc->SelectObject( &m_HiLightPen );
|
|
pDc->MoveTo( rect.right - rightOffset, rect.top + topOffset );
|
|
pDc->LineTo( rect.right - rightOffset, rect.top + m_TotalHeight + 1 );
|
|
// Inside line
|
|
pDc->SelectObject( &m_LightPen );// note - this is usually the same color as btnface
|
|
if( vertPos == POS_TOP )
|
|
pDc->MoveTo( rect.right - rightOffset - 1, rect.top + topOffset + 1 );
|
|
else
|
|
pDc->MoveTo( rect.right - rightOffset - 1, rect.top + topOffset );
|
|
pDc->LineTo( rect.right - rightOffset - 1, rect.top + m_TotalHeight + 2 );
|
|
}
|
|
// top edge
|
|
if( ( vertPos == POS_TOP ) || ( vertPos == POS_SINGLE ) ) {
|
|
// Outside lighter
|
|
pDc->SelectObject( &m_ShadowPen );
|
|
pDc->MoveTo( rect.left + leftOffset, rect.top + topOffset );
|
|
pDc->LineTo( rect.right - rightOffset + 1, rect.top + topOffset );
|
|
// Inside edge darker
|
|
pDc->SelectObject( &m_DarkShadowPen );
|
|
if( horzPos == POS_LEFT )
|
|
pDc->MoveTo( rect.left + leftOffset + 1, rect.top + topOffset + 1 );
|
|
else
|
|
pDc->MoveTo( rect.left + leftOffset - 3, rect.top + topOffset + 1 );
|
|
pDc->LineTo( rect.right - rightOffset, rect.top + topOffset + 1);
|
|
}
|
|
// bottom edge
|
|
if( ( vertPos == POS_BOTTOM ) || ( vertPos == POS_SINGLE ) ) {
|
|
// Outside line
|
|
pDc->SelectObject( &m_HiLightPen );
|
|
if( horzPos == POS_LEFT )
|
|
pDc->MoveTo( rect.left + leftOffset + 1, rect.top + m_TotalHeight );
|
|
else
|
|
pDc->MoveTo( rect.left + leftOffset - 1, rect.top + m_TotalHeight );
|
|
pDc->LineTo( rect.right - rightOffset, rect.top + m_TotalHeight );
|
|
// Inside line
|
|
pDc->SelectObject( &m_LightPen );
|
|
if( horzPos == POS_LEFT )
|
|
pDc->MoveTo( rect.left + leftOffset + 2, rect.top + m_TotalHeight - 1 );
|
|
else
|
|
pDc->MoveTo( rect.left + leftOffset - 2, rect.top + m_TotalHeight - 1 );
|
|
pDc->LineTo( rect.right - rightOffset - 1, rect.top + m_TotalHeight - 1 );
|
|
|
|
}
|
|
pDc->SelectObject( pSavePen );
|
|
|
|
}
|
|
|
|
void CIeList::OnClick(
|
|
NMHDR* /* pNMHDR */, LRESULT* pResult
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
When the list is clicked, we invalidate the
|
|
rectangle for the currently selected item
|
|
|
|
Arguments:
|
|
|
|
pResult - ununsed
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
CRect rect;
|
|
|
|
// Get the selected item
|
|
int curIndex = GetNextItem( -1, LVNI_SELECTED );
|
|
if( curIndex != -1 ) {
|
|
GetItemRect( curIndex, &rect, LVIR_BOUNDS );
|
|
InvalidateRect( rect );
|
|
UpdateWindow();
|
|
}
|
|
|
|
*pResult = 0;
|
|
}
|
|
/*++
|
|
|
|
Routine Description:
|
|
Repaint the currently selected item if the style is LVS_SHOWSELALWAYS.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
void CIeList::RepaintSelectedItems()
|
|
{
|
|
CRect rcItem, rcLabel;
|
|
//
|
|
// invalidate focused item so it can repaint properly
|
|
//
|
|
int nItem = GetNextItem(-1, LVNI_FOCUSED);
|
|
|
|
if(nItem != -1)
|
|
{
|
|
GetItemRect(nItem, rcItem, LVIR_BOUNDS);
|
|
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 = GetNextItem(-1, LVNI_SELECTED);
|
|
nItem != -1; nItem = GetNextItem(nItem, LVNI_SELECTED))
|
|
{
|
|
GetItemRect(nItem, rcItem, LVIR_BOUNDS);
|
|
GetItemRect(nItem, rcLabel, LVIR_LABEL);
|
|
rcItem.left = rcLabel.left;
|
|
|
|
InvalidateRect(rcItem, FALSE);
|
|
}
|
|
}
|
|
|
|
// update changes
|
|
|
|
UpdateWindow();
|
|
}
|
|
|
|
int CIeList::GetItemHeight(
|
|
IN LONG fontHeight
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Calculates the item height (the height of each drawing
|
|
rectangle in the control) based on the supplied fontHeight. This
|
|
function is used by the parent to set the item height for the
|
|
control.
|
|
|
|
Arguments:
|
|
|
|
fontHeight - The height of the current font.
|
|
|
|
Return Value:
|
|
|
|
Item height.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
int itemHeight =
|
|
m_VertRaisedSpace +
|
|
m_BorderThickness +
|
|
m_VerticalTextOffsetTop +
|
|
fontHeight +
|
|
2 +
|
|
m_VerticalTextOffsetBottom +
|
|
m_BorderThickness +
|
|
1;
|
|
return itemHeight;
|
|
|
|
}
|
|
|
|
void CIeList::OnSetFocus(
|
|
CWnd* pOldWnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Repaint the selected item.
|
|
|
|
Arguments:
|
|
|
|
pOldWnd - Not used by this function
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
CListCtrl::OnSetFocus(pOldWnd);
|
|
|
|
// repaint items that should change appearance
|
|
RepaintSelectedItems();
|
|
|
|
}
|
|
|
|
void CIeList::OnKillFocus(
|
|
CWnd* pNewWnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Repaint the selected item.
|
|
|
|
Arguments:
|
|
|
|
pOldWnd - Not used by this function
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
CListCtrl::OnKillFocus(pNewWnd);
|
|
|
|
// repaint items that should change appearance
|
|
RepaintSelectedItems();
|
|
}
|
|
|
|
void CIeList::PreSubclassWindow()
|
|
/*++
|
|
|
|
Routine Description:
|
|
Calculate height parameters based on the font size. Set
|
|
colors for the control.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
CFont *pFont;
|
|
LOGFONT logFont;
|
|
|
|
pFont = GetFont( );
|
|
pFont->GetLogFont( &logFont );
|
|
|
|
LONG fontHeight = abs ( logFont.lfHeight );
|
|
|
|
m_Textheight = fontHeight + 2;
|
|
|
|
m_TotalHeight =
|
|
m_VertRaisedSpace +
|
|
m_BorderThickness +
|
|
m_VerticalTextOffsetTop +
|
|
m_Textheight +
|
|
m_VerticalTextOffsetBottom +
|
|
m_BorderThickness;
|
|
|
|
SetColors();
|
|
CListCtrl::PreSubclassWindow();
|
|
}
|
|
|
|
void CIeList::OnSysColorChange()
|
|
/*++
|
|
|
|
Routine Description:
|
|
Set the system colors and invalidate the control.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
SetColors();
|
|
Invalidate();
|
|
}
|
|
|
|
void CIeList::SetColors()
|
|
/*++
|
|
|
|
Routine Description:
|
|
Store the system colors and create pens.
|
|
|
|
Arguments:
|
|
|
|
none.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
|
|
// Text colors
|
|
m_clrText = ::GetSysColor(COLOR_WINDOWTEXT);
|
|
m_clrTextBk = ::GetSysColor(COLOR_BTNFACE);
|
|
m_clrBkgnd = ::GetSysColor(COLOR_BTNFACE);
|
|
m_clrHighlightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
|
|
m_clrHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
|
|
|
|
// Line colors
|
|
m_clr3DDkShadow = ::GetSysColor( COLOR_3DDKSHADOW );
|
|
m_clr3DShadow = ::GetSysColor( COLOR_3DSHADOW );
|
|
m_clr3DLight = ::GetSysColor( COLOR_3DLIGHT );
|
|
m_clr3DHiLight = ::GetSysColor( COLOR_3DHIGHLIGHT );
|
|
|
|
SetBkColor( m_clrBkgnd );
|
|
SetTextColor( m_clrText );
|
|
SetTextBkColor( m_clrTextBk );
|
|
|
|
// Pens for 3D rectangles
|
|
if( m_DarkShadowPen.GetSafeHandle() != NULL )
|
|
m_DarkShadowPen.DeleteObject();
|
|
m_DarkShadowPen.CreatePen ( PS_SOLID, 1, m_clr3DDkShadow );
|
|
|
|
if( m_ShadowPen.GetSafeHandle() != NULL )
|
|
m_ShadowPen.DeleteObject();
|
|
m_ShadowPen.CreatePen ( PS_SOLID, 1, m_clr3DShadow );
|
|
|
|
if( m_LightPen.GetSafeHandle() != NULL )
|
|
m_LightPen.DeleteObject();
|
|
m_LightPen.CreatePen ( PS_SOLID, 1, m_clr3DLight );
|
|
|
|
if( m_HiLightPen.GetSafeHandle() != NULL )
|
|
m_HiLightPen.DeleteObject();
|
|
m_HiLightPen.CreatePen ( PS_SOLID, 1, m_clr3DHiLight );
|
|
|
|
}
|
|
|
|
BOOL CIeList::SortItems(
|
|
IN PFNLVCOMPARE pfnCompare,
|
|
IN DWORD dwData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Override for SortItems. Checks the text of the sortColumn
|
|
for each line in the control against it's neighbors (above and
|
|
below) and assigns each line a position within it's panel.
|
|
|
|
Arguments:
|
|
|
|
pfnCompare - sort callback function
|
|
dwData - Unused
|
|
|
|
Return Value:
|
|
|
|
TRUE, FALSE
|
|
|
|
--*/
|
|
{
|
|
BOOL retVal = FALSE;
|
|
BOOL bEqualAbove = FALSE;
|
|
BOOL bEqualBelow = FALSE;
|
|
CString thisText;
|
|
CString aboveText;
|
|
CString belowText;
|
|
|
|
int numItems = GetItemCount();
|
|
//
|
|
// Call the base class to sort the items
|
|
//
|
|
if( CListCtrl::SortItems( pfnCompare, dwData ) ) {
|
|
//
|
|
// Get the vertical position (position within a panel) by comparing the text
|
|
// of the sort column and stash it in the array of vertical positions
|
|
//
|
|
if( m_pVertPos ) {
|
|
|
|
free( m_pVertPos );
|
|
|
|
}
|
|
m_pVertPos = (int *) malloc( numItems * sizeof( int ) );
|
|
if( m_pVertPos ) {
|
|
|
|
retVal = TRUE;
|
|
|
|
for( int itemID = 0; itemID < numItems; itemID++ ) {
|
|
//
|
|
// Get the text of the item and it's neighbors
|
|
//
|
|
thisText = GetItemText( itemID, m_SortCol );
|
|
aboveText = GetItemText( itemID - 1, m_SortCol );
|
|
belowText = GetItemText( itemID + 1, m_SortCol );
|
|
//
|
|
// Set booleans for the relationship of this item to it's
|
|
// neighbors
|
|
//
|
|
if( ( itemID == 0) || ( thisText.CompareNoCase( aboveText ) != 0 ) ){
|
|
|
|
bEqualAbove = FALSE;
|
|
|
|
} else {
|
|
|
|
bEqualAbove = TRUE;
|
|
|
|
}
|
|
if( ( itemID == GetItemCount() - 1 ) || ( thisText.CompareNoCase( belowText ) != 0 ) ) {
|
|
|
|
bEqualBelow = FALSE;
|
|
|
|
} else {
|
|
|
|
bEqualBelow = TRUE;
|
|
|
|
}
|
|
//
|
|
// Determine the position in the panel
|
|
//
|
|
if ( bEqualAbove && bEqualBelow ) m_pVertPos[ itemID ] = POS_MIDDLE;
|
|
else if( bEqualAbove && !bEqualBelow ) m_pVertPos[ itemID ] = POS_BOTTOM;
|
|
else if( !bEqualAbove && bEqualBelow ) m_pVertPos[ itemID ] = POS_TOP;
|
|
else m_pVertPos[ itemID ] = POS_SINGLE;
|
|
}
|
|
}
|
|
}
|
|
return( retVal );
|
|
}
|