/cdex1/branches/CDEX_160_BRANCH/cdexos/LineList.cpp
C++ | 472 lines | 286 code | 69 blank | 117 comment | 54 complexity | 3d5c0757bbba971f790d7f24d7abf24b MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, LGPL-2.0, BSD-3-Clause, AGPL-1.0, CC-BY-SA-3.0, GPL-3.0
- /*
- ** Copyright (C) 1999 Albert L. Faber
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program 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 General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- #include "Stdafx.h"
- #include "LineList.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- // LListCtrl
- /////////////////////////////////////////////////////////////////////////////
- // GetCurSel -
- // an obvious CListCtrl deficiency, tell us index of current selection.
- /////////////////////////////////////////////////////////////////////////////
- int LListCtrl::GetCurSel() const
- {
- return GetNextItem(-1,LVNI_ALL|LVNI_SELECTED);
- }
- /////////////////////////////////////////////////////////////////////////////
- // SetCurSel -
- // an obvious CListCtrl deficiency, specify and make visible a new selection.
- /////////////////////////////////////////////////////////////////////////////
- int LListCtrl::SetCurSel(int nSelect)
- {
- if(!SetItemState(nSelect,LVIS_SELECTED,LVIS_SELECTED))
- {
- return LB_ERR;
- }
- if(!EnsureVisible(nSelect,FALSE))
- {
- return LB_ERR;
- }
- return TRUE;
- }
- BEGIN_MESSAGE_MAP(LListCtrl, CListCtrl)
- //{{AFX_MSG_MAP(LListCtrl)
- ON_NOTIFY_REFLECT(LVN_INSERTITEM, OnInsertitem)
- ON_WM_GETDLGCODE()
- ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
- //}}AFX_MSG_MAP
- // ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
- // ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginlabeledit)
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // OnGetDialogCode -
- // allow our control to recieve crack at parent dialog's key codes
- // this allows the control to catch RETURN rather than the dialog's
- // default push button and hence to support up arrow/down arrow/return
- // item selection (must also place a NM_RETURN message handler in the
- // dialog's message map).
- /////////////////////////////////////////////////////////////////////////////
- //UINT LListCtrl::OnGetDlgCode()
- //{
- //return CListCtrl::OnGetDlgCode() | DLGC_WANTALLKEYS;
- //}
- /////////////////////////////////////////////////////////////////////////////
- // OnInsertItem -
- // make item selectable and hi-lighted by entire row, not just first
- // column sub-item (an undocumented tid-bit of the Net). Yes there must
- // be a better place for this but I'll be damned if I can find it.
- // OnCreate(), Create(), etc, as added by ClassWizard do not hook,
- // place it here for now.
- /////////////////////////////////////////////////////////////////////////////
- void LListCtrl::OnInsertitem(NMHDR* pNMHDR, LRESULT* pResult)
- {
- ListView_SetExtendedListViewStyle(m_hWnd,LVS_EX_FULLROWSELECT);
- }
- // hard coded margins in inches and pixels:
- #define PRINTMARGIN_Y 0.50
- #define PRINTMARGIN_X 0.50
- #define PRINTMARGINY ((int)((double)pDC->GetDeviceCaps(LOGPIXELSY)*PRINTMARGIN_Y))
- #define PRINTMARGINX ((int)((double)pDC->GetDeviceCaps(LOGPIXELSX)*PRINTMARGIN_X))
- #define LINESPACING ((csCharSize.cy * 6)/5)
- void LListCtrl::OnPrint(CString strHeader, CString strFooter, DWORD dwFlags)
- {
- CRect crPrintedPage;
- CSize csCharSize;
- CPoint cpCurPos;
- DWORD dwLinesPerPage;
- DWORD dwPagesTotal;
- DWORD dwLinesTotal;
- CFont Font;
- CDC *pDC;
- // confirm null-list print:
- if( GetItemCount() == 0 && AfxMessageBox( _T( "" ), MB_OKCANCEL | MB_ICONQUESTION) == IDCANCEL )
- {
- return;
- }
- // Create and do a print setup dialog (bPrintSetupOnly=TRUE to get a more useful dialog, loses the "print all/select" and "copies" controls):
- CPrintDialog dlg(TRUE,PD_ALLPAGES|PD_RETURNDC,NULL);
- dlg.m_pd.Flags |= PD_NOSELECTION;
- if(dwFlags&LLC_LANDSCAPE)
- {
- // ((theApp*)AfxGetApp())->SetPortraitLandscape(dlg.m_pd,DMORIENT_LANDSCAPE);
- }
- if(dlg.DoModal() != IDOK || dlg.m_pd.hDC == NULL)
- {
- return;
- }
- // create a new CDC object to access printer device context:
- pDC = new CDC;
- pDC->Attach(dlg.m_pd.hDC);
-
- // setup a printer font if none provided:
- csCharSize.cy = ((pDC->GetDeviceCaps(LOGPIXELSY)*10)/72);
-
- Font.CreateFont(-((int)csCharSize.cy),0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET
- ,OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,
- DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, _T( "Courier New" ) );
-
- // activate the printer font:
- CFont *pOldFont = pDC->SelectObject(&Font);
-
- // get size, lines/page, and page count:
- TEXTMETRIC tm;
- pDC->GetTextMetrics(&tm);
- csCharSize.cx = tm.tmAveCharWidth;
- csCharSize.cy = tm.tmHeight + tm.tmExternalLeading;
- dwLinesTotal = GetItemCount();
- dwLinesPerPage = (pDC->GetDeviceCaps(VERTRES) - 2*PRINTMARGINY - 3*LINESPACING) / LINESPACING;
- dwPagesTotal = max(1,(dwLinesTotal + (dwLinesPerPage-1))/dwLinesPerPage);
- crPrintedPage.left = PRINTMARGINX;
- crPrintedPage.right = pDC->GetDeviceCaps(HORZRES) - PRINTMARGINX;
- crPrintedPage.top = PRINTMARGINY;
- crPrintedPage.bottom = pDC->GetDeviceCaps(VERTRES) - PRINTMARGINY;
- // prep for printing:
- pDC->StartDoc( _T( "Error Stack Document" ) );
- // print page loop:
- for(DWORD dwPage=0; dwPage<dwPagesTotal; dwPage++ )
- {
- pDC->StartPage();
- print_header(pDC, crPrintedPage, csCharSize, cpCurPos, strHeader, dwFlags);
- // print line loop:
- for(DWORD dwLine=0; dwLine<dwLinesPerPage && dwPage*dwLinesPerPage+dwLine<(DWORD)GetItemCount(); dwLine++ )
- {
- print_line(pDC, crPrintedPage, csCharSize, cpCurPos, dwPage*dwLinesPerPage+dwLine);
- }
- print_footer(pDC, crPrintedPage, csCharSize, strFooter, dwPage+1, dwPagesTotal);
- pDC->EndPage();
- }
- // end printing:
- pDC->EndDoc();
- // clean up fonts:
- pDC->SelectObject(pOldFont);
- Font.DeleteObject();
- // clean up CDC:
- pDC->DeleteDC();
- pDC->Detach();
- delete pDC;
- }
- void LListCtrl::print_header(CDC *pDC,CRect crPrintedPage,CSize csCharSize, CPoint& cpCurPos, CString& strHeader, DWORD dwFlags )
- {
- CString strTime;
- LV_COLUMN lvcColumn;
- DWORD dwColumnWidths=0;
- TCHAR pszBuffer[ MAX_PATH ];
- int iCol=0;
- CRect r;
- // format time string for above margin header:
- CTime m_ctTime = CTime::GetCurrentTime();
- if(!(dwFlags&LLC_HDRNODATE))
- {
- strTime = m_ctTime.Format("%m/%d/%y");
- }
- if(!(dwFlags&LLC_HDRNOTIME))
- {
- if(!(dwFlags&LLC_HDRNODATE))
- {
- strTime += " - ";
- }
- strTime += m_ctTime.Format("%I:%M:%S %p");
- }
- // print it and user supplied header above the margin:
- cpCurPos.y = crPrintedPage.top - LINESPACING;
- pDC->TextOut(crPrintedPage.left,cpCurPos.y,strHeader);
- pDC->TextOut(crPrintedPage.right-pDC->GetTextExtent(strTime).cx,cpCurPos.y,strTime);
- cpCurPos.y += LINESPACING;
- // underline it:
- pDC->MoveTo(crPrintedPage.left,crPrintedPage.top);
- pDC->LineTo(crPrintedPage.right,crPrintedPage.top);
- // display sub-header as on-screen column headers:
- cpCurPos.x = crPrintedPage.left;
- cpCurPos.y = crPrintedPage.top + LINESPACING/2;
- GetClientRect(&r);
- lvcColumn.mask = LVCF_WIDTH | LVCF_FMT | LVCF_TEXT;
- lvcColumn.pszText = pszBuffer;
- lvcColumn.cchTextMax = MAX_PATH;
- while( GetColumn( iCol, &lvcColumn ) )
- {
- // postition column wise:
- cpCurPos.x = crPrintedPage.left + (dwColumnWidths*crPrintedPage.Width())/r.Width();
- if(lvcColumn.fmt&LVCFMT_CENTER)
- {
- cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/(2*r.Width());
- cpCurPos.x -= pDC->GetTextExtent(lvcColumn.pszText).cx/2;
- }
- else if(lvcColumn.fmt&LVCFMT_RIGHT)
- {
- cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/r.Width();
- cpCurPos.x -= pDC->GetTextExtent(lvcColumn.pszText).cx;
- }
- // print:
- pDC->TextOut(cpCurPos.x,cpCurPos.y,lvcColumn.pszText);
- dwColumnWidths += lvcColumn.cx;
- iCol++;
- }
- // underline it:
- cpCurPos.y += (3*LINESPACING)/2;
- cpCurPos.x = crPrintedPage.left + (dwColumnWidths*crPrintedPage.Width())/r.Width();
- pDC->MoveTo(crPrintedPage.left,cpCurPos.y);
- pDC->LineTo(crPrintedPage.right,cpCurPos.y);
- // prep for first data line:
- cpCurPos.y += LINESPACING/2;
- }
- void LListCtrl::print_line(CDC *pDC, CRect crPrintedPage, CSize csCharSize, CPoint& cpCurPos, DWORD dwLine)
- {
- LV_COLUMN lvcColumn;
- DWORD dwColumnWidths=0;
- int iCol=0;
- CRect r;
- // display item text as on-screen:
- GetClientRect(&r);
- cpCurPos.x = crPrintedPage.left;
- lvcColumn.mask = LVCF_WIDTH | LVCF_FMT;
- while( GetColumn( iCol, &lvcColumn ) )
- {
- // postition column wise:
- cpCurPos.x = crPrintedPage.left + (dwColumnWidths*crPrintedPage.Width())/r.Width();
- if(lvcColumn.fmt&LVCFMT_CENTER)
- {
- cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/(2*r.Width());
- cpCurPos.x -= pDC->GetTextExtent(GetItemText(dwLine,iCol)).cx/2;
- }
- else if(lvcColumn.fmt&LVCFMT_RIGHT)
- {
- cpCurPos.x += (lvcColumn.cx*crPrintedPage.Width())/r.Width();
- cpCurPos.x -= pDC->GetTextExtent(GetItemText(dwLine,iCol)).cx;
- }
- // print
- pDC->TextOut(cpCurPos.x,cpCurPos.y,GetItemText(dwLine,iCol));
- dwColumnWidths += lvcColumn.cx;
- iCol++;
- }
- // advance for next line call:
- cpCurPos.y += LINESPACING;
- }
- void LListCtrl::print_footer(CDC *pDC,CRect crPrintedPage,CSize csCharSize, CString& strFooter, DWORD dwPage, DWORD dwPagesTotal)
- {
- // overline it:
- pDC->MoveTo(crPrintedPage.left,crPrintedPage.bottom);
- pDC->LineTo(crPrintedPage.right,crPrintedPage.bottom);
- // print user footer:
- pDC->TextOut(crPrintedPage.left,crPrintedPage.bottom+LINESPACING,strFooter);
- // format footer as page n of N:
- CString strPage;
- strPage.Format( _T( "%d of %d" ), dwPage, dwPagesTotal );
- // print it:
- pDC->TextOut(crPrintedPage.right-pDC->GetTextExtent(strPage).cx,crPrintedPage.bottom+LINESPACING,strPage);
- }
- int LListCtrl::SelectAll()
- {
- for (int i=0;i<GetItemCount();i++)
- {
- SetCurSel(i);
- }
- // Scroll up to the first selected
- SetCurSel(0);
- SetItemState(-1,LVIS_FOCUSED,LVIS_FOCUSED);
- return TRUE;
- }
- #define VK_C 67
- #define VK_V 86
- #define VK_X 88
- #define VK_Z 90
- BOOL LListCtrl::PreTranslateMessage(MSG* pMsg)
- {
- // If edit control is visible in tree view control, sending a
- // WM_KEYDOWN message to the edit control will dismiss the edit
- // control. When ENTER key was sent to the edit control, the parent
- // window of the tree view control is responsible for updating the
- // item's label in TVN_ENDLABELEDIT notification code.
- if ( pMsg->message == WM_KEYDOWN )
- {
- CHAR ckey=toupper( pMsg->wParam &0xFF );
- if ( VK_RETURN == pMsg->wParam )
- m_bEditNext = TRUE;
- if ( VK_ESCAPE == pMsg->wParam )
- m_bEditNext = FALSE;
- if( GetKeyState( VK_CONTROL )<-1 && (ckey== 'A') )
- {
- SelectAll();
- return TRUE;
- }
- if( GetKeyState( VK_CONTROL )<-1 && (ckey== 'N') )
- {
- SelectNone();
- return TRUE;
- }
- CEdit* edit = GetEditControl();
- if (edit)
- {
- // LTRACE("Control key status = %d %d\n",LOBYTE(GetKeyState( VK_CONTROL )),HIWORD(GetKeyState( VK_CONTROL )));
- if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'C' ) ) )
- {
- edit->Copy();
- return TRUE;
- }
- if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'V' ) ) )
- {
- edit->Paste();
- return TRUE;
- }
- if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'X' ) ) )
- {
- edit->Cut();
- return TRUE;
- }
- if( GetKeyState( VK_CONTROL )<-1 && (ckey== _T( 'Z' ) ) )
- {
- edit->Undo();
- return TRUE;
- }
- if( pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_CONTROL || pMsg->wParam == VK_INSERT || pMsg->wParam == VK_SHIFT )
- {
- edit->SendMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
- return TRUE;
- }
- }
- }
- return CListCtrl::PreTranslateMessage(pMsg);
- }
- int LListCtrl::SelectNone()
- {
- // -1 changes the state of all items in the list.
- return SetItemState(-1, ~LVIS_SELECTED, LVIS_SELECTED);
- // return SetCurSel(-1);
- }
- void LListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
- {
- /*
- LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
- LV_ITEM *pItem = &pDispInfo->item;
- if ( pItem->pszText != NULL )
- SetItemText( pItem->iItem, pItem->iSubItem, pItem->pszText );
- */
- int nFocused = GetNextItem(-1,LVNI_FOCUSED);
- // select next item
- nFocused++;
- // PostMessage( WM_KEYDOWN, 28, 0x1500001 );
- // PostMessage( WM_KEYUP, 28, 0x1500001 );
- // PostMessage( WM_KEYDOWN, 71, 0x3c0001 );
- // PostMessage( WM_KEYUP, 71, 0x3c0001 );
- /*
- int nCount = GetItemCount();
- if ( nFocused < GetItemCount() )
- {
- // SetFocus( nFocused );
- EditLabel( nFocused );
- }
- */
- *pResult = TRUE;
- }
- CMutex myLockListCtrl;
- void LListCtrl::SetHeaderControlText( DWORD dwPos, const CString& strValue )
- {
- myLockListCtrl.Lock();
- if ( m_hWnd )
- {
- CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
- ASSERT( dwPos < pHeaderCtrl->GetItemCount() );
- HDITEM hdi;
- memset( &hdi, 0, sizeof( HDITEM ) );
- // Get header item data
- pHeaderCtrl->GetItem( dwPos, &hdi );
- // modify item data
- hdi.pszText = (LPTSTR)(LPCTSTR)strValue;
- hdi.mask = HDI_TEXT;
- // Set item data
- pHeaderCtrl->SetItem( dwPos, &hdi );
- }
- myLockListCtrl.Unlock();
- }
- void LListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
- {
- // TODO: Add your control notification handler code here
-
- *pResult = 0;
- }