Non Gamstop Betting SitesNon Gamstop CasinosBest Casinos Not On GamstopNon Gamstop CasinoCasino Not On Gamstop

Owner - worked example
(task 1, task 2, task 3)


key : purple - original code / blue - new code

Task 1 : Displaying the image and names

Step 1.1 :

Continue with the program names.

Step 1.2 :

Add the LVS_OWNERDRAWFIXED style to the ListCtrl :

void CNameListView::SetListStyle()
{

CListCtrl& m_listCtrl = GetListCtrl();

SetListView( LVS_REPORT | LVS_SHOWSELALWAYS |
LVS_SINGLESEL
| LVS_OWNERDRAWFIXED );

Step 1.3 :

Add the virtual function DrawItem() to the ListCtrl :

// Implementation
protected:
void SetListView( DWORD dwView );
virtual ~CNameListView();

virtual void DrawItem( LPDRAWITEMSTRUCT lpdis );

Step 1.4 :

Edit the code to allow the images and names to be displayed :

void CNameListView::DrawItem( LPDRAWITEMSTRUCT lpdis )
{

CListCtrl& m_listCtrl = GetListCtrl();
CRect rc = lpdis->rcItem;
CDC *pdcTmp = CDC::FromHandle( lpdis->hDC );

// get item data
LV_ITEM lvi;
lvi.iItem = lpdis->itemID;
lvi.mask = LVIF_PARAM;
lvi.iSubItem = 0;
m_listCtrl.GetItem(&lvi);

// Creates a pointer to the CName class
CName* pName = (CName*)lvi.lParam;

// Sets the string values
CString strSecondName = pName->GetSecondName();
CString strTitle = pName->GetTitle();
CString strFirstName = pName->GetFirstName();

LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH;
lvc.iSubItem = COLUMN_SECOND_NAME;

// To draw the image
CImageList* pImages = m_listCtrl.GetImageList(LVSIL_SMALL);


if( strTitle == "Mr" || strTitle == "Sir")
{

pImages->DrawIndirect(pdcTmp, 0, rc.TopLeft(), CSize(16, 16), CPoint(0, 0));

}
else if( strTitle == "Dr" || strTitle == "Prof")
{

pImages->DrawIndirect(pdcTmp, 2, rc.TopLeft(), CSize(16, 16), CPoint(0, 0));

}
else
{

pImages->DrawIndirect(pdcTmp, 1, rc.TopLeft(), CSize(16, 16), CPoint(0, 0));

}

m_listCtrl.GetColumn(COLUMN_SECOND_NAME, &lvc);
rc.right = lvc.cx;

// Draws the text in the rectangle - after the bitmap
rc.left += 20;
pdcTmp->DrawText( strSecondName, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= 20;

lvc.iSubItem = COLUMN_TITLE;
m_listCtrl.GetColumn(COLUMN_TITLE, &lvc);
rc.left = rc.right;
rc.right += lvc.cx;
rc.left += 6;
pdcTmp->DrawText( strTitle, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= 6;

lvc.iSubItem = COLUMN_FIRST_NAME;
m_listCtrl.GetColumn(COLUMN_FIRST_NAME, &lvc);
rc.left = rc.right;
rc.right += lvc.cx;
rc.left += 6;
pdcTmp->DrawText( strFirstName, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= 6;

}

Task 2 : Displaying the image and names

Step 2.1 :

Add the following code to the DrawItem() function :

void CNameListView::DrawItem( LPDRAWITEMSTRUCT lpdis )
{

CListCtrl& m_listCtrl = GetListCtrl();
CRect rc = lpdis->rcItem;
CDC *pdcTmp = CDC::FromHandle( lpdis->hDC );

// this is the window focus boolean variable
BOOL bFocus = (GetFocus() == this);

// get item data
LV_ITEM lvi;
lvi.iItem = lpdis->itemID;
lvi.mask = LVIF_STATE | LVIF_PARAM;
lvi.iSubItem = COLUMN_SECOND_NAME;
lvi.stateMask = 0xFFFF; // get all state flags
m_listCtrl.GetItem(&lvi);

// Creates a pointer to the CName class
CName* pName = (CName*)lvi.lParam;

// Sets the string values
CString strSecondName = pName->GetSecondName();
CString strTitle = pName->GetTitle();
CString strFirstName = pName->GetFirstName();

LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH;
lvc.iSubItem = COLUMN_SECOND_NAME;

m_listCtrl.GetColumn(COLUMN_SECOND_NAME, &lvc);
rc.right = lvc.cx;

// move the rectangle to the right to allow space for the image
rc.left = 17;


// Handle item highlighting:

COLORREF clrBackground;
COLORREF clrText;
COLORREF clrOldBackground;
COLORREF clrOldText;
CBrush* pbrOld;
BOOL bSelectFlag = FALSE;

if( lpdis->itemAction & (ODA_DRAWENTIRE | ODA_SELECT) )
{

// If we are gaining or losing the selection status,
// choose the proper colour for the background

if( lpdis->itemState & ODS_SELECTED )
{

clrBackground = GetSysColor( COLOR_HIGHLIGHT );
clrText = GetSysColor( COLOR_HIGHLIGHTTEXT );

}
else
{

clrBackground = GetSysColor( COLOR_WINDOW );
clrText = GetSysColor( COLOR_WINDOWTEXT );

}

// Fill the item's rectangle with the selected color
CBrush brHighlight( clrBackground );
pbrOld = pdcTmp->SelectObject( &brHighlight );
clrOldBackground = pdcTmp->SetBkColor( clrBackground );
clrOldText = pdcTmp->SetTextColor( clrText );
pdcTmp->FillRect( rc, &brHighlight );
bSelectFlag = TRUE;

}

// draw focus rectangle if item has focus
// this will leave the focus rectangle there even
// if the item is not selected


if ( (lpdis->itemState & ODS_FOCUS && bFocus) )
{

pdcTmp->DrawFocusRect( rc );

}

// turning grey when the window focus has gone:
if( (lpdis->itemState & ODS_FOCUS && !bFocus) )
{

clrBackground = GetSysColor( COLOR_INACTIVECAPTION );
clrText = GetSysColor( COLOR_WINDOWTEXT );

// Fill the item's rectangle with the new color
CBrush brHighlight( clrBackground );
pdcTmp->FillRect( rc, &brHighlight );

}

// Handle the focus rectangle:
if( (lpdis->itemState & ODS_FOCUS) &&
!(lpdis->itemState & ODS_SELECTED) )
{

pdcTmp->DrawFocusRect( rc );

}


// move the rectangle back to the left
rc.left = 0;

CImageList* pImages = m_listCtrl.GetImageList(LVSIL_SMALL);

if( strTitle == "Mr" || strTitle == "Sir")
{

pImages->DrawIndirect(pdcTmp, 0, rc.TopLeft(), CSize(16, 16), CPoint(0, 0));

}
else if( strTitle == "Dr" || strTitle == "Prof")
{

pImages->DrawIndirect(pdcTmp, 2, rc.TopLeft(), CSize(16, 16), CPoint(0, 0));

}
else
{

pImages->DrawIndirect(pdcTmp, 1, rc.TopLeft(), CSize(16, 16), CPoint(0, 0));

}

// Draws the text in the rectangle - leaving room for the icon
rc.left += 18;
pdcTmp->DrawText( strSecondName, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= 18;

if( bSelectFlag ) // Item currently selected
{

// Pen and background colours need to be changed back to normal
// the second two columns will be penned in black not white!

pdcTmp->SetBkColor( clrOldBackground );
pdcTmp->SetTextColor( clrOldText );
pdcTmp->SelectObject( pbrOld );

}

lvc.iSubItem = COLUMN_TITLE;
m_listCtrl.GetColumn(COLUMN_TITLE, &lvc);
rc.left = rc.right;
rc.right += lvc.cx;
rc.left += 6;
pdcTmp->DrawText( strTitle, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= 6;

lvc.iSubItem = COLUMN_FIRST_NAME;
m_listCtrl.GetColumn(COLUMN_FIRST_NAME, &lvc);
rc.left = rc.right;
rc.right += lvc.cx;
rc.left += 6;
pdcTmp->DrawText( strFirstName, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= 6;

}

Task 3 : Trimming the strings

Step 3.1 :

Add the new function MakeShortString() :

BOOL CNameListView::MakeShortString(CDC *pDC, CString &strTemp,
int nColumnWidth, int nOffset)
{

// if the string does not need trimming then leave this function

if( (pDC->GetTextExtent(strTemp).cx + nOffset) < nColumnWidth )
{

return(FALSE);

}

// tell the program that the string HAS been changed
bool bChanged = TRUE;
int nStringLength = strTemp.GetLength();
int nTrim = nStringLength;
int nInc = 1;

// calculate the required number of letters needed to be trimmed from
// the string to allow the three dots to appear

do
{

strTemp = strTemp.Left(nTrim - nInc);
nInc++;
nStringLength = strTemp.GetLength();

// never allow all the letters to be chopped!!!
if( nStringLength == 1 )
break;

}
while( (pDC->GetTextExtent(strTemp, nStringLength).cx) +
(pDC->GetTextExtent("...").cx) + nOffset > nColumnWidth);

// change the value of strTemp in the memory to include the three dots
strTemp = strTemp + "...";

return(bChanged);

}

Step 3.2 :

Call this function before each DrawText() command in the DrawItem() function :

// Draws the text in the rectangle - leaving room for the icon
rc.left += nOffset;
BOOL bHasStringBeenShortened = FALSE;
bHasStringBeenShortened = MakeShortString( pdcTmp, strSecondName,
lvc.cx, nOffset );

pdcTmp->DrawText( strSecondName, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= nOffset;

if( bSelectFlag ) // Item currently selected
{

// Pen and background colours need to be changed back to normal
// the second two columns will be penned in black not white!

pdcTmp->SetBkColor( clrOldBackground );
pdcTmp->SetTextColor( clrOldText );
pdcTmp->SelectObject( pbrOld );

}

nOffset = 6;

lvc.iSubItem = COLUMN_TITLE;
m_listCtrl.GetColumn(COLUMN_TITLE, &lvc);
rc.left = rc.right;
rc.right += lvc.cx;
rc.left += nOffset;
bHasStringBeenShortened = MakeShortString( pdcTmp, strTitle, lvc.cx, nOffset );
pdcTmp->DrawText( strTitle, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= nOffset;
if( bHasStringBeenShortened )

m_listCtrl.InvalidateRect(rc, FALSE);

lvc.iSubItem = COLUMN_FIRST_NAME;
m_listCtrl.GetColumn(COLUMN_FIRST_NAME, &lvc);
rc.left = rc.right;
rc.right += lvc.cx;
rc.left += nOffset;
bHasStringBeenShortened = MakeShortString( pdcTmp, strFirstName, lvc.cx, nOffset );
pdcTmp->DrawText( strFirstName, rc, DT_LEFT | DT_SINGLELINE );
rc.left -= nOffset;
if( bHasStringBeenShortened )

m_listCtrl.InvalidateRect(rc, FALSE);

}


Click here for the basic exercise

Click here for the source code

Click here to return to menu

Worth your time