|
/////////////////////////////////////////////////////////////////////////////
// ListCtrlEx.cpp : implementation file
/////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "ListCtrlEx.h"
#include "..\MainView.h"
#include "..\Dbf\Dbf.h"
/////////////////////////////////////////////////////////////////////////////
// MESSAGE MAP
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
//{{AFX_MSG_MAP(CChildFrame)
ON_WM_MEASUREITEM_REFLECT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx
/////////////////////////////////////////////////////////////////////////////
CListCtrlEx::CListCtrlEx() {
//*** Main application pointer
m_pMainApp = reinterpret_cast<CMainApp *>(AfxGetApp());
if(!m_pMainApp) {
_M("CListCtrlEx: Empty object of the CMainApp class!");
return;
}
//*** Table Id
m_eTable = m_pMainApp->m_eTable;
//*** Current meta table structure
m_MetaTable = m_pMainApp->m_aMetaTable[m_eTable];
//*** Current document
m_pDoc = NULL;
} // CListCtrlEx
/////////////////////////////////////////////////////////////////////////////
// CListCtrlEx
/////////////////////////////////////////////////////////////////////////////
CListCtrlEx::~CListCtrlEx() {
} // ~CListCtrlEx
/////////////////////////////////////////////////////////////////////////////
// MeasureItem
/////////////////////////////////////////////////////////////////////////////
void CListCtrlEx::MeasureItem(LPMEASUREITEMSTRUCT pMIS) {
//*** The table list height
pMIS->itemHeight = m_MetaTable.nListHeight;
} // MeasureItem
/////////////////////////////////////////////////////////////////////////////
// OnChildNotify
/////////////////////////////////////////////////////////////////////////////
BOOL CListCtrlEx::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult) {
NMHDR *pNMHdr = reinterpret_cast<NMHDR *>(lParam);
LV_DISPINFO *pLVDI = reinterpret_cast<LV_DISPINFO *>(lParam);
LV_ITEM *pItem = &pLVDI->item;
if(message == WM_NOTIFY) {
switch(pNMHdr->code) {
case LVN_GETDISPINFO: {
if(pItem->mask & LVIF_TEXT) {
//*** Item row
UINT nRow = pItem->iItem;
//*** Item column
UINT nCol = pItem->iSubItem;
//*** The message buffer
TCHAR szStr[MAXITEMTEXT];
//*** Current document
m_pDoc = m_pMainApp->m_apDoc[m_eTable];
if(!m_pDoc) {
_M("CListCtrlEx::CListCtrlEx : Empty document!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** Number of fields in dbf file
ULONG nColCount = m_pDoc->m_nFldCount; // = m_MetaTable.nColCount;
if(nColCount == 0) {
_M("CListCtrlEx::OnChildNotify : Column count = 0!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
if(m_MetaTable.nColCount != nColCount) {
swprintf(
szStr,
_T("CListCtrlEx::OnChildNotify : Table (%d) and Dbf (%d) columns are different!"),
m_MetaTable.nColCount,
nColCount
);
_M(szStr);
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** Number of records in dbf file
ULONG nRowCount = m_pDoc->m_nRecCount;
if(nRowCount == 0) {
_M("CListCtrlEx::OnChildNotify : Row count = 0!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** Sets row count into meta table
//if(m_MetaTable.nRowCount != nRowCount)
m_MetaTable.nRowCount = nRowCount;
//*** Length of one data record (including delete flag)
ULONG nRowSize = m_pDoc->m_nRecSize;
if(nRowSize == 0) {
_M("CListCtrlEx::OnChildNotify : Row size = 0!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** Line displacement of nCol-th field of nRow-th record
ULONG nLineInd = nRow*nRowSize + m_pDoc->m_anOff[nCol];
if(nLineInd < 0) {
_M("CListCtrlEx::OnChildNotify : Line index < 0!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** Maps view of dbf file for its second part (where are data)
DBF_FILE2 *m_pDbfView2 = m_pDoc->m_pDbfView2;
if(!m_pDbfView2) {
_M("CListCtrlEx::OnChildNotify : Empty view of dbf file!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** The Visual FoxPro records
BYTE *aDbfRec = m_pDbfView2->aDbfRec;
if(!aDbfRec) {
_M("CListCtrlEx::OnChildNotify : Empty array of dbf file!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
if(!aDbfRec) {
_M("CListCtrlEx::OnChildNotify : Empty records into dbf file!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
//*** Line table cell index
UINT ji = nRow*nColCount + nCol;
if(ji < 0) {
_M("CListCtrlEx::OnChildNotify : Line cell index < 0!");
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
if(ji < nRowCount*nColCount) {
try {
//*** Copies (j, i) field value of m_anLen[i]-th length
// We do this as it hasn't null terminator
CString sFldVal(
(LPCSTR) &aDbfRec[nLineInd],
m_pDoc->m_acLen[nCol]
);
//*** Formates date string into German style
if(m_pDoc->m_acFldType[nCol] == 68) { // = 0x44 ("D") - Date
CString sDate =
sFldVal.Right(2) + _T(".") +
sFldVal.Mid(4, 2) + _T(".") +
sFldVal.Left(4);
sFldVal = sDate;
}
wcscpy((wchar_t *)(pItem->pszText), sFldVal);
} catch (...) {
//*** Forces to exit from the application as else will be a lot messages
exit(-1);
}
} else {
wcscpy((wchar_t *)(pItem->pszText), _T("***"));
}
}
break;
}
}
}
return CListCtrl::OnChildNotify(message, wParam, lParam, pResult);
} // OnChildNotify
/////////////////////////////////////////////////////////////////////////////
// SetColItemText
/////////////////////////////////////////////////////////////////////////////
void CListCtrlEx::SetColItemText(CDC *pDC, CString& stColText,
CRect& TextRect, UINT nJustify) {
int x = 0; // x-coordinate of reference point
int y = 0; // y-coordinate of reference point
UINT nOptions = 0; // Text-output options ETO_CLIPPED|ETO_OPAQUE
int nTextLen = stColText.GetLength();
HDC hDC = pDC->m_hDC;
SIZE Size = {0};
if(!GetTextExtentPoint(hDC, stColText, nTextLen, &Size)) {
_M("Failed to call GetTextExtentPoint for table list!");
return;
}
//*** Align the text in the whole table
CRect TmpRect(TextRect);
//*** x-coordinate of reference point
x = (TextRect.left + TextRect.right - Size.cx)/2 - 1;
x = (x < TextRect.left + 2) ? TextRect.left + 2 : x;
//*** y-coordinate of reference point
y = (TextRect.bottom - TextRect.top - Size.cy)/2 - 1;
//*** Specifies that the current background color fills the rectangle
nOptions |= ETO_OPAQUE;
//*** Draw the background fast
pDC->ExtTextOut(TextRect.left, TextRect.top, nOptions, TextRect, NULL, 0, NULL);
TmpRect.left++; // Cosmetic
TmpRect.top += y; // y-coordinate of reference point
TmpRect.InflateRect(-3, 0); // Text does not touch borders
UINT nFormat = 0;
switch(nJustify & LVCFMT_JUSTIFYMASK) {
case LVCFMT_LEFT:
nFormat = DT_LEFT;
break;
case LVCFMT_RIGHT:
nFormat = DT_RIGHT;
break;
case LVCFMT_CENTER:
nFormat = DT_CENTER;
break;
default:
_M("CListCtrlEx: Error of the text formatting!");
return;
}
//*** Writes the text in the TmpRect
::DrawText(hDC, stColText, nTextLen, TmpRect, nFormat);
} // SetColItemText
/////////////////////////////////////////////////////////////////////////////
// SetRowText
/////////////////////////////////////////////////////////////////////////////
void CListCtrlEx::SetRowText(LPDRAWITEMSTRUCT pDIS) {
CString sItemText;
//*** Retrieve the item rectangle size.
CRect TextRect = pDIS->rcItem;
//*** You should get the pointer to the device context from the "pDIS" ptr.
CDC *pDC = CDC::FromHandle(pDIS->hDC);
//*** Selects necessary font
pDC->SelectObject(m_MetaTable.pListFont);
UINT nColumn = 0;
LV_COLUMN lvc;
lvc.mask = LVCF_FMT;
while(nColumn < m_MetaTable.nColCount && GetColumn(nColumn, &lvc)) {
//*** Get the text to be drawn and calculate its bounding rectangle
sItemText = GetItemText(pDIS->itemID, nColumn);
TextRect.right = TextRect.left + GetColumnWidth(nColumn);
if(pDC->RectVisible(TextRect))
SetColItemText(pDC, sItemText, TextRect, lvc.fmt);
//*** Move the left side of the previous rect already forward to be good
// for the next Text. The right of the previous bounding rect is the
// left of the following
TextRect.left = TextRect.right;
nColumn++;
}
//*** Back to the old state
pDIS->rcItem.right = TextRect.right;
pDIS->rcItem.bottom = TextRect.bottom;
//*** Restore system font
pDC->SelectStockObject(SYSTEM_FONT);
} // SetRowText
/////////////////////////////////////////////////////////////////////////////
// DrawItem
/////////////////////////////////////////////////////////////////////////////
void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT pDIS) {
if(pDIS->itemID == -1)
return;
//*** You should get the pointer to the device context from the "pDIS" ptr.
CDC *pDC = CDC::FromHandle(pDIS->hDC);
switch(pDIS->itemAction) {
case ODA_DRAWENTIRE: {
//*** Populate the listview with column text
SetRowText(pDIS);
break;
}
default: {
TCHAR szStr[MAXITEMTEXT];
swprintf(
szStr,
_T("CGridListEx::DrawItem : Unexpected case in switch : %i"),
pDIS->itemAction
);
_M(szStr);
}
}
} // DrawItem
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.