Blame | Last modification | View Log
////////////////////////////////////////////////////////////////////////////// File: ReportCtrl.cpp// Version: 2.0.1//// Author: Maarten Hoeben// E-mail: hamster@xs4all.nl//// Implementation of the CReportCtrl and associated classes.//// This code may be used in compiled form in any way you desire. This// file may be redistributed unmodified by any means PROVIDING it is// not sold for profit without the authors written consent, and// providing that this notice and the authors name and all copyright// notices remains intact.//// An email letting me know how you are using it would be nice as well.//// This file is provided "as is" with no expressed or implied warranty.// The author accepts no liability for any damage/loss of business that// this product may cause.//// Version history//// 1.0.1 - Initial release.// 1.1.0 - Changed copyright notice.// - Added RVN_LAYOUTCHANGED notification message.// - Fixed SB_THUMBPOSITION and SB_THUMBTRACK problems.// - Removed IDC_HEADERCTRL and IDC_REPORTCTRL definitions.// Now hardcoded because conflicts with some implementations.// - Added SortAllColumns(), contributed by Roger Parkinson.// - Added Chris Hambleton's suggestion to sort on image.// indices when the (sub)item does not have text.// - Fixed DeleteAllItems(), as suggested by Paul Leung.// - Fixed DeleteAllItems() focus problem, as suggested by Dmitry ??.// - Fixed DeleteItem(), as noted by Eugenio Ciceri.// - Added fixes and suggestions of Serge Weinstock:// - Fixed GetNextSelectedItem().// - Fixed "no items to show" position.// - Added support for WS_BORDER style.// - Added RVN_ITEMDELETED notification.// - Added mouse-wheel support.// - Added extended horizontal grid style and changed regular// horizontal grid style.// - Fixed selection inversion using space key.// - Fixed focus selection using ctrl key.// - Fixed focus on deleted items.// - Added RVS_OWNERDATA style.// - Changed notification structure to facilitate// RVS_OWNERDATA style.// - Changed hit test info structure to facilitate// RVS_FOCUSSUBITEMS style.// - Added RVS_FOCUSSUBITEMS style to enable focus on individual// subitems to facilitate subitem editing.// - Added dialog control ID to WPARAM of notification messages.// - Added subitem editing functionality.// - Added CReportEditCtrl edit control.// - Added CReportComboCtrl edit control.// - Added support for RVIM_TEXT on empty strings (required for// editing).// - Added RVIS_READONLY state.// - Added rect member to RVHITTESTINFO structure.// - Added RVS_EXPANDSUBITEMS style.// - Added CReportTipCtrl, based on code by Zafir Anjum.// - Added background image support, based on code contributed by// Ernest Laurentin.// 1.1.1 - Added RVN_KEYDOWN notification.// - Fixed DeleteItem as suggested by Thomas Freudenberg// (Luca; this time I tested the function :-).// - Removed use of GetBuffer() in CReportData::GetSubItem()// to improve performance.// - Improved sorting performance by using quick sort instead// of bubble sort (QuickSort based on Martin Ziacek's// QArray implementation).// - Added item to row mapping for improved lookup performance.// - Fixed GetItemFromRow to retrieve ITEM in OWNERDATA style.// - Added item/row manipulation functions.// - Fixed column reordering and storage for invisible// controls.// - Added GetItemHeight function.// - Added NMRVHEADER notification structure.// - Replaced RVN_COLUMNCLICK with RVN_HEADERCLICK. This// new notification uses the new NMRVHEADER structure.// - Added MeasureItem function.// - Added RVN_DIVIDERDBLCLICK notification and code that// implements optimal column sizing.// - Added right mouse button handling and RVN_ITEMRCLICK// notification.// - Added item cache to optimize lookup of ITEM structures// in RVS_OWNERDATA style.// - Fixed a bug related to creation of the control from// from dialog templates.// - Fixed double RVN_ENDITEMEDIT messages in edit controls.// - Fixed edit cancelation on style changes.// - Fixed control keys in edit controls.// - Added AddItem operations.// - Added FindItem operation.// - Changed text string parameter of InsertItem to LPCTSTR.// - Changed behavior of edit row and RVS_FOCUSSUBITEMS style.// The focus on the edit row is now always on individual columns,// while the focus on other rows is only on individual columns// if the RVS_FOCUSSUBITEMS style is used.// - Fixed a bug related to editing of edit row while not visible.// - Added BeginEdit functions to edit controls.// - Changed 'Column' handling function names in order to stop// confusion about what is a column and what is a subitem.// A column is a visible (or active) subitem.// - Added GetSubItemWidth and SetSubItemWidth functions, courtesy// of Jonathan Kotas.// - Removed restriction to sort on columns only.// - Added Focus manipulation functions, suggested by Attila Hajdrik.// - Added subitem persistent style, as suggested by Attila Hajdrik.// - Fixed assertion on column invisible deactivation.// - Fixed several bugs related to subitem dynamic (de)activation and// column manipulation.// - Added RVP_SORTTOOLTIP property to allow changing "Sort by"// tooltip.// - Fixed pResult assignment in OnHdnItemClick.// - Added ResortItems function.// - Removed restriction for at least one visible subitem.// - Added GetActiveSubItemCount().// - Added flat style to CReportSubItemListCtrl// (use WS_EX_STATICEDGE).// - Added subitem disable to CReportSubItemListCtrl.// - Added UndefineAllSubItems, as suggested by Brian Pollack.// - Added RVCF_SUBITEM_NOFOCUS, as suggested by Attila Hajdrik.// - Added RVP_NOTIFYMASK property for setting a mask on what// notifications must be generated, as suggested by A. Hajdrik.// - Made Notify function virtual.// - Fixed OnVScroll thumb track for item count > 32767.// - Improved SelectRows performance by using list instead of// itteration through all items to clear the previous selection.// - Fixed several glitches related to subitem activation.// - Added IsItemVisible().// - Fixed scrollbar assertion in SetItemCount().// - Improved performance of CReportData.// - Added PreviewHeight function to calculate the height of// preview text.// - Made several implementation function virtual.// - Minor performance improvement by replacing printf with prepared// fixed in New.// 1.1.2 - Fixed MoveUp/MoveDown related selection bug.// - Fixed focus on item sort as suggested by Matija Jerkovic.// - Fixed GetProfile and improved GetItem as suggested by// Eugenio Ciceri.// - Several fixes to CReportView as suggested by Eugenio Ciceri.// - Fixed ClearSelection, added InvertSelection SelectAll and// SetSelection variants (SelectMatch and SelectLessEq) as// contributed by Eugenio Ciceri.// - Fixed SelectRows as suggested by Matija Jerkovic.// - Fixed InsertItem and DeleteItem as suggested by Eugenio Ciceri.// - Fixed DeleteAllItems.// - Fixed grid property, thanks to Roland Kopetzky.// - Applied fixes to edit row as suggested by Alex.// - Added support for disabled style.// - Fixed obstructed bottom selected row redraw problem.// - Added GetColor, SetColor and DeleteAllColors methods.// - Fixed (ctrl+)page-up assertion in empty reports.// - Added UpdateWindow on strategic places to improve// drawing on slower or heavy loaded systems.// - Fixed assertion in HitTest on edit row.// - Added "browse" button option to CReportEditCtrl.// - Added RVN_BUTTONCLICK notification.// - Added RVIS_OWNERDRAW state and RVN_ITEMDRAW notification// to support owner drawn subitems.// - Changed default font to default GUI font.// - Added second PreviewHeight function to calculate the height of// preview text from the text and an optional rectangle.// - Fixed a selection bug in SetItemCount().// - Fixed another selection bug in DeleteItem().// - Fixed FindItem for LPARAM as suggested by Armin Zürcher.// 2.0.0 - Made scrolling with left or right cursor key dependent on// focus subitems style.// - Fixed resource leak in empty list, as suggested by Florent// Odelain.// - Fixed ResortItems and DeactivateSubItem bugs as suggested by// Rafael Lombardi Santos.// - Fixed HitTest on reordered columns, reported by Trevor Ash.// - Fixed item rect returned in hitinfo structure for scrolled// controls. This fixes incorrect positioning of tip windows.// - Added CReportHeaderCtrl to access CFlatHeaderCtrl's protected// members.// - Added first column indent functions, to support hierarchy// GUI elements.// - Fixed HitTest to retrieve correct item data.// - Added parameter to sort callback.// - Removed SortAllSubItems, because implementation was not// maintained and buggy.// - Fixed IsItemVisible and added GetTopIndex(), PageUp() and// PageDown() as suggested by Alina Kozlovsky.// - Added tree control features, both in preparation of group// view mode as well as a standalone feature.// - Fixed subitem text drawing following uninitialized subitems.// - Changed CompareItems callback and functions to support// separate subitems to enable tree view and group view sorting.// - Extended CompareItems to sort on checkboxes as suggested by// Peter Lagerhem.// - Fixed offset of subitem tip for items with images or checks// and text and related hittesting issues.// - Fixed NOHEADER style.// - Changed selected items and tree boxes in tree view mode visuals// to match common control look and feel.// - Fixed default height setting for font size updates with images.// - Fixed cosmetic bug with RVS_SHOWHGRID style, as suggested by Matrix.// - Fixed SelectAll() for empty control as suggested by Dmitry Sazonov.// - Added GetStyle().// - Added RVN_HEADERRCLICK to support popup menus on header.// - Fixed tooltip double click and ALT key relay events by removing// mouse capture.// 2.0.1 - Fixed bug in DeleteItem for tree control mode.// - Fixed item expansion for single subitem hierarchy items.// - Added GetExpandedItemText to allow expanded items to show different// text from the subitem text.// - Added support for radio button and disabled check marks and// radio buttons.// - Added RVP_ENABLEFLATCHECKMARK property, to control the visual style// of check marks or radio buttons.// - Added support for check mark and radio button image list.// - Changed CurrentFocus() to GetCurrentFocus().// - Changed OnKillFocus to recognize all child windows.// - Extended MeasureItem function.// - Fixed GetNextItem() for RVTI_ROOT.// - Added support for SetRedraw suggested by Phil J Pearson.// - Optimized InsertItem performance by skipping GetRowFromItem// when the focus is not on an reorderable row, as suggested by// Phil J Pearson.// - Added disabled background function to CReportSubItemListCtrl.// - Added pre-create style passing to CReportView.// - Adjusted edit box position.// - Fixed a bug related to keydown messages in unfocused state.// - Fixed tip redraw problem and tip background color mismatch.// - Fixed kill tip on WM_KILLFOCUS, finally fixing click and double// click on expanded subitems.// - Added GetSelectedItems method.// - Fixed a selection bug in ClearSelection.// - Made GetReportCtrlPtr virtual and changed CReportView to use// overriden function to get a pointer to the embedded CReportCtrl.// This allows control derived from CReportCtrl to be embedded in// CReportView.// - Added UpdateWindow to SetRedraw when re-enabling redrawing.// - Removed legacy definitions from header file.// - Added blended image support through state bits, focus and selection// through the RVP_ENABLEIMAGEBLENDING and RVP_BLENDCOLOR properties.// - Added support for overlay images.// - Added Win2K tip fading to CReportTipCtrl.// - Fixed nFormat subitem member update in OnHdnItemChanged, as suggested// by Sven Ritter.// - Added selective item cache flush to SetItemCount.// - Added GetItemString() function to retrieve an item as a string.// - Added clipboard Copy support and clipboard separator and indent// properties.// - Fixed OnRvnEndItemEdit to not loose lParam, as suggested by// Paul Hurley.// - Added GetSortSettings() to retrieve sorting settings.// - Made SelectRows virtual to allow owner data multiple selection// management.// - Fixed a bug in DeleteItem for trees.// - Fixed various mouse button, keyboard selection/focus issues.//////////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "ReportCtrl.h"#include "MemDC.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define REPORTDATA_MAX_NODATA 20static TCHAR g_cSeparator = _T('|');static TCHAR g_cCBSeparator = _T('\t');static CString g_strCBIndent = _T(" ");static TCHAR g_szNoData[REPORTDATA_MAX_NODATA];static lpfnUpdateLayeredWindow g_lpfnUpdateLayeredWindow = NULL;static lpfnSetLayeredWindowAttributes g_lpfnSetLayeredWindowAttributes = NULL;#define IsShiftDown() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 )#define IsCtrlDown() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 )/////////////////////////////////////////////////////////////////////////////// CReportDataCReportData::CReportData(){}CReportData::~CReportData(){}BOOL CReportData::New(INT iSubItems){LPTSTR lpsz = GetBuffer(iSubItems*REPORTDATA_MAX_NODATA);lpsz[0] = 0;for(INT i=0;i<iSubItems;i++)lpsz = _tcscat( lpsz, g_szNoData );ReleaseBuffer();return TRUE;}BOOL CReportData::GetSubItem(INT iSubItem, LPINT lpiImage, LPINT lpiOverlay, LPINT lpiCheck, LPINT lpiColor, LPTSTR lpszText, LPINT lpiTextMax){INT i, iPos, iText;for(i=0,iPos=0;i<iSubItem&&iPos>=0;i++,iPos++)iPos = Find(g_cSeparator, iPos);if(iPos<0)return FALSE;LPCTSTR lpsz = m_pchData;lpsz = &lpsz[iPos];VERIFY(_stscanf(lpsz, _T("(%d,%d,%d,%d,%d)"), lpiImage, lpiOverlay, lpiCheck, lpiColor, &iText));if(iText < 0)*lpiTextMax = -1;if(*lpiImage == -1 && *lpiOverlay == -1 && *lpiCheck == -1 && *lpiColor == -1 && *lpiTextMax == -1)return FALSE;if(iText < 0)return TRUE;lpsz = _tcspbrk(lpsz, _T(")"))+1;if(lpsz && lpszText){for(INT iTextSize=0;iTextSize<(*lpiTextMax)-1 && *lpsz!=g_cSeparator;iTextSize++)lpszText[iTextSize] = *lpsz++;lpszText[iTextSize] = 0;}return TRUE;}BOOL CReportData::SetSubItem(INT iSubItem, INT iImage, INT iOverlay, INT iCheck, INT iColor, LPCTSTR lpszText){if(!InsertSubItem(iSubItem, iImage, iOverlay, iCheck, iColor, lpszText))return FALSE;if(!DeleteSubItem(iSubItem+1))return FALSE;return TRUE;}BOOL CReportData::InsertSubItem(INT iSubItem, INT iImage, INT iOverlay, INT iCheck, INT iColor, LPCTSTR lpszText){INT i, iPos, iText;for(i=0,iPos=0;i<iSubItem&&iPos>=0;i++,iPos++)iPos = Find(g_cSeparator, iPos);if(iPos<0)return FALSE;if(lpszText == NULL){lpszText = _T("");iText = -1;}elseiText = _tcslen(lpszText);TCHAR sz[32+REPORTCTRL_MAX_TEXT];_stprintf(sz, _T("(%d,%d,%d,%d,%d)%s%c"), iImage, iOverlay, iCheck, iColor, iText, lpszText, g_cSeparator);Insert(iPos, sz);return TRUE;}BOOL CReportData::DeleteSubItem(INT iSubItem){INT i, iPos1, iPos2;for(i=0,iPos1=0;i<iSubItem&&iPos1>=0;i++,iPos1++)iPos1 = Find(g_cSeparator, iPos1);if(iPos1<0)return FALSE;iPos2 = Find(g_cSeparator, iPos1);if(iPos2++<0)return FALSE;Delete(iPos1, iPos2-iPos1);return TRUE;}/////////////////////////////////////////////////////////////////////////////// CReportViewIMPLEMENT_DYNCREATE(CReportView, CView)CReportView::CReportView(){m_bCreated = FALSE;}CReportView::~CReportView(){}BOOL CReportView::PreCreateWindow(CREATESTRUCT& cs){BOOL bResult = CView::PreCreateWindow(cs);m_wndReportCtrl.m_dwStyle = cs.style&0xFFFF;return bResult;}void CReportView::OnInitialUpdate(){CView::OnInitialUpdate();if(!m_bCreated && GetReportCtrlPtr() == &m_wndReportCtrl){m_wndReportCtrl.m_dwStyle |= WS_CHILD|WS_TABSTOP|WS_VISIBLE;CRect rect;GetClientRect(rect);if(m_wndReportCtrl.Create(m_wndReportCtrl.m_dwStyle, rect, this, 0) == NULL)AfxThrowMemoryException();}m_bCreated = TRUE;}BEGIN_MESSAGE_MAP(CReportView, CView)//{{AFX_MSG_MAP(CReportView)ON_WM_SIZE()ON_WM_SETFOCUS()ON_WM_ERASEBKGND()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportView drawingvoid CReportView::OnDraw(CDC* pDC){;}/////////////////////////////////////////////////////////////////////////////// CReportView diagnostics#ifdef _DEBUGvoid CReportView::AssertValid() const{CView::AssertValid();}void CReportView::Dump(CDumpContext& dc) const{CView::Dump(dc);}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CReportView attributesCReportCtrl& CReportView::GetReportCtrl(){ASSERT(GetReportCtrlPtr() == &m_wndReportCtrl); // Don't use this function// GetReportCtrlPtr is overridden.return m_wndReportCtrl;}CReportCtrl* CReportView::GetReportCtrlPtr(){return &m_wndReportCtrl;}/////////////////////////////////////////////////////////////////////////////// CReportView implementationBOOL CReportView::OnEraseBkgnd(CDC* pDC){return TRUE;}void CReportView::OnSize(UINT nType, int cx, int cy){CView::OnSize(nType, cx, cy);if(m_bCreated && GetReportCtrlPtr()->GetSafeHwnd() != NULL){CRect rect;GetClientRect(rect);GetReportCtrlPtr()->MoveWindow(rect);}}void CReportView::OnSetFocus(CWnd* pOldWnd){if(m_bCreated && GetReportCtrlPtr()->GetSafeHwnd() != NULL)GetReportCtrlPtr()->SetFocus();}/////////////////////////////////////////////////////////////////////////////// CReportCtrlIMPLEMENT_DYNCREATE(CReportCtrl, CWnd)CReportCtrl::CReportCtrl(){WNDCLASS wndclass;HINSTANCE hInst = AfxGetInstanceHandle();if(!(::GetClassInfo(hInst, REPORTCTRL_CLASSNAME, &wndclass))){wndclass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW;wndclass.lpfnWndProc = ::DefWindowProc;wndclass.cbClsExtra = wndclass.cbWndExtra = 0;wndclass.hInstance = hInst;wndclass.hIcon = NULL;wndclass.hCursor = LoadCursor(hInst, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)COLOR_WINDOW;wndclass.lpszMenuName = NULL;wndclass.lpszClassName = REPORTCTRL_CLASSNAME;if (!AfxRegisterClass(&wndclass))AfxThrowResourceException();}m_bSubclassFromCreate = FALSE;m_bDoubleBuffer = TRUE;m_bRedrawFlag = TRUE;m_iSpacing = 6;m_nRowsPerWheelNotch = GetMouseScrollLines();m_dwStyle = 0;m_bPreview = TRUE;m_bHorzScrollBar = TRUE;m_font.CreateStockObject( DEFAULT_GUI_FONT );m_pImageList = NULL;m_pCheckList = NULL;m_sizeImage.cx = 0;m_sizeImage.cy = 0;m_sizeCheck.cx = 8;m_sizeCheck.cy = 8;m_arrayColors.SetSize(0, 8);m_iGridStyle = PS_SOLID;m_nFrameControlStyle = DFCS_FLAT;m_nBlendStyle = RVP_BLEND_NONE;m_crBlendColor = RGB(0xff, 0xff, 0xff);m_strNoItems = _T("There are no items to show in this view.");m_strSortBy = _T("Sort by: %s");_stprintf(g_szNoData, _T("(-1,-1,-1,-1,-1)%c"), g_cSeparator);m_iDefaultWidth = 200;m_iDefaultHeight = 10;m_iVirtualWidth = 0;m_iVirtualHeight = 0;m_arraySubItems.SetSize(0, 8);m_arrayItems.SetSize(0, 128);m_tiRoot.bOpen = TRUE;m_bEditValid = FALSE;m_bUseItemCacheMap = TRUE;for(UINT n=0;n<REPORTCTRL_MAX_CACHE;n++)m_aciCache[n].iItem = RVI_INVALID;m_bProcessKey = FALSE;m_bUpdateItemMap = FALSE;m_bColumnsReordered = FALSE;m_arrayColumns.SetSize(0, 8);m_bFocus = FALSE;m_iFocusRow = RVI_EDIT;m_iFocusColumn = -1;m_iSelectRow = 0;m_arrayRows.SetSize(0, 128);m_bIndentColumn = FALSE;m_bIndentGrey = FALSE;m_iIndentColumn = 0;m_iIndentColumnPending = -1;m_iEditItem = RVI_INVALID;m_iEditSubItem = -1;m_hEditWnd = NULL;m_lprsilc = NULL;m_lpfnrvc = NULL;m_lParamCompare = 0;m_uNotifyMask = RVNM_ALL;}CReportCtrl::~CReportCtrl(){m_wndHeader.DestroyWindow();m_wndTip.DestroyWindow();if(m_palette.m_hObject)m_palette.DeleteObject();if( m_bitmap.m_hObject != NULL )m_bitmap.DeleteObject();if(m_font.m_hObject)m_font.DeleteObject();if(m_fontBold.m_hObject)m_fontBold.DeleteObject();}BOOL CReportCtrl::Create(){CRect rect(0, 0, 0, 0);DWORD dwStyle = HDS_HORZ|HDS_BUTTONS|HDS_FULLDRAG|HDS_DRAGDROP|CCS_TOP;if(!m_wndHeader.Create(dwStyle, rect, this, 0))return FALSE;if(!m_wndTip.Create(this))return FALSE;CWnd* pWnd = GetParent();if(pWnd){CFont* pFont = pWnd->GetFont();if(pFont){LOGFONT lf;pFont->GetLogFont(&lf);m_font.DeleteObject();m_font.CreateFontIndirect(&lf);}}OnSetFont((WPARAM)((HFONT)m_font), FALSE);m_wndHeader.SetFont(&m_font, FALSE);m_dwStyle = CWnd::GetStyle();GetClientRect(rect);Layout(rect.Width(), rect.Height());GetSysColors();return TRUE;}BOOL CReportCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext){m_bSubclassFromCreate = TRUE;if(!CWnd::Create(REPORTCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID, pContext))return FALSE;return Create();}void CReportCtrl::PreSubclassWindow(){CWnd::PreSubclassWindow();if(!m_bSubclassFromCreate)if(!Create())AfxThrowMemoryException();}void CReportCtrl::OnDestroy(){DeleteAllItems();CWnd::OnDestroy();}BEGIN_MESSAGE_MAP(CReportCtrl, CWnd)//{{AFX_MSG_MAP(CReportCtrl)ON_WM_DESTROY()ON_WM_SIZE()ON_WM_ERASEBKGND()ON_WM_PAINT()ON_WM_SYSCOLORCHANGE()ON_WM_SETTINGCHANGE()ON_NOTIFY(HDN_ITEMCHANGED, 0, OnHdnItemChanged)ON_NOTIFY(HDN_ITEMCLICK, 0, OnHdnItemClick)ON_NOTIFY(HDN_BEGINDRAG, 0, OnHdnBeginDrag)ON_NOTIFY(HDN_ENDDRAG, 0, OnHdnEndDrag)ON_NOTIFY(HDN_DIVIDERDBLCLICK, 0, OnHdnDividerDblClick)ON_NOTIFY(RVN_ENDITEMEDIT, 0, OnRvnEndItemEdit)ON_WM_HSCROLL()ON_WM_VSCROLL()ON_WM_LBUTTONDOWN()ON_WM_SETCURSOR()ON_WM_KEYDOWN()ON_WM_GETDLGCODE()ON_WM_LBUTTONDBLCLK()ON_WM_QUERYNEWPALETTE()ON_WM_PALETTECHANGED()ON_WM_SETFOCUS()ON_WM_KILLFOCUS()ON_WM_NCCALCSIZE()ON_WM_NCPAINT()ON_WM_MOUSEWHEEL()ON_WM_CHAR()ON_WM_MOUSEMOVE()ON_WM_RBUTTONDOWN()ON_WM_WINDOWPOSCHANGING()//}}AFX_MSG_MAPON_MESSAGE(WM_SETFONT, OnSetFont)ON_MESSAGE(WM_GETFONT, OnGetFont)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportCtrl attributesDWORD CReportCtrl::GetStyle() const{return (CWnd::GetStyle()&0xFFFF0000)|m_dwStyle;}BOOL CReportCtrl::ModifyProperty(WPARAM wParam, LPARAM lParam){switch(wParam){case RVP_SPACING:m_iSpacing = (INT)lParam;break;case RVP_CHECK:m_sizeCheck.cx = LOWORD(lParam);m_sizeCheck.cy = HIWORD(lParam);break;case RVP_NOITEMTEXT:m_strNoItems = (LPCTSTR)lParam;break;case RVP_GRIDSTYLE:switch(lParam){case RVP_GRIDSTYLE_DOT: m_iGridStyle = PS_DOT; break;case RVP_GRIDSTYLE_DASH: m_iGridStyle = PS_DASH; break;case RVP_GRIDSTYLE_SOLID: m_iGridStyle = PS_SOLID; break;default:return FALSE;}break;case RVP_SORTTOOLTIP:m_strSortBy = (LPCTSTR)lParam;break;case RVP_NOTIFYMASK:m_uNotifyMask = (ULONG)lParam;break;case RVP_ENABLEITEMCACHEMAP:m_bUseItemCacheMap = (BOOL)lParam;break;case RVP_SEPARATOR:g_cSeparator = (TCHAR)lParam;_stprintf(g_szNoData, _T("(-1,-1,-1,-1)%c"), g_cSeparator);break;case RVP_ENABLEPREVIEW:m_bPreview = (BOOL)lParam;break;case RVP_ENABLEHORZSCROLLBAR:m_bHorzScrollBar = (BOOL)lParam;break;case RVP_FRAMECONTROLSTYLE:switch(lParam){case RVP_FCSTYLE_FLAT: m_nFrameControlStyle = DFCS_FLAT; break;case RVP_FCSTYLE_MONO: m_nFrameControlStyle = DFCS_MONO; break;case RVP_FCSTYLE_NORMAL: m_nFrameControlStyle = 0; break;default:return FALSE;}break;case RVP_ENABLEIMAGEBLENDING:m_nBlendStyle = (UINT)lParam;break;case RVP_BLENDCOLOR:m_crBlendColor = (COLORREF)lParam;break;case RVP_CBSEPARATOR:g_cCBSeparator = (TCHAR)lParam;break;case RVP_CBINDENT:g_strCBIndent = (LPCTSTR)lParam;break;default:return FALSE;}CRect rect;GetClientRect(rect);Layout(rect.Width(), rect.Height());return TRUE;}INT CReportCtrl::ActivateSubItem(INT iSubItem, INT iColumn){ASSERT(iSubItem>=0);ASSERT(iSubItem<m_arraySubItems.GetSize()); // Specify a valid subitemSUBITEM& subitem = m_arraySubItems[iSubItem];INT iResult = -1;if(GetColumnFromSubItem(iSubItem) < 0){UnindentFirstColumn();try{HDITEM hdi;hdi.mask = HDI_FORMAT|HDI_WIDTH|HDI_LPARAM|HDI_ORDER;hdi.fmt = subitem.nFormat&RVCF_MASK;hdi.cxy = subitem.iWidth;hdi.iOrder = iColumn;hdi.lParam = (LPARAM)iSubItem;if(subitem.nFormat&RVCF_IMAGE){hdi.mask |= HDI_IMAGE;hdi.iImage = subitem.iImage;}if(subitem.nFormat&RVCF_TEXT){hdi.mask |= HDI_TEXT;hdi.pszText = subitem.strText.GetBuffer(0);}iResult = m_wndHeader.InsertItem(m_arrayColumns.GetSize(), &hdi);if(iResult >= 0){m_iVirtualWidth += subitem.iWidth;HDITEMEX hditemex;hditemex.nStyle = (subitem.nFormat&RVCF_EX_MASK)>>16;hditemex.iMinWidth = subitem.iMinWidth;hditemex.iMaxWidth = subitem.iMaxWidth;if(hditemex.nStyle&HDF_EX_TOOLTIP)hditemex.strToolTip.Format(m_strSortBy, subitem.strText);m_wndHeader.SetItemEx(iResult, &hditemex);hdi.mask = HDI_WIDTH;m_wndHeader.GetItem(iResult, &hdi);subitem.iWidth = hdi.cxy;ReorderColumns();ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));}IndentFirstColumn();}catch(CMemoryException* e){e->Delete();if(iResult >= 0)m_wndHeader.DeleteItem(iResult);}}return iResult;}BOOL CReportCtrl::DeactivateSubItem(INT iSubItem){ASSERT(iSubItem>=0);ASSERT(iSubItem<m_arraySubItems.GetSize()); // Specify a valid subitemINT iColumn = GetColumnFromSubItem(iSubItem);if(iColumn < 0)return FALSE;UnindentFirstColumn();BOOL bAscending;INT iSortColumn = m_wndHeader.GetSortColumn(&bAscending);if(iColumn == iSortColumn)m_wndHeader.SetSortColumn(-1, TRUE);else if(iColumn < iSortColumn)m_wndHeader.SetSortColumn(m_arrayColumns[iSortColumn-1], bAscending);HDITEM hdi;hdi.mask = HDI_WIDTH;m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);BOOL bResult = m_wndHeader.DeleteItem(m_arrayColumns[iColumn]);m_iVirtualWidth -= hdi.cxy;ReorderColumns();ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));IndentFirstColumn();return bResult;}BOOL CReportCtrl::DeactivateAllSubItems(){INT iSubItems = m_arraySubItems.GetSize();for(INT iSubItem=0;iSubItem<iSubItems;iSubItem++){if(IsActiveSubItem(iSubItem)){if(!DeactivateSubItem(iSubItem))return FALSE;}}return TRUE;}BOOL CReportCtrl::IsActiveSubItem(INT iSubItem){INT iColumn = GetColumnFromSubItem(iSubItem);return iColumn<0 ? FALSE:TRUE;}INT CReportCtrl::GetActiveSubItemCount(){return m_arrayColumns.GetSize();}INT CReportCtrl::GetSubItemWidth(INT iSubItem){INT iSubItems = m_arraySubItems.GetSize();ASSERT(iSubItem <= iSubItems);try{INT iWidth = m_arraySubItems[iSubItem].iWidth;if(m_bIndentColumn &&GetColumnFromSubItem(iSubItem) == 0)iWidth -= m_iIndentColumn;return iWidth;}catch(CMemoryException* e){e->Delete();return -1;}}BOOL CReportCtrl::SetSubItemWidth(INT iSubItem, INT iWidth){BOOL bResult;UnindentFirstColumn();bResult = SetSubItemWidthImpl(iSubItem, iWidth);IndentFirstColumn();return bResult;}INT CReportCtrl::GetItemIndex(HTREEITEM hItem){ASSERT(m_dwStyle&RVS_TREEVIEW);return ((LPTREEITEM)hItem)->iItem;}HTREEITEM CReportCtrl::GetItemHandle(INT iItem){ASSERT(m_dwStyle&RVS_TREEVIEW);return iItem>=RVI_FIRST ? (HTREEITEM)m_arrayItems[iItem].lptiItem:NULL;}void CReportCtrl::SetTreeSubItem(HTREEITEM hItem, INT iSubItem){((LPTREEITEM)hItem)->iSubItem = iSubItem;}HTREEITEM CReportCtrl::GetNextItem(HTREEITEM hItem, UINT nCode){LPTREEITEM lpti = (LPTREEITEM)hItem;if( hItem == RVTI_ROOT )lpti = &m_tiRoot;switch(nCode){case RVGN_ROOT:while(lpti->lptiParent != &m_tiRoot)lpti = lpti->lptiParent;break;case RVGN_NEXT:lpti = lpti->lptiSibling;break;case RVGN_PREVIOUS:if(lpti->lptiParent->lptiChildren != lpti){LPTREEITEM lptiSibling = lpti->lptiParent->lptiChildren;ASSERT(lptiSibling != NULL);while(lptiSibling->lptiSibling != lpti){lptiSibling = lptiSibling->lptiSibling;ASSERT(lptiSibling != NULL);}lpti = lptiSibling;}elselpti = NULL;break;case RVGN_PARENT:lpti = lpti->lptiParent != &m_tiRoot ? lpti->lptiParent:NULL;break;case RVGN_CHILD:lpti = lpti->lptiChildren;break;case RVGN_FOCUSED:{INT iFocusItem = GetItemFromRow(m_iFocusRow);if(iFocusItem >= RVI_FIRST)lpti = m_arrayItems[iFocusItem].lptiItem;elselpti = NULL;}break;default:lpti = NULL;break;}return (HTREEITEM)lpti;}BOOL CReportCtrl::GetItem(LPRVITEM lprvi){ASSERT(lprvi->iItem > RVI_INVALID);ASSERT(lprvi->iItem < GetItemCount()); // Specify itemASSERT(lprvi->iSubItem < m_arraySubItems.GetSize()); // Specify subitemif((lprvi->iItem <= RVI_INVALID) ||(lprvi->iItem >= GetItemCount()) ||(lprvi->iSubItem >= m_arraySubItems.GetSize()))return FALSE;UINT nMask = lprvi->nMask;INT iTextMax = lprvi->iTextMax;ITEM& item = GetItemStruct(lprvi->iItem, lprvi->iSubItem, nMask);lprvi->nMask = 0;lprvi->iBkColor = item.iBkColor;if(lprvi->iBkColor >= 0)lprvi->nMask |= RVIM_BKCOLOR;lprvi->nPreview = item.nPreview;if(lprvi->nPreview > 0)lprvi->nMask |= RVIM_PREVIEW;lprvi->iIndent = item.iIndent;if(lprvi->iIndent >= 0)lprvi->nMask |= RVIM_INDENT;lprvi->lpszText = nMask&RVIM_TEXT ? lprvi->lpszText:NULL;item.rdData.GetSubItem(lprvi->iSubItem, &lprvi->iImage, &lprvi->iOverlay, &lprvi->iCheck, &lprvi->iTextColor, lprvi->lpszText, &iTextMax);if(lprvi->lpszText && iTextMax >= 0)lprvi->nMask |= RVIM_TEXT;if(lprvi->iImage >= 0)lprvi->nMask |= RVIM_IMAGE;if(lprvi->iOverlay >= 0)lprvi->nMask |= RVIM_OVERLAY;if(lprvi->iCheck >= 0)lprvi->nMask |= RVIM_CHECK;if(lprvi->iTextColor >= 0)lprvi->nMask |= RVIM_TEXTCOLOR;lprvi->nMask |= RVIM_STATE|RVIM_LPARAM;lprvi->nState = item.nState;lprvi->lParam = item.lParam;return TRUE;}BOOL CReportCtrl::SetItem(LPRVITEM lprvi){ASSERT(!(lprvi->iItem != RVI_EDIT && m_dwStyle&RVS_OWNERDATA)); // Not supported when using this styleif(m_dwStyle&RVS_OWNERDATA)return FALSE;m_wndTip.Hide();TCHAR szText[REPORTCTRL_MAX_TEXT];RVITEM rvi;rvi.iItem = lprvi->iItem;rvi.iSubItem = lprvi->iSubItem;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;rvi.nMask = RVIM_TEXT|RVIM_STATE;VERIFY(GetItem(&rvi));if(lprvi->nMask&RVIM_TEXT){if(lprvi->lpszText != NULL){_tcsncpy(rvi.lpszText, lprvi->lpszText, REPORTCTRL_MAX_TEXT-1);rvi.lpszText[REPORTCTRL_MAX_TEXT-1] = 0;}elservi.lpszText = NULL;}else if(!(rvi.nMask&RVIM_TEXT))rvi.lpszText = NULL;if(lprvi->nMask&RVIM_TEXTCOLOR)rvi.iTextColor = lprvi->iTextColor;if(lprvi->nMask&RVIM_IMAGE){ASSERT(m_pImageList != NULL && lprvi->iImage < m_pImageList->GetImageCount());rvi.iImage = lprvi->iImage;}if(lprvi->nMask&RVIM_OVERLAY){ASSERT(m_pImageList != NULL && lprvi->iOverlay < m_pImageList->GetImageCount());rvi.iOverlay = lprvi->iOverlay;}if(lprvi->nMask&RVIM_CHECK)rvi.iCheck = lprvi->iCheck;if(lprvi->nMask&RVIM_BKCOLOR)rvi.iBkColor = lprvi->iBkColor;ASSERT(!(lprvi->iItem == RVI_EDIT && lprvi->nMask&RVIM_PREVIEW)); // Preview not supported on edit rowif(lprvi->nMask&RVIM_PREVIEW)rvi.nPreview = lprvi->nPreview;if(lprvi->nMask&RVIM_INDENT)rvi.iIndent = lprvi->iIndent;// Note: focus, selection and tree-GUI elements cannot be changed through this functionif(lprvi->nMask&RVIM_STATE){rvi.nState &= RVIS_FOCUSED|RVIS_SELECTED|RVIS_TREEMASK;rvi.nState |= lprvi->nState&~(RVIS_FOCUSED|RVIS_SELECTED|RVIS_TREEMASK);}if(lprvi->nMask&RVIM_LPARAM)rvi.lParam = lprvi->lParam;ITEM& item = GetItemStruct(rvi.iItem, rvi.iSubItem);VERIFY(item.rdData.InsertSubItem(rvi.iSubItem, rvi.iImage, rvi.iOverlay, rvi.iCheck, rvi.iTextColor, rvi.lpszText));VERIFY(item.rdData.DeleteSubItem(rvi.iSubItem+1));item.iBkColor = rvi.iBkColor;item.nPreview = rvi.nPreview;item.iIndent = rvi.iIndent;item.nState = rvi.nState;item.lParam = rvi.lParam;SetItemStruct(rvi.iItem, item);ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));if(m_bRedrawFlag == TRUE)RedrawItems(rvi.iItem);return TRUE;}INT CReportCtrl::GetItemText(INT iItem, INT iSubItem, LPTSTR lpszText, INT iLen){RVITEM rvi;rvi.nMask = RVIM_TEXT;rvi.iItem = iItem;rvi.iSubItem = iSubItem;rvi.lpszText = lpszText;rvi.iTextMax = iLen;return GetItem(&rvi) ? _tcslen(rvi.lpszText):0;}CString CReportCtrl::GetItemText(INT iItem, INT iSubItem){CString str;TCHAR szText[REPORTCTRL_MAX_TEXT];if(GetItemText(iItem, iSubItem, szText, REPORTCTRL_MAX_TEXT))str = szText;return str;}BOOL CReportCtrl::SetItemText(INT iItem, INT iSubItem, LPCTSTR lpszText){RVITEM rvi;rvi.nMask = RVIM_TEXT;rvi.iItem = iItem;rvi.iSubItem = iSubItem;rvi.lpszText = (LPTSTR)lpszText;return SetItem(&rvi);}INT CReportCtrl::GetItemImage(INT iItem, INT iSubItem){RVITEM rvi;rvi.nMask = RVIM_IMAGE;rvi.iItem = iItem;rvi.iSubItem = iSubItem;return GetItem(&rvi) ? rvi.iImage:-1;}BOOL CReportCtrl::SetItemImage(INT iItem, INT iSubItem, INT iImage){RVITEM rvi;rvi.nMask = RVIM_IMAGE;rvi.iItem = iItem;rvi.iSubItem = iSubItem;rvi.iImage = iImage;return SetItem(&rvi);}INT CReportCtrl::GetItemCheck(INT iItem, INT iSubItem){RVITEM rvi;rvi.nMask = RVIM_CHECK;rvi.iItem = iItem;rvi.iSubItem = iSubItem;return GetItem(&rvi) ? rvi.iCheck:-1;}BOOL CReportCtrl::SetItemCheck(INT iItem, INT iSubItem, INT iCheck){RVITEM rvi;rvi.nMask = RVIM_CHECK;rvi.iItem = iItem;rvi.iSubItem = iSubItem;rvi.iCheck = iCheck;return SetItem(&rvi);}DWORD CReportCtrl::GetItemData(INT iItem){RVITEM rvi;rvi.nMask = RVIM_LPARAM;rvi.iItem = iItem;return GetItem(&rvi) ? rvi.lParam:0;}BOOL CReportCtrl::SetItemData(INT iItem, DWORD dwData){RVITEM rvi;rvi.nMask = RVIM_LPARAM;rvi.iItem = iItem;rvi.lParam = dwData;return SetItem(&rvi);}BOOL CReportCtrl::GetItemRect(INT iItem, INT iSubItem, LPRECT lpRect, UINT nCode){INT iRow = GetRowFromItem(iItem);INT iColumn = GetColumnFromSubItem(iSubItem);if( nCode == RVIR_TEXTNOCOLUMNS )iColumn = 0;if(!GetRowRect(iRow, iColumn, lpRect, nCode))return FALSE;RVITEM rvi;rvi.iItem = iItem;rvi.iSubItem = iSubItem;GetItem(&rvi);if(nCode != RVIR_BOUNDS && iColumn == 0 && rvi.nMask&RVIM_INDENT && rvi.iIndent >= 0){lpRect->left += rvi.iIndent*m_iDefaultHeight;if(lpRect->left > lpRect->right)return FALSE;}switch(nCode){case RVIR_BOUNDS:return TRUE;case RVIR_IMAGE:if(!(rvi.nMask&RVIM_IMAGE))return FALSE;lpRect->left += m_iSpacing;if(lpRect->left + m_sizeImage.cx > lpRect->right - m_iSpacing)return FALSE;lpRect->right = lpRect->left + m_sizeImage.cx;return TRUE;case RVIR_CHECK:if(!(rvi.nMask&RVIM_CHECK))return FALSE;lpRect->left += m_iSpacing + (rvi.nMask&RVIM_IMAGE ? m_sizeImage.cx+m_iSpacing:0);if(lpRect->left + m_sizeCheck.cx > lpRect->right - m_iSpacing)return FALSE;lpRect->right = lpRect->left + m_sizeCheck.cx;return TRUE;case RVIR_TEXT:case RVIR_TEXTNOCOLUMNS:lpRect->left += m_iSpacing +(rvi.nMask&RVIM_IMAGE ? m_sizeImage.cx+m_iSpacing:0) +(rvi.nMask&RVIM_CHECK ? m_sizeCheck.cx+m_iSpacing:0);if(lpRect->left > lpRect->right - m_iSpacing)return FALSE;lpRect->right -= m_iSpacing;return TRUE;default:return FALSE;}}BOOL CReportCtrl::MeasureItem(INT iItem, INT iSubItem, LPRECT lpRect, BOOL bTextOnly){lpRect->top = 0;lpRect->bottom = m_iDefaultHeight;lpRect->left = 0;lpRect->right = m_iDefaultWidth;if(iSubItem != -1){TCHAR szText[REPORTCTRL_MAX_TEXT];RVITEM rvi;rvi.nMask = RVIM_TEXT;rvi.iItem = iItem;rvi.iSubItem = iSubItem;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;GetItem(&rvi);lpRect->right = m_iSpacing;if(bTextOnly == FALSE){lpRect->right +=(rvi.nMask&RVIM_IMAGE ? m_sizeImage.cx+m_iSpacing:0) +(rvi.nMask&RVIM_CHECK ? m_sizeCheck.cx+m_iSpacing:0);}if(rvi.nMask&RVIM_TEXT){CClientDC dc(this);CFont *pFontDC = dc.SelectObject(rvi.nState&RVIS_BOLD ? &m_fontBold:&m_font);lpRect->right += dc.GetTextExtent(rvi.lpszText, _tcslen(rvi.lpszText)).cx + m_iSpacing;dc.SelectObject(pFontDC);}}return TRUE;}INT CReportCtrl::GetItemHeight(){return m_iDefaultHeight;}void CReportCtrl::SetItemHeight(INT iHeight){m_iDefaultHeight = iHeight;CRect rect;GetClientRect(rect);Layout(rect.Width(), rect.Height());}CString CReportCtrl::GetItemString(INT iItem, TCHAR cSeparator){CString str;TCHAR szText[REPORTCTRL_MAX_TEXT+1];INT iColumn, iColumns = m_arrayColumns.GetSize();for(iColumn=0;iColumn<iColumns;iColumn++){HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);RVITEM rvi;rvi.iItem = iItem;rvi.iSubItem = hdi.lParam;rvi.nMask = RVIM_TEXT;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;VERIFY(GetItem(&rvi));if(rvi.nMask&RVIM_TEXT){LPTSTR lpsz = rvi.lpszText;do{lpsz = _tcschr( lpsz, cSeparator );if( lpsz != NULL )*lpsz = _T(' ');} while( lpsz != NULL );}else if(rvi.nMask&RVIM_IMAGE){_stprintf(szText, _T("%d"), rvi.iImage );}else if(rvi.nMask&RVIM_CHECK){_stprintf(szText, _T("%d"), rvi.iCheck );}elseszText[0] = 0;if(m_dwStyle&RVS_TREEMASK && iColumn == 0 && rvi.nMask&RVIM_INDENT){for(INT i=1;i<rvi.iIndent;i++)str += g_strCBIndent;HTREEITEM hItem = GetItemHandle(iItem);ASSERT(hItem != NULL);if(HasChildren(hItem))str += GetNextItem(hItem, RVGN_CHILD) != NULL ? _T('-'):_T('+');elsestr += _T(' ');}str += rvi.lpszText;str += iColumn < iColumns-1 ? cSeparator:_T('\n');}return str;}INT CReportCtrl::GetVisibleCount(BOOL bUnobstructed){return GetVisibleRows(bUnobstructed);}INT CReportCtrl::GetTopIndex(){return GetScrollPos32(SB_VERT);}BOOL CReportCtrl::IsItemVisible(INT iItem, BOOL bUnobstructed){INT iFirst, iLast, iRow;iRow = GetRowFromItem(iItem);iFirst = GetScrollPos32(SB_VERT);GetVisibleRows(bUnobstructed, &iFirst, &iLast);return (iRow>=iFirst && iRow<=iLast) ? TRUE:FALSE;}void CReportCtrl::PageUp(){INT iPos = GetTopIndex() - GetVisibleCount();ScrollWindow(SB_VERT, iPos<0 ? 0:iPos);}void CReportCtrl::PageDown(){INT iPos = GetTopIndex() + GetVisibleCount();ScrollWindow(SB_VERT, iPos);}INT CReportCtrl::GetItemCount(){return m_dwStyle&RVS_OWNERDATA ? m_iVirtualHeight:m_arrayItems.GetSize();}INT CReportCtrl::GetItemCount(HTREEITEM hParent, BOOL bRecurse){INT iCount = 0;LPTREEITEM lptiSibling =hParent == RVTI_ROOT?m_tiRoot.lptiChildren:((LPTREEITEM)hParent)->lptiChildren;while(lptiSibling != NULL){if(bRecurse == TRUE && lptiSibling->lptiChildren != NULL)iCount += GetItemCount((HTREEITEM)lptiSibling, bRecurse);lptiSibling = lptiSibling->lptiSibling;iCount ++;}return iCount;}void CReportCtrl::SetItemCount(INT iCount){ASSERT(m_dwStyle&RVS_OWNERDATA); // Only supported when using RVS_OWNERDATA styleASSERT(iCount >= 0);INT i;m_iVirtualHeight = iCount;m_iFocusRow = m_iFocusRow>=m_iVirtualHeight ? m_iVirtualHeight-1:m_iFocusRow;CList<INT, INT> list;while( !m_listSelection.IsEmpty() ){i = m_listSelection.GetHead();if(i < iCount)list.AddTail(i);m_listSelection.RemoveHead();}m_listSelection.AddTail(&list);for( i=0; i<REPORTCTRL_MAX_CACHE; i++ ){if( m_aciCache[i].iItem >= iCount )m_aciCache[i].iItem = RVI_INVALID;}RedrawRows(RVI_EDIT, RVI_LAST, TRUE);INT iPos = GetScrollPos32(SB_VERT);ScrollWindow(SB_VERT, iPos>iCount ? iCount : iPos);}INT CReportCtrl::GetFirstSelectedItem(){return GetNextSelectedItem(RVI_INVALID);}INT CReportCtrl::GetNextSelectedItem(INT iItem){RVITEM rvi;rvi.nMask = RVIM_STATE;INT iItems = GetItemCount();for(rvi.iItem=iItem+1;rvi.iItem<iItems;rvi.iItem++)if(GetItem(&rvi) && rvi.nState&RVIS_SELECTED)return rvi.iItem;return RVI_INVALID;}INT CReportCtrl::GetSelectedItems(LPINT lpiItems, INT iMax){INT iItem = GetFirstSelectedItem(), iItems = 0;while(iItem != RVI_INVALID){if(lpiItems != NULL && iItems < iMax)lpiItems[iItems] = iItem;iItem = GetNextSelectedItem(iItem);iItems++;}return iItems;}void CReportCtrl::ClearSelection(){POSITION pos = m_listSelection.GetHeadPosition();while(pos != NULL){INT iItem = m_listSelection.GetAt(pos);INT iRow = GetRowFromItem( iItem );SetState(iRow, GetState(iRow) & ~RVIS_SELECTED, RVIS_SELECTED);RedrawRows( iRow );m_listSelection.GetNext(pos);}m_listSelection.RemoveAll();}void CReportCtrl::InvertSelection(){INT iRows = m_arrayRows.GetSize();INT iFocusRow = m_iFocusRow;SelectRows(RVI_FIRST, iRows-1, TRUE, TRUE, TRUE, FALSE);SelectRows(iFocusRow, iFocusRow, FALSE, FALSE, FALSE, FALSE);}void CReportCtrl::SelectAll(){if( m_arrayRows.GetSize() ){ClearSelection();InvertSelection();}}void CReportCtrl::SetSelection(INT iItem, BOOL bKeepSelection){ASSERT(iItem > RVI_INVALID && iItem < GetItemCount());INT iRow = GetRowFromItem(iItem);SelectRows(iRow, iRow, TRUE, bKeepSelection, FALSE, FALSE);}void CReportCtrl::SetSelection(LPINT lpiItems, INT iCount, BOOL bKeepSelection){INT i, iRow;for(i=0;i<iCount;i++){ASSERT(lpiItems[i] > RVI_INVALID && lpiItems[i] < GetItemCount());iRow = GetRowFromItem(lpiItems[i]);SelectRows(iRow, iRow, TRUE, bKeepSelection|(i != 0), FALSE, FALSE);}}void CReportCtrl::SetSelection(INT iSubItem, CString& strPattern, BOOL bKeepSelection){INT iRows = m_arrayRows.GetSize();if(bKeepSelection == FALSE)ClearSelection();for(INT iRow=0; iRow<iRows; iRow++){INT iItem = GetItemFromRow(iRow);if(MatchString(GetItemText(iItem, iSubItem), strPattern))SelectRows(iRow, iRow, TRUE, TRUE, FALSE, FALSE);}}void CReportCtrl::SetSelectionLessEq(INT iSubItem, INT iMatch, BOOL bKeepSelection){RVITEM rvi;INT iRows = m_arrayRows.GetSize();if(bKeepSelection == FALSE)ClearSelection();rvi.iSubItem = iSubItem;rvi.nMask = RVIM_LPARAM;for(INT iRow=0; iRow<iRows; iRow++){rvi.iItem = GetItemFromRow(iRow);if(GetItem(&rvi)){if(rvi.lParam <= iMatch)SelectRows(iRow, iRow, TRUE, TRUE, FALSE, FALSE);}}}void CReportCtrl::SetSelection(HTREEITEM hItem, BOOL bKeepSelection){SetSelection(((LPTREEITEM)hItem)->iItem, bKeepSelection);}void CReportCtrl::SetSelection(HTREEITEM* lphItems, INT iCount, BOOL bKeepSelection){INT i, iItem, iRow;for(i=0;i<iCount;i++){iItem = ((LPTREEITEM)lphItems[i])->iItem;ASSERT(iItem > RVI_INVALID && iItem < GetItemCount());iRow = GetRowFromItem(iItem);SelectRows(iRow, iRow, TRUE, bKeepSelection|(i != 0), FALSE, FALSE);}}INT CReportCtrl::GetItemRow(INT iItem){ASSERT(!(m_dwStyle&RVS_OWNERDATA));return GetRowFromItem(iItem);}CArray<INT, INT>* CReportCtrl::GetItemRowArray(){ASSERT(!(m_dwStyle&RVS_OWNERDATA));return &m_arrayRows;}BOOL CReportCtrl::SetItemRowArray(CArray<INT, INT>& arrayRows){if(m_dwStyle&RVS_OWNERDATA)return FALSE;ASSERT(m_arrayRows.GetSize() == arrayRows.GetSize()); // Must matchif(m_arrayRows.GetSize() != arrayRows.GetSize())return FALSE;INT iFocusItem = GetItemFromRow(m_iFocusRow);m_arrayRows.Copy(arrayRows);m_bUpdateItemMap = TRUE;m_iFocusRow = GetRowFromItem(iFocusItem);Invalidate();return TRUE;}BOOL CReportCtrl::MoveUp(INT iRow){if(m_dwStyle&RVS_OWNERDATA)return FALSE;if(iRow <= RVI_FIRST)return FALSE;ASSERT(iRow < m_arrayRows.GetSize());INT iTemp = m_arrayRows[iRow-1];m_arrayRows[iRow-1] = m_arrayRows[iRow];m_arrayRows[iRow] = iTemp;if(m_iFocusRow == iRow)m_iFocusRow--;Invalidate();m_bUpdateItemMap = TRUE;return TRUE;}BOOL CReportCtrl::MoveDown(INT iRow){if(m_dwStyle&RVS_OWNERDATA)return FALSE;if(iRow >= m_arrayRows.GetSize()-1)return FALSE;ASSERT(iRow >= RVI_FIRST);INT iTemp = m_arrayRows[iRow+1];m_arrayRows[iRow+1] = m_arrayRows[iRow];m_arrayRows[iRow] = iTemp;if(m_iFocusRow == iRow)m_iFocusRow++;Invalidate();m_bUpdateItemMap = TRUE;return TRUE;}BOOL CReportCtrl::SetImageList(CImageList* pImageList, CImageList* pCheckList){BOOL bResult = TRUE;IMAGEINFO info;m_pImageList = pImageList;m_wndHeader.SetImageList(pImageList);if(pImageList != NULL){if(pImageList->GetImageInfo(0, &info)){m_sizeImage.cx = info.rcImage.right - info.rcImage.left;m_sizeImage.cy = info.rcImage.bottom - info.rcImage.top;m_iDefaultHeight = m_sizeImage.cy+1>m_iDefaultHeight ? m_sizeImage.cy+1:m_iDefaultHeight;}elsebResult = FALSE;}m_pCheckList = pCheckList;if(pCheckList != NULL){if(pCheckList->GetImageInfo(0, &info)){m_sizeCheck.cx = info.rcImage.right - info.rcImage.left;m_sizeCheck.cy = info.rcImage.bottom - info.rcImage.top;m_iDefaultHeight = m_sizeCheck.cy+1>m_iDefaultHeight ? m_sizeCheck.cy+1:m_iDefaultHeight;}elsebResult = FALSE;}Invalidate();return bResult;}CImageList* CReportCtrl::GetImageList(void){return m_pImageList;}BOOL CReportCtrl::SetBkImage(UINT nIDResource){return SetBkImage( (LPCTSTR)nIDResource );}BOOL CReportCtrl::SetBkImage(LPCTSTR lpszResourceName){if(m_bitmap.m_hObject != NULL)m_bitmap.DeleteObject();HBITMAP hBitmap = (HBITMAP)::LoadImage( AfxGetInstanceHandle(),lpszResourceName, IMAGE_BITMAP, 0,0, LR_CREATEDIBSECTION );Invalidate();if(hBitmap == NULL)return FALSE;m_bitmap.Attach(hBitmap);BITMAP bitmap;m_bitmap.GetBitmap(&bitmap);m_sizeBitmap.cx = bitmap.bmWidth;m_sizeBitmap.cy = bitmap.bmHeight;BOOL bResult = CreatePalette();Invalidate();return bResult;}COLORREF CReportCtrl::GetColor(INT iIndex){return m_arrayColors[iIndex];}BOOL CReportCtrl::SetColor(INT iIndex, COLORREF crColor){if(iIndex<0 || iIndex>=m_arrayColors.GetSize())return FALSE;m_arrayColors.SetAt(iIndex, crColor);BOOL bResult = CreatePalette();Invalidate();return bResult;}BOOL CReportCtrl::HasFocus(){return m_bFocus;}INT CReportCtrl::GetCurrentFocus(LPINT lpiColumn){if(lpiColumn != NULL)*lpiColumn = m_iFocusColumn;return m_iFocusRow;}BOOL CReportCtrl::AdjustFocus(INT iRow, INT iColumn){INT iSubItem = GetSubItemFromColumn(iColumn);if(iSubItem>=0 && m_arraySubItems[iSubItem].nFormat&RVCF_SUBITEM_NOFOCUS)return FALSE;if(iRow < RVI_INVALID || iRow > m_iVirtualHeight-1 ||iColumn < -1 || iColumn > m_arrayColumns.GetSize()-1)return FALSE;if(m_iFocusRow > RVI_INVALID && iRow != m_iFocusRow){SetState(m_iFocusRow, 0, RVIS_FOCUSED);RedrawRows(m_iFocusRow);}m_iFocusColumn = iColumn;m_iFocusRow = iRow;if(iRow > RVI_INVALID){SetState(iRow, RVIS_FOCUSED, RVIS_FOCUSED);RedrawRows(m_iFocusRow);}return TRUE;}BOOL CReportCtrl::HasChildren(HTREEITEM hItem){ASSERT(m_dwStyle&RVS_TREEMASK);return ((LPTREEITEM)hItem)->lptiChildren != NULL ? TRUE:FALSE;}BOOL CReportCtrl::IsChild(HTREEITEM hParent, HTREEITEM hItem){ASSERT(m_dwStyle&RVS_TREEMASK);return ((LPTREEITEM)hItem)->lptiParent == (LPTREEITEM)hParent ? TRUE:FALSE;}BOOL CReportCtrl::IsDescendent(HTREEITEM hParent, HTREEITEM hItem){ASSERT(m_dwStyle&RVS_TREEMASK);LPTREEITEM lptiAncestor = ((LPTREEITEM)hItem)->lptiParent;while(lptiAncestor != NULL){if(lptiAncestor == (LPTREEITEM)hParent)return TRUE;lptiAncestor = lptiAncestor->lptiParent;}return FALSE;}CReportHeaderCtrl* CReportCtrl::GetHeaderCtrl(){return m_wndHeader.GetSafeHwnd() != NULL ? &m_wndHeader:NULL;}BOOL CReportCtrl::SetReportSubItemListCtrl(CReportSubItemListCtrl* lprsilc){if(m_lprsilc != NULL){m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, NULL);m_lprsilc->SetReportCtrl(NULL);}m_lprsilc = lprsilc;if(m_lprsilc != NULL){m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, (LPARAM)m_lprsilc->m_hWnd);m_lprsilc->SetReportCtrl(this);}return TRUE;}CReportSubItemListCtrl* CReportCtrl::GetReportSubItemListCtrl(){return m_lprsilc;}BOOL CReportCtrl::SetSortCallback(LPFNRVCOMPARE lpfnrvc, LPARAM lParam){m_lpfnrvc = lpfnrvc;m_lParamCompare = lParam;return TRUE;}LPFNRVCOMPARE CReportCtrl::GetSortCallback(){return m_lpfnrvc;}BOOL CReportCtrl::GetSortSettings(INT *lpiSubItem, BOOL *lpbAscending){INT iColumn = m_wndHeader.GetSortColumn(lpbAscending);if(iColumn >= 0){*lpiSubItem = GetSubItemFromColumn(iColumn);return TRUE;}*lpiSubItem = -1;return FALSE;}BOOL CReportCtrl::WriteProfile(LPCTSTR lpszSection, LPCTSTR lpszEntry){CString str, strProfile;UnindentFirstColumn();if(m_bColumnsReordered)ReorderColumns();INT i;INT iSubItems = m_arraySubItems.GetSize();INT iColumns = m_arrayColumns.GetSize();strProfile.Format(_T("(%d,%d)"), iSubItems, iColumns);for(i=0;i<iSubItems;i++){str.Format(" %d", m_arraySubItems[i].iWidth);strProfile += str;}for(i=0;i<iColumns;i++){HDITEM hdi;hdi.mask = HDI_LPARAM;m_wndHeader.GetItem(m_arrayColumns[i], &hdi);str.Format(" %d", hdi.lParam);strProfile += str;}IndentFirstColumn();CWinApp* pApp = AfxGetApp();return pApp->WriteProfileString(lpszSection, lpszEntry, strProfile);}BOOL CReportCtrl::GetProfile(LPCTSTR lpszSection, LPCTSTR lpszEntry){CString str, strProfile;CWinApp* pApp = AfxGetApp();strProfile = pApp->GetProfileString(lpszSection, lpszEntry);if(strProfile.IsEmpty())return FALSE;UnindentFirstColumn();LPTSTR lpsz = strProfile.GetBuffer(0);INT i;INT iSubItems;INT iColumns;iSubItems = _tcstol(++lpsz, &lpsz, 10);iColumns = _tcstol(++lpsz, &lpsz, 10);if(iSubItems != m_arraySubItems.GetSize())return FALSE;if(iColumns == 0)return FALSE;for(i=0;i<iSubItems;i++)m_arraySubItems[i].iWidth = _tcstol(++lpsz, &lpsz, 10);for(i=0;i<iColumns;i++)ActivateSubItem(_tcstol(++lpsz, &lpsz, 10), i);ReorderColumns();//IndentFirstColumn();return TRUE;}/////////////////////////////////////////////////////////////////////////////// CReportCtrl operationsBOOL CReportCtrl::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags){DWORD dwStyle = CWnd::GetStyle();ASSERT(!(dwRemove&(RVS_OWNERDATA|RVS_TREEVIEW))); // Can't dynamically remove this stylesASSERT(!(dwAdd&(RVS_OWNERDATA|RVS_TREEVIEW))); // Can't dynamically add this stylesif(m_hEditWnd != NULL)EndEdit();if(CWnd::ModifyStyle(dwRemove, dwAdd, nFlags)){if(!(dwStyle&RVS_SHOWHGRID) && dwAdd&RVS_SHOWHGRID)m_iDefaultHeight++;if(dwStyle&RVS_SHOWHGRID && dwRemove&RVS_SHOWHGRID)m_iDefaultHeight--;if(dwRemove&RVS_FOCUSSUBITEMS)m_iFocusColumn = -1;m_dwStyle = CWnd::GetStyle();CRect rect;GetClientRect(rect);Layout(rect.Width(), rect.Height());return TRUE;}return FALSE;}INT CReportCtrl::DefineSubItem(INT iSubItem, LPRVSUBITEM lprvs, BOOL bUpdateList){INT i;INT iSubItems = m_arraySubItems.GetSize();ASSERT(iSubItem <= iSubItems);ASSERT(lprvs->lpszText != NULL); // Must supply (descriptive) text for subitem selectorASSERT(_tcslen(lprvs->lpszText) < FLATHEADER_TEXT_MAX);try{SUBITEM subitem;subitem.nFormat = lprvs->nFormat;subitem.iWidth = lprvs->iWidth<0 ? m_iDefaultWidth:lprvs->iWidth;subitem.iMinWidth = lprvs->iMinWidth;subitem.iMaxWidth = lprvs->iMaxWidth;subitem.iImage = lprvs->nFormat&RVCF_IMAGE ? lprvs->iImage:0;subitem.strText = lprvs->lpszText;m_arraySubItems.InsertAt(iSubItem, subitem);HDITEM hdi;hdi.mask = HDI_LPARAM;INT iHeaderItems = m_arrayColumns.GetSize();for(i=0;i<iHeaderItems;i++)if(m_wndHeader.GetItem(m_arrayColumns[i], &hdi))if(hdi.lParam >= iSubItem){hdi.lParam++;m_wndHeader.SetItem(m_arrayColumns[i], &hdi);}VERIFY(m_itemEdit.rdData.InsertSubItem(iSubItem, -1, -1, -1, -1, NULL));if(!(m_dwStyle&RVS_OWNERDATA)){INT iItems = m_arrayItems.GetSize();for(i=0;i<iItems;i++)VERIFY(m_arrayItems[i].rdData.InsertSubItem(iSubItem, -1, -1, -1, -1, NULL));}if(bUpdateList && m_lprsilc != NULL)m_lprsilc->UpdateList();return iSubItem;}catch(CMemoryException* e){e->Delete();return -1;}}BOOL CReportCtrl::RedefineSubItem(INT iSubItem, LPRVSUBITEM lprvs, BOOL bUpdateList){INT iSubItems = m_arraySubItems.GetSize();ASSERT(iSubItem <= iSubItems);ASSERT(lprvs->lpszText != NULL); // Must supply (descriptive) text for subitem selectorASSERT(_tcslen(lprvs->lpszText) < FLATHEADER_TEXT_MAX);try{SUBITEM subitem;subitem.nFormat = lprvs->nFormat;subitem.iWidth = lprvs->iWidth<0 ? m_iDefaultWidth:lprvs->iWidth;subitem.iMinWidth = lprvs->iMinWidth;subitem.iMaxWidth = lprvs->iMaxWidth;subitem.iImage = lprvs->nFormat&RVCF_IMAGE ? lprvs->iImage:0;subitem.strText = lprvs->lpszText;m_arraySubItems.SetAt(iSubItem, subitem);if(bUpdateList && m_lprsilc != NULL)m_lprsilc->UpdateList();return SetSubItemWidth(iSubItem, lprvs->iWidth);}catch(CMemoryException* e){e->Delete();return FALSE;}}BOOL CReportCtrl::UndefineSubItem(INT iSubItem){ASSERT(iSubItem >= 0);ASSERT(iSubItem < m_arraySubItems.GetSize()); // Specify a valid subitemVERIFY(!DeactivateSubItem(iSubItem));m_arraySubItems.RemoveAt(iSubItem);HDITEM hdi;hdi.mask = HDI_LPARAM;INT i;INT iHeaderItems = m_arrayColumns.GetSize();for(i=0;i<iHeaderItems;i++)if(m_wndHeader.GetItem(m_arrayColumns[i], &hdi))if(hdi.lParam > iSubItem){hdi.lParam--;m_wndHeader.SetItem(m_arrayColumns[i], &hdi);}VERIFY(m_itemEdit.rdData.DeleteSubItem(iSubItem));if(!(m_dwStyle&RVS_OWNERDATA)){INT iItems = m_arrayItems.GetSize();for(i=0;i<iItems;i++)VERIFY(m_arrayItems[i].rdData.DeleteSubItem(iSubItem));}if(m_lprsilc != NULL)m_lprsilc->UpdateList();return TRUE;}void CReportCtrl::UndefineAllSubItems(){while (m_arraySubItems.GetSize() > 0)UndefineSubItem(0);}INT CReportCtrl::AddItem(LPCTSTR lpszText, INT iImage, INT iCheck, INT iTextColor){INT iItems = m_arrayItems.GetSize();return InsertItem(iItems, lpszText, iImage, iCheck, iTextColor);}INT CReportCtrl::AddItem(LPRVITEM lprvi){INT iItems = m_arrayItems.GetSize();if(lprvi == NULL){INT iSubItem = 0, iSubItems = m_arraySubItems.GetSize();RVITEM rvi;TCHAR szText[REPORTCTRL_MAX_TEXT];rvi.iItem = RVI_EDIT;rvi.iSubItem = 0;rvi.nMask = RVIM_TEXT;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;VERIFY(GetItem(&rvi));rvi.iItem = iItems;INT iItem = InsertItem(&rvi);if(iItem != RVI_INVALID){for(iSubItem = 1;iSubItem<iSubItems;iSubItem++){rvi.iItem = RVI_EDIT;rvi.iSubItem = iSubItem;rvi.nMask = RVIM_TEXT;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;VERIFY(GetItem(&rvi));rvi.iItem = iItem;VERIFY(SetItem(&rvi));}}return iItem;}elsereturn InsertItem(lprvi);}INT CReportCtrl::InsertItem(INT iItem, LPCTSTR lpszText, INT iImage, INT iCheck, INT iTextColor){RVITEM rvi;rvi.nMask = RVIM_TEXT;rvi.iItem = iItem;rvi.iSubItem = 0;rvi.lpszText = (LPTSTR)lpszText;rvi.iTextColor = iTextColor;rvi.iImage = iImage;rvi.iCheck = iCheck;if(iTextColor >= 0)rvi.nMask |= RVIM_TEXTCOLOR;if(iImage >= 0)rvi.nMask |= RVIM_IMAGE;if(iCheck >= 0)rvi.nMask |= RVIM_CHECK;return InsertItem(&rvi);}INT CReportCtrl::InsertItem(LPRVITEM lprvi){if(m_dwStyle&RVS_OWNERDATA || m_dwStyle&RVS_TREEVIEW )return RVI_INVALID; // Use set SetItemCount() when using OWNERDATA style// Use tree item variants when using TREEVIEW styleINT iItem = InsertItemImpl(lprvi);if(iItem != RVI_INVALID){m_bUpdateItemMap = TRUE;m_iVirtualHeight++;if(m_iFocusRow >= RVI_FIRST && m_iFocusRow >= GetRowFromItem(iItem))m_iFocusRow++;}return iItem;}BOOL CReportCtrl::DeleteItem(INT iItem){if(m_dwStyle&RVS_OWNERDATA || m_dwStyle&RVS_TREEVIEW)return RVI_INVALID; // Use set SetItemCount() when using OWNERDATA style// Use tree item variants when using TREEVIEW styleif(iItem < RVI_FIRST)return FALSE;ASSERT(iItem <= m_arrayItems.GetSize());INT iRow = GetRowFromItem(iItem);BOOL bResult = DeleteItemImpl(iItem);m_bUpdateItemMap = TRUE;m_iVirtualHeight--;if(m_iFocusRow >= iRow)m_iFocusRow--;m_iFocusRow = m_iFocusRow >= m_iVirtualHeight ? m_iVirtualHeight-1 : m_iFocusRow;INT iRows = m_arrayRows.GetSize();INT iFirst = GetScrollPos32(SB_VERT), iLast;GetVisibleRows(TRUE, &iFirst, &iLast);if (iRow <= iFirst || iLast >= iRows - 1)GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);ScrollWindow(SB_VERT, iFirst > RVI_INVALID ? iFirst : 0);return bResult;}HTREEITEM CReportCtrl::InsertItem(LPCTSTR lpszText, INT iImage, INT iCheck, INT iTextColor, HTREEITEM hParent, HTREEITEM hInsertAfter, INT iSubItem){RVITEM rvi;rvi.nMask = RVIM_TEXT;rvi.lpszText = (LPTSTR)lpszText;rvi.iTextColor = iTextColor;rvi.iImage = iImage;rvi.iCheck = iCheck;if(iTextColor >= 0)rvi.nMask |= RVIM_TEXTCOLOR;if(iImage >= 0)rvi.nMask |= RVIM_IMAGE;if(iCheck >= 0)rvi.nMask |= RVIM_CHECK;return InsertItem(&rvi, hParent, hInsertAfter, iSubItem);}HTREEITEM CReportCtrl::InsertItem(LPRVITEM lprvi, HTREEITEM hParent, HTREEITEM hInsertAfter, INT iSubItem){if(!(m_dwStyle&RVS_TREEVIEW))return NULL; // TREEVIEW style must be set to use this style.LPTREEITEM lptiFocus = GetTreeFocus();LPTREEITEM lpti = new TREEITEM;if( lpti != NULL ){lprvi->iItem = m_arrayItems.GetSize();lprvi->iSubItem = 0;lpti->iItem = InsertItemImpl(lprvi);lpti->iSubItem = iSubItem;if(lpti->iItem != RVI_INVALID){LPTREEITEM lptiParent = hParent==RVTI_ROOT ? &m_tiRoot:(LPTREEITEM)hParent;InsertTree(lprvi->iSubItem, lptiParent, (LPTREEITEM)hInsertAfter, lpti, TRUE);m_arrayItems[lpti->iItem].lptiItem = lpti;lpti->iIndent = hParent==RVTI_ROOT ? 1:lptiParent->iIndent+1;lpti->lptiParent = lptiParent;}else{delete lpti;lpti = NULL;}}BuildTree();SetTreeFocus(lptiFocus);return (HTREEITEM)lpti;}BOOL CReportCtrl::DeleteItem(HTREEITEM hItem){if(!(m_dwStyle&RVS_TREEVIEW))return FALSE; // TREEVIEW style must be set to use this style.LPTREEITEM lptiFocus = GetTreeFocus();if(lptiFocus != NULL&& (IsDescendent(hItem, (HTREEITEM)lptiFocus) || (HTREEITEM)lptiFocus == hItem)) {if(lptiFocus->lptiSibling != NULL)lptiFocus = lptiFocus->lptiSibling;else if(lptiFocus->lptiParent != &m_tiRoot)lptiFocus = lptiFocus->lptiParent;elselptiFocus = NULL;}BOOL bResult = DeleteItemImpl((LPTREEITEM)hItem, FALSE);BuildTree();SetTreeFocus(lptiFocus);return bResult;}BOOL CReportCtrl::DeleteAllItems(){BOOL bResult = TRUE;if(m_dwStyle&RVS_OWNERDATA) // Use set SetItemCount() when using this stylereturn FALSE;if(m_dwStyle&RVS_TREEMASK){bResult = DeleteItemImpl(&m_tiRoot, TRUE);}else{RVITEM rvi;for (int iItem=0; iItem<m_arrayItems.GetSize(); iItem++){rvi.nMask = RVIM_LPARAM;rvi.iItem = iItem;GetItem(&rvi);Notify(RVN_ITEMDELETED, iItem, 0, 0, rvi.lParam);}}m_arrayRows.RemoveAll();m_arrayItems.RemoveAll();m_listSelection.RemoveAll();m_bUpdateItemMap = TRUE;m_iVirtualHeight = 0;m_iFocusRow = RVI_INVALID;ScrollWindow(SB_VERT, 0);return bResult;}void CReportCtrl::RedrawItems(INT iFirst, INT iLast){CRect rect;if(iFirst == iLast || iLast == RVI_INVALID){GetItemRect(iFirst, -1, rect);if(m_bPreview)rect.bottom += GetItemStruct(iFirst, -1, RVIM_PREVIEW).nPreview;rect.OffsetRect(GetScrollPos32(SB_HORZ), 0);}elserect = m_rectReport;InvalidateRect(rect);}BOOL CReportCtrl::EnsureVisible(INT iItem, BOOL bUnobstructed){INT iFirst = GetScrollPos32(SB_VERT), iLast;INT iRow = GetRowFromItem(iItem);if(iRow < RVI_FIRST)return FALSE;GetVisibleRows(bUnobstructed, &iFirst, &iLast);if(iRow<iFirst)ScrollWindow(SB_VERT, iRow);if(iRow>iLast){iLast = iRow;GetVisibleRows(bUnobstructed, &iFirst, &iLast, TRUE);ScrollWindow(SB_VERT, iFirst);}return TRUE;}BOOL CReportCtrl::EnsureVisible(HTREEITEM hItem, BOOL bUnobstructed){LPTREEITEM lpti = (LPTREEITEM)hItem;while(lpti->lptiParent != &m_tiRoot){Expand((HTREEITEM)lpti->lptiParent, RVE_EXPAND);lpti = lpti->lptiParent;}lpti = (LPTREEITEM)hItem;return EnsureVisible(lpti->iItem, bUnobstructed);}INT CReportCtrl::InsertColor(INT iIndex, COLORREF crColor){try{m_arrayColors.InsertAt(iIndex, crColor);if(CreatePalette())return iIndex;return -1;}catch(CMemoryException* e){e->Delete();return -1;}}BOOL CReportCtrl::DeleteColor(INT iIndex){if(iIndex >= m_arrayColors.GetSize())return FALSE;m_arrayColors.RemoveAt(iIndex);CreatePalette();return TRUE;}void CReportCtrl::DeleteAllColors(){m_arrayColors.RemoveAll();CreatePalette();}INT CReportCtrl::HitTest(LPRVHITTESTINFO lprvhti){ASSERT(lprvhti);lprvhti->nFlags = 0;lprvhti->iItem = RVI_INVALID;lprvhti->iSubItem = -1;lprvhti->hItem = NULL;lprvhti->iRow = RVI_INVALID;lprvhti->iColumn = -1;CRect rectItem = m_rectEdit;rectItem.bottom -= GetSystemMetrics(SM_CYFIXEDFRAME)*2;if(rectItem.PtInRect(lprvhti->point) ||m_rectReport.PtInRect(lprvhti->point)) {INT iHPos = GetScrollPos32(SB_HORZ);INT iFirst = GetScrollPos32(SB_VERT), iLast;BOOL bCheckItem = FALSE;rectItem.left = -iHPos;rectItem.right = rectItem.left + m_iVirtualWidth;if(rectItem.PtInRect(lprvhti->point)){iFirst = RVI_EDIT;lprvhti->iItem = RVI_EDIT;lprvhti->nFlags |= RVHT_ONITEMEDIT;bCheckItem = TRUE;}else if(!bCheckItem && GetVisibleRows(FALSE, &iFirst, &iLast)){ITEM item;rectItem.SetRect(m_rectReport.left-iHPos, m_rectReport.top,m_rectReport.left-iHPos+m_iVirtualWidth, m_rectReport.top);for(;iFirst<=iLast;iFirst++){GetItemFromRow(iFirst, item);rectItem.bottom += m_iDefaultHeight + (m_bPreview ? item.nPreview:0);if(rectItem.PtInRect(lprvhti->point))break;rectItem.top = rectItem.bottom;}if(iFirst<=iLast){lprvhti->iItem = GetItemFromRow(iFirst);lprvhti->iRow = iFirst;if(m_dwStyle&RVS_TREEMASK && lprvhti->iItem>=RVI_FIRST)lprvhti->hItem = (HTREEITEM)m_arrayItems[lprvhti->iItem].lptiItem;if(m_bPreview && item.nPreview){CRect rectPreview(rectItem);rectPreview.top += m_iDefaultHeight;if(rectPreview.PtInRect(lprvhti->point)){lprvhti->nFlags |= RVHT_ONITEMPREVIEW;return lprvhti->iItem;}}bCheckItem = TRUE;}}if(bCheckItem == TRUE){bCheckItem = FALSE;if(m_dwStyle&RVS_TREEMASK &&m_arrayItems[lprvhti->iItem].lptiItem->iSubItem >= 0) {LPTREEITEM lpti = m_arrayItems[lprvhti->iItem].lptiItem;lprvhti->iSubItem = lpti->iSubItem;lprvhti->iColumn = 0;rectItem.OffsetRect(iHPos, 0);lprvhti->rect = rectItem;lprvhti->rect.right = lprvhti->rect.left + m_iVirtualWidth;lprvhti->rect.bottom = rectItem.top + m_iDefaultHeight;bCheckItem = TRUE;}else{INT iHeaderItem;INT iHeaderItems = m_arrayColumns.GetSize();HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;rectItem.right = rectItem.left;for(iHeaderItem=0;iHeaderItem<iHeaderItems;iHeaderItem++){CRect rect;m_wndHeader.GetItemRect(iHeaderItem, &rect);CPoint point = lprvhti->point;point.y = (rect.bottom - rect.top) / 2;point.x += iHPos;if(point.x>=rect.left && point.x<rect.right){rectItem.left = rect.left;rectItem.right = rect.right;break;}}ASSERT(iHeaderItem < iHeaderItems);m_wndHeader.GetItem(iHeaderItem, &hdi);lprvhti->iSubItem = hdi.lParam;lprvhti->iColumn = GetColumnFromSubItem(lprvhti->iSubItem);if(iHeaderItem<iHeaderItems)bCheckItem = TRUE;}if(bCheckItem == TRUE){RVITEM rvi;rvi.iItem = GetItemFromRow(iFirst);rvi.iSubItem = lprvhti->iSubItem;GetItem(&rvi);if(lprvhti->iColumn == 0 && rvi.nMask&RVIM_INDENT && rvi.iIndent >= 0){rectItem.left += rvi.iIndent*m_iDefaultHeight;if(rvi.nState&RVIS_TREEMASK){if(lprvhti->point.x >= rectItem.left - m_iDefaultHeight &&lprvhti->point.x < rectItem.left) {lprvhti->rect = rectItem;lprvhti->rect.left -= iHPos + m_iDefaultHeight;lprvhti->rect.right -= lprvhti->rect.left;lprvhti->rect.bottom = rectItem.top + m_iDefaultHeight;lprvhti->nFlags |= RVHT_ONITEMTREEBOX;return lprvhti->iItem;}}}rectItem.OffsetRect(-iHPos, 0);lprvhti->rect = rectItem;lprvhti->rect.bottom = rectItem.top + m_iDefaultHeight;rectItem.right = rectItem.left + m_iSpacing;if(rvi.nMask&RVIM_IMAGE){rectItem.right += m_sizeImage.cx + m_iSpacing;if(lprvhti->point.x < rectItem.right){lprvhti->nFlags |= RVHT_ONITEMIMAGE;return lprvhti->iItem;}}if(rvi.nMask&RVIM_CHECK){rectItem.right += m_sizeCheck.cx + m_iSpacing;if(lprvhti->point.x < rectItem.right){lprvhti->nFlags |= RVHT_ONITEMCHECK;return lprvhti->iItem;}}if(lprvhti->point.x >= rectItem.right &&lprvhti->point.x < lprvhti->rect.right - m_iSpacing) {lprvhti->nFlags |= RVHT_ONITEMTEXT;return lprvhti->iItem;}lprvhti->nFlags = RVHT_NOWHERE;}elselprvhti->nFlags = RVHT_NOWHERE;}elselprvhti->nFlags = RVHT_NOWHERE;}else{lprvhti->nFlags |= lprvhti->point.y<m_rectReport.top ? RVHT_ABOVE:0;lprvhti->nFlags |= lprvhti->point.y>m_rectReport.bottom ? RVHT_BELOW:0;lprvhti->nFlags |= lprvhti->point.x<m_rectReport.left ? RVHT_TOLEFT:0;lprvhti->nFlags |= lprvhti->point.x>m_rectReport.right ? RVHT_TORIGHT:0;}return lprvhti->iItem;}BOOL CReportCtrl::ResortItems(){INT iColumn;INT iSubItem;BOOL bAscending;iColumn = m_wndHeader.GetSortColumn(&bAscending);iSubItem = GetSubItemFromColumn(iColumn);if(iSubItem >= 0)return SortItems(iSubItem, bAscending);elsereturn FALSE;}BOOL CReportCtrl::SortItems(INT iSubItem, BOOL bAscending){if(m_dwStyle&RVS_OWNERDATA)return FALSE; // Can't sort if data is managed by ownerINT iColumn = GetColumnFromSubItem(iSubItem);if(iColumn < 0)return FALSE;m_wndHeader.SetSortColumn(m_arrayColumns[iColumn], bAscending);if(m_dwStyle&RVS_TREEMASK){LPTREEITEM lptiFocus = GetTreeFocus();TreeSort(iSubItem, &m_tiRoot, bAscending, TRUE);BuildTree();SetTreeFocus(lptiFocus);}else{INT iRows = m_arrayRows.GetSize();if(!iRows)return FALSE;INT iFocusItem = GetItemFromRow(m_iFocusRow);QuickSort(iSubItem, 0, iRows-1, bAscending);m_bUpdateItemMap = TRUE;if(iFocusItem>=0){m_iFocusRow = GetRowFromItem(iFocusItem);INT iFirst = m_iFocusRow, iLast;GetVisibleRows(TRUE, &iFirst, &iLast);GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);ScrollWindow(SB_VERT, iFirst);}}Invalidate();return TRUE;}INT CReportCtrl::CompareItems(LPRVITEM lprvi1, LPRVITEM lprvi2){ASSERT(!(m_dwStyle&RVS_OWNERDATA)); // Can't sort if data is managed by ownerif((!_tcslen(lprvi1->lpszText)) && (!_tcslen(lprvi2->lpszText))){if((lprvi1->nMask&RVIM_CHECK || lprvi2->nMask&RVIM_CHECK)){if(lprvi1->iCheck < lprvi2->iCheck)return -1;else if(lprvi1->iCheck > lprvi2->iCheck)return 1;elsereturn 0;}if(lprvi1->iImage < lprvi2->iImage)return -1;else if(lprvi1->iImage > lprvi2->iImage)return 1;elsereturn 0;}elsereturn _tcscmp(lprvi1->lpszText, lprvi2->lpszText);}INT CReportCtrl::CompareItems(INT iItem1, INT iSubItem1, INT iItem2, INT iSubItem2){ASSERT(!(m_dwStyle&RVS_OWNERDATA)); // Can't sort if data is managed by ownerif(m_lpfnrvc == NULL){RVITEM rvi1, rvi2;TCHAR szText1[REPORTCTRL_MAX_TEXT], szText2[REPORTCTRL_MAX_TEXT];rvi1.nMask = RVIM_TEXT;rvi1.iItem = iItem1;rvi1.iSubItem = iSubItem1;rvi1.lpszText = szText1;rvi1.iTextMax = REPORTCTRL_MAX_TEXT;VERIFY(GetItem(&rvi1));rvi2.nMask = RVIM_TEXT;rvi2.iItem = iItem2;rvi2.iSubItem = iSubItem2;rvi2.lpszText = szText2;rvi2.iTextMax = REPORTCTRL_MAX_TEXT;VERIFY(GetItem(&rvi2));if(!(rvi1.nMask&RVIM_TEXT || rvi2.nMask&RVIM_TEXT)){if((rvi1.nMask&RVIM_CHECK || rvi2.nMask&RVIM_CHECK)){if(rvi1.iCheck < rvi2.iCheck)return -1;else if(rvi1.iCheck > rvi2.iCheck)return 1;elsereturn 0;}if(rvi1.iImage < rvi2.iImage)return -1;else if(rvi1.iImage > rvi2.iImage)return 1;elsereturn 0;}elsereturn _tcscmp(szText1, szText2);}elsereturn m_lpfnrvc(iItem1, iSubItem1, iItem2, iSubItem2, m_lParamCompare);}INT CReportCtrl::FindItem(LPRVFINDINFO lprvfi, INT iSubItem, INT iStart){if(m_dwStyle&RVS_OWNERDATA)return FALSE; // Can't find data if data is managed by ownerINT iItems = m_arrayItems.GetSize();INT iItem = iStart + (lprvfi->nFlags&RVFI_UP ? -1:1);RVITEM rvi;TCHAR szText[REPORTCTRL_MAX_TEXT];rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;BOOL bMatch;while(iItem != iStart){if(iItem >= iItems){if(lprvfi->nFlags&RVFI_WRAP)iItem = RVI_EDIT;elsebreak;}if(iItem < RVI_EDIT){if(lprvfi->nFlags&RVFI_WRAP)iItem = iItems-1;elsebreak;}rvi.nMask = RVIM_TEXT|RVIM_IMAGE|RVIM_CHECK|RVIM_LPARAM;rvi.iItem = iItem;rvi.iSubItem = iSubItem;VERIFY(GetItem(&rvi));bMatch = TRUE;if(lprvfi->nFlags&RVFI_TEXT && rvi.nMask&RVIM_TEXT){INT iMatch;if(lprvfi->nFlags&RVFI_PARTIAL)iMatch = _tcsncmp(lprvfi->lpszText, rvi.lpszText, _tcslen(lprvfi->lpszText));elseiMatch = _tcscmp(lprvfi->lpszText, rvi.lpszText);bMatch &= !iMatch ? TRUE:FALSE;}elseif(lprvfi->nFlags&RVFI_TEXT)bMatch = FALSE;if(lprvfi->nFlags&RVFI_IMAGE && rvi.nMask&RVIM_IMAGE)bMatch &= lprvfi->iImage == rvi.iImage ? TRUE:FALSE;elseif(lprvfi->nFlags&RVFI_IMAGE)bMatch = FALSE;if(lprvfi->nFlags&RVFI_CHECK && rvi.nMask&RVIM_CHECK)bMatch &= lprvfi->iCheck == rvi.iCheck ? TRUE:FALSE;elseif(lprvfi->nFlags&RVFI_CHECK)bMatch = FALSE;if(lprvfi->nFlags&RVFI_LPARAM && rvi.nMask&RVIM_LPARAM)bMatch &= lprvfi->lParam == rvi.lParam ? TRUE:FALSE;elseif(lprvfi->nFlags&RVFI_LPARAM)bMatch = FALSE;if(bMatch)return iItem;iItem += lprvfi->nFlags&RVFI_UP ? -1:1;}return RVI_INVALID;}BOOL CReportCtrl::Expand(HTREEITEM hItem, UINT nCode){if(!(m_dwStyle&RVS_TREEMASK))return FALSE;LPTREEITEM lpti = (LPTREEITEM)hItem;switch(nCode){case RVE_COLLAPSE: lpti->bOpen = FALSE; break;case RVE_EXPAND: lpti->bOpen = TRUE; break;case RVE_TOGGLE: lpti->bOpen = !lpti->bOpen; break;default: return FALSE;}SetState(m_iFocusRow, 0, RVIS_FOCUSED);INT iFocusItem = GetItemFromRow(m_iFocusRow);BuildTree();if(iFocusItem >= RVI_FIRST){LPTREEITEM lptiAncestor = GetVisibleAncestor(m_arrayItems[iFocusItem].lptiItem);ASSERT(lptiAncestor != &m_tiRoot && lptiAncestor != NULL);m_iFocusRow = GetRowFromItem(lptiAncestor->iItem);ASSERT(m_iFocusRow != RVI_INVALID);SetState(m_iFocusRow, RVIS_FOCUSED, RVIS_FOCUSED);DeselectDescendents(lptiAncestor);}INT iRows = m_arrayRows.GetSize();INT iFirst = GetScrollPos32(SB_VERT), iLast;GetVisibleRows(TRUE, &iFirst, &iLast);if(m_iFocusRow <= iFirst || iLast >= m_iFocusRow - 1)GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);ScrollWindow(SB_VERT, iFirst > RVI_INVALID ? iFirst : 0);return TRUE;}BOOL CReportCtrl::ExpandAll(HTREEITEM hItem, UINT nCode, INT iLevels){if(!(m_dwStyle&RVS_TREEMASK))return FALSE;LPTREEITEM lpti;if(hItem == RVTI_ROOT){lpti = &m_tiRoot;}else{Expand(hItem, nCode);lpti = (LPTREEITEM)hItem;}return ExpandAllImpl(hItem, nCode, iLevels, 0);}void CReportCtrl::FlushCache(INT iItem){if(!(m_dwStyle&RVS_OWNERDATA || m_bUseItemCacheMap))return;CacheDelete(iItem);}void CReportCtrl::Copy(){CString str;if (OpenClipboard() == FALSE || ::EmptyClipboard() == FALSE)return;HGLOBAL hMem = NULL, h;CArray<INT, INT> arraySelection;SelectionToSortedArray(arraySelection);INT i, iSize = arraySelection.GetSize();UINT nData = 0;for(i=0;i<iSize;i++){INT iRow = arraySelection[i];INT iItem = GetItemFromRow(iRow);ASSERT(iItem > RVI_INVALID);str = GetItemString( iItem, g_cCBSeparator );ASSERT(str.GetLength() > 0 );if( hMem == NULL )h = ::GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT, str.GetLength()*(sizeof(TCHAR)+1) );elseh = ::GlobalReAlloc( hMem, nData + str.GetLength()*(sizeof(TCHAR)+1), GMEM_MOVEABLE|GMEM_DDESHARE );if( h == NULL )break;hMem = h;LPBYTE lpx = (LPBYTE)::GlobalLock(hMem);ASSERT(lpx != NULL);memcpy(lpx + nData, (LPCTSTR)str, str.GetLength()*sizeof(TCHAR));::GlobalUnlock(hMem);nData += str.GetLength()*sizeof(TCHAR);((LPTSTR)lpx)[nData/sizeof(TCHAR)] = 0;}if(hMem != NULL)::SetClipboardData(CF_TEXT, hMem);::CloseClipboard();}void CReportCtrl::Cut(){}void CReportCtrl::Paste(){}/////////////////////////////////////////////////////////////////////////////// CReportCtrl miscINT CReportCtrl::PreviewHeight(CFont* pFont, UINT nLines){INT iHeight = -1;ASSERT(pFont != NULL);CDC* pDC = GetDC();if(pDC){CFont* pDCFont = pDC->SelectObject(pFont);TEXTMETRIC tm;pDC->GetTextMetrics(&tm);pDC->SelectObject(pDCFont);ReleaseDC(pDC);iHeight = (tm.tmHeight + tm.tmExternalLeading)*nLines;}return iHeight;}INT CReportCtrl::PreviewHeight(CFont* pFont, LPCTSTR lpszText, LPRECT lpRect){INT iHeight = -1;ASSERT(pFont != NULL);CDC* pDC = GetDC();if(pDC){CRect rect( 0, 0, m_iVirtualWidth, 0);if(lpRect != NULL)rect = *lpRect;CFont* pDCFont = pDC->SelectObject(pFont);iHeight = pDC->DrawText( lpszText, -1, rect, DT_CALCRECT|DT_EXPANDTABS|DT_WORDBREAK|DT_NOCLIP );ReleaseDC(pDC);}return iHeight;}/////////////////////////////////////////////////////////////////////////////// CReportCtrl implementationvoid CReportCtrl::GetSysColors(){m_crBackground = ::GetSysColor(COLOR_WINDOW);m_crBkSelected = ::GetSysColor(COLOR_HIGHLIGHT);m_crBkSelectedNoFocus = ::GetSysColor(COLOR_BTNFACE);m_crText = ::GetSysColor(COLOR_WINDOWTEXT);m_crTextSelected = ::GetSysColor(COLOR_HIGHLIGHTTEXT);m_crTextSelectedNoFocus = ::GetSysColor(COLOR_WINDOWTEXT);m_crGrid = ::GetSysColor(COLOR_BTNFACE);m_cr3DFace = ::GetSysColor(COLOR_3DFACE);m_cr3DLight = ::GetSysColor(COLOR_3DLIGHT);m_cr3DShadow = ::GetSysColor(COLOR_3DSHADOW);m_cr3DHiLight = ::GetSysColor(COLOR_3DHILIGHT);m_cr3DDkShadow = ::GetSysColor(COLOR_3DDKSHADOW);}UINT CReportCtrl::GetMouseScrollLines(){UINT nScrollLines = 3; // Reasonable defaultHKEY hKey;if(RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"),0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {TCHAR szData[128];DWORD dwKeyDataType;DWORD dwDataBufSize = sizeof(szData);if(RegQueryValueEx(hKey, _T("WheelScrollLines"), NULL, &dwKeyDataType,(LPBYTE) &szData, &dwDataBufSize) == ERROR_SUCCESS)nScrollLines = _tcstoul(szData, NULL, 10);RegCloseKey(hKey);}return nScrollLines;}BOOL CReportCtrl::CreatePalette(){if(m_palette.m_hObject)m_palette.DeleteObject();INT iUserColors = m_arrayColors.GetSize();INT iBitmapColors = 0;DIBSECTION ds;BITMAPINFOHEADER &bmInfo = ds.dsBmih;if( (HBITMAP)m_bitmap != NULL ){m_bitmap.GetObject( sizeof(ds), &ds );iBitmapColors = bmInfo.biClrUsed ? bmInfo.biClrUsed : 1 << bmInfo.biBitCount;}INT iColors = iUserColors + iBitmapColors;if( !iColors )return FALSE;CClientDC cdc(NULL);if( iColors <= 256 ){UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * iColors);LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];pLP->palVersion = 0x300;pLP->palNumEntries = iColors;INT i;for( i=0;i<iUserColors;i++ ){pLP->palPalEntry[i].peRed = GetRValue(m_arrayColors[i]);pLP->palPalEntry[i].peGreen = GetGValue(m_arrayColors[i]);pLP->palPalEntry[i].peBlue = GetBValue(m_arrayColors[i]);pLP->palPalEntry[i].peFlags = 0;}if( iBitmapColors > 0 ){// Create the paletteRGBQUAD *pRGB = new RGBQUAD[iBitmapColors];CDC dc;dc.CreateCompatibleDC(&cdc);dc.SelectObject( &m_bitmap );::GetDIBColorTable( dc, 0, iColors, pRGB );for( INT i=0;i<iBitmapColors;i++ ){pLP->palPalEntry[iUserColors+i].peRed = pRGB[i].rgbRed;pLP->palPalEntry[iUserColors+i].peGreen = pRGB[i].rgbGreen;pLP->palPalEntry[iUserColors+i].peBlue = pRGB[i].rgbBlue;pLP->palPalEntry[iUserColors+i].peFlags = 0;}delete[] pRGB;}m_palette.CreatePalette( pLP );delete[] pLP;}elsem_palette.CreateHalftonePalette( &cdc );return TRUE;}BOOL CReportCtrl::NotifyHdr(LPNMRVHEADER lpnmrvhdr, UINT nCode, INT iHdrItem){lpnmrvhdr->hdr.hwndFrom = GetSafeHwnd();lpnmrvhdr->hdr.idFrom = GetDlgCtrlID();lpnmrvhdr->hdr.code = nCode;HDITEM hdi;hdi.mask = HDI_LPARAM;hdi.lParam = -1;m_wndHeader.GetItem(iHdrItem, &hdi);lpnmrvhdr->iSubItem = hdi.lParam;return Notify((LPNMREPORTVIEW)lpnmrvhdr);}BOOL CReportCtrl::Notify(UINT nCode, INT iItem, INT iSubItem, UINT nState, LPARAM lParam){NMREPORTVIEW nmrv;nmrv.hdr.hwndFrom = GetSafeHwnd();nmrv.hdr.idFrom = GetDlgCtrlID();nmrv.hdr.code = nCode;nmrv.iItem = iItem;nmrv.iSubItem = iSubItem;if(m_dwStyle&RVS_TREEMASK && iItem>=RVI_FIRST)nmrv.hItem = (HTREEITEM)m_arrayItems[iItem].lptiItem;nmrv.nState = nState;nmrv.lParam = lParam;return Notify(&nmrv);}BOOL CReportCtrl::Notify(UINT nCode, UINT nKeys, LPRVHITTESTINFO lprvhti){NMREPORTVIEW nmrv;nmrv.hdr.hwndFrom = GetSafeHwnd();nmrv.hdr.idFrom = GetDlgCtrlID();nmrv.hdr.code = nCode;nmrv.nKeys = nKeys;nmrv.point = lprvhti->point;nmrv.nFlags = lprvhti->nFlags;nmrv.iItem = lprvhti->iItem;nmrv.iSubItem = lprvhti->iSubItem;if(m_dwStyle&RVS_TREEMASK && lprvhti->iItem>=RVI_FIRST)nmrv.hItem = (HTREEITEM)m_arrayItems[lprvhti->iItem].lptiItem;if(lprvhti->iItem >= 0 && (!(m_dwStyle&RVS_OWNERDATA)))nmrv.lParam = GetItemStruct(lprvhti->iItem, -1).lParam;return Notify(&nmrv);}BOOL CReportCtrl::Notify(LPNMREPORTVIEW lpnmrv){INT iCode = 0-(lpnmrv->hdr.code-RVN_FIRST);if(m_uNotifyMask&(1<<iCode)){CWnd* pWnd = GetParent();if(pWnd)return pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)lpnmrv);}return FALSE;}void CReportCtrl::Layout(INT cx, INT cy){HDLAYOUT hdl;WINDOWPOS wpos;hdl.prc = &m_rectReport;hdl.pwpos = &wpos;m_rectReport.SetRect(0, 0, cx, cy);if(IsWindow(m_wndHeader.GetSafeHwnd())){m_wndTip.Hide();VERIFY(m_wndHeader.SendMessage(HDM_LAYOUT, 0, (LPARAM)&hdl));if(m_dwStyle&RVS_NOHEADER){m_rectHeader.SetRect(wpos.x, 0, wpos.x+wpos.cx, 0);m_rectReport.top = m_rectHeader.bottom;;}elsem_rectHeader.SetRect(wpos.x, wpos.y, wpos.x+wpos.cx, wpos.y+wpos.cy);m_rectTop = m_rectHeader;if(m_dwStyle&RVS_SHOWEDITROW){UINT nFrameHeight = GetSystemMetrics(SM_CYFIXEDFRAME);m_rectTop.bottom += m_iDefaultHeight + 2*nFrameHeight;m_rectReport.top += m_iDefaultHeight + 2*nFrameHeight;m_rectEdit = m_rectTop;m_rectEdit.top = m_rectHeader.bottom;}elsem_rectEdit.SetRectEmpty();ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));}}CReportCtrl::LPITEM CReportCtrl::CacheLookup(INT iItem){if(iItem == RVI_EDIT)return m_bEditValid ? &m_itemEdit:NULL;UINT nIndex = iItem%REPORTCTRL_MAX_CACHE;if(m_aciCache[nIndex].iItem == iItem)return &m_aciCache[nIndex].item;return NULL;}CReportCtrl::LPITEM CReportCtrl::CacheAdd(INT iItem){if(iItem == RVI_EDIT){m_bEditValid = TRUE;return &m_itemEdit;}UINT nIndex = iItem%REPORTCTRL_MAX_CACHE;m_aciCache[nIndex].iItem = iItem;return &m_aciCache[nIndex].item;}void CReportCtrl::CacheDelete(INT iItem){if(iItem == RVI_INVALID){for(UINT n=0;n<REPORTCTRL_MAX_CACHE;n++)m_aciCache[n].iItem = RVI_INVALID;}else if(iItem == RVI_EDIT){m_bEditValid = FALSE;}else{UINT nIndex = iItem%REPORTCTRL_MAX_CACHE;if(m_aciCache[nIndex].iItem == iItem)m_aciCache[nIndex].iItem = RVI_INVALID;}}void CReportCtrl::BuildTree(){m_iVirtualHeight = 0;m_arrayRows.RemoveAll();BuildTree(&m_tiRoot);m_bUpdateItemMap = TRUE;}void CReportCtrl::BuildTree(LPTREEITEM lpti){LPTREEITEM lptiSibling = lpti->lptiChildren;while(lptiSibling != NULL){INT iRow = m_arrayRows.Add(lptiSibling->iItem);m_iVirtualHeight++;ITEM& item = GetItemStruct(lptiSibling->iItem, lptiSibling->iItem, RVIM_STATE|RVIM_INDENT);item.nState &= ~RVIS_TREEMASK;item.iIndent = lptiSibling->iIndent;if(lptiSibling->lptiChildren != NULL){item.nState |= lptiSibling->bOpen ? RVIS_TREEOPENED:RVIS_TREECLOSED;SetItemStruct(lptiSibling->iItem, item);SetState(iRow, item.nState&RVIS_TREEMASK, RVIS_TREEMASK);if(lptiSibling->bOpen)BuildTree((LPTREEITEM)lptiSibling);}lptiSibling = lptiSibling->lptiSibling;}}void CReportCtrl::InsertTree(INT iSubItem, LPTREEITEM lptiParent, LPTREEITEM lptiInsertAfter, LPTREEITEM lpti, BOOL bAscending){LPTREEITEM lptiSibling = lptiParent->lptiChildren;if(lptiSibling == NULL){ASSERT(lptiParent != NULL);lptiParent->lptiChildren = lpti;}else{switch((ULONG)lptiInsertAfter){case RVTI_FIRST:lpti->lptiSibling = lptiSibling;lptiParent->lptiChildren = lpti;break;case RVTI_LAST:while(lptiSibling->lptiSibling != NULL)lptiSibling = lptiSibling->lptiSibling;lptiSibling->lptiSibling = lpti;break;case RVTI_SORT:{INT iSubItem1 = lpti->iSubItem<0 ? iSubItem:lpti->iSubItem;INT iSubItem2 = lptiSibling->iSubItem<0 ? iSubItem:lptiSibling->iSubItem;if((bAscending && CompareItems(lpti->iItem, iSubItem1, lptiSibling->iItem, iSubItem2) <= 0) ||(!bAscending && CompareItems(lpti->iItem, iSubItem1, lptiSibling->iItem, iSubItem2) >= 0)) {lpti->lptiSibling = lptiSibling;lptiParent->lptiChildren = lpti;break;}else{while(lptiSibling->lptiSibling != NULL){iSubItem1 = lpti->iSubItem<0 ? iSubItem:lpti->iSubItem;iSubItem2 = lptiSibling->iSubItem<0 ? iSubItem:lptiSibling->iSubItem;if((bAscending && CompareItems(lpti->iItem, iSubItem1, lptiSibling->lptiSibling->iItem, iSubItem2) <= 0) ||(!bAscending && CompareItems(lpti->iItem, iSubItem1, lptiSibling->lptiSibling->iItem, iSubItem2) >= 0))break;lptiSibling = lptiSibling->lptiSibling;}lptiInsertAfter = lptiSibling;}}//// Intentional//default:lpti->lptiSibling = lptiInsertAfter->lptiSibling;lptiInsertAfter->lptiSibling = lpti;break;}}}BOOL CReportCtrl::ExpandAllImpl(HTREEITEM hRoot, UINT nCode, INT iLevels, INT iDeep){HTREEITEM hItem = GetNextItem(hRoot, RVGN_CHILD);iDeep++;if(iLevels >= 0 && iDeep <= iLevels)return TRUE;while(hItem != NULL){Expand(hItem, nCode);if(ExpandAllImpl(hItem, nCode, iLevels, iDeep) == FALSE)return FALSE;hItem = GetNextItem(hItem, RVGN_NEXT);}return TRUE;}INT CReportCtrl::InsertItemImpl(LPRVITEM lprvi){ASSERT(lprvi->iItem >= 0); // Use SetItem to set Edit row itemASSERT(lprvi->iItem <= m_arrayItems.GetSize());ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize());INT iRow = -1;BOOL bInserted1 = FALSE, bInserted2 = FALSE;try{ITEM item;item.rdData.New(m_arraySubItems.GetSize());m_arrayItems.InsertAt(lprvi->iItem, item); bInserted1 = TRUE;VERIFY(SetItem(lprvi));if(!(m_dwStyle&RVS_TREEMASK)){iRow = lprvi->iItem;m_arrayRows.InsertAt(iRow, INT_MIN); bInserted2 = TRUE;INT iItems = m_arrayRows.GetSize();for(INT i=0;i<iItems;i++)if(m_arrayRows[i] >= iRow)m_arrayRows[i]++;m_arrayRows[iRow] = lprvi->iItem;}ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));CList<INT, INT> list;POSITION pos = m_listSelection.GetHeadPosition();while(pos != NULL){INT iSelectedItem = m_listSelection.GetAt(pos);if(iSelectedItem >= lprvi->iItem)list.AddTail(iSelectedItem + 1);elselist.AddTail(iSelectedItem);m_listSelection.GetNext(pos);}m_listSelection.RemoveAll();m_listSelection.AddTail(&list);return lprvi->iItem;}catch(CMemoryException* e){if(bInserted1)m_arrayItems.RemoveAt(lprvi->iItem);if(bInserted2)m_arrayRows.RemoveAt(iRow);e->Delete();return RVI_INVALID;}}BOOL CReportCtrl::DeleteItemImpl(INT iItem){RVITEM rvi;rvi.nMask = RVIM_LPARAM;rvi.iItem = iItem;GetItem(&rvi);Notify(RVN_ITEMDELETED, iItem, 0, 0, rvi.lParam);INT i, iItems = m_arrayItems.GetSize();if(m_dwStyle&RVS_TREEMASK){for(i=0;i<iItems;i++){LPTREEITEM lpti = m_arrayItems[i].lptiItem;ASSERT(i == lpti->iItem);if(lpti->iItem > iItem)lpti->iItem--;}}m_arrayItems.RemoveAt(iItem);if(!(m_dwStyle&RVS_TREEMASK)){for(i=0;i<m_arrayRows.GetSize();i++)if (m_arrayRows[i] == iItem)m_arrayRows.RemoveAt(i);INT iRows = m_arrayRows.GetSize();for(i=0;i<iRows;i++)if(m_arrayRows[i] > iItem)m_arrayRows[i]--;}POSITION pos = m_listSelection.Find(iItem);if(pos != NULL)m_listSelection.RemoveAt(pos);CList<INT, INT> list;pos = m_listSelection.GetHeadPosition();while(pos != NULL){INT iSelectedItem = m_listSelection.GetAt(pos);if(iSelectedItem >= iItem)list.AddTail(iSelectedItem - 1);elselist.AddTail(iSelectedItem);m_listSelection.GetNext(pos);}m_listSelection.RemoveAll();m_listSelection.AddTail(&list);return TRUE;}BOOL CReportCtrl::DeleteItemImpl(LPTREEITEM lpti, BOOL bChildrenOnly){LPTREEITEM lptiSibling = lpti->lptiChildren;while(lptiSibling != NULL){if(lptiSibling->lptiChildren != NULL)DeleteItemImpl(lptiSibling, TRUE);DeleteItemImpl(lptiSibling->iItem);LPTREEITEM lptiChild = lptiSibling;lptiSibling = lptiSibling->lptiSibling;delete lptiChild;}lpti->lptiChildren = NULL;if(!bChildrenOnly){DeleteItemImpl(lpti->iItem);lptiSibling = (LPTREEITEM)GetNextItem((HTREEITEM)lpti, RVGN_PREVIOUS);if(lptiSibling != NULL)lptiSibling->lptiSibling = lpti->lptiSibling;else if(lpti->lptiParent->lptiChildren == lpti)lpti->lptiParent->lptiChildren = lpti->lptiSibling;delete lpti;}return TRUE;}CReportCtrl::ITEM& CReportCtrl::GetItemStruct(INT iItem, INT iSubItem, UINT nMask){if(m_dwStyle&RVS_OWNERDATA){INT iSubItems = m_arraySubItems.GetSize();TCHAR szText[REPORTCTRL_MAX_TEXT+1];memset(szText, 0, sizeof(szText));LPITEM lpItem = CacheLookup(iItem);if(m_bUseItemCacheMap && lpItem != NULL){if(iSubItem < 0)return *lpItem;INT iImage, iOverlay, iCheck, iColor, iTextMax;if(lpItem->rdData.GetSubItem(iSubItem, &iImage, &iOverlay, &iCheck, &iColor, szText, &iTextMax))return *lpItem;}else{VERIFY(lpItem = CacheAdd(iItem));lpItem->rdData.New(iSubItems);}VERIFY(LoadItemData(lpItem, iItem, iSubItem, nMask));return *lpItem;}return iItem == RVI_EDIT ? m_itemEdit:m_arrayItems[iItem];}void CReportCtrl::SetItemStruct(INT iItem, ITEM& item){if(m_dwStyle&RVS_OWNERDATA)return;if(iItem == RVI_EDIT)m_itemEdit = item;elsem_arrayItems[iItem] = item;}BOOL CReportCtrl::LoadItemData(LPITEM lpItem, INT iItem, INT iSubItem, UINT nMask){CWnd* pWnd = GetParent();if(pWnd){TCHAR szText[REPORTCTRL_MAX_TEXT+1];memset(szText, 0, sizeof(szText));NMRVITEMCALLBACK nmrvic;nmrvic.hdr.hwndFrom = GetSafeHwnd();nmrvic.hdr.idFrom = GetDlgCtrlID();nmrvic.hdr.code = RVN_ITEMCALLBACK;nmrvic.item.iItem = iItem;nmrvic.item.iSubItem = iSubItem;nmrvic.item.nMask = nMask;if(iSubItem >= 0){nmrvic.item.nMask |= RVIM_TEXT;nmrvic.item.lpszText = szText;nmrvic.item.iTextMax = REPORTCTRL_MAX_TEXT;}Notify((LPNMREPORTVIEW)&nmrvic);INT iColor = nmrvic.item.nMask&RVIM_TEXTCOLOR ? nmrvic.item.iTextColor:-1;INT iImage = nmrvic.item.nMask&RVIM_IMAGE ? nmrvic.item.iImage:-1;INT iOverlay = nmrvic.item.nMask&RVIM_OVERLAY ? nmrvic.item.iOverlay:-1;INT iCheck = nmrvic.item.nMask&RVIM_CHECK ? nmrvic.item.iCheck:-1;if(iSubItem >= 0)lpItem->rdData.SetSubItem(iSubItem, iImage, iOverlay, iCheck, iColor, szText);lpItem->iBkColor = nmrvic.item.nMask&RVIM_BKCOLOR ? nmrvic.item.iBkColor:-1;lpItem->nPreview = nmrvic.item.nMask&RVIM_PREVIEW ? nmrvic.item.nPreview:0;lpItem->nState = nmrvic.item.nMask&RVIM_STATE ? nmrvic.item.nState:0;lpItem->iIndent = nmrvic.item.nMask&RVIM_INDENT ? nmrvic.item.iIndent:-1;return TRUE;}return FALSE;}INT CReportCtrl::GetItemFromRow(INT iRow){if(m_dwStyle&RVS_OWNERDATA)return iRow;if(iRow == RVI_INVALID)return RVI_INVALID;return iRow == RVI_EDIT ? RVI_EDIT:m_arrayRows[iRow];}INT CReportCtrl::GetItemFromRow(INT iRow, ITEM& item){if(iRow == RVI_INVALID)return RVI_INVALID;INT iItem = iRow;if(!(m_dwStyle&RVS_OWNERDATA))iItem = GetItemFromRow(iItem);item = GetItemStruct(iItem, -1);return iItem;}INT CReportCtrl::GetRowFromItem(INT iItem){if(iItem == RVI_EDIT || m_dwStyle&RVS_OWNERDATA)return iItem;INT iRows = m_arrayRows.GetSize(), iRow;if(iRows > 0){if(m_bUpdateItemMap){for(iRow=0;iRow<iRows;iRow++)m_mapItemToRow[m_arrayRows[iRow]] = iRow;m_bUpdateItemMap = FALSE;}if(m_mapItemToRow.Lookup(iItem, iRow))return iRow;}return RVI_INVALID;}INT CReportCtrl::GetSubItemFromColumn(INT iColumn){if(iColumn < 0)return -1;HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);return hdi.lParam;}INT CReportCtrl::GetColumnFromSubItem(INT iSubItem){if(iSubItem < 0)return -1;INT iColumn, iColumns = m_arrayColumns.GetSize();for(iColumn=0;iColumn<iColumns;iColumn++){HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);if(hdi.lParam == iSubItem)return iColumn;}return -1;}CReportCtrl::LPTREEITEM CReportCtrl::GetVisibleAncestor(LPTREEITEM lpti){BOOL bExit = FALSE;LPTREEITEM lptiAncestor = GetVisibleAncestor(lpti, &bExit);return bExit ? lptiAncestor:lpti;}CReportCtrl::LPTREEITEM CReportCtrl::GetVisibleAncestor(LPTREEITEM lpti, LPBOOL lpbExit){if(lpti->lptiParent == &m_tiRoot)return lpti;LPTREEITEM lptiAncestor = GetVisibleAncestor(lpti->lptiParent, lpbExit);if(*lpbExit == TRUE)return lptiAncestor;if(lptiAncestor->bOpen == FALSE){*lpbExit = TRUE;return lptiAncestor;}return lpti;}BOOL CReportCtrl::SetSubItemWidthImpl(INT iSubItem, INT iWidth){INT iSubItems = m_arraySubItems.GetSize();ASSERT(iSubItem <= iSubItems);try{iWidth = iWidth<0 ? m_iDefaultWidth:iWidth;SUBITEM subitem;subitem = m_arraySubItems.GetAt(iSubItem);iWidth = iWidth<subitem.iMinWidth ? subitem.iMinWidth:iWidth;iWidth = iWidth>subitem.iMaxWidth && subitem.iMaxWidth > 0 ? subitem.iMaxWidth:iWidth;INT iOldWidth = subitem.iWidth;subitem.iWidth = iWidth;m_arraySubItems.SetAt(iSubItem, subitem);INT iColumn = GetColumnFromSubItem(iSubItem);if(iColumn < 0)return TRUE;HDITEM hditem;hditem.mask = HDI_WIDTH;if(!m_wndHeader.GetItem(m_arrayColumns[iColumn], &hditem))return FALSE;m_iVirtualWidth += iWidth - iOldWidth;hditem.cxy = iWidth;m_wndHeader.SetItem(m_arrayColumns[iColumn], &hditem);return TRUE;}catch(CMemoryException* e){e->Delete();return FALSE;}}void CReportCtrl::GetExpandedItemText(LPRVITEM lprvi){}void CReportCtrl::SetState(INT iRow, UINT nState, UINT nMask){ASSERT(iRow >= RVI_EDIT);if(iRow == RVI_EDIT){m_itemEdit.nState &= ~nMask;m_itemEdit.nState |= nState&nMask;}else if(!(m_dwStyle&RVS_OWNERDATA)){m_arrayItems[m_arrayRows[iRow]].nState &= ~nMask;m_arrayItems[m_arrayRows[iRow]].nState |= nState&nMask;}FlushCache(iRow);}UINT CReportCtrl::GetState(INT iRow){RVITEM rvi;rvi.iItem = GetItemFromRow(iRow);rvi.nMask = RVIM_STATE;GetItem(&rvi);ASSERT(rvi.nMask&RVIM_STATE); // Need to return state of the itemreturn rvi.nState;}CReportCtrl::LPTREEITEM CReportCtrl::GetTreeFocus(){INT iFocusItem = GetItemFromRow(m_iFocusRow);if(iFocusItem >= RVI_EDIT)SetState(m_iFocusRow, 0, RVIS_FOCUSED);m_iFocusRow = RVI_INVALID;return iFocusItem >= RVI_FIRST ? m_arrayItems[iFocusItem].lptiItem:NULL;}void CReportCtrl::SetTreeFocus(LPTREEITEM lptiFocus){INT iRows = m_arrayRows.GetSize();INT iFirst = GetScrollPos32(SB_VERT), iLast;if(lptiFocus != NULL){m_iFocusRow = GetRowFromItem(lptiFocus->iItem);if( m_iFocusRow == RVI_INVALID ){ScrollWindow(SB_VERT, 0);return;}}elsem_iFocusRow = RVI_EDIT;SetState(m_iFocusRow, RVIS_FOCUSED, RVIS_FOCUSED);GetVisibleRows(TRUE, &iFirst, &iLast);if(m_iFocusRow <= iFirst || iLast >= m_iFocusRow - 1)GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);ScrollWindow(SB_VERT, iFirst > RVI_INVALID ? iFirst : 0);}void CReportCtrl::DeselectDescendents(LPTREEITEM lptiParent){LPTREEITEM lptiSibling = lptiParent->lptiChildren;while(lptiSibling != NULL){if(lptiSibling->lptiChildren != NULL)DeselectDescendents(lptiSibling);POSITION pos = m_listSelection.Find(lptiSibling->iItem);if(pos != NULL){m_arrayItems[lptiSibling->iItem].nState &= ~RVIS_SELECTED;m_listSelection.RemoveAt(pos);}lptiSibling = lptiSibling->lptiSibling;}}void CReportCtrl::ReorderColumns(){LPINT lpi;INT iColumns = m_wndHeader.GetItemCount();if(iColumns){m_iFocusColumn = m_iFocusColumn >= iColumns ? iColumns-1:m_iFocusColumn;INT iSubItem = m_arrayColumns.GetSize() ? GetSubItemFromColumn(m_iFocusColumn):-1;m_arrayColumns.SetSize(iColumns, 8);lpi = m_arrayColumns.GetData();if(!m_wndHeader.GetOrderArray(lpi, iColumns))return;if(iSubItem > 0)m_iFocusColumn = GetColumnFromSubItem(iSubItem);elsem_iFocusColumn = -1;}else{m_arrayColumns.RemoveAll();m_iFocusColumn = -1;}if(m_lprsilc != NULL)m_lprsilc->UpdateList();m_bColumnsReordered = FALSE;}BOOL CReportCtrl::GetRowRect(INT iRow, INT iColumn, LPRECT lpRect, UINT nCode){// Select a visible sub-itemif(iColumn < 0 && nCode != RVIR_BOUNDS)return FALSE;INT iFirst, iLast;if(iRow != RVI_EDIT){iFirst = GetScrollPos32(SB_VERT);GetVisibleRows(FALSE, &iFirst, &iLast);// Select a visible itemif(iFirst > iRow || iLast < iRow)return FALSE;*lpRect = m_rectReport;for(;iFirst<iRow;iFirst++)lpRect->top +=m_iDefaultHeight +(m_bPreview ? GetItemStruct(GetItemFromRow(iFirst), -1).nPreview:0);}else*lpRect = m_rectEdit;lpRect->bottom = lpRect->top + m_iDefaultHeight;INT iPos = GetScrollPos32(SB_HORZ);lpRect->left -= iPos;lpRect->right -= iPos;INT iLeft = lpRect->left;if(iColumn < 0)return TRUE;HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;for(iFirst=0;iFirst<iColumn;iFirst++){m_wndHeader.GetItem(m_arrayColumns[iFirst], &hdi);lpRect->left += hdi.cxy;}m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);if(nCode == RVIR_TEXTNOCOLUMNS)lpRect->right = iLeft + m_iVirtualWidth;elselpRect->right = lpRect->left + hdi.cxy;return TRUE;}INT CReportCtrl::GetVisibleRows(BOOL bUnobstructed, LPINT lpiFirst, LPINT lpiLast, BOOL bReverse){INT iHeight = m_rectReport.Height();INT iRows = 0;if(!bReverse){INT iRow;INT iMaxRows = m_iVirtualHeight;if(lpiFirst)iRow = *lpiFirst;elseiRow = GetScrollPos32(SB_VERT);for(;iRow<iMaxRows&&iHeight>0;iRow++,iRows++){iHeight -=m_iDefaultHeight +(m_bPreview ? GetItemStruct(GetItemFromRow(iRow), -1).nPreview:0);if(bUnobstructed && iHeight<=0)break;}if(lpiLast)*lpiLast = iRow-1;}else{ASSERT(lpiFirst);ASSERT(lpiLast);for(*lpiFirst=*lpiLast;*lpiFirst>=0&&iHeight>0;*lpiFirst-=1,iRows++){iHeight -=m_iDefaultHeight +(m_bPreview ? GetItemStruct(GetItemFromRow(*lpiFirst), -1).nPreview:0);if(bUnobstructed && iHeight<=0)break;}*lpiFirst += 1;}return iRows;}void CReportCtrl::SelectRows(INT iFirst, INT iLast, BOOL bSelect, BOOL bKeepSelection, BOOL bInvert, BOOL bNotify){INT i;if(m_dwStyle&RVS_SINGLESELECT){iLast = iFirst;bKeepSelection = FALSE;}if(m_iFocusRow > RVI_INVALID && iFirst != m_iFocusRow){SetState(m_iFocusRow, 0, RVIS_FOCUSED);RedrawRows(m_iFocusRow);}m_iFocusRow = iFirst;SetState(iFirst, RVIS_FOCUSED, RVIS_FOCUSED);if(iFirst > iLast){iLast += iFirst;iFirst = iLast - iFirst;iLast -= iFirst;}if(bSelect){for(i=iFirst;i<=iLast;i++){INT iItem = GetItemFromRow(i);UINT nOldState, nNewState;nOldState = nNewState = GetState(i);if(bInvert)nNewState ^= RVIS_SELECTED;elsenNewState |= RVIS_SELECTED;if(nNewState != nOldState){if(bNotify && Notify(RVN_SELECTIONCHANGING, iItem, -1, nNewState))continue;POSITION pos = m_listSelection.Find(iItem);if(nNewState&RVIS_SELECTED){if(pos == NULL)m_listSelection.AddTail(iItem);}elsem_listSelection.RemoveAt(pos);SetState(i, nNewState, RVIS_SELECTED);if(bNotify)Notify(RVN_SELECTIONCHANGED, iItem, -1, nNewState);}}RedrawRows(iFirst, iLast);}elseRedrawRows(iFirst);if(!bKeepSelection && bSelect){CList<INT, INT> list;POSITION pos = m_listSelection.GetHeadPosition();while(pos != NULL){INT iItem = m_listSelection.GetAt(pos);INT i = GetRowFromItem(iItem);UINT nOldState, nNewState;nOldState = nNewState = GetState(i);if((i<iFirst || i>iLast) && nOldState&RVIS_SELECTED){nNewState &= ~RVIS_SELECTED;if(nNewState != nOldState){if(bNotify && Notify(RVN_SELECTIONCHANGING, iItem, -1, nNewState))continue;SetState(i, nNewState, RVIS_SELECTED);if(bNotify)Notify(RVN_SELECTIONCHANGED, iItem, -1, nNewState);RedrawRows(i);}}elselist.AddTail(iItem);m_listSelection.GetNext(pos);}m_listSelection.RemoveAll();m_listSelection.AddTail(&list);}UpdateWindow();}INT CReportCtrl::GetScrollPos32(INT iBar, BOOL bGetTrackPos){SCROLLINFO si;si.cbSize = sizeof(SCROLLINFO);INT iMax = iBar==SB_HORZ ? m_iVirtualWidth:m_iVirtualHeight;if(bGetTrackPos){if(GetScrollInfo(iBar, &si, SIF_TRACKPOS))return min(si.nTrackPos, iMax);}else{if(GetScrollInfo(iBar, &si, SIF_POS))return min(si.nPos, iMax);}return 0;}BOOL CReportCtrl::SetScrollPos32(INT iBar, INT iPos, BOOL bRedraw){SCROLLINFO si;si.cbSize = sizeof(SCROLLINFO);si.fMask = SIF_POS;si.nPos = iPos;return SetScrollInfo(iBar, &si, bRedraw);}void CReportCtrl::ScrollWindow(INT iBar, INT iPos){if(m_rectReport.Width()<=0 || m_rectReport.Height()<=0)return;m_wndTip.Hide();if(iBar == SB_HORZ){SCROLLINFO si;INT iWidth = m_rectReport.Width();si.cbSize = sizeof(SCROLLINFO);si.fMask = SIF_PAGE|SIF_RANGE|SIF_POS;si.nPage = iWidth;si.nMin = 0;si.nMax = iWidth<m_iVirtualWidth ? m_iVirtualWidth-1:0;si.nPos = iPos;SetScrollInfo(SB_HORZ, &si, TRUE);INT x = GetScrollPos32(SB_HORZ);INT cx = iWidth<m_iVirtualWidth ? m_iVirtualWidth:iWidth;VERIFY(m_wndHeader.SetWindowPos(&wndTop, -x, m_rectHeader.top, cx, m_rectHeader.Height(), m_dwStyle&RVS_NOHEADER ? SWP_HIDEWINDOW:SWP_SHOWWINDOW));}if(iBar == SB_VERT){ASSERT(iPos >= 0 && iPos<=m_iVirtualHeight);INT iFirst = iPos, iLast;GetVisibleRows(TRUE, &iFirst, &iLast);SCROLLINFO si;si.cbSize = sizeof(SCROLLINFO);si.fMask = SIF_PAGE|SIF_RANGE|SIF_POS;si.nPage = (iLast - iFirst + 1);si.nMin = 0;si.nMax = (iLast - iFirst + 1)<m_iVirtualHeight ? m_iVirtualHeight-1:0;si.nPos = iFirst;SetScrollInfo(SB_VERT, &si, TRUE);}if(m_dwStyle&RVS_SHOWEDITROW)InvalidateRect(m_rectEdit);InvalidateRect(m_rectReport);//// May solve slow redrawing problems//// UpdateWindow();}void CReportCtrl::EnsureVisibleColumn(INT iColumn){if(iColumn > -1){INT iWidth = m_rectReport.Width();INT iPos = GetScrollPos(SB_HORZ);INT iOffset = 0;HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;for(INT i=0;i<iColumn;i++){m_wndHeader.GetItem(m_arrayColumns[i], &hdi);iOffset += hdi.cxy;}m_wndHeader.GetItem(m_arrayColumns[i], &hdi);if(iOffset + hdi.cxy > iPos+iWidth || iOffset < iPos)ScrollWindow(SB_HORZ, iOffset);}}void CReportCtrl::SetIndentFirstColumn(INT iIndent){UnindentFirstColumn();m_iIndentColumn = iIndent;IndentFirstColumn();}void CReportCtrl::IndentFirstColumn(){if(m_arrayColumns.GetSize() > 0 && m_iIndentColumn > 0){ASSERT(m_bIndentColumn == FALSE);INT iSubItem = GetSubItemFromColumn(0);ASSERT(iSubItem >= 0);SUBITEM& subitem = m_arraySubItems[iSubItem];subitem.iMinWidth += m_iIndentColumn;subitem.iMaxWidth += subitem.iMaxWidth>0 ? m_iIndentColumn:0;SetSubItemWidthImpl(iSubItem, subitem.iWidth+m_iIndentColumn);m_wndHeader.SetMinMax(m_wndHeader.OrderToIndex(0),subitem.iMinWidth,subitem.iMaxWidth);m_bIndentColumn = TRUE;}}void CReportCtrl::UnindentFirstColumn(){if(m_bIndentColumn && m_iIndentColumn>=0){INT iSubItem = GetSubItemFromColumn(0);ASSERT(iSubItem >= 0);SUBITEM& subitem = m_arraySubItems[iSubItem];subitem.iMaxWidth -= subitem.iMaxWidth>0 ? m_iIndentColumn:0;subitem.iMinWidth -= m_iIndentColumn;SetSubItemWidthImpl(iSubItem,(subitem.iMinWidth <= 0 && subitem.iWidth-m_iIndentColumn < 20)?20:subitem.iWidth-m_iIndentColumn);m_iIndentColumnPending =m_iIndentColumnPending >= 0?m_iIndentColumnPending:m_wndHeader.OrderToIndex(0);m_wndHeader.SetMinMax(m_iIndentColumnPending,subitem.iMinWidth,subitem.iMaxWidth);}m_bIndentColumn = FALSE;m_iIndentColumnPending = -1;}void CReportCtrl::SetRedraw(BOOL bRedraw){CWnd::SetRedraw(bRedraw);m_bRedrawFlag = bRedraw;if(bRedraw == TRUE)UpdateWindow();}void CReportCtrl::RedrawRows(INT iFirst, INT iLast, BOOL bUpdate){CRect rect;if(iFirst == iLast || iLast == RVI_INVALID){if(iFirst == RVI_INVALID && iLast == RVI_INVALID)return;GetRowRect(iFirst, -1, rect);if(m_bPreview)rect.bottom += GetItemStruct(GetItemFromRow(iFirst), -1, RVIM_PREVIEW).nPreview;rect.OffsetRect(GetScrollPos32(SB_HORZ), 0);}elserect = m_rectReport;InvalidateRect(rect);if(bUpdate)UpdateWindow();}void CReportCtrl::SelectionToSortedArray(CArray<INT, INT>& arrayRows){INT iPos = 0, iSize;POSITION pos = m_listSelection.GetHeadPosition();while( pos != NULL ){INT iRow = GetRowFromItem(m_listSelection.GetAt(pos));iSize = arrayRows.GetSize();if(iSize){INT iTest = arrayRows[iPos];if(arrayRows[iPos] <= iRow){while(iPos<iSize && arrayRows[iPos] <= iRow)iPos++;}else{while( iPos>0 && arrayRows[iPos-1] > iRow)iPos--;}}arrayRows.InsertAt(iPos, iRow);m_listSelection.GetNext(pos);}}void CReportCtrl::DrawCtrl(CDC* pDC){CRect rectClip;if (pDC->GetClipBox(&rectClip) == ERROR)return;INT iHPos = GetScrollPos32(SB_HORZ);INT iVPos = GetScrollPos32(SB_VERT);DrawBkgnd(pDC, rectClip, m_dwStyle&WS_DISABLED ? m_cr3DFace:m_crBackground);CPen pen(m_iGridStyle, 1, m_crGrid);CPen* pPen = pDC->SelectObject(&pen);CFont* pFont = pDC->SelectObject(GetFont());pDC->SetBkMode(TRANSPARENT);CRect rect;CRect rectRow(m_rectReport.left-iHPos, m_rectReport.top, m_rectReport.left-iHPos+m_iVirtualWidth, m_rectReport.top);GetClientRect( rect );rect.right = rect.left + m_iDefaultHeight;rect.OffsetRect( -iHPos, 0 );if(m_iIndentColumn > 0 && m_bIndentGrey &&rectClip.left < rect.right && rect.right > 0)pDC->FillSolidRect( rect, m_cr3DFace );TCHAR szText[REPORTCTRL_MAX_TEXT];RVITEM rvi;rvi.nMask = RVIM_TEXT;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;NMRVDRAWPREVIEW nmrvdp;nmrvdp.hdr.hwndFrom = GetSafeHwnd();nmrvdp.hdr.idFrom = GetDlgCtrlID();nmrvdp.hdr.code = RVN_ITEMDRAWPREVIEW;nmrvdp.hDC = pDC->m_hDC;INT iRows = m_iVirtualHeight;INT iColumns = m_arrayColumns.GetSize();if(m_bColumnsReordered){UnindentFirstColumn();ReorderColumns();IndentFirstColumn();}if(m_dwStyle&RVS_SHOWEDITROW){GetClientRect(rect);rect.bottom = m_rectEdit.bottom;rect.top = rect.bottom - GetSystemMetrics(SM_CYFIXEDFRAME)*2;pDC->FillSolidRect(rect, m_cr3DFace);pDC->Draw3dRect(rect, m_cr3DHiLight, m_cr3DDkShadow);rvi.iItem = RVI_EDIT;rvi.nMask = RVIM_TEXT;GetItem(&rvi);rect = m_rectEdit;rect.bottom -= GetSystemMetrics(SM_CYFIXEDFRAME)*2;rect.left -= iHPos;DrawRow(pDC, rect, rectClip, RVI_EDIT, &rvi, FALSE);if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == RVI_EDIT && m_iFocusColumn < 0){if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))rect.DeflateRect(1, 0, 1, 0);pDC->SetBkColor(m_dwStyle&WS_DISABLED ? m_cr3DFace:m_crBackground);pDC->SetTextColor(m_crText);pDC->DrawFocusRect(rect);}}if(!iRows){rectRow.top += 2;rectRow.bottom = rectRow.top + m_iDefaultHeight;GetClientRect(rect);rect.top = rectRow.top;rect.bottom = rectRow.bottom;if(rectRow.Width() < rect.Width())rect = rectRow;if(!m_strNoItems.IsEmpty()){pDC->SetTextColor(m_crText);pDC->DrawText(m_strNoItems, rect, DT_CENTER|DT_END_ELLIPSIS);}}else{INT iRow = iVPos;while(iRow<iRows && rectRow.top<rectClip.bottom){rvi.iItem = GetItemFromRow(iRow);rvi.nMask = RVIM_TEXT;rvi.lpszText = szText;VERIFY(GetItem(&rvi));rectRow.left = m_rectReport.left-iHPos;rectRow.bottom = rectRow.top + m_iDefaultHeight + (m_bPreview ? rvi.nPreview:0);if(rectRow.bottom >= rectClip.top){if(rvi.iIndent >= 0){rectRow.left += rvi.iIndent*m_iDefaultHeight;rectRow.right = max(rectRow.left, rectRow.right);}DrawRow(pDC, rectRow, rectClip, iRow, &rvi, iRow&1);if(m_bPreview && rvi.nMask&RVIM_PREVIEW && rvi.nPreview){nmrvdp.iItem = rvi.iItem;nmrvdp.nState = rvi.nState;nmrvdp.rect = rectRow;nmrvdp.rect.top += m_iDefaultHeight;nmrvdp.lParam = rvi.lParam;Notify((LPNMREPORTVIEW)&nmrvdp);}if(m_dwStyle&RVS_SHOWHGRID){pDC->MoveTo(rectRow.left, rectRow.bottom-1);pDC->LineTo(rectRow.right, rectRow.bottom-1);}if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == iRow && (!(m_dwStyle&RVS_FOCUSSUBITEMS) || m_iFocusColumn < 0)){if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))rectRow.DeflateRect(1, 0, 1, 1);pDC->SetBkColor(m_dwStyle&WS_DISABLED ? m_cr3DFace:m_crBackground);pDC->SetTextColor(m_crText);pDC->DrawFocusRect(rectRow);if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))rectRow.InflateRect(1, 0, 1, 1);}}rectRow.top = rectRow.bottom;iRow++;}rectRow.top = m_rectReport.top;rectRow.bottom =m_rectReport.bottom<rectRow.bottom?m_rectReport.bottom:rectRow.bottom;if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID)){if(m_dwStyle&RVS_SHOWHGRIDEX){pDC->MoveTo(rectRow.left, m_rectReport.top);pDC->LineTo(rectRow.left, m_rectReport.bottom);pDC->MoveTo(rectRow.right-1, m_rectReport.top);pDC->LineTo(rectRow.right-1, m_rectReport.bottom);}else{pDC->MoveTo(rectRow.left, rectRow.top);pDC->LineTo(rectRow.left, rectRow.bottom);pDC->MoveTo(rectRow.right-1, rectRow.top);pDC->LineTo(rectRow.right-1, rectRow.bottom);}}if(m_dwStyle&RVS_SHOWHGRID && m_dwStyle&RVS_SHOWHGRIDEX && iRow>=iRows){while(rectRow.bottom<=rectClip.bottom){pDC->MoveTo(rectRow.left, rectRow.bottom-1);pDC->LineTo(rectRow.right, rectRow.bottom-1);rectRow.bottom += m_iDefaultHeight;}}if(m_dwStyle&RVS_SHOWVGRID){for(INT iColumn=0;iColumn<iColumns&&rectRow.left<rectClip.right;iColumn++){HDITEM hdi;hdi.mask = HDI_WIDTH;m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);rectRow.left += hdi.cxy;pDC->MoveTo(rectRow.left-1, rectRow.top);pDC->LineTo(rectRow.left-1, rectRow.bottom);}}}pDC->SelectObject(pFont);pDC->SelectObject(pPen);pen.DeleteObject();}void CReportCtrl::DrawRow(CDC* pDC, CRect rectRow, CRect rectClip, INT iRow, LPRVITEM lprvi, BOOL bAlternate){INT iColumns = m_arrayColumns.GetSize();// You have to insert at least 1 color to use color alternate style.ASSERT(!(m_dwStyle&RVS_SHOWCOLORALTERNATE && !m_arrayColors.GetSize()));ASSERT(lprvi->lpszText != NULL);LPTSTR lpszText = lprvi->lpszText;COLORREF crItem, crBackground = m_dwStyle&WS_DISABLED ? m_cr3DFace:m_crBackground;crItem = (m_dwStyle&RVS_SHOWCOLORALTERNATE && bAlternate) ? m_arrayColors[0]:crBackground;crItem = lprvi->iBkColor>=0 ? m_arrayColors[lprvi->iBkColor]:crItem;if(lprvi->nState&RVIS_SELECTED){if(m_bFocus)crItem = m_crBkSelected;elseif(m_dwStyle&RVS_SHOWSELALWAYS)crItem = m_crBkSelectedNoFocus;}if(m_bitmap.m_hObject == NULL || crItem != crBackground || iRow == RVI_EDIT){pDC->FillSolidRect(rectRow, crItem);pDC->SetBkColor(crItem);}if(lprvi->nState&RVIS_BOLD)pDC->SelectObject(&m_fontBold);CRect rectItem(rectRow.left, rectRow.top, rectRow.left, rectRow.top+m_iDefaultHeight);for(INT iColumn=0;iColumn<iColumns&&rectItem.left<rectClip.right;iColumn++){HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_LPARAM;m_wndHeader.GetItem(m_arrayColumns[iColumn], &hdi);lprvi->iSubItem = hdi.lParam;rectItem.right = rectItem.left + hdi.cxy -(iColumn == 0 && lprvi->iIndent >= 0?lprvi->iIndent*m_iDefaultHeight:0);if(rectItem.right > rectClip.left){lprvi->nMask = RVIM_TEXT;lprvi->lpszText = lpszText;VERIFY(GetItem(lprvi));COLORREF crText = lprvi->nMask&RVIM_TEXTCOLOR ? m_arrayColors[lprvi->iTextColor]:m_crText;if(lprvi->nState&RVIS_SELECTED){if(m_bFocus)crText = (m_dwStyle&RVS_SHOWCOLORALWAYS && lprvi->nMask&RVIM_TEXTCOLOR) ? crText:m_crTextSelected;elseif(m_dwStyle&RVS_SHOWSELALWAYS)crText = lprvi->nMask&RVIM_TEXTCOLOR && m_dwStyle&RVS_SHOWCOLORALWAYS ? crText:m_crTextSelectedNoFocus;}if(m_iFocusRow == iRow && m_iFocusColumn == iColumn && (m_iFocusRow == RVI_EDIT || m_dwStyle&RVS_FOCUSSUBITEMS)){pDC->FillSolidRect(rectItem, crBackground);crText = m_crText;}pDC->SetTextColor(crText);if(iColumn == 0 && lprvi->iIndent >= 0){if(lprvi->nState&RVIS_TREEMASK){rectItem.left -= m_iDefaultHeight;DrawTreeBox(pDC, rectItem, lprvi->nState&RVIS_TREEOPENED);rectItem.left += m_iDefaultHeight;}if(!(m_dwStyle&RVS_OWNERDATA)){LPTREEITEM lpti = m_arrayItems[lprvi->iItem].lptiItem;if(lpti != NULL ){if(lpti->iSubItem >= 0){rectItem.right = rectRow.right;lprvi->iSubItem = lpti->iSubItem;lprvi->nMask = RVIM_TEXT;lprvi->lpszText = lpszText;VERIFY(GetItem(lprvi));rectItem.DeflateRect(m_iSpacing, 0);DrawItem(pDC, rectItem, lprvi);rectItem.InflateRect(m_iSpacing, 0);break;}}}}rectItem.DeflateRect(m_iSpacing, 0);DrawItem(pDC, rectItem, lprvi);rectItem.InflateRect(m_iSpacing, 0);if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == iRow && m_iFocusColumn == iColumn && (m_iFocusRow == RVI_EDIT || m_dwStyle&RVS_FOCUSSUBITEMS)){if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))rectItem.DeflateRect(1, 0, 1, 1);pDC->SetBkColor(crBackground);pDC->SetTextColor(m_crText);pDC->DrawFocusRect(rectItem);if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))rectItem.InflateRect(1, 0, 1, 1);}}rectItem.left = rectItem.right;}if(lprvi->nState&RVIS_BOLD)pDC->SelectObject(GetFont());}void CReportCtrl::DrawItem(CDC* pDC, CRect rect, LPRVITEM lprvi){BOOL bResult = FALSE;if(lprvi->nState&RVIS_OWNERDRAW){NMRVITEMDRAW nmrvid;nmrvid.hdr.hwndFrom = GetSafeHwnd();nmrvid.hdr.idFrom = GetDlgCtrlID();nmrvid.hdr.code = RVN_ITEMDRAW;nmrvid.lprvi = lprvi;nmrvid.hDC = pDC->GetSafeHdc();nmrvid.rect = rect;bResult = Notify((LPNMREPORTVIEW)&nmrvid);}if( !bResult ){INT iWidth = 0;rect.left += (iWidth = DrawImage(pDC, rect, lprvi)) ? iWidth+m_iSpacing : 0;if(lprvi->nMask&RVIM_IMAGE && !iWidth)return;rect.left += (iWidth = DrawCheck(pDC, rect, lprvi)) ? iWidth+m_iSpacing : 0;if(lprvi->nMask&RVIM_CHECK && !iWidth)return;DrawText(pDC, rect, lprvi);}}INT CReportCtrl::DrawTreeBox(CDC* pDC, CRect rectBox, BOOL bOpen){if(rectBox.right < rectBox.left)return rectBox.right;rectBox.right = rectBox.left + rectBox.Height();CPoint point = rectBox.CenterPoint();CRect rect;rect.SetRect(point, point);rect.InflateRect(4, 4, 5, 5);pDC->FillSolidRect(rect, m_cr3DShadow);rect.DeflateRect(1, 1);pDC->FillSolidRect(rect, m_crBackground);CPen pen(PS_SOLID, 1, m_crText);CPen* pPen = pDC->SelectObject(&pen);pDC->MoveTo(point.x-2, point.y);pDC->LineTo(point.x+3, point.y);if(!bOpen){pDC->MoveTo(point.x, point.y-2);pDC->LineTo(point.x, point.y+3);}pDC->SelectObject(pPen);return rectBox.right;}INT CReportCtrl::DrawImage(CDC* pDC, CRect rect, LPRVITEM lprvi){CImageList* pImageList = GetImageList();INT iWidth = 0;if(lprvi->nMask&RVIM_IMAGE){ASSERT(pImageList);ASSERT(lprvi->iImage>=0 && lprvi->iImage<pImageList->GetImageCount());if(rect.Width()>0){POINT point;UINT nStyle = ILD_NORMAL;COLORREF crColor = 0;point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1) + 1;point.x = rect.left;switch( m_nBlendStyle ){case RVP_BLEND_FOCUS:nStyle = lprvi->nState&RVIS_FOCUSED ? ILD_FOCUS:ILD_NORMAL;crColor = m_crBackground;break;case RVP_BLEND_SELECT:nStyle = lprvi->nState&RVIS_SELECTED ? ILD_SELECTED:ILD_NORMAL;crColor = pDC->GetBkColor();break;case RVP_BLEND_ALL:nStyle = lprvi->nState&RVIS_FOCUSED ? ILD_FOCUS:ILD_NORMAL;crColor = m_crBackground;if( lprvi->nState&RVIS_SELECTED ){nStyle = lprvi->nState&RVIS_SELECTED ? ILD_SELECTED:ILD_NORMAL;crColor = pDC->GetBkColor();}break;default:if( lprvi->nState&RVIS_BLENDMASK ){nStyle = lprvi->nState&RVIS_BLEND25 ? ILD_BLEND25:ILD_BLEND50;crColor = m_crBlendColor;}break;}SIZE size;size.cx = rect.Width()<m_sizeImage.cx ? rect.Width():m_sizeImage.cx;size.cy = m_sizeImage.cy;pImageList->DrawIndirect(pDC, lprvi->iImage, point, size, CPoint(0, 0),nStyle, SRCCOPY, CLR_DEFAULT, crColor);if(lprvi->nMask&RVIM_OVERLAY)pImageList->DrawIndirect(pDC, lprvi->iOverlay, point, size, CPoint(0, 0),nStyle, SRCCOPY, CLR_DEFAULT, crColor);iWidth = m_sizeImage.cx;}}elseiWidth = m_arraySubItems[lprvi->iSubItem].nFormat&RVCF_SUBITEM_IMAGE ? m_sizeImage.cx:0;return iWidth;}INT CReportCtrl::DrawCheck(CDC* pDC, CRect rect, LPRVITEM lprvi){INT iWidth = 0;if(lprvi->nMask&RVIM_CHECK){if(rect.Width()>m_sizeCheck.cx){if( m_pCheckList == NULL ){rect.top = rect.CenterPoint().y - (m_sizeCheck.cy>>1);rect.left = rect.left;rect.bottom = rect.top + m_sizeCheck.cx;rect.right = rect.left + m_sizeCheck.cy;UINT nState = m_nFrameControlStyle;BOOL bDisable = FALSE;switch(lprvi->iCheck){case 2: bDisable = TRUE; // Intentionalcase 0: nState |= DFCS_BUTTONCHECK; break;case 3: bDisable = TRUE; // Intentionalcase 1: nState |= DFCS_BUTTONCHECK|DFCS_CHECKED; break;case 6: bDisable = TRUE; // Intentionalcase 4: nState |= DFCS_BUTTONRADIO; break;case 7: bDisable = TRUE; // Intentionalcase 5: nState |= DFCS_BUTTONRADIO|DFCS_CHECKED; break;}pDC->DrawFrameControl(rect, DFC_BUTTON, nState);CPen pen(PS_SOLID, 2, RGB(0xFF, 0, 0));CPen* pPen = pDC->SelectObject(&pen);if(bDisable == TRUE){rect.DeflateRect(1, 1);if( lprvi->iCheck >= 4 )rect.OffsetRect(1, 0);pDC->MoveTo(rect.left, rect.top);pDC->LineTo(rect.right-1, rect.bottom-1);pDC->MoveTo(rect.right-1, rect.top);pDC->LineTo(rect.left, rect.bottom-1);pDC->SelectObject(pPen);}}else{POINT point;point.y = rect.CenterPoint().y - (m_sizeCheck.cy>>1) + 1;point.x = rect.left;SIZE size;size.cx = rect.Width()<m_sizeCheck.cx ? rect.Width():m_sizeCheck.cx;size.cy = m_sizeCheck.cy;m_pCheckList->DrawIndirect(pDC, lprvi->iCheck, point, size, CPoint(0, 0));}iWidth = m_sizeCheck.cx;}}elseiWidth = m_arraySubItems[lprvi->iSubItem].nFormat&RVCF_SUBITEM_CHECK ? m_sizeCheck.cx:0;return iWidth;}INT CReportCtrl::DrawText(CDC* pDC, CRect rect, LPRVITEM lprvi){CSize size;if(rect.Width()>0 && lprvi->nMask&RVIM_TEXT){size = pDC->GetTextExtent(lprvi->lpszText);switch(m_arraySubItems[lprvi->iSubItem].nFormat&HDF_JUSTIFYMASK){case HDF_LEFT:case HDF_LEFT|HDF_RTLREADING:pDC->DrawText(lprvi->lpszText, -1, rect, DT_LEFT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);break;case HDF_CENTER:case HDF_CENTER|HDF_RTLREADING:pDC->DrawText(lprvi->lpszText, -1, rect, DT_CENTER|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);break;case HDF_RIGHT:case HDF_RIGHT|HDF_RTLREADING:pDC->DrawText(lprvi->lpszText, -1, rect, DT_RIGHT|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER);break;}}size.cx = rect.Width()>size.cx ? size.cx:rect.Width();return size.cx>0 ? size.cx:0;}BOOL CReportCtrl::DrawBkgnd(CDC* pDC, CRect rect, COLORREF crBackground){if(m_bitmap.m_hObject != NULL){CDC dc;CRgn rgnBitmap;CRect rectBitmap;dc.CreateCompatibleDC(pDC);dc.SelectObject(&m_bitmap);rect.IntersectRect(rect, m_rectReport);INT iHPos = GetScrollPos32(SB_HORZ);rectBitmap.top = rect.top - rect.top%m_sizeBitmap.cy;rectBitmap.bottom = rect.top + m_sizeBitmap.cy;rectBitmap.left = rect.left - (rect.left+iHPos)%m_sizeBitmap.cx;rectBitmap.right = rect.left + m_sizeBitmap.cx;INT x, y;for(x = rectBitmap.left; x < rect.right; x += m_sizeBitmap.cx)for(y = rectBitmap.top; y < rect.bottom; y += m_sizeBitmap.cy)pDC->BitBlt(x, y, m_sizeBitmap.cx, m_sizeBitmap.cy, &dc, 0, 0, SRCCOPY);return TRUE;}pDC->FillSolidRect(rect, crBackground);return FALSE;}BOOL CReportCtrl::BeginEdit(INT iRow, INT iColumn, UINT nKey){if(iRow == RVI_INVALID || iColumn < 0)return FALSE;if(iRow == RVI_EDIT && !(m_dwStyle&RVS_SHOWEDITROW))return FALSE;TCHAR szText[REPORTCTRL_MAX_TEXT];m_iEditItem = GetItemFromRow(iRow);m_iEditSubItem = GetSubItemFromColumn(iColumn);// Make sure that the item to edit actually existsASSERT(m_iEditItem != RVI_INVALID && m_iEditSubItem != -1);RVITEM rvi;rvi.iItem = m_iEditItem;rvi.iSubItem = m_iEditSubItem;rvi.nMask = RVIM_TEXT|RVIM_STATE|RVIM_LPARAM;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;GetItem(&rvi);if(rvi.nState&RVIS_READONLY)return FALSE;NMRVITEMEDIT nmrvie;memset(&nmrvie, 0, sizeof(nmrvie));nmrvie.hdr.hwndFrom = GetSafeHwnd();nmrvie.hdr.idFrom = GetDlgCtrlID();nmrvie.hdr.code = RVN_BEGINITEMEDIT;nmrvie.iItem = m_iEditItem;nmrvie.iSubItem = m_iEditSubItem;nmrvie.hWnd = NULL;if(!GetItemRect(m_iEditItem, m_iEditSubItem, &nmrvie.rect))return FALSE;nmrvie.nKey = nKey;if(rvi.nMask&RVIM_TEXT)nmrvie.lpszText = szText;nmrvie.lParam = rvi.lParam;BOOL bResult = FALSE;if(GetParent() != NULL)bResult = Notify((LPNMREPORTVIEW)&nmrvie);if(!bResult){if(!(rvi.nMask&RVIM_TEXT))return FALSE;if(!GetItemRect(m_iEditItem, m_iEditSubItem, &nmrvie.rect, RVIR_TEXT))return FALSE;nmrvie.rect.top += 2;CReportEditCtrl* pWnd= new CReportEditCtrl(m_iEditItem, m_iEditSubItem, nmrvie.bButton);if(pWnd == NULL)return FALSE;if(!pWnd->Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,nmrvie.rect,this,0)) {delete pWnd;return FALSE;}pWnd->SetFont(rvi.nMask&RVIM_STATE && rvi.nState&RVIS_BOLD?&m_fontBold:&m_font);pWnd->SetWindowText(szText);pWnd->BeginEdit(nKey);m_hEditWnd = pWnd->GetSafeHwnd();}else{if(nmrvie.hWnd == NULL)return FALSE;m_hEditWnd = nmrvie.hWnd;}if(m_hEditWnd != NULL)::SetFocus(m_hEditWnd);return TRUE;}void CReportCtrl::EndEdit(BOOL bUpdate, LPNMRVITEMEDIT lpnmrvie){if(!(m_dwStyle&RVS_OWNERDATA) && bUpdate){if(lpnmrvie == NULL){TCHAR szText[REPORTCTRL_MAX_TEXT];INT i = ::GetWindowText(m_hEditWnd, szText, REPORTCTRL_MAX_TEXT-1);szText[REPORTCTRL_MAX_TEXT-1] = 0;if(i || !::GetLastError())SetItemText(m_iEditItem, m_iEditSubItem, szText);}elseSetItemText(m_iEditItem, m_iEditSubItem, lpnmrvie->lpszText);}if(IsWindow(m_hEditWnd))::PostMessage(m_hEditWnd, WM_CLOSE, 0, 0);m_hEditWnd = NULL;CWnd* pWnd = GetFocus();if(pWnd){if(pWnd->GetSafeHwnd() != m_hWnd)m_bFocus = FALSE;}RedrawRows(m_iFocusRow);}void CReportCtrl::QuickSort(INT iColumn, INT iLow, INT iHigh, BOOL bAscending){INT i, j;i = iHigh;j = iLow;INT iRow = m_arrayRows[((INT) ((iLow+iHigh) / 2))];do{if(bAscending){while(CompareItems(m_arrayRows[j], iColumn, iRow, iColumn) < 0) j++;while(CompareItems(m_arrayRows[i], iColumn, iRow, iColumn) > 0) i--;}else{while(CompareItems(m_arrayRows[j], iColumn, iRow, iColumn) > 0) j++;while(CompareItems(m_arrayRows[i], iColumn, iRow, iColumn) < 0) i--;}if(i >= j){if (i != j){INT iTemp;iTemp = m_arrayRows[i];m_arrayRows[i] = m_arrayRows[j];m_arrayRows[j] = iTemp;}i--;j++;}} while(j <= i);if(iLow < i) QuickSort(iColumn, iLow, i, bAscending);if(j < iHigh) QuickSort(iColumn, j, iHigh, bAscending);}void CReportCtrl::TreeSort(INT iSubItem, LPTREEITEM lptiParent, BOOL bAscending, BOOL bTraverse){TREEITEM ti;LPTREEITEM lpti, lptiSibling = lptiParent->lptiChildren;while(lptiSibling != NULL){lpti = lptiSibling;lptiSibling = lptiSibling->lptiSibling;lpti->lptiSibling = NULL;if(bTraverse && lpti->lptiChildren != NULL)TreeSort(iSubItem, lpti, bAscending);InsertTree(iSubItem, &ti, (LPTREEITEM)RVTI_SORT, lpti, bAscending);}lptiParent->lptiChildren = ti.lptiChildren;}/////////////////////////////////////////////////////////////////////////////// CReportCtrl message handlersBOOL CReportCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message){SetCursor(::LoadCursor(NULL, IDC_ARROW));return CWnd::OnSetCursor(pWnd, nHitTest, message);}void CReportCtrl::OnSetFocus(CWnd* pOldWnd){CWnd::OnSetFocus(pOldWnd);m_bFocus = TRUE;Invalidate();}void CReportCtrl::OnKillFocus(CWnd* pNewWnd){CWnd::OnKillFocus(pNewWnd);if(CWnd::IsChild(pNewWnd) == FALSE)m_bFocus = FALSE;if( m_bFocus == FALSE && pNewWnd != NULL && pNewWnd->GetSafeHwnd() != m_wndTip.GetSafeHwnd())m_wndTip.Hide();Invalidate();}void CReportCtrl::OnSysColorChange(){CWnd::OnSysColorChange();GetSysColors();}void CReportCtrl::OnSettingChange(UINT uFlags, LPCTSTR lpszSection){CWnd::OnSettingChange(uFlags, lpszSection);m_nRowsPerWheelNotch = GetMouseScrollLines();}BOOL CReportCtrl::OnQueryNewPalette(){Invalidate();return CWnd::OnQueryNewPalette();}void CReportCtrl::OnPaletteChanged(CWnd* pFocusWnd){CWnd::OnPaletteChanged(pFocusWnd);if(pFocusWnd->GetSafeHwnd() != GetSafeHwnd())Invalidate();}void CReportCtrl::OnSize(UINT nType, int cx, int cy){if(m_hEditWnd != NULL)EndEdit();CWnd::OnSize(nType, cx, cy);CRect rect;GetClientRect(rect);Layout(rect.Width(), rect.Height());}void CReportCtrl::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos){CWnd::OnWindowPosChanging(lpwndpos);if(!m_bHorzScrollBar){ShowScrollBar( SB_HORZ, FALSE );ModifyStyle( WS_HSCROLL, 0, SWP_DRAWFRAME );}}LRESULT CReportCtrl::OnGetFont(WPARAM wParam, LPARAM lParam){return (LRESULT)m_font.m_hObject;}LRESULT CReportCtrl::OnSetFont(WPARAM wParam, LPARAM lParam){LRESULT lResult = Default();CFont *pFont = CFont::FromHandle((HFONT)wParam);if(pFont){LOGFONT lf;pFont->GetLogFont(&lf);m_font.DeleteObject();m_font.CreateFontIndirect(&lf);lf.lfWeight = FW_BOLD;m_fontBold.DeleteObject();m_fontBold.CreateFontIndirect(&lf);}CDC* pDC = GetDC();if (pDC){CFont* pFont = pDC->SelectObject(&m_font);TEXTMETRIC tm;pDC->GetTextMetrics(&tm);pDC->SelectObject(pFont);ReleaseDC(pDC);INT iDefaultHeight;iDefaultHeight = tm.tmHeight + tm.tmExternalLeading + 2;iDefaultHeight += m_dwStyle&RVS_SHOWHGRID ? 1:0;if( m_pImageList != NULL )m_iDefaultHeight = max(iDefaultHeight, m_sizeImage.cy+1);elsem_iDefaultHeight = iDefaultHeight;m_sizeCheck.cx = m_iDefaultHeight-2;m_sizeCheck.cy = m_iDefaultHeight-2;}if(::IsWindow(GetSafeHwnd()) && lParam){CRect rect;GetClientRect(rect);Layout(rect.Width(), rect.Height());}return lResult;}BOOL CReportCtrl::OnEraseBkgnd(CDC* pDC){return TRUE;}void CReportCtrl::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp){LONG lStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);if(lStyle & WS_BORDER)::InflateRect(&lpncsp->rgrc[0], -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));Default();}void CReportCtrl::OnNcPaint(){Default();LONG lStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);if(lStyle & WS_BORDER){CWindowDC dc(this);CRect rcBounds;GetWindowRect(rcBounds);ScreenToClient(rcBounds);rcBounds.OffsetRect(-rcBounds.left, -rcBounds.top);dc.DrawEdge(rcBounds, EDGE_SUNKEN, BF_RECT);}}void CReportCtrl::OnPaint(){CPaintDC dc(this);CPalette* pPalette = NULL;if(dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE){pPalette = dc.SelectPalette(&m_palette, FALSE);dc.RealizePalette();}dc.ExcludeClipRect(m_rectHeader);if(m_bDoubleBuffer){CMemDC MemDC(&dc);DrawCtrl(&MemDC);if(m_hEditWnd != NULL){RECT rect;::GetWindowRect(m_hEditWnd, &rect);ScreenToClient(&rect);dc.ExcludeClipRect(&rect);}}elseDrawCtrl(&dc);if(pPalette && dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)dc.SelectPalette(pPalette, FALSE);}void CReportCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){INT iScrollPos = GetScrollPos32(SB_HORZ);INT iScroll;if(m_hEditWnd != NULL)EndEdit();switch (nSBCode){case SB_LINERIGHT:iScroll = min(m_iVirtualWidth-(m_rectReport.Width()+iScrollPos), m_rectReport.Width()>>3);ScrollWindow(SB_HORZ, iScrollPos + iScroll);break;case SB_LINELEFT:iScroll = min(iScrollPos, m_rectReport.Width()>>3);ScrollWindow(SB_HORZ, iScrollPos - iScroll);break;case SB_PAGERIGHT:iScrollPos = min(m_iVirtualWidth, iScrollPos + m_rectReport.Width());ScrollWindow(SB_HORZ, iScrollPos);break;case SB_PAGELEFT:iScrollPos = max(0, iScrollPos - m_rectReport.Width());ScrollWindow(SB_HORZ, iScrollPos);break;case SB_THUMBPOSITION:case SB_THUMBTRACK:iScrollPos = nPos;ScrollWindow(SB_HORZ, iScrollPos);break;case SB_RIGHT:ScrollWindow(SB_HORZ, m_iVirtualWidth);break;case SB_LEFT:ScrollWindow(SB_HORZ, 0);break;default:break;}}void CReportCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){INT iFirst = GetScrollPos32(SB_VERT), iLast;INT iItems = GetVisibleRows(TRUE, &iFirst, &iLast);if(m_hEditWnd != NULL)EndEdit();switch(nSBCode){case SB_LINEUP:if(iFirst>0)iFirst--;break;case SB_LINEDOWN:if(iFirst+iItems < m_iVirtualHeight)iFirst++;break;case SB_PAGEUP:GetVisibleRows(TRUE, &iLast, &iFirst, TRUE);iFirst = iLast-1;iFirst = iFirst<0 ? 0:iFirst;break;case SB_PAGEDOWN:iFirst += iItems;GetVisibleRows(TRUE, &iFirst, &iLast);GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);break;case SB_THUMBPOSITION:case SB_THUMBTRACK:SetScrollPos32(SB_VERT, GetScrollPos32(SB_VERT, TRUE));iFirst = GetScrollPos32(SB_VERT);GetVisibleRows(TRUE, &iFirst, &iLast);GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);break;case SB_TOP:iFirst = 0;break;case SB_BOTTOM:iLast = m_iVirtualHeight-1;GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);break;default:return;}ScrollWindow(SB_VERT, iFirst);}void CReportCtrl::OnLButtonDown(UINT nFlags, CPoint point){SetFocus();RVHITTESTINFO rvhti;rvhti.point = point;HitTest(&rvhti);if(m_dwStyle&RVS_TREEMASK && rvhti.nFlags&RVHT_ONITEMTREEBOX){if(!Notify(RVN_ITEMEXPANDING, rvhti.iItem, rvhti.iSubItem)){Expand((HTREEITEM)m_arrayItems[rvhti.iItem].lptiItem, RVE_TOGGLE);Notify(RVN_ITEMEXPANDED, rvhti.iItem, rvhti.iSubItem);return;}}if(Notify(RVN_ITEMCLICK, nFlags, &rvhti)){CWnd::OnLButtonDown(nFlags, point);return;}INT iFocusRow = m_iFocusRow, iFocusColumn = m_iFocusColumn;INT iSubItem = GetSubItemFromColumn(rvhti.iColumn);if(m_dwStyle&RVS_FOCUSSUBITEMS &&iSubItem >= 0 &&!(m_arraySubItems[iSubItem].nFormat&RVCF_SUBITEM_NOFOCUS))m_iFocusColumn = rvhti.iColumn;elsem_iFocusColumn = -1;if(rvhti.iItem != RVI_INVALID){INT iRow = GetRowFromItem(rvhti.iItem);ASSERT(iRow != RVI_INVALID);switch(nFlags&(MK_CONTROL|MK_SHIFT)){case MK_CONTROL:SelectRows(iRow, iRow, TRUE, TRUE, TRUE);m_iSelectRow = iRow;break;case MK_SHIFT:SelectRows(iRow, m_iSelectRow, TRUE);break;case MK_CONTROL|MK_SHIFT:SelectRows(iRow, m_iSelectRow, TRUE, TRUE);m_iSelectRow = iRow;break;default:SelectRows(iRow, iRow, TRUE);m_iSelectRow = iRow;if(m_iFocusRow == iFocusRow && m_iFocusColumn == iFocusColumn && (m_iFocusRow == RVI_EDIT || m_dwStyle&RVS_FOCUSSUBITEMS))BeginEdit(m_iFocusRow, m_iFocusColumn, VK_LBUTTON);break;}}}void CReportCtrl::OnRButtonDown(UINT nFlags, CPoint point){SetFocus();RVHITTESTINFO rvhti;rvhti.point = point;HitTest(&rvhti);if(Notify(RVN_ITEMRCLICK, nFlags, &rvhti)){CWnd::OnRButtonDown(nFlags, point);return;}if(rvhti.iItem != RVI_INVALID){INT iRow = GetRowFromItem(rvhti.iItem);ASSERT(iRow != RVI_INVALID);if(!(nFlags&(MK_CONTROL|MK_SHIFT))){SelectRows(iRow, iRow, TRUE);m_iSelectRow = iRow;}}}void CReportCtrl::OnLButtonDblClk(UINT nFlags, CPoint point){RVHITTESTINFO rvhti;rvhti.point = point;HitTest(&rvhti);if(Notify(RVN_ITEMDBCLICK, nFlags, &rvhti)){CWnd::OnLButtonDblClk(nFlags, point);return;}if(m_dwStyle&RVS_TREEMASK){if(rvhti.iItem >= RVI_FIRST &&m_arrayItems[rvhti.iItem].lptiItem->lptiChildren != NULL) {Expand((HTREEITEM)m_arrayItems[rvhti.iItem].lptiItem, RVE_TOGGLE);Notify(RVN_ITEMEXPANDED, rvhti.iItem, rvhti.iSubItem);}}}UINT CReportCtrl::OnGetDlgCode(){return DLGC_WANTARROWS;}void CReportCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){INT iFirst = GetScrollPos32(SB_VERT), iLast;GetVisibleRows(TRUE, &iFirst, &iLast);NMREPORTVIEW nmrv;nmrv.hdr.hwndFrom = GetSafeHwnd();nmrv.hdr.idFrom = GetDlgCtrlID();nmrv.hdr.code = RVN_KEYDOWN;nmrv.nKeys = nChar;nmrv.nFlags = nFlags;nmrv.iItem = GetItemFromRow(m_iFocusRow);nmrv.iSubItem = GetSubItemFromColumn(m_iFocusColumn);if(nmrv.iItem != RVI_INVALID && (!(m_dwStyle&RVS_OWNERDATA)))nmrv.lParam = GetItemStruct(nmrv.iItem, -1).lParam;m_bProcessKey = FALSE;if(!Notify(&nmrv)){switch (nChar){case VK_SPACE:SelectRows(m_iFocusRow, m_iFocusRow, TRUE, TRUE, IsCtrlDown() ? TRUE:FALSE);return;case VK_LEFT:if(m_dwStyle&RVS_TREEMASK && m_iFocusColumn == -1){INT iFocusItem = GetItemFromRow(m_iFocusRow);if(iFocusItem >= RVI_FIRST){LPTREEITEM lpti = m_arrayItems[iFocusItem].lptiItem;if(lpti->lptiChildren != NULL && lpti->bOpen == TRUE){Expand((HTREEITEM)lpti, RVE_COLLAPSE);break;}else{if(lpti->lptiParent != &m_tiRoot){lpti = lpti->lptiParent;INT iFocusRow = GetRowFromItem(lpti->iItem);ASSERT(iFocusRow != RVI_INVALID);SelectRows(iFocusRow, iFocusRow);EnsureVisible(lpti->iItem);break;}else if(m_dwStyle&RVS_SHOWEDITROW){SelectRows(RVI_EDIT, RVI_EDIT);break;}}}}if(m_dwStyle&RVS_FOCUSSUBITEMS){if(m_iFocusColumn > 0){m_iFocusColumn--;while(m_iFocusColumn >= 0){INT iSubItem = GetSubItemFromColumn(m_iFocusColumn);if(iSubItem >= 0 && !(m_arraySubItems[iSubItem].nFormat&RVCF_SUBITEM_NOFOCUS))break;m_iFocusColumn--;}}elsem_iFocusColumn = -1;EnsureVisibleColumn(m_iFocusColumn);iFirst = GetRowFromItem(m_iFocusRow);RedrawRows(iFirst);}else{INT iScrollPos = GetScrollPos32(SB_HORZ);INT iScroll = min(iScrollPos, m_rectReport.Width()>>3);ScrollWindow(SB_HORZ, iScrollPos - iScroll);}return;case VK_RIGHT:if(m_dwStyle&RVS_TREEMASK && m_iFocusColumn == -1){INT iFocusItem = GetItemFromRow(m_iFocusRow);if(iFocusItem >= RVI_FIRST){LPTREEITEM lpti = m_arrayItems[iFocusItem].lptiItem;if(lpti->lptiChildren != NULL){if(lpti->bOpen == FALSE){Expand((HTREEITEM)lpti, RVE_EXPAND);break;}else{lpti = lpti->lptiChildren;INT iFocusRow = GetRowFromItem(lpti->iItem);ASSERT(iFocusRow != RVI_INVALID);SelectRows(iFocusRow, iFocusRow);EnsureVisible(lpti->iItem);break;}}}}if(m_dwStyle&RVS_FOCUSSUBITEMS){if(m_iFocusColumn < m_arrayColumns.GetSize()-1){INT iFocusColumn = m_iFocusColumn;m_iFocusColumn++;while(m_iFocusColumn < m_arrayColumns.GetSize()){INT iSubItem = GetSubItemFromColumn(m_iFocusColumn);if(iSubItem >= 0 && !(m_arraySubItems[iSubItem].nFormat&RVCF_SUBITEM_NOFOCUS))break;m_iFocusColumn++;if(m_iFocusColumn == m_arrayColumns.GetSize()){m_iFocusColumn = iFocusColumn;break;}}}elsem_iFocusColumn = m_arrayColumns.GetSize()-1;EnsureVisibleColumn(m_iFocusColumn);iFirst = GetRowFromItem(m_iFocusRow);RedrawRows(iFirst);}else{INT iScrollPos = GetScrollPos32(SB_HORZ);INT iScroll = min(m_iVirtualWidth-(m_rectReport.Width()+iScrollPos), m_rectReport.Width()>>3);ScrollWindow(SB_HORZ, iScrollPos + iScroll);}return;case VK_DOWN:if(m_iFocusRow<m_iVirtualHeight-1){if(m_iFocusRow == RVI_INVALID &&!(m_dwStyle&RVS_SHOWEDITROW) &&m_iVirtualHeight > 0)m_iFocusRow = RVI_EDIT;if(IsCtrlDown()){SelectRows(m_iFocusRow+1, m_iFocusRow+1, FALSE);m_iSelectRow = m_iFocusRow;}else if(!IsShiftDown()){SelectRows(m_iFocusRow+1, m_iFocusRow+1, TRUE);m_iSelectRow = m_iFocusRow;}elseSelectRows(m_iFocusRow+1, m_iSelectRow, TRUE);EnsureVisible(GetItemFromRow(m_iFocusRow));}return;case VK_UP:if((m_dwStyle&RVS_SHOWEDITROW && m_iFocusRow > RVI_EDIT) ||m_iFocusRow > RVI_FIRST) {if(IsCtrlDown()){SelectRows(m_iFocusRow-1, m_iFocusRow-1, FALSE);m_iSelectRow = m_iFocusRow;}else if(!IsShiftDown()){SelectRows(m_iFocusRow-1, m_iFocusRow-1, TRUE);m_iSelectRow = m_iFocusRow;}elseSelectRows(m_iFocusRow-1, m_iSelectRow, TRUE);EnsureVisible(GetItemFromRow(m_iFocusRow));}return;case VK_NEXT:if(m_iFocusRow == iLast){SendMessage(WM_VSCROLL, SB_PAGEDOWN, 0);iFirst = GetScrollPos32(SB_VERT);GetVisibleRows(TRUE, &iFirst, &iLast);}if(IsCtrlDown()){SelectRows(iLast, iLast, FALSE);m_iSelectRow = m_iFocusRow;return;}else if(!IsShiftDown()){iFirst = iLast;m_iSelectRow = iLast;}elseiFirst = m_iSelectRow;SelectRows(iLast, iFirst, TRUE);return;case VK_PRIOR:if(m_iFocusRow == iFirst){SendMessage(WM_VSCROLL, SB_PAGEUP, 0);iFirst = GetScrollPos32(SB_VERT);}iFirst = iLast<iFirst ? iLast:iFirst;if(IsCtrlDown()){SelectRows(iFirst, iFirst, FALSE);m_iSelectRow = m_iFocusRow;return;}else if(!IsShiftDown()){iLast = iFirst;m_iSelectRow = iFirst;}elseiLast = m_iSelectRow;SelectRows(iFirst, iLast, TRUE);return;case VK_HOME:if(m_iFocusRow>0){SendMessage(WM_VSCROLL, SB_TOP, 0);if(!IsShiftDown())m_iSelectRow = 0;SelectRows(0, m_iSelectRow, IsCtrlDown()?FALSE:TRUE);}break;case VK_END:if(m_iFocusRow<m_iVirtualHeight){SendMessage(WM_VSCROLL, SB_BOTTOM, 0);if(!IsShiftDown())m_iSelectRow = m_iVirtualHeight-1;SelectRows(m_iVirtualHeight-1, m_iSelectRow, IsCtrlDown()?FALSE:TRUE);}break;case VK_ESCAPE:break;default:m_bProcessKey = !IsCtrlDown() ? TRUE:FALSE;break;}}CWnd::OnKeyDown(nChar, nRepCnt, nFlags);}void CReportCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){if(m_bProcessKey && m_iFocusColumn != -1 && (m_iFocusRow == RVI_EDIT || m_dwStyle&RVS_FOCUSSUBITEMS))if(BeginEdit(m_iFocusRow, m_iFocusColumn, nChar))return;CWnd::OnChar(nChar, nRepCnt, nFlags);}BOOL CReportCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt){int i;// A m_nRowsPerWheelNotch value less than 0 indicates that the mouse// wheel scrolls whole pages, not just lines.if (m_nRowsPerWheelNotch == -1){int iPagesScrolled = zDelta / 120;if (iPagesScrolled > 0)for (i=0;i<iPagesScrolled;i++)PostMessage(WM_VSCROLL, SB_PAGEUP, 0);elsefor (i=0;i>iPagesScrolled;i--)PostMessage(WM_VSCROLL, SB_PAGEDOWN, 0);}else{int iRowsScrolled = (int)m_nRowsPerWheelNotch * zDelta / 120;if (iRowsScrolled>0)for (i=0;i<iRowsScrolled;i++)PostMessage(WM_VSCROLL, SB_LINEUP, 0);elsefor (i=0;i>iRowsScrolled;i--)PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);}return CWnd::OnMouseWheel(nFlags, zDelta, pt);}void CReportCtrl::OnMouseMove(UINT nFlags, CPoint point){BOOL bHide = TRUE;if(m_bFocus && !nFlags && m_dwStyle&RVS_EXPANDSUBITEMS && m_hEditWnd == NULL){RVHITTESTINFO rvhti;rvhti.point = point;if(HitTest(&rvhti) != RVI_INVALID){TCHAR szText[REPORTCTRL_MAX_TEXT];RVITEM rvi;rvi.iItem = rvhti.iItem;rvi.iSubItem = rvhti.iSubItem;rvi.lpszText = szText;rvi.iTextMax = REPORTCTRL_MAX_TEXT;rvi.nMask = RVIM_TEXT|RVIM_STATE;GetItem(&rvi);if(rvhti.nFlags&RVHT_ONITEMTEXT && rvi.nMask&RVIM_TEXT && _tcslen(rvi.lpszText)){CRect rect;if(m_dwStyle&RVS_TREEMASK &&m_arrayItems[rvhti.iItem].lptiItem->iSubItem >= 0)GetItemRect(rvhti.iItem, rvhti.iSubItem, rect, RVIR_TEXTNOCOLUMNS);elseGetItemRect(rvhti.iItem, rvhti.iSubItem, rect, RVIR_TEXT);GetExpandedItemText(&rvi);bHide = !m_wndTip.Show(rect,rvi.lpszText,rvi.nState&RVIS_BOLD ? &m_fontBold:&m_font);}}}if( m_wndTip.IsWindowVisible() && bHide )m_wndTip.Hide();CWnd::OnMouseMove(nFlags, point);}void CReportCtrl::OnHdnItemChanged(NMHDR* pNMHDR, LRESULT* pResult){LPHDITEM lphdi = (LPHDITEM)((LPNMHEADER)pNMHDR)->pitem;if(m_hEditWnd != NULL)EndEdit();HDITEM hdi;hdi.mask = HDI_WIDTH|HDI_ORDER|HDI_LPARAM;m_wndHeader.GetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi);if(lphdi->mask&HDI_FORMAT)m_arraySubItems[hdi.lParam].nFormat =(m_arraySubItems[hdi.lParam].nFormat & ~RVCF_JUSTIFYMASK) |(lphdi->fmt & HDF_JUSTIFYMASK);if(lphdi->mask&HDI_WIDTH){m_iVirtualWidth += lphdi->cxy - m_arraySubItems[hdi.lParam].iWidth;ASSERT(m_iVirtualWidth >= 0);m_arraySubItems[hdi.lParam].iWidth = lphdi->cxy;}if(m_wndHeader.IsAutoSizing() == FALSE)ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));Notify(RVN_LAYOUTCHANGED, RVI_INVALID, (INT)hdi.lParam);*pResult = FALSE;}void CReportCtrl::OnHdnItemClick(NMHDR* pNMHDR, LRESULT* pResult){if(m_hEditWnd != NULL)EndEdit();NMRVHEADER nmrvhdr;if(!NotifyHdr(&nmrvhdr, RVN_HEADERCLICK, ((LPNMHEADER)pNMHDR)->iItem)){if(!(m_dwStyle&(RVS_NOSORT|RVS_OWNERDATA))){BOOL bAscending;INT iOld = m_wndHeader.GetSortColumn(&bAscending);INT iNew = ((LPNMHEADER)pNMHDR)->iItem;if(iNew == iOld)bAscending = !bAscending;elsebAscending = TRUE;SortItems(nmrvhdr.iSubItem, bAscending);}}*pResult = FALSE;}void CReportCtrl::OnHdnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult){LPNMHEADER lpnmhdr = (LPNMHEADER)pNMHDR;if(m_hEditWnd != NULL)EndEdit();pResult = FALSE;}void CReportCtrl::OnHdnEndDrag(NMHDR* pNMHDR, LRESULT* pResult){LPNMHEADER lpnmhdr = (LPNMHEADER)pNMHDR;INT iDropResult = m_wndHeader.GetDropResult();if(iDropResult == FHDR_DROPPED || iDropResult == FHDR_ONTARGET){if(m_dwStyle&RVS_ALLOWCOLUMNREMOVAL)DeactivateSubItem(lpnmhdr->pitem->lParam);*pResult = TRUE;}else{m_bColumnsReordered = TRUE;m_iIndentColumnPending = m_wndHeader.OrderToIndex(0);Invalidate();*pResult = FALSE;}}void CReportCtrl::OnHdnDividerDblClick(NMHDR* pNMHDR, LRESULT* pResult){if(m_hEditWnd != NULL)EndEdit();NMRVHEADER nmrvhdr;if(!NotifyHdr(&nmrvhdr, RVN_DIVIDERDBLCLICK, ((LPNMHEADER)pNMHDR)->iItem) &&!(m_dwStyle&RVS_OWNERDATA) &&!(m_arraySubItems[nmrvhdr.iSubItem].nFormat&RVCF_EX_FIXEDWIDTH)) {INT iItems = m_arrayItems.GetSize();if(iItems > 0){INT iWidth = 0;RECT rect;for(INT iItem=0;iItem<iItems;iItem++){if(MeasureItem(iItem, nmrvhdr.iSubItem, &rect)){INT cx = rect.right - rect.left;iWidth = cx > iWidth ? cx:iWidth;}}HDITEM hdi;hdi.mask = HDI_WIDTH;hdi.cxy = iWidth;m_wndHeader.SetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi);}}*pResult = FALSE;}void CReportCtrl::OnRvnEndItemEdit(NMHDR* pNMHDR, LRESULT* pResult){LPNMRVITEMEDIT lpnmrvie = (LPNMRVITEMEDIT)pNMHDR;ASSERT(m_iEditItem == lpnmrvie->iItem);ASSERT(m_iEditSubItem == lpnmrvie->iSubItem);NMRVITEMEDIT nmrvie;memset(&nmrvie, 0, sizeof(nmrvie));nmrvie.hdr.hwndFrom = GetSafeHwnd();nmrvie.hdr.idFrom = GetDlgCtrlID();nmrvie.hdr.code = RVN_ENDITEMEDIT;nmrvie.iItem = m_iEditItem;nmrvie.iSubItem = m_iEditSubItem;nmrvie.hWnd = lpnmrvie->hWnd;nmrvie.nKey = lpnmrvie->nKey;nmrvie.lpszText = lpnmrvie->lpszText;nmrvie.lParam = lpnmrvie->lParam;BOOL bResult = FALSE;if(GetParent() != NULL)bResult = Notify((LPNMREPORTVIEW)&nmrvie);if(bResult)EndEdit(FALSE);elseEndEdit(nmrvie.nKey != VK_ESCAPE ? TRUE:FALSE, &nmrvie);pResult = FALSE;}/////////////////////////////////////////////////////////////////////////////// CReportSubItemListCtrlCReportSubItemListCtrl::CReportSubItemListCtrl(){m_pReportCtrl = NULL;m_iSubItem = -1;m_pDragWnd = NULL;}CReportSubItemListCtrl::~CReportSubItemListCtrl(){}BEGIN_MESSAGE_MAP(CReportSubItemListCtrl, CDragListBox)//{{AFX_MSG_MAP(CReportSubItemListCtrl)ON_WM_ERASEBKGND()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportSubItemListCtrl attributesBOOL CReportSubItemListCtrl::SetReportCtrl(CReportCtrl* pReportCtrl){if(pReportCtrl == NULL)return FALSE;ASSERT_KINDOF(CReportCtrl, pReportCtrl);m_pReportCtrl = pReportCtrl;ResetContent();return TRUE;}CReportCtrl* CReportSubItemListCtrl::GetReportCtrl(){return m_pReportCtrl;}/////////////////////////////////////////////////////////////////////////////// CReportSubItemListCtrl operationsBOOL CReportSubItemListCtrl::UpdateList(){INT iSubItem, iSubItems = m_pReportCtrl->m_arraySubItems.GetSize();ResetContent();for(iSubItem=0;iSubItem<iSubItems;iSubItem++){if(!m_pReportCtrl->IsActiveSubItem(iSubItem) && Include(iSubItem)){INT iItem = AddString(m_pReportCtrl->m_arraySubItems[iSubItem].strText);SetItemData(iItem, iSubItem);}}return TRUE;}BOOL CReportSubItemListCtrl::Include(INT iSubItem){return TRUE;}BOOL CReportSubItemListCtrl::Disable(INT iSubItem){return FALSE;}/////////////////////////////////////////////////////////////////////////////// CReportSubItemListCtrl message handlersvoid CReportSubItemListCtrl::PreSubclassWindow(){CDragListBox::PreSubclassWindow();SetItemHeight(0, GetItemHeight(0)+2);}void CReportSubItemListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct){CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);CRect rcItem(lpDrawItemStruct->rcItem);if(GetCount() > 0){BOOL bDisable = Disable(lpDrawItemStruct->itemData);if(GetExStyle()&WS_EX_STATICEDGE){pDC->Draw3dRect(rcItem, m_pReportCtrl->m_cr3DHiLight, m_pReportCtrl->m_cr3DDkShadow);rcItem.DeflateRect(1, 1);pDC->FillSolidRect(rcItem, m_pReportCtrl->m_cr3DFace);rcItem.DeflateRect(1, 1);}else{pDC->DrawFrameControl(rcItem, DFC_BUTTON, DFCS_BUTTONPUSH);rcItem.DeflateRect(2, 2);}pDC->SetBkMode(TRANSPARENT);if(lpDrawItemStruct->itemState&ODS_SELECTED){pDC->FillRect(rcItem, &CBrush(::GetSysColor(COLOR_3DSHADOW)));pDC->SetTextColor(bDisable ? ::GetSysColor(COLOR_BTNFACE) : ::GetSysColor(COLOR_3DHIGHLIGHT));}else{if(bDisable){pDC->SetTextColor(::GetSysColor(COLOR_3DHIGHLIGHT));CRect rect = rcItem;rect.left += 1;rect.top += 1;rect.right += 1;rect.bottom += 1;pDC->DrawText(m_pReportCtrl->m_arraySubItems[lpDrawItemStruct->itemData].strText,-1,rect,DT_SINGLELINE|DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));}elsepDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));}pDC->DrawText(m_pReportCtrl->m_arraySubItems[lpDrawItemStruct->itemData].strText,-1,rcItem,DT_SINGLELINE|DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);}elsepDC->FillSolidRect(rcItem, ::GetSysColor(COLOR_WINDOW));}BOOL CReportSubItemListCtrl::BeginDrag(CPoint pt){if(GetCount() <= 0)return FALSE;BOOL bAutoScroll = FALSE;INT iItem = ItemFromPt(pt);if(iItem >= 0){m_iSubItem = GetItemData(iItem);if(Disable(m_iSubItem)){m_iSubItem = -1;return FALSE;}GetClientRect(m_rcDragWnd);m_rcDragWnd.bottom = m_rcDragWnd.top + GetItemHeight(0);_tcscpy(m_szSubItemText, m_pReportCtrl->m_arraySubItems[m_iSubItem].strText);m_hdiSubItem.mask = HDI_WIDTH|HDI_TEXT|HDI_FORMAT;m_hdiSubItem.cxy = m_rcDragWnd.Width();m_hdiSubItem.pszText = m_szSubItemText;m_hdiSubItem.cchTextMax = sizeof(m_szSubItemText);m_hdiSubItem.fmt = HDF_STRING|HDF_LEFT;m_pDragWnd = new CFHDragWnd;if(m_pDragWnd)m_pDragWnd->Create(m_rcDragWnd, &m_pReportCtrl->m_wndHeader, -2, &m_hdiSubItem);GetWindowRect(m_rcDropTarget1);m_pReportCtrl->m_wndHeader.GetWindowRect(m_rcDropTarget2);}m_iDropIndex = -1;return TRUE;}UINT CReportSubItemListCtrl::Dragging(CPoint pt){CPoint point = pt;point.Offset(-(m_rcDragWnd.Width()>>1), -(m_rcDragWnd.Height()>>1));if(m_pDragWnd != NULL)m_pDragWnd->SetWindowPos(&wndTop,point.x, point.y,0, 0, SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE);if(m_rcDropTarget1.PtInRect(pt))return DL_MOVECURSOR;m_iDropIndex = m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, TRUE, MAKELONG(pt.x, pt.y));if(m_rcDropTarget2.PtInRect(pt))return DL_MOVECURSOR;return DL_STOPCURSOR;}void CReportSubItemListCtrl::CancelDrag(CPoint pt){m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1);if(m_pDragWnd != NULL){m_pDragWnd->DestroyWindow();m_pDragWnd = NULL;}m_iSubItem = -1;}void CReportSubItemListCtrl::Dropped(INT iSrcIndex, CPoint pt){m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1);if(m_pDragWnd != NULL){m_pDragWnd->DestroyWindow();m_pDragWnd = NULL;}if(m_iSubItem >= 0){if(!m_pReportCtrl->GetActiveSubItemCount())m_pReportCtrl->ActivateSubItem(m_iSubItem);elseif(m_iDropIndex >= 0)m_pReportCtrl->ActivateSubItem(m_iSubItem, m_iDropIndex);}m_iSubItem = -1;}BOOL CReportSubItemListCtrl::OnEraseBkgnd(CDC* pDC){if(!IsWindowEnabled()){CRect rect;GetClientRect( rect );pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE));return TRUE;}elsereturn CDragListBox::OnEraseBkgnd(pDC);}/////////////////////////////////////////////////////////////////////////////// CReportEditCtrlCReportEditCtrl::CReportEditCtrl(INT iItem, INT iSubItem, BOOL bButton){m_bEndEdit = FALSE;m_iItem = iItem;m_iSubItem = iSubItem;m_bButton = bButton;m_nLastKey = VK_RETURN;}CReportEditCtrl::~CReportEditCtrl(){}BOOL CReportEditCtrl::PreCreateWindow(CREATESTRUCT& cs){if(m_bButton){if(cs.cx > cs.cy+10)cs.cx -= cs.cy;elsem_bButton = FALSE;}return CEdit::PreCreateWindow(cs);}int CReportEditCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct){if(CEdit::OnCreate(lpCreateStruct) == -1)return -1;if(m_bButton){CRect rect(lpCreateStruct->x + lpCreateStruct->cx,lpCreateStruct->y,lpCreateStruct->x + lpCreateStruct->cx + lpCreateStruct->cy,lpCreateStruct->y + lpCreateStruct->cy);CWnd *pParent = GetParent();ASSERT(pParent != NULL);if(!m_wndButton.Create(_T("..."), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, rect, pParent, 0))return -1;m_wndButton.SetFont(pParent->GetFont());}return 0;}void CReportEditCtrl::PostNcDestroy(){CEdit::PostNcDestroy();delete this;}BEGIN_MESSAGE_MAP(CReportEditCtrl, CEdit)//{{AFX_MSG_MAP(CReportEditCtrl)ON_WM_KILLFOCUS()ON_WM_GETDLGCODE()ON_WM_CREATE()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportEditCtrl operationsvoid CReportEditCtrl::BeginEdit(UINT nKey){CString str;GetWindowText(str);switch (nKey){case VK_LBUTTON:case VK_RETURN:SetSel(str.GetLength(), -1);break;case VK_BACK:SetSel(str.GetLength(), -1);SendMessage(WM_CHAR, nKey);break;case VK_TAB:case VK_DOWN:case VK_UP:case VK_RIGHT:case VK_LEFT:case VK_NEXT:case VK_PRIOR:case VK_HOME:case VK_SPACE:case VK_END:SetSel(0,-1);break;default:SetSel(0,-1);SendMessage(WM_CHAR, nKey);break;}}void CReportEditCtrl::EndEdit(){CString str;if(m_bEndEdit)return;m_bEndEdit = TRUE;GetWindowText(str);NMRVITEMEDIT nmrvie;memset(&nmrvie, 0, sizeof(nmrvie));nmrvie.hdr.hwndFrom = GetSafeHwnd();nmrvie.hdr.idFrom = GetDlgCtrlID();nmrvie.hdr.code = RVN_ENDITEMEDIT;nmrvie.iItem = m_iItem;nmrvie.iSubItem = m_iSubItem;nmrvie.bButton = m_bButton;nmrvie.hWnd = nmrvie.hdr.hwndFrom;nmrvie.nKey = m_nLastKey;nmrvie.lpszText = (LPTSTR)(LPCTSTR)str;CWnd* pWnd = GetOwner();if(pWnd != NULL)pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie);PostMessage(WM_CLOSE, 0, 0);}/////////////////////////////////////////////////////////////////////////////// CReportEditCtrl message handlersvoid CReportEditCtrl::OnKillFocus(CWnd* pNewWnd){CWnd::OnKillFocus(pNewWnd);if(m_bButton){if(pNewWnd->GetSafeHwnd() == m_wndButton.GetSafeHwnd()){BOOL bResult = FALSE;CString str;NMRVITEMEDIT nmrvie;memset(&nmrvie, 0, sizeof(nmrvie));CReportCtrl* pWnd = DYNAMIC_DOWNCAST(CReportCtrl, GetOwner());if(pWnd != NULL){GetWindowText(str);nmrvie.hdr.hwndFrom = pWnd->GetSafeHwnd();nmrvie.hdr.idFrom = pWnd->GetDlgCtrlID();nmrvie.hdr.code = RVN_BUTTONCLICK;nmrvie.iItem = m_iItem;nmrvie.iSubItem = m_iSubItem;nmrvie.bButton = m_bButton;nmrvie.hWnd = GetSafeHwnd();VERIFY(nmrvie.lpszText = str.GetBuffer(REPORTCTRL_MAX_TEXT));bResult = pWnd->Notify((LPNMREPORTVIEW)&nmrvie);str.ReleaseBuffer();}if(bResult == TRUE)SetWindowText(nmrvie.lpszText);SetFocus();return;}}EndEdit();}UINT CReportEditCtrl::OnGetDlgCode(){return DLGC_WANTALLKEYS;}BOOL CReportEditCtrl::PreTranslateMessage(MSG* pMsg){if(pMsg->message == WM_KEYDOWN &&(pMsg->wParam == VK_TAB || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)) {m_nLastKey = pMsg->wParam;GetParent()->SetFocus();return TRUE;}if(pMsg->message == WM_SYSCHAR)return TRUE;return CEdit::PreTranslateMessage(pMsg);}/////////////////////////////////////////////////////////////////////////////// CReportComboCtrlCReportComboCtrl::CReportComboCtrl(INT iItem, INT iSubItem){m_bEndEdit = FALSE;m_iItem = iItem;m_iSubItem = iSubItem;m_nLastKey = VK_RETURN;}CReportComboCtrl::~CReportComboCtrl(){}void CReportComboCtrl::PostNcDestroy(){CComboBox::PostNcDestroy();delete this;}BEGIN_MESSAGE_MAP(CReportComboCtrl, CComboBox)//{{AFX_MSG_MAP(CReportComboCtrl)ON_WM_GETDLGCODE()ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus)//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportComboCtrl operationsvoid CReportComboCtrl::BeginEdit(UINT nKey){CString str;GetWindowText(str);if(GetStyle()&CBS_DROPDOWN){switch (nKey){case VK_LBUTTON:case VK_RETURN:break;default:PostMessage(WM_CHAR, nKey);break;}}}void CReportComboCtrl::EndEdit(){CString str;if(m_bEndEdit)return;m_bEndEdit = TRUE;GetWindowText(str);NMRVITEMEDIT nmrvie;memset(&nmrvie, 0, sizeof(nmrvie));nmrvie.hdr.hwndFrom = GetSafeHwnd();nmrvie.hdr.idFrom = GetDlgCtrlID();nmrvie.hdr.code = RVN_ENDITEMEDIT;nmrvie.iItem = m_iItem;nmrvie.iSubItem = m_iSubItem;nmrvie.hWnd = nmrvie.hdr.hwndFrom;nmrvie.nKey = m_nLastKey;nmrvie.lpszText = (LPTSTR)(LPCTSTR)str;CWnd* pWnd = GetOwner();if(pWnd != NULL)pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie);PostMessage(WM_CLOSE, 0, 0);}/////////////////////////////////////////////////////////////////////////////// CReportComboCtrl message handlersUINT CReportComboCtrl::OnGetDlgCode(){return DLGC_WANTALLKEYS;}BOOL CReportComboCtrl::PreTranslateMessage(MSG* pMsg){if(pMsg->message == WM_KEYDOWN &&(pMsg->wParam == VK_TAB || pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)) {m_nLastKey = pMsg->wParam;GetParent()->SetFocus();return TRUE;}if (pMsg->message == WM_SYSCHAR)return TRUE;return CComboBox::PreTranslateMessage(pMsg);}void CReportComboCtrl::OnKillfocus(){EndEdit();}/////////////////////////////////////////////////////////////////////////////// CReportTipCtrlCReportTipCtrl::CReportTipCtrl(){WNDCLASS wndcls;HINSTANCE hInst = AfxGetInstanceHandle();if(!(::GetClassInfo(hInst, REPORTTIPCTRL_CLASSNAME, &wndcls))){wndcls.style = CS_SAVEBITS ;wndcls.lpfnWndProc = ::DefWindowProc;wndcls.cbClsExtra = wndcls.cbWndExtra = 0;wndcls.hInstance = hInst;wndcls.hIcon = NULL;wndcls.hCursor = LoadCursor(hInst, IDC_ARROW);wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK+1);wndcls.lpszMenuName = NULL;wndcls.lpszClassName = REPORTTIPCTRL_CLASSNAME;if(!AfxRegisterClass(&wndcls))AfxThrowResourceException();}m_bLayeredWindows = InitLayeredWindows();m_nAlpha = 0;m_dwLastLButtonDown = ULONG_MAX;m_dwDblClickMsecs = GetDoubleClickTime();m_pReportCtrl = NULL;}CReportTipCtrl::~CReportTipCtrl(){}BEGIN_MESSAGE_MAP(CReportTipCtrl, CWnd)//{{AFX_MSG_MAP(CReportTipCtrl)ON_WM_MOUSEMOVE()ON_WM_TIMER()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportTipCtrl message handlersBOOL CReportTipCtrl::Create(CReportCtrl* pReportCtrl){ASSERT_VALID(pReportCtrl);m_pReportCtrl = pReportCtrl;return CreateEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW|WS_EX_LAYERED,REPORTTIPCTRL_CLASSNAME, NULL,WS_BORDER|WS_POPUP,CRect(0, 0, 0, 0),pReportCtrl, 0, NULL);}BOOL CReportTipCtrl::Show(CRect rectText, LPCTSTR lpszText, CFont* pFont){BOOL bResult = FALSE;ASSERT(::IsWindow(GetSafeHwnd()));if(rectText.IsRectEmpty() ||GetFocus() == NULL) {Hide();return FALSE;}if( rectText != m_rectText ){Invalidate();UpdateWindow();m_rectTip.top = -1;m_rectTip.bottom = rectText.Height() + 1;m_rectTip.left = -1;m_rectTip.right = rectText.Width()+1;m_rectTip.InflateRect(m_pReportCtrl->m_iSpacing, 0);m_pReportCtrl->ClientToScreen(rectText);CClientDC dc(this);pFont = pFont == NULL ? m_pReportCtrl->GetFont():pFont;CFont *pFontDC = dc.SelectObject(pFont);CRect rectDisplay = rectText;CSize size = dc.GetTextExtent(lpszText, _tcslen(lpszText));rectDisplay.right = rectDisplay.left + size.cx;if(rectDisplay.right > rectText.right){rectDisplay.InflateRect(m_pReportCtrl->m_iSpacing, 0);SetWindowPos(&wndTop,rectDisplay.left, rectDisplay.top,rectDisplay.Width(), rectDisplay.Height(),SWP_NOOWNERZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);dc.SetBkMode(TRANSPARENT);dc.TextOut(m_pReportCtrl->m_iSpacing-1, 1, lpszText);if(m_bLayeredWindows){UpdateWindow();if(m_nAlpha < 255)SetTimer(1, REPORTTIPCTRL_FADETIME/(255/REPORTTIPCTRL_FADESTEP), NULL);g_lpfnSetLayeredWindowAttributes(GetSafeHwnd(),RGB(0xFF, 0, 0xFF),m_nAlpha,ULW_ALPHA);}bResult = TRUE;}elseHide();m_rectText = rectText;dc.SelectObject(pFontDC);}elseHide();return bResult;}void CReportTipCtrl::Hide(){if (!::IsWindow(GetSafeHwnd()))return;if(m_bLayeredWindows){m_nAlpha = 255;SetTimer( 1, REPORTTIPCTRL_FADETIMEOUT, NULL );}if(IsWindowVisible())ShowWindow(SW_HIDE);}void CReportTipCtrl::OnMouseMove(UINT nFlags, CPoint point){if(!m_rectTip.PtInRect(point)){Hide();ClientToScreen(&point);CWnd *pWnd = WindowFromPoint(point);if(pWnd == this)pWnd = m_pReportCtrl;INT iHitTest = (INT)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y));if(iHitTest == HTCLIENT){pWnd->ScreenToClient(&point);pWnd->PostMessage(WM_MOUSEMOVE,nFlags,MAKELONG(point.x,point.y));}else{pWnd->PostMessage(WM_NCMOUSEMOVE,iHitTest,MAKELONG(point.x,point.y));}}}BOOL CReportTipCtrl::PreTranslateMessage(MSG* pMsg){DWORD dwTick = 0;BOOL bDoubleClick = FALSE;CWnd *pWnd;INT iHitTest;switch (pMsg->message){case WM_LBUTTONDOWN:dwTick = GetTickCount();bDoubleClick = ((dwTick - m_dwLastLButtonDown) <= m_dwDblClickMsecs);m_dwLastLButtonDown = dwTick;// Notice fall-throughcase WM_RBUTTONDOWN:case WM_MBUTTONDOWN:POINTS points = MAKEPOINTS(pMsg->lParam);POINT point;point.x = points.x;point.y = points.y;ClientToScreen(&point);pWnd = WindowFromPoint(point);if(pWnd == this)pWnd = m_pReportCtrl;iHitTest = (INT)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x, point.y));if(iHitTest == HTCLIENT){pWnd->ScreenToClient(&point);pMsg->lParam = MAKELONG(point.x,point.y);}else{switch (pMsg->message){case WM_LBUTTONDOWN: pMsg->message = WM_NCLBUTTONDOWN; break;case WM_RBUTTONDOWN: pMsg->message = WM_NCRBUTTONDOWN; break;case WM_MBUTTONDOWN: pMsg->message = WM_NCMBUTTONDOWN; break;}pMsg->wParam = iHitTest;pMsg->lParam = MAKELONG(point.x,point.y);}Hide();pWnd->PostMessage(bDoubleClick ? WM_LBUTTONDBLCLK : pMsg->message,pMsg->wParam,pMsg->lParam);return TRUE;case WM_KEYDOWN:case WM_SYSKEYDOWN:Hide();m_pReportCtrl->PostMessage(pMsg->message,pMsg->wParam,pMsg->lParam);return TRUE;}if(GetFocus() == NULL){Hide();return TRUE;}return CWnd::PreTranslateMessage(pMsg);}void CReportTipCtrl::OnTimer(UINT nIDEvent){if(nIDEvent == 1 ){ASSERT(m_bLayeredWindows == TRUE);if(m_nAlpha < 255){m_nAlpha += REPORTTIPCTRL_FADESTEP;if( m_nAlpha >= 255 ){m_nAlpha = 255;KillTimer(1);}g_lpfnSetLayeredWindowAttributes(GetSafeHwnd(),RGB(0xFF, 0, 0xFF),m_nAlpha,ULW_ALPHA);}else{m_nAlpha = 0;KillTimer(1);}}CWnd::OnTimer(nIDEvent);}/////////////////////////////////////////////////////////////////////////////// Global utilities//BOOL InitLayeredWindows(){if( g_lpfnUpdateLayeredWindow == NULL ){HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));g_lpfnUpdateLayeredWindow =(lpfnUpdateLayeredWindow)GetProcAddress(hUser32,_T("UpdateLayeredWindow"));g_lpfnSetLayeredWindowAttributes =(lpfnSetLayeredWindowAttributes)GetProcAddress(hUser32,_T("SetLayeredWindowAttributes"));return g_lpfnUpdateLayeredWindow != NULL ? TRUE:FALSE;}return TRUE;}BOOL MatchString(const CString& strString, const CString& strPattern){CString strStr = strString;CString strPat = strPattern;strStr.MakeLower();strPat.MakeLower();BOOL bStopSearch = FALSE;while(!strString.IsEmpty() && !strPat.IsEmpty() && !bStopSearch)if(strPat[0] == _T('*')){strPat = strPat.Right(strPat.GetLength() - 1);if(strPat.IsEmpty())return TRUE;CString strBuf = strPat;INT iWild = strBuf.FindOneOf(_T("*?"));if(iWild != -1)strBuf = strBuf.Left(iWild);INT iFound = strStr.Find(strBuf);if(iFound == -1)return FALSE;if(iWild == -1)return TRUE;strStr = strStr.Right(strStr.GetLength() - iFound);}else{bStopSearch = strStr[0] != strPat[0] && strPat[0] != _T('?');if(!bStopSearch){strStr = strStr.Right(strStr.GetLength() - 1);strPat = strPat.Right(strPat.GetLength() - 1);}}bStopSearch = bStopSearch || !strStr.IsEmpty() && strPat.IsEmpty() || strStr.IsEmpty() && !strPat.IsEmpty();return !bStopSearch || bStopSearch && !strPat.IsEmpty() && strPat[0] == _T('*');}/////////////////////////////////////////////////////////////////////////////// CReportHeaderCtrlCReportHeaderCtrl::CReportHeaderCtrl(){}CReportHeaderCtrl::~CReportHeaderCtrl(){}BEGIN_MESSAGE_MAP(CReportHeaderCtrl, CFlatHeaderCtrl)//{{AFX_MSG_MAP(CReportHeaderCtrl)ON_WM_RBUTTONDOWN()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CReportHeaderCtrl attributesvoid CReportHeaderCtrl::SetMinMax(INT iPos, INT iMin, INT iMax){ASSERT(iPos < m_arrayHdrItemEx.GetSize());m_arrayHdrItemEx[iPos].iMinWidth = iMin;m_arrayHdrItemEx[iPos].iMaxWidth = iMax;};/////////////////////////////////////////////////////////////////////////////// CReportHeaderCtrl messagesvoid CReportHeaderCtrl::OnRButtonDown(UINT nFlags, CPoint point){CReportCtrl* pReportCtrl = DYNAMIC_DOWNCAST(CReportCtrl, GetParent());if( pReportCtrl != NULL ){HDHITTESTINFO hdhti;hdhti.pt = point;INT iItem = ::SendMessage(GetSafeHwnd(), HDM_HITTEST, 0, (LPARAM)(&hdhti));NMRVHEADER nmrvhdr;if(pReportCtrl->NotifyHdr(&nmrvhdr, RVN_HEADERRCLICK, iItem))return;}CFlatHeaderCtrl::OnRButtonDown(nFlags, point);}