4372 lines
97 KiB
C++
4372 lines
97 KiB
C++
////////////////////////////////////////////////////////////////////////////
|
|
// File: CReportCtrl.cpp
|
|
// Version: 1.1.0
|
|
//
|
|
// Author: Maarten Hoeben
|
|
// E-mail: maarten.hoeben@nwn.com
|
|
//
|
|
// 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.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ReportCtrl.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "ReportCtrl.h"
|
|
|
|
#include "MemDC.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
TCHAR* g_szSeparator = _T("|");
|
|
|
|
#define IsShiftDown() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 )
|
|
#define IsCtrlDown() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 )
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportData
|
|
|
|
CReportData::CReportData()
|
|
{
|
|
}
|
|
|
|
CReportData::~CReportData()
|
|
{
|
|
}
|
|
|
|
BOOL CReportData::New(INT iSubItems)
|
|
{
|
|
for(INT i=0;i<iSubItems;i++)
|
|
{
|
|
CString str;
|
|
str.Format(_T("(-1,-1,-1,-1)%s"), g_szSeparator);
|
|
|
|
*this += str;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportData::GetSubItem(INT iSubItem, LPINT lpiImage, 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_szSeparator, iPos);
|
|
|
|
if(iPos<0)
|
|
return FALSE;
|
|
|
|
LPTSTR lpsz = GetBuffer(0);
|
|
lpsz = &lpsz[iPos];
|
|
VERIFY(_stscanf(lpsz, _T("(%d,%d,%d,%d)"), lpiImage, lpiCheck, lpiColor, &iText));
|
|
|
|
if(iText < 0)
|
|
{
|
|
*lpiTextMax = -1;
|
|
return TRUE;
|
|
}
|
|
|
|
lpsz = _tcspbrk(lpsz, _T(")"))+1;
|
|
if(lpsz && lpszText)
|
|
{
|
|
for(INT iTextSize=0;iTextSize<(*lpiTextMax)-1 && *lpsz!=g_szSeparator[0];iTextSize++)
|
|
lpszText[iTextSize] = *lpsz++;
|
|
|
|
lpszText[iTextSize] = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportData::SetSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText)
|
|
{
|
|
if(!InsertSubItem(iSubItem, iImage, iCheck, iColor, lpszText))
|
|
return FALSE;
|
|
|
|
if(!DeleteSubItem(iSubItem+1))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportData::InsertSubItem(INT iSubItem, INT iImage, INT iCheck, INT iColor, LPCTSTR lpszText)
|
|
{
|
|
INT i, iPos, iText;
|
|
|
|
for(i=0,iPos=0;i<iSubItem&&iPos>=0;i++,iPos++)
|
|
iPos = Find(g_szSeparator, iPos);
|
|
|
|
if(iPos<0)
|
|
return FALSE;
|
|
|
|
if(lpszText == NULL)
|
|
{
|
|
lpszText = _T("");
|
|
iText = -1;
|
|
}
|
|
else
|
|
iText = _tcslen(lpszText);
|
|
|
|
CString str;
|
|
str.Format("(%d,%d,%d,%d)%s%s", iImage, iCheck, iColor, iText, lpszText, g_szSeparator);
|
|
|
|
Insert(iPos, str);
|
|
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_szSeparator, iPos1);
|
|
|
|
if(iPos1<0)
|
|
return FALSE;
|
|
|
|
iPos2 = Find(g_szSeparator, iPos1);
|
|
if(iPos2++<0)
|
|
return FALSE;
|
|
|
|
Delete(iPos1, iPos2-iPos1);
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportView
|
|
|
|
IMPLEMENT_DYNCREATE(CReportView, CView)
|
|
|
|
CReportView::CReportView()
|
|
{
|
|
m_bCreated = FALSE;
|
|
}
|
|
|
|
CReportView::~CReportView()
|
|
{
|
|
}
|
|
|
|
void CReportView::OnInitialUpdate()
|
|
{
|
|
CView::OnInitialUpdate();
|
|
|
|
if(!m_bCreated)
|
|
{
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
if(m_wndReportCtrl.Create(WS_CHILD|WS_TABSTOP|WS_VISIBLE, 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_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportView drawing
|
|
|
|
void CReportView::OnDraw(CDC* pDC)
|
|
{
|
|
;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportView diagnostics
|
|
|
|
#ifdef _DEBUG
|
|
void CReportView::AssertValid() const
|
|
{
|
|
CView::AssertValid();
|
|
}
|
|
|
|
void CReportView::Dump(CDumpContext& dc) const
|
|
{
|
|
CView::Dump(dc);
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportView attributes
|
|
|
|
CReportCtrl& CReportView::GetReportCtrl()
|
|
{
|
|
return m_wndReportCtrl;
|
|
}
|
|
|
|
CReportCtrl* CReportView::GetReportCtrlPtr()
|
|
{
|
|
return &m_wndReportCtrl;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportView implementation
|
|
|
|
BOOL CReportView::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
void CReportView::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CView::OnSize(nType, cx, cy);
|
|
|
|
if(m_wndReportCtrl.GetSafeHwnd())
|
|
{
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
m_wndReportCtrl.MoveWindow(rect);
|
|
}
|
|
}
|
|
|
|
void CReportView::OnSetFocus(CWnd* pOldWnd)
|
|
{
|
|
m_wndReportCtrl.SetFocus();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportCtrl
|
|
|
|
IMPLEMENT_DYNCREATE(CReportCtrl, CWnd)
|
|
|
|
CReportCtrl::CReportCtrl()
|
|
{
|
|
// Register the window class if it has not already been registered.
|
|
WNDCLASS wndclass;
|
|
HINSTANCE hInst = AfxGetInstanceHandle();
|
|
|
|
if(!(::GetClassInfo(hInst, REPORTCTRL_CLASSNAME, &wndclass)))
|
|
{
|
|
// Otherwise we need to register a new class
|
|
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_iSpacing = 6;
|
|
m_nRowsPerWheelNotch = GetMouseScrollLines();
|
|
|
|
m_dwStyle = 0;
|
|
|
|
// Initially use the system message font for the ReportCtrl font
|
|
NONCLIENTMETRICS ncm;
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
|
|
m_font.CreateFontIndirect(&(ncm.lfMessageFont));
|
|
|
|
m_pImageList = NULL;
|
|
m_sizeImage.cx = 0;
|
|
m_sizeImage.cy = 0;
|
|
m_sizeCheck.cx = 8;
|
|
m_sizeCheck.cy = 8;
|
|
|
|
GetSysColors();
|
|
|
|
m_arrayColors.SetSize(0, 8);
|
|
|
|
m_iGridStyle = PS_SOLID;
|
|
|
|
m_strNoItems = _T("There are no items to show in this view.");
|
|
|
|
m_iDefaultWidth = 200;
|
|
m_iDefaultHeight = 10;
|
|
m_iVirtualWidth = 0;
|
|
m_iVirtualHeight = 0;
|
|
|
|
m_arraySubItems.SetSize(0, 8);
|
|
m_arrayItems.SetSize(0, 128);
|
|
|
|
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);
|
|
|
|
INT m_iEditItem = RVI_INVALID;
|
|
INT m_iEditSubItem = -1;
|
|
m_hEditWnd = NULL;
|
|
|
|
m_lprclc = NULL;
|
|
m_lpfnrvc = NULL;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
INT 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;
|
|
}
|
|
|
|
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);
|
|
|
|
GetClientRect(rect);
|
|
Layout(rect.Width(), rect.Height());
|
|
|
|
m_dwStyle = GetStyle();
|
|
if(m_dwStyle&RVS_FOCUSSUBITEMS)
|
|
m_iFocusColumn = 0;
|
|
|
|
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(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()
|
|
//}}AFX_MSG_MAP
|
|
ON_MESSAGE(WM_SETFONT, OnSetFont)
|
|
ON_MESSAGE(WM_GETFONT, OnGetFont)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportCtrl attributes
|
|
|
|
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(wParam)
|
|
{
|
|
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;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
Layout(rect.Width(), rect.Height());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT CReportCtrl::ActivateColumn(INT iColumn, INT iOrder)
|
|
{
|
|
ASSERT(iColumn>=0);
|
|
ASSERT(iColumn<m_arraySubItems.GetSize()); // Specify a valid column
|
|
|
|
SUBITEM& subitem = m_arraySubItems[iColumn];
|
|
INT iResult = -1;
|
|
|
|
INT iHeaderItems = m_arrayColumns.GetSize();
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_LPARAM;
|
|
|
|
for(INT iItem=0;iItem<iHeaderItems;iItem++)
|
|
if(m_wndHeader.GetItem(iItem, &hdi))
|
|
if(hdi.lParam == iColumn)
|
|
break;
|
|
|
|
if(iItem == iHeaderItems)
|
|
{
|
|
try
|
|
{
|
|
hdi.mask = HDI_FORMAT|HDI_WIDTH|HDI_LPARAM|HDI_ORDER;
|
|
hdi.fmt = subitem.nFormat&RVCF_MASK;
|
|
hdi.cxy = subitem.iWidth;
|
|
hdi.iOrder = iOrder;
|
|
hdi.lParam = (LPARAM)iColumn;
|
|
|
|
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(iHeaderItems, &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(_T("Sort by %s"), subitem.strText);
|
|
|
|
m_wndHeader.SetItemEx(iResult, &hditemex);
|
|
|
|
hdi.mask = HDI_WIDTH;
|
|
m_wndHeader.GetItem(iResult, &hdi);
|
|
subitem.iWidth = hdi.cxy;
|
|
|
|
m_bColumnsReordered = TRUE;
|
|
|
|
ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
|
|
}
|
|
}
|
|
catch(CMemoryException* e)
|
|
{
|
|
e->Delete();
|
|
if(iResult >= 0)
|
|
m_wndHeader.DeleteItem(iResult);
|
|
}
|
|
}
|
|
|
|
return iResult;
|
|
}
|
|
|
|
BOOL CReportCtrl::DeactivateColumn(INT iColumn)
|
|
{
|
|
ASSERT(iColumn>=0);
|
|
ASSERT(iColumn<m_arraySubItems.GetSize()); // Specify a valid column
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_WIDTH|HDI_LPARAM;
|
|
|
|
INT iHeaderItems = m_arrayColumns.GetSize();
|
|
for(INT iItem=0;iItem<iHeaderItems;iItem++)
|
|
if(m_wndHeader.GetItem(iItem, &hdi))
|
|
if(hdi.lParam == iColumn)
|
|
break;
|
|
|
|
if(iItem == iHeaderItems)
|
|
return FALSE;
|
|
|
|
ASSERT(iHeaderItems>0); // At least one column must be active
|
|
|
|
BOOL bResult = m_wndHeader.DeleteItem(iItem);
|
|
|
|
m_iVirtualWidth -= hdi.cxy;
|
|
m_bColumnsReordered = TRUE;
|
|
|
|
ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
|
|
return bResult;
|
|
}
|
|
|
|
BOOL CReportCtrl::IsActiveColumn(INT iColumn)
|
|
{
|
|
INT iHeaderItems = m_arrayColumns.GetSize();
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_LPARAM;
|
|
|
|
for(INT iItem=0;iItem<iHeaderItems;iItem++)
|
|
if(m_wndHeader.GetItem(iItem, &hdi))
|
|
if(hdi.lParam == iColumn)
|
|
break;
|
|
|
|
if(iItem == iHeaderItems)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportCtrl::GetItem(LPRVITEM lprvi)
|
|
{
|
|
ASSERT(lprvi->iItem > RVI_INVALID);
|
|
ASSERT(lprvi->iItem < GetItemCount()); // Specify item
|
|
ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize()); // Specify subitem
|
|
|
|
UINT nMask = lprvi->nMask;
|
|
INT iTextMax = lprvi->iTextMax;
|
|
ITEM item = GetItemStruct(lprvi->iItem, lprvi->iSubItem, nMask);
|
|
|
|
lprvi->nMask = 0;
|
|
lprvi->nPreview = item.nPreview;
|
|
if(lprvi->nPreview > 0)
|
|
lprvi->nMask |= RVIM_PREVIEW;
|
|
|
|
lprvi->iBkColor = item.iBkColor;
|
|
if(lprvi->iBkColor >= 0)
|
|
lprvi->nMask |= RVIM_BKCOLOR;
|
|
|
|
lprvi->lpszText = nMask&RVIM_TEXT ? lprvi->lpszText:NULL;
|
|
item.rdData.GetSubItem(lprvi->iSubItem, &lprvi->iImage, &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->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)
|
|
{
|
|
if(m_dwStyle&RVS_OWNERDATA)
|
|
return FALSE;
|
|
// Not supported when using this style
|
|
ASSERT(!(lprvi->iItem != RVI_EDIT && m_dwStyle&RVS_OWNERDATA));
|
|
|
|
|
|
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;
|
|
}
|
|
else
|
|
rvi.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)
|
|
rvi.iImage = lprvi->iImage;
|
|
|
|
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 row
|
|
if(lprvi->nMask&RVIM_PREVIEW)
|
|
rvi.nPreview = lprvi->nPreview;
|
|
|
|
// Note: focus and selection cannot be changed through this function
|
|
if(lprvi->nMask&RVIM_STATE)
|
|
{
|
|
rvi.nState &= RVIS_FOCUSED|RVIS_SELECTED;
|
|
rvi.nState |= lprvi->nState&~(RVIS_FOCUSED|RVIS_SELECTED);
|
|
}
|
|
|
|
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.iCheck, rvi.iTextColor, rvi.lpszText));
|
|
VERIFY(item.rdData.DeleteSubItem(rvi.iSubItem+1));
|
|
|
|
item.iBkColor = rvi.iBkColor;
|
|
item.nPreview = rvi.nPreview;
|
|
item.nState = rvi.nState;
|
|
item.lParam = rvi.lParam;
|
|
SetItemStruct(rvi.iItem, item);
|
|
|
|
ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
|
|
|
|
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);
|
|
|
|
// Select a visible sub-item
|
|
if(iColumn == -1 && nCode != RVIR_BOUNDS)
|
|
return FALSE;
|
|
|
|
INT iFirst, iLast;
|
|
|
|
if(iRow != RVI_EDIT)
|
|
{
|
|
iFirst = GetScrollPos32(SB_VERT);
|
|
|
|
GetVisibleRows(TRUE, &iFirst, &iLast);
|
|
|
|
// Select a visible item
|
|
if(iFirst > iRow || iLast < iRow)
|
|
return FALSE;
|
|
|
|
*lpRect = m_rectReport;
|
|
for(;iFirst<iRow;iFirst++)
|
|
lpRect->top += m_iDefaultHeight + GetItemStruct(GetItemFromRow(iFirst), -1).nPreview;
|
|
}
|
|
else
|
|
*lpRect = m_rectEdit;
|
|
|
|
lpRect->bottom = lpRect->top + m_iDefaultHeight;
|
|
|
|
INT iPos = GetScrollPos32(SB_HORZ);
|
|
|
|
lpRect->left -= iPos;
|
|
lpRect->right -= iPos;
|
|
|
|
if(iSubItem == -1)
|
|
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);
|
|
lpRect->right = lpRect->left + hdi.cxy;
|
|
|
|
RVITEM rvi;
|
|
rvi.iItem = iItem;
|
|
rvi.iSubItem = iSubItem;
|
|
GetItem(&rvi);
|
|
|
|
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:
|
|
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;
|
|
}
|
|
}
|
|
|
|
void CReportCtrl::SetItemHeight(INT iHeight)
|
|
{
|
|
m_iDefaultHeight = iHeight;
|
|
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
Layout(rect.Width(), rect.Height());
|
|
}
|
|
|
|
INT CReportCtrl::GetVisibleCount(BOOL bUnobstructed)
|
|
{
|
|
return GetVisibleRows(bUnobstructed);
|
|
}
|
|
|
|
INT CReportCtrl::GetItemCount()
|
|
{
|
|
return m_dwStyle&RVS_OWNERDATA ? m_iVirtualHeight:m_arrayItems.GetSize();
|
|
}
|
|
|
|
void CReportCtrl::SetItemCount(INT iCount)
|
|
{
|
|
ASSERT(m_dwStyle&RVS_OWNERDATA); // Only supported when using RVS_OWNERDATA style
|
|
ASSERT(iCount >= 0);
|
|
|
|
m_iVirtualHeight = iCount;
|
|
m_iFocusRow = m_iFocusRow>=m_iVirtualHeight ? m_iVirtualHeight-1:m_iFocusRow;
|
|
|
|
RedrawItems(RVI_EDIT, RVI_LAST);
|
|
ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void CReportCtrl::ClearSelection()
|
|
{
|
|
SelectRows(m_iFocusRow, m_iFocusRow, FALSE, FALSE, FALSE, FALSE);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
BOOL CReportCtrl::SetImageList(CImageList* pImageList)
|
|
{
|
|
m_pImageList = pImageList;
|
|
m_wndHeader.SetImageList(pImageList);
|
|
|
|
IMAGEINFO info;
|
|
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>m_iDefaultHeight ? m_sizeImage.cy:m_iDefaultHeight;
|
|
|
|
Invalidate();
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
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;
|
|
|
|
CreatePalette();
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportCtrl::HasFocus()
|
|
{
|
|
return m_bFocus;
|
|
}
|
|
|
|
CFlatHeaderCtrl* CReportCtrl::GetHeaderCtrl()
|
|
{
|
|
return &m_wndHeader;
|
|
}
|
|
|
|
BOOL CReportCtrl::SetReportColumnListCtrl(CReportColumnListCtrl* lprclc)
|
|
{
|
|
if(m_lprclc != NULL)
|
|
{
|
|
m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, NULL);
|
|
m_lprclc->SetReportCtrl(NULL);
|
|
}
|
|
|
|
m_lprclc = lprclc;
|
|
if(m_lprclc != NULL)
|
|
{
|
|
m_wndHeader.ModifyProperty(FH_PROPERTY_DROPTARGET, (LPARAM)m_lprclc->m_hWnd);
|
|
m_lprclc->SetReportCtrl(this);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CReportColumnListCtrl* CReportCtrl::GetReportColumnListCtrl()
|
|
{
|
|
return m_lprclc;
|
|
}
|
|
|
|
BOOL CReportCtrl::SetSortCallback(LPFNRVCOMPARE lpfnrvc)
|
|
{
|
|
m_lpfnrvc = lpfnrvc;
|
|
return TRUE;
|
|
}
|
|
|
|
LPFNRVCOMPARE CReportCtrl::GetSortCallback()
|
|
{
|
|
return m_lpfnrvc;
|
|
}
|
|
|
|
|
|
|
|
//**********************************************
|
|
//************************************************
|
|
//************************************************
|
|
//create a profile string for saving
|
|
BOOL CReportCtrl::WriteProfile(CString* strpProfile)
|
|
{
|
|
CString str, strProfile;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
*strpProfile=strProfile;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//SEt the control properties based on passed profile string
|
|
BOOL CReportCtrl::GetProfile(CString* strpProfile)
|
|
{
|
|
CString str, strProfile;
|
|
|
|
strProfile=*strpProfile;
|
|
if(strProfile.IsEmpty())
|
|
return FALSE;
|
|
|
|
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;
|
|
|
|
for(i=0;i<iSubItems;i++)
|
|
m_arraySubItems[i].iWidth = _tcstol(++lpsz, &lpsz, 10);
|
|
|
|
for(i=0;i<iColumns;i++)
|
|
ActivateColumn(_tcstol(++lpsz, &lpsz, 10), i);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//********************************************************
|
|
//********************************************************
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportCtrl operations
|
|
|
|
BOOL CReportCtrl::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
|
|
{
|
|
DWORD dwStyle = GetStyle();
|
|
|
|
ASSERT(!(dwRemove&RVS_OWNERDATA)); // Can't dynamically remove this style
|
|
ASSERT(!(dwAdd&RVS_OWNERDATA)); // Can't dynamically add this style
|
|
|
|
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(!(dwStyle&RVS_FOCUSSUBITEMS) && dwAdd&RVS_FOCUSSUBITEMS)
|
|
m_iFocusColumn = 0;
|
|
|
|
if(dwStyle&RVS_FOCUSSUBITEMS && dwRemove&RVS_FOCUSSUBITEMS)
|
|
m_iFocusColumn = -1;
|
|
|
|
m_dwStyle = GetStyle();
|
|
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
Layout(rect.Width(), rect.Height());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT CReportCtrl::DefineColumn(INT iColumn, LPRVCOLUMN lprvc, BOOL bUpdateList)
|
|
{
|
|
INT i;
|
|
INT iColumns = m_arraySubItems.GetSize();
|
|
|
|
ASSERT(iColumn <= iColumns);
|
|
ASSERT(lprvc->lpszText != NULL); // Must supply (descriptive) text for subitem selector
|
|
ASSERT(_tcslen(lprvc->lpszText) < FLATHEADER_TEXT_MAX);
|
|
|
|
try
|
|
{
|
|
SUBITEM subitem;
|
|
|
|
subitem.nFormat = lprvc->nFormat;
|
|
subitem.iWidth = lprvc->iWidth<0 ? m_iDefaultWidth:lprvc->iWidth;
|
|
subitem.iMinWidth = lprvc->iMinWidth;
|
|
subitem.iMaxWidth = lprvc->iMaxWidth;
|
|
subitem.iImage = lprvc->nFormat&RVCF_IMAGE ? lprvc->iImage:0;
|
|
subitem.strText = lprvc->lpszText;
|
|
|
|
m_arraySubItems.InsertAt(iColumn, subitem);
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_LPARAM;
|
|
|
|
INT iHeaderItems = m_arrayColumns.GetSize();
|
|
for(i=0;i<iHeaderItems;i++)
|
|
if(m_wndHeader.GetItem(i, &hdi))
|
|
if(hdi.lParam >= iColumn)
|
|
{
|
|
hdi.lParam++;
|
|
m_wndHeader.SetItem(i, &hdi);
|
|
}
|
|
|
|
VERIFY(m_itemEdit.rdData.InsertSubItem(iColumn, -1, -1, -1, NULL));
|
|
|
|
if(!(m_dwStyle&RVS_OWNERDATA))
|
|
{
|
|
INT iItems = GetItemCount();
|
|
for(i=0;i<iItems;i++)
|
|
VERIFY(m_arrayItems[i].rdData.InsertSubItem(iColumn, -1, -1, -1, NULL));
|
|
}
|
|
|
|
if(bUpdateList && m_lprclc != NULL)
|
|
m_lprclc->UpdateList();
|
|
|
|
return iColumn;
|
|
}
|
|
catch(CMemoryException* e)
|
|
{
|
|
e->Delete();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
BOOL CReportCtrl::UndefineColumn(INT iColumn)
|
|
{
|
|
ASSERT(iColumn >= 0);
|
|
ASSERT(iColumn < m_arraySubItems.GetSize()); // Specify a valid column
|
|
|
|
VERIFY(!DeactivateColumn(iColumn));
|
|
m_arraySubItems.RemoveAt(iColumn);
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_LPARAM;
|
|
|
|
INT i;
|
|
INT iHeaderItems = m_arrayColumns.GetSize();
|
|
for(i=0;i<iHeaderItems;i++)
|
|
if(m_wndHeader.GetItem(i, &hdi))
|
|
if(hdi.lParam > iColumn)
|
|
{
|
|
hdi.lParam--;
|
|
m_wndHeader.SetItem(i, &hdi);
|
|
}
|
|
|
|
VERIFY(m_itemEdit.rdData.DeleteSubItem(iColumn));
|
|
|
|
if(!(m_dwStyle&RVS_OWNERDATA))
|
|
{
|
|
INT iItems = GetItemCount();
|
|
for(i=0;i<iItems;i++)
|
|
VERIFY(m_arrayItems[i].rdData.DeleteSubItem(iColumn));
|
|
}
|
|
|
|
if(m_lprclc != NULL)
|
|
m_lprclc->UpdateList();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
INT CReportCtrl::InsertItem(INT iItem, LPTSTR lpszText, INT iImage, INT iCheck, INT iTextColor)
|
|
{
|
|
RVITEM rvi;
|
|
rvi.nMask = RVIM_TEXT;
|
|
rvi.iItem = iItem;
|
|
rvi.iSubItem = 0;
|
|
rvi.lpszText = 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) // Use set SetItemCount() when using this style
|
|
return RVI_INVALID;
|
|
|
|
ASSERT(lprvi->iItem >= 0); // Use SetItem to set Edit row item
|
|
ASSERT(lprvi->iItem <= GetItemCount());
|
|
ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize());
|
|
|
|
BOOL bInserted = FALSE;
|
|
|
|
try
|
|
{
|
|
ITEM item;
|
|
item.rdData.New(m_arraySubItems.GetSize());
|
|
|
|
m_arrayItems.InsertAt(lprvi->iItem, item); bInserted = TRUE;
|
|
m_arrayRows.InsertAt(lprvi->iItem, INT_MIN);
|
|
|
|
INT iItems = m_arrayRows.GetSize();
|
|
for(INT i=0;i<iItems;i++)
|
|
if(m_arrayRows[i]>=lprvi->iItem)
|
|
m_arrayRows[i]++;
|
|
|
|
m_arrayRows[lprvi->iItem] = lprvi->iItem;
|
|
|
|
m_iVirtualHeight++;
|
|
|
|
VERIFY(SetItem(lprvi));
|
|
|
|
ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
|
|
return lprvi->iItem;
|
|
}
|
|
catch(CMemoryException* e)
|
|
{
|
|
if(bInserted)
|
|
m_arrayItems.RemoveAt(lprvi->iItem);
|
|
|
|
e->Delete();
|
|
return RVI_INVALID;
|
|
}
|
|
}
|
|
|
|
BOOL CReportCtrl::DeleteItem(INT iItem)
|
|
{
|
|
ASSERT(iItem <= GetItemCount());
|
|
|
|
if(m_dwStyle&RVS_OWNERDATA) // Use set SetItemCount() when using this style
|
|
return FALSE;
|
|
|
|
RVITEM rvi;
|
|
rvi.nMask = RVIM_LPARAM;
|
|
rvi.iItem = iItem;
|
|
GetItem(&rvi);
|
|
Notify(RVN_ITEMDELETED, iItem, 0, 0, rvi.lParam);
|
|
|
|
m_arrayItems.RemoveAt(iItem);
|
|
|
|
INT iRows = m_arrayRows.GetSize();
|
|
for(INT i=0;i<iRows;i++)
|
|
{
|
|
if(m_arrayRows[i] == iItem)
|
|
m_arrayRows.RemoveAt(i);
|
|
|
|
if(m_arrayRows[i] > iItem)
|
|
m_arrayRows[i]--;
|
|
}
|
|
|
|
m_iVirtualHeight--;
|
|
m_iFocusRow = m_iFocusRow >= m_iVirtualHeight ? m_iVirtualHeight-1 : m_iFocusRow;
|
|
|
|
INT iItems = GetItemCount();
|
|
INT iFirst = GetScrollPos32(SB_VERT), iLast;
|
|
GetVisibleRows(TRUE, &iFirst, &iLast);
|
|
|
|
if(iItem<=iFirst || iLast>=iItems-1)
|
|
GetVisibleRows(TRUE, &iFirst, &iLast, TRUE);
|
|
|
|
ScrollWindow(SB_VERT, iFirst);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportCtrl::DeleteAllItems()
|
|
{
|
|
if(m_dwStyle&RVS_OWNERDATA) // Use set SetItemCount() when using this style
|
|
return FALSE;
|
|
|
|
RVITEM rvi;
|
|
for (int iItem = 0; iItem < GetItemCount(); 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_iVirtualHeight = 0;
|
|
m_iFocusRow = RVI_INVALID;
|
|
|
|
ScrollWindow(SB_VERT, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
void CReportCtrl::RedrawItems(INT iFirst, INT iLast)
|
|
{
|
|
// TODO: Optimize to redraw indivual rows
|
|
// taking into account that the row height
|
|
// may have changed. Redrawing everything
|
|
// will work as well :)
|
|
|
|
if(iFirst == RVI_EDIT)
|
|
InvalidateRect(m_rectEdit);
|
|
|
|
InvalidateRect(m_rectReport);
|
|
}
|
|
|
|
BOOL CReportCtrl::EnsureVisible(INT iItem, BOOL bUnobstructed)
|
|
{
|
|
INT iFirst = GetScrollPos32(SB_VERT), iLast;
|
|
INT iRow = GetRowFromItem(iItem);
|
|
if(iRow < 0)
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
INT CReportCtrl::HitTest(LPRVHITTESTINFO lprvhti)
|
|
{
|
|
ASSERT(lprvhti);
|
|
|
|
lprvhti->nFlags = 0;
|
|
lprvhti->iItem = RVI_INVALID;
|
|
lprvhti->iSubItem = -1;
|
|
|
|
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;
|
|
|
|
if(rectItem.PtInRect(lprvhti->point))
|
|
{
|
|
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+item.nPreview;
|
|
|
|
if(rectItem.PtInRect(lprvhti->point))
|
|
break;
|
|
|
|
rectItem.top = rectItem.bottom;
|
|
}
|
|
|
|
if(iFirst<=iLast)
|
|
{
|
|
lprvhti->iItem = GetItemFromRow(iFirst);
|
|
lprvhti->iRow = iFirst;
|
|
|
|
if(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)
|
|
{
|
|
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++)
|
|
{
|
|
m_wndHeader.GetItem(m_arrayColumns[iHeaderItem], &hdi);
|
|
rectItem.right += hdi.cxy;
|
|
|
|
if(rectItem.PtInRect(lprvhti->point))
|
|
break;
|
|
|
|
rectItem.left = rectItem.right;
|
|
}
|
|
|
|
lprvhti->iSubItem = hdi.lParam;
|
|
lprvhti->iColumn = iHeaderItem;
|
|
|
|
if(iHeaderItem<iHeaderItems)
|
|
{
|
|
RVITEM rvi;
|
|
rvi.iItem = iFirst;
|
|
rvi.iSubItem = lprvhti->iSubItem;
|
|
GetItem(&rvi);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
lprvhti->nFlags |= RVHT_ONITEMTEXT;
|
|
}
|
|
else
|
|
lprvhti->nFlags = RVHT_NOWHERE;
|
|
}
|
|
else
|
|
lprvhti->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::SortItems(INT iColumn, BOOL bAscending)
|
|
{
|
|
INT iHeaderColumn = FindColumnInHeader(iColumn);
|
|
if(iHeaderColumn < 0 || m_dwStyle&RVS_OWNERDATA)
|
|
return FALSE; // Can't sort on columns that are not active
|
|
// Can't sort if data is managed by owner
|
|
|
|
INT iFocusItem = GetItemFromRow(m_iFocusRow);
|
|
|
|
INT iRows = m_arrayRows.GetSize();
|
|
if(iRows>1)
|
|
{
|
|
for(INT i=0;i<iRows-1;i++)
|
|
{
|
|
for(INT j=i+1;j<iRows;j++)
|
|
{
|
|
INT iSort = CompareItems(iColumn, m_arrayRows[i], m_arrayRows[j]);
|
|
if((bAscending && iSort>0) ||
|
|
(!bAscending && iSort<0))
|
|
{
|
|
INT iItem = m_arrayRows[i];
|
|
m_arrayRows[i] = m_arrayRows[j];
|
|
m_arrayRows[j] = iItem;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_wndHeader.SetSortColumn(m_arrayColumns[iHeaderColumn], bAscending);
|
|
|
|
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;
|
|
}
|
|
|
|
BOOL CReportCtrl::SortAllColumns(BOOL bAscending /*=TRUE*/)
|
|
{
|
|
if(m_dwStyle&RVS_OWNERDATA)
|
|
return FALSE; // Can't sort if data is managed by owner
|
|
|
|
// Save current position
|
|
INT iFocusItem = GetItemFromRow(m_iFocusRow);
|
|
|
|
// Scan all the rows.
|
|
INT iRows = m_arrayRows.GetSize();
|
|
if(iRows>1)
|
|
{
|
|
for(INT i=0;i<iRows-1;i++)
|
|
{
|
|
for(INT j=i+1;j<iRows;j++)
|
|
{
|
|
// Scan the visible columns and extract each internal column number
|
|
INT iColumns = m_arrayColumns.GetSize();
|
|
for(INT k=0;k<iColumns;k++)
|
|
{
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_WIDTH|HDI_LPARAM;
|
|
m_wndHeader.GetItem(m_arrayColumns[k], &hdi);
|
|
INT iInternalColumn = hdi.lParam;
|
|
|
|
INT iSort = CompareItems(iInternalColumn, m_arrayRows[i], m_arrayRows[j]);
|
|
if (iSort == 0)
|
|
continue; // ie try next column
|
|
|
|
if((bAscending && iSort>0) ||
|
|
(!bAscending && iSort<0))
|
|
{
|
|
INT iItem = m_arrayRows[i];
|
|
m_arrayRows[i] = m_arrayRows[j];
|
|
m_arrayRows[j] = iItem;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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(INT iColumn, INT iItem1, INT iItem2)
|
|
{
|
|
ASSERT(!(m_dwStyle&RVS_OWNERDATA)); // Can't sort if data is managed by owner
|
|
|
|
if(m_lpfnrvc == NULL)
|
|
{
|
|
RVITEM rvi1, rvi2;
|
|
|
|
TCHAR szText1[REPORTCTRL_MAX_TEXT], szText2[REPORTCTRL_MAX_TEXT];
|
|
|
|
rvi1.nMask = RVIM_TEXT;
|
|
rvi1.iItem = iItem1;
|
|
rvi1.iSubItem = iColumn;
|
|
rvi1.lpszText = szText1;
|
|
rvi1.iTextMax = REPORTCTRL_MAX_TEXT;
|
|
VERIFY(GetItem(&rvi1));
|
|
|
|
rvi2.nMask = RVIM_TEXT;
|
|
rvi2.iItem = iItem2;
|
|
rvi2.iSubItem = iColumn;
|
|
rvi2.lpszText = szText2;
|
|
rvi2.iTextMax = REPORTCTRL_MAX_TEXT;
|
|
VERIFY(GetItem(&rvi2));
|
|
|
|
if((!_tcslen(szText1)) && (!_tcslen(szText2)))
|
|
{
|
|
if(rvi1.iImage < rvi2.iImage)
|
|
return -1;
|
|
else if(rvi1.iImage > rvi2.iImage)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
else
|
|
return _tcscmp(szText1, szText2);
|
|
}
|
|
else
|
|
return m_lpfnrvc(iColumn, iItem1, iItem2);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportCtrl implementation
|
|
|
|
void 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_cr3DHiLight = GetSysColor(COLOR_3DHILIGHT);
|
|
m_cr3DDkShadow = GetSysColor(COLOR_3DDKSHADOW);
|
|
}
|
|
|
|
UINT CReportCtrl::GetMouseScrollLines()
|
|
{
|
|
UINT nScrollLines = 3; // Reasonable default
|
|
HKEY 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 palette
|
|
RGBQUAD *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;
|
|
}
|
|
else
|
|
m_palette.CreateHalftonePalette( &cdc );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
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;
|
|
nmrv.nState = nState;
|
|
|
|
nmrv.lParam = lParam;
|
|
|
|
CWnd* pWnd = GetParent();
|
|
if(pWnd)
|
|
return pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrv);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
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(lprvhti->iItem >= 0 && (!(m_dwStyle&RVS_OWNERDATA)))
|
|
nmrv.lParam = GetItemStruct(lprvhti->iItem, -1).lParam;
|
|
|
|
CWnd* pWnd = GetParent();
|
|
if(pWnd)
|
|
return pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrv);
|
|
|
|
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();
|
|
|
|
if(!(m_dwStyle&RVS_NOHEADER))
|
|
{
|
|
VERIFY(m_wndHeader.SendMessage(HDM_LAYOUT, 0, (LPARAM)&hdl));
|
|
|
|
m_rectHeader.SetRect(wpos.x, wpos.y, wpos.x+wpos.cx, wpos.y+wpos.cy);
|
|
}
|
|
else
|
|
m_rectHeader.SetRect(0, 0, cx, 0);
|
|
|
|
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;
|
|
}
|
|
else
|
|
m_rectEdit.SetRectEmpty();
|
|
|
|
ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
|
|
ScrollWindow(SB_VERT, GetScrollPos32(SB_VERT));
|
|
}
|
|
}
|
|
|
|
CReportCtrl::ITEM& CReportCtrl::GetItemStruct(INT iItem, INT iSubItem, UINT nMask)
|
|
{
|
|
if(m_dwStyle&RVS_OWNERDATA)
|
|
{
|
|
INT iSubItems = m_arraySubItems.GetSize();
|
|
|
|
ITEM item;
|
|
item.rdData.New(iSubItems);
|
|
|
|
CWnd* pWnd = GetParent();
|
|
if(pWnd)
|
|
{
|
|
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;
|
|
|
|
TCHAR szText[REPORTCTRL_MAX_TEXT+1];
|
|
memset(szText, 0, sizeof(szText));
|
|
|
|
if(iSubItem >= 0)
|
|
{
|
|
nmrvic.item.nMask |= RVIM_TEXT;
|
|
nmrvic.item.lpszText = szText;
|
|
nmrvic.item.iTextMax = REPORTCTRL_MAX_TEXT;
|
|
}
|
|
|
|
pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvic);
|
|
|
|
INT iColor = nmrvic.item.nMask&RVIM_TEXTCOLOR ? nmrvic.item.iTextColor:-1;
|
|
INT iImage = nmrvic.item.nMask&RVIM_IMAGE ? nmrvic.item.iImage:-1;
|
|
INT iCheck = nmrvic.item.nMask&RVIM_CHECK ? nmrvic.item.iCheck:-1;
|
|
|
|
if(iSubItem >= 0)
|
|
item.rdData.SetSubItem(iSubItem, iImage, iCheck, iColor, szText);
|
|
|
|
item.iBkColor = nmrvic.item.nMask&RVIM_BKCOLOR ? nmrvic.item.iBkColor:-1;
|
|
item.nPreview = nmrvic.item.nMask&RVIM_PREVIEW ? nmrvic.item.nPreview:0;
|
|
item.nState = nmrvic.item.nMask&RVIM_STATE ? nmrvic.item.nState:0;
|
|
}
|
|
|
|
m_itemCache = item;
|
|
return m_itemCache;
|
|
}
|
|
|
|
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;
|
|
else
|
|
m_arrayItems[iItem] = item;
|
|
}
|
|
|
|
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(m_dwStyle&RVS_OWNERDATA)
|
|
return iRow;
|
|
|
|
if(iRow == RVI_INVALID)
|
|
return RVI_INVALID;
|
|
|
|
INT iItem = GetItemFromRow(iRow);
|
|
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();
|
|
for(INT iRow=0;iRow<iRows;iRow++)
|
|
if(m_arrayRows[iRow] == iItem)
|
|
return iRow;
|
|
|
|
return RVI_INVALID;
|
|
}
|
|
|
|
INT CReportCtrl::GetSubItemFromColumn(INT iColumn)
|
|
{
|
|
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 == -1)
|
|
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;
|
|
}
|
|
|
|
void CReportCtrl::SetState(INT iRow, UINT nState, UINT nMask)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
|
|
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 item
|
|
return rvi.nState;
|
|
}
|
|
|
|
INT CReportCtrl::FindColumnInHeader(INT iColumn)
|
|
{
|
|
INT iColumns = m_arrayColumns.GetSize();
|
|
for(INT i=0;i<iColumns;i++)
|
|
{
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_WIDTH|HDI_LPARAM;
|
|
m_wndHeader.GetItem(m_arrayColumns[i], &hdi);
|
|
if(hdi.lParam == iColumn)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
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;
|
|
else
|
|
iRow = GetScrollPos32(SB_VERT);
|
|
|
|
for(;iRow<iMaxRows&&iHeight>0;iRow++,iRows++)
|
|
{
|
|
iHeight -= m_iDefaultHeight + GetItemStruct(GetItemFromRow(iRow), -1).nPreview;
|
|
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+GetItemStruct(GetItemFromRow(*lpiFirst), -1).nPreview;
|
|
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);
|
|
RedrawItems(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;
|
|
else
|
|
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);
|
|
}
|
|
}
|
|
|
|
RedrawItems(iFirst, iLast);
|
|
}
|
|
else
|
|
RedrawItems(iFirst);
|
|
|
|
|
|
if(!bKeepSelection && bSelect)
|
|
{
|
|
INT iRows = m_iVirtualHeight;
|
|
for(i=RVI_EDIT;i<iRows;i++)
|
|
{
|
|
INT iItem = GetItemFromRow(i);
|
|
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);
|
|
|
|
RedrawItems(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
INT CReportCtrl::GetScrollPos32(INT iBar, BOOL bGetTrackPos)
|
|
{
|
|
SCROLLINFO si;
|
|
si.cbSize = sizeof(SCROLLINFO);
|
|
|
|
if(bGetTrackPos)
|
|
{
|
|
if(GetScrollInfo(iBar, &si, SIF_TRACKPOS))
|
|
return si.nTrackPos;
|
|
}
|
|
else
|
|
{
|
|
if(GetScrollInfo(iBar, &si, SIF_POS))
|
|
return si.nPos;
|
|
}
|
|
|
|
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)
|
|
{
|
|
INT iItems = GetItemCount();
|
|
ASSERT(iPos >= 0 && iPos<=iItems);
|
|
|
|
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)<iItems ? iItems-1:0;
|
|
si.nPos = iFirst;
|
|
SetScrollInfo(SB_VERT, &si, TRUE);
|
|
}
|
|
|
|
if(m_dwStyle&RVS_SHOWEDITROW)
|
|
InvalidateRect(m_rectEdit);
|
|
|
|
InvalidateRect(m_rectReport);
|
|
}
|
|
|
|
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::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_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);
|
|
|
|
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;
|
|
|
|
CWnd* pwndParent = GetParent();
|
|
|
|
INT iRows = m_iVirtualHeight;
|
|
INT iColumns = m_wndHeader.GetItemCount();
|
|
|
|
ASSERT(iColumns>0); // Make sure that always one column is active
|
|
|
|
if(m_bColumnsReordered)
|
|
{
|
|
LPINT lpi;
|
|
|
|
m_iFocusColumn = m_iFocusColumn >= iColumns ? iColumns-1:m_iFocusColumn;
|
|
|
|
m_arrayColumns.SetSize(iColumns, 8);
|
|
lpi = m_arrayColumns.GetData();
|
|
if(!m_wndHeader.GetOrderArray(lpi, iColumns))
|
|
return;
|
|
|
|
if(m_lprclc != NULL)
|
|
m_lprclc->UpdateList();
|
|
|
|
m_bColumnsReordered = FALSE;
|
|
}
|
|
|
|
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 = -1;
|
|
rvi.nMask = RVIM_TEXT;
|
|
GetItem(&rvi);
|
|
|
|
rect = m_rectEdit;
|
|
rect.bottom -= GetSystemMetrics(SM_CYFIXEDFRAME)*2;
|
|
rect.OffsetRect(-iHPos, 0);
|
|
|
|
DrawRow(pDC, rect, rectClip, RVI_EDIT, &rvi, FALSE);
|
|
|
|
if(m_bFocus && m_hEditWnd == NULL && m_iFocusRow == RVI_EDIT && m_iFocusColumn == -1)
|
|
{
|
|
if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))
|
|
rect.DeflateRect(1, 0, 1, 0);
|
|
|
|
pDC->SetBkColor(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;
|
|
|
|
pDC->SetTextColor(m_crText);
|
|
pDC->DrawText(m_strNoItems, rect, DT_CENTER|DT_END_ELLIPSIS);
|
|
return;
|
|
}
|
|
|
|
INT iRow = iVPos;
|
|
while(iRow<iRows && rectRow.top<rectClip.bottom)
|
|
{
|
|
rvi.iItem = GetItemFromRow(iRow);
|
|
rvi.nMask = RVIM_TEXT;
|
|
VERIFY(GetItem(&rvi));
|
|
|
|
rectRow.bottom = rectRow.top + m_iDefaultHeight+rvi.nPreview;
|
|
if(rectRow.bottom >= rectClip.top)
|
|
{
|
|
DrawRow(pDC, rectRow, rectClip, iRow, &rvi, iRow&1);
|
|
|
|
if(rvi.nMask&RVIM_PREVIEW && rvi.nPreview && pwndParent)
|
|
{
|
|
nmrvdp.iItem = rvi.iItem;
|
|
nmrvdp.nState = rvi.nState;
|
|
nmrvdp.rect = rectRow;
|
|
nmrvdp.rect.top += m_iDefaultHeight;
|
|
nmrvdp.lParam = rvi.lParam;
|
|
|
|
pwndParent->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&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_iFocusColumn == -1)
|
|
{
|
|
if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))
|
|
rectRow.DeflateRect(1, 0, 1, 1);
|
|
|
|
pDC->SetBkColor(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_wndHeader.GetItemCount();
|
|
|
|
// You have to insert at least 1 color to use color alternate style.
|
|
ASSERT(!(m_dwStyle&RVS_SHOWCOLORALTERNATE && !m_arrayColors.GetSize()));
|
|
|
|
COLORREF crItem;
|
|
crItem = (m_dwStyle&RVS_SHOWCOLORALTERNATE && bAlternate) ? m_arrayColors[0]:m_crBackground;
|
|
crItem = lprvi->iBkColor>=0 ? m_arrayColors[lprvi->iBkColor]:crItem;
|
|
if(lprvi->nState&RVIS_SELECTED)
|
|
{
|
|
if(m_bFocus)
|
|
crItem = m_crBkSelected;
|
|
else
|
|
if(m_dwStyle&RVS_SHOWSELALWAYS)
|
|
crItem = m_crBkSelectedNoFocus;
|
|
}
|
|
|
|
if(m_bitmap.m_hObject == NULL || crItem != m_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;
|
|
if(rectItem.right > rectClip.left)
|
|
{
|
|
lprvi->nMask = RVIM_TEXT;
|
|
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;
|
|
else
|
|
if(m_dwStyle&RVS_SHOWSELALWAYS)
|
|
crText = lprvi->nMask&RVIM_TEXTCOLOR && m_dwStyle&RVS_SHOWCOLORALWAYS ? crText:m_crTextSelectedNoFocus;
|
|
}
|
|
|
|
if(m_iFocusRow == iRow && m_iFocusColumn == iColumn)
|
|
{
|
|
pDC->FillSolidRect(rectItem, m_crBackground);
|
|
crText = m_crText;
|
|
}
|
|
|
|
pDC->SetTextColor(crText);
|
|
|
|
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)
|
|
{
|
|
if(m_dwStyle&(RVS_SHOWHGRID|RVS_SHOWVGRID))
|
|
rectItem.DeflateRect(1, 0, 1, 1);
|
|
|
|
pDC->SetBkColor(m_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)
|
|
{
|
|
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::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;
|
|
|
|
point.y = rect.CenterPoint().y - (m_sizeImage.cy>>1);
|
|
point.x = rect.left;
|
|
|
|
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));
|
|
|
|
iWidth = m_sizeImage.cx;
|
|
}
|
|
}
|
|
else
|
|
iWidth = 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)
|
|
{
|
|
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;
|
|
|
|
pDC->FillSolidRect(rect, m_crBackground); // Fixes visual problem with bigger fonts
|
|
pDC->DrawFrameControl(
|
|
rect,
|
|
DFC_BUTTON,
|
|
DFCS_BUTTONCHECK|DFCS_FLAT|(lprvi->iCheck?DFCS_CHECKED:0)
|
|
);
|
|
|
|
iWidth = m_sizeCheck.cx;
|
|
}
|
|
}
|
|
else
|
|
iWidth = 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 == -1)
|
|
return FALSE;
|
|
|
|
TCHAR szText[REPORTCTRL_MAX_TEXT];
|
|
|
|
m_iEditItem = GetItemFromRow(iRow);
|
|
m_iEditSubItem = GetSubItemFromColumn(iColumn);
|
|
|
|
// Make sure that the item to edit actually exists
|
|
ASSERT(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;
|
|
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;
|
|
CWnd* pWnd = GetParent();
|
|
if(pWnd != NULL)
|
|
bResult = pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie);
|
|
|
|
if(!bResult)
|
|
{
|
|
if(!(rvi.nMask&RVIM_TEXT))
|
|
return FALSE;
|
|
|
|
if(!GetItemRect(m_iEditItem, m_iEditSubItem, &nmrvie.rect, RVIR_TEXT))
|
|
return FALSE;
|
|
|
|
CReportEditCtrl* pWnd= new CReportEditCtrl(m_iEditItem, m_iEditSubItem);
|
|
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);
|
|
|
|
switch (nKey){
|
|
case VK_LBUTTON:
|
|
case VK_RETURN:
|
|
pWnd->SetSel((INT)_tcslen(szText), -1);
|
|
break;
|
|
case VK_BACK:
|
|
pWnd->SetSel((INT)_tcslen(szText), -1);
|
|
pWnd->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:
|
|
pWnd->SetSel(0,-1);
|
|
break;
|
|
default:
|
|
pWnd->SetSel(0,-1);
|
|
pWnd->SendMessage(WM_CHAR, nKey);
|
|
break;
|
|
}
|
|
|
|
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);
|
|
}
|
|
else
|
|
SetItemText(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;
|
|
}
|
|
|
|
RedrawItems(m_iFocusRow, m_iFocusRow);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportCtrl message handlers
|
|
|
|
BOOL 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(pNewWnd)
|
|
{
|
|
if(pNewWnd->m_hWnd != m_hEditWnd)
|
|
m_bFocus = FALSE;
|
|
}
|
|
else
|
|
m_bFocus = FALSE;
|
|
|
|
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());
|
|
}
|
|
|
|
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);
|
|
|
|
m_iDefaultHeight = tm.tmHeight + tm.tmExternalLeading + 2;
|
|
m_iDefaultHeight += m_dwStyle&RVS_SHOWHGRID ? 1:0;
|
|
|
|
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);
|
|
}
|
|
}
|
|
else
|
|
DrawCtrl(&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:
|
|
iFirst = nPos;
|
|
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(Notify(RVN_ITEMCLICK, nFlags, &rvhti))
|
|
{
|
|
CWnd::OnLButtonDown(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
INT iFocusRow = m_iFocusRow, iFocusColumn = m_iFocusColumn;
|
|
m_iFocusColumn = m_dwStyle&RVS_FOCUSSUBITEMS? rvhti.iColumn:-1;
|
|
|
|
if(rvhti.iItem >= -1)
|
|
{
|
|
INT iRow = GetRowFromItem(rvhti.iItem);
|
|
ASSERT(iRow >= -1);
|
|
|
|
switch(nFlags&(MK_CONTROL|MK_SHIFT))
|
|
{
|
|
case MK_CONTROL:
|
|
SelectRows(iRow, iRow, TRUE, TRUE, TRUE);
|
|
m_iSelectRow = iRow;
|
|
break;
|
|
|
|
case MK_SHIFT:
|
|
SelectRows(m_iSelectRow, iRow, TRUE);
|
|
break;
|
|
|
|
case MK_CONTROL|MK_SHIFT:
|
|
SelectRows(m_iSelectRow, iRow, TRUE, TRUE);
|
|
m_iSelectRow = iRow;
|
|
break;
|
|
|
|
default:
|
|
SelectRows(iRow, iRow, TRUE);
|
|
m_iSelectRow = iRow;
|
|
|
|
if(m_iFocusRow == iFocusRow && m_iFocusColumn == iFocusColumn)
|
|
BeginEdit(m_iFocusRow, m_iFocusColumn, VK_LBUTTON);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
switch (nChar)
|
|
{
|
|
case VK_SPACE:
|
|
SelectRows(m_iFocusRow, m_iFocusRow, TRUE, TRUE, IsCtrlDown() ? TRUE:FALSE);
|
|
return;
|
|
|
|
case VK_LEFT:
|
|
if(m_dwStyle&RVS_FOCUSSUBITEMS)
|
|
{
|
|
m_iFocusColumn -= m_iFocusColumn>0 ? 1:0;
|
|
|
|
EnsureVisibleColumn(m_iFocusColumn);
|
|
|
|
iFirst = GetRowFromItem(m_iFocusRow);
|
|
RedrawItems(iFirst, iFirst);
|
|
}
|
|
else
|
|
SendMessage(WM_HSCROLL, LOWORD(SB_LINELEFT), NULL);
|
|
return;
|
|
|
|
case VK_RIGHT:
|
|
if(m_dwStyle&RVS_FOCUSSUBITEMS)
|
|
{
|
|
m_iFocusColumn += m_iFocusColumn<m_arrayColumns.GetSize()-1 ? 1:0;
|
|
|
|
EnsureVisibleColumn(m_iFocusColumn);
|
|
|
|
iFirst = GetRowFromItem(m_iFocusRow);
|
|
RedrawItems(iFirst, iFirst);
|
|
}
|
|
else
|
|
SendMessage(WM_HSCROLL, LOWORD(SB_LINERIGHT), NULL);
|
|
return;
|
|
|
|
case VK_DOWN:
|
|
if(m_iFocusRow<m_iVirtualHeight-1)
|
|
{
|
|
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;
|
|
}
|
|
else
|
|
SelectRows(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;
|
|
}
|
|
else
|
|
SelectRows(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;
|
|
}
|
|
else
|
|
iFirst = m_iSelectRow;
|
|
|
|
SelectRows(iLast, iFirst, TRUE);
|
|
return;
|
|
|
|
case VK_PRIOR:
|
|
if(m_iFocusRow == iFirst)
|
|
{
|
|
SendMessage(WM_VSCROLL, SB_PAGEUP, 0);
|
|
|
|
iFirst = GetScrollPos32(SB_VERT);
|
|
}
|
|
|
|
if(IsCtrlDown())
|
|
{
|
|
SelectRows(iFirst, iFirst, FALSE);
|
|
m_iSelectRow = m_iFocusRow;
|
|
return;
|
|
}
|
|
else if(!IsShiftDown())
|
|
{
|
|
iLast = iFirst;
|
|
m_iSelectRow = iFirst;
|
|
}
|
|
else
|
|
iLast = 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_iSelectRow, m_iVirtualHeight-1, IsCtrlDown()?FALSE:TRUE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CReportCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if(!IsCtrlDown() && nChar != VK_ESCAPE)
|
|
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);
|
|
else
|
|
for (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);
|
|
else
|
|
for (i=0;i>iRowsScrolled;i--)
|
|
PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
|
|
}
|
|
|
|
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
|
|
}
|
|
|
|
void CReportCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if(!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(rvi.nMask&RVIM_TEXT && _tcslen(rvi.lpszText))
|
|
m_wndTip.Show(
|
|
rvhti.rect,
|
|
rvi.lpszText,
|
|
rvi.nState&RVIS_BOLD ? &m_fontBold:&m_font
|
|
);
|
|
}
|
|
}
|
|
|
|
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 = 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;
|
|
}
|
|
|
|
ScrollWindow(SB_HORZ, GetScrollPos32(SB_HORZ));
|
|
Notify(RVN_LAYOUTCHANGED, -1, (INT)hdi.lParam);
|
|
|
|
*pResult = FALSE;
|
|
}
|
|
|
|
void CReportCtrl::OnHdnItemClick(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
LPHDITEM lphdi = (LPHDITEM)((LPNMHEADER)pNMHDR)->pitem;
|
|
|
|
if(m_hEditWnd != NULL)
|
|
EndEdit();
|
|
|
|
HDITEM hdi;
|
|
hdi.mask = HDI_ORDER|HDI_LPARAM;
|
|
m_wndHeader.GetItem(((LPNMHEADER)pNMHDR)->iItem, &hdi);
|
|
|
|
if(!Notify(RVN_COLUMNCLICK, -1, (INT)hdi.lParam))
|
|
{
|
|
if(!(m_dwStyle&(RVS_NOSORT|RVS_OWNERDATA)))
|
|
{
|
|
BOOL bAscending;
|
|
if(((LPNMHEADER)pNMHDR)->iItem == m_wndHeader.GetSortColumn(&bAscending))
|
|
bAscending = !bAscending;
|
|
else
|
|
bAscending = TRUE;
|
|
|
|
VERIFY(SortItems((INT)hdi.lParam, 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;
|
|
|
|
if(m_wndHeader.GetDropResult())
|
|
{
|
|
if(m_dwStyle&RVS_ALLOWCOLUMNREMOVAL && m_arrayColumns.GetSize()>1)
|
|
DeactivateColumn(lpnmhdr->pitem->lParam);
|
|
|
|
*pResult = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_bColumnsReordered = TRUE;
|
|
Invalidate();
|
|
|
|
*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;
|
|
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;
|
|
|
|
BOOL bResult = FALSE;
|
|
CWnd* pWnd = GetParent();
|
|
if(pWnd != NULL)
|
|
bResult = pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie);
|
|
|
|
if(bResult)
|
|
EndEdit(FALSE);
|
|
else
|
|
EndEdit(nmrvie.nKey != VK_ESCAPE, &nmrvie);
|
|
|
|
pResult = FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportColumnListCtrl
|
|
|
|
CReportColumnListCtrl::CReportColumnListCtrl()
|
|
{
|
|
m_pReportCtrl = NULL;
|
|
|
|
m_iColumn = -1;
|
|
m_pDragWnd = NULL;
|
|
}
|
|
|
|
CReportColumnListCtrl::~CReportColumnListCtrl()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CReportColumnListCtrl, CDragListBox)
|
|
//{{AFX_MSG_MAP(CReportColumnListCtrl)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportColumnListCtrl attributes
|
|
|
|
BOOL CReportColumnListCtrl::SetReportCtrl(CReportCtrl* pReportCtrl)
|
|
{
|
|
ASSERT_KINDOF(CReportCtrl, pReportCtrl);
|
|
|
|
m_pReportCtrl = pReportCtrl;
|
|
ResetContent();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CReportCtrl* CReportColumnListCtrl::GetReportCtrl()
|
|
{
|
|
return m_pReportCtrl;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportColumnListCtrl operations
|
|
|
|
BOOL CReportColumnListCtrl::UpdateList()
|
|
{
|
|
INT iColumn, iColumns = m_pReportCtrl->m_arraySubItems.GetSize();
|
|
|
|
ResetContent();
|
|
|
|
for(iColumn=0;iColumn<iColumns;iColumn++)
|
|
{
|
|
if(!m_pReportCtrl->IsActiveColumn(iColumn) && Include(iColumn))
|
|
{
|
|
INT iItem = AddString(m_pReportCtrl->m_arraySubItems[iColumn].strText);
|
|
SetItemData(iItem, iColumn);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CReportColumnListCtrl::Include(INT iColumn)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportColumnListCtrl message handlers
|
|
|
|
void CReportColumnListCtrl::PreSubclassWindow()
|
|
{
|
|
CDragListBox::PreSubclassWindow();
|
|
|
|
SetItemHeight(0, GetItemHeight(0)+2);
|
|
}
|
|
|
|
void CReportColumnListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
|
{
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
|
|
|
CRect rcItem(lpDrawItemStruct->rcItem);
|
|
|
|
if(GetCount() > 0)
|
|
{
|
|
pDC->DrawFrameControl(rcItem, DFC_BUTTON, DFCS_BUTTONPUSH);
|
|
|
|
rcItem.DeflateRect(2, 2);
|
|
if(lpDrawItemStruct->itemState&ODS_SELECTED)
|
|
{
|
|
pDC->FillRect(rcItem, &CBrush(::GetSysColor(COLOR_3DSHADOW)));
|
|
pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
|
|
}
|
|
else
|
|
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
|
|
|
|
pDC->SetBkMode(TRANSPARENT);
|
|
|
|
pDC->DrawText(
|
|
m_pReportCtrl->m_arraySubItems[lpDrawItemStruct->itemData].strText,
|
|
-1,
|
|
rcItem,
|
|
DT_SINGLELINE|DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_END_ELLIPSIS|DT_LEFT);
|
|
}
|
|
else
|
|
pDC->FillSolidRect(rcItem, ::GetSysColor(COLOR_WINDOW));
|
|
}
|
|
|
|
BOOL CReportColumnListCtrl::BeginDrag(CPoint pt)
|
|
{
|
|
if(GetCount() <= 0)
|
|
return FALSE;
|
|
|
|
BOOL bAutoScroll = FALSE;
|
|
INT iItem = ItemFromPt(pt);
|
|
if(iItem >= 0)
|
|
{
|
|
GetClientRect(m_rcDragWnd);
|
|
m_rcDragWnd.bottom = m_rcDragWnd.top + GetItemHeight(0);
|
|
|
|
m_iColumn = GetItemData(iItem);
|
|
|
|
_tcscpy(m_szColumnText, m_pReportCtrl->m_arraySubItems[m_iColumn].strText);
|
|
|
|
m_hdiColumn.mask = HDI_WIDTH|HDI_TEXT|HDI_FORMAT;
|
|
m_hdiColumn.cxy = m_rcDragWnd.Width();
|
|
m_hdiColumn.pszText = m_szColumnText;
|
|
m_hdiColumn.cchTextMax = sizeof(m_szColumnText);
|
|
m_hdiColumn.fmt = HDF_STRING|HDF_LEFT;
|
|
|
|
m_pDragWnd = new CFHDragWnd;
|
|
if(m_pDragWnd)
|
|
m_pDragWnd->Create(m_rcDragWnd, &m_pReportCtrl->m_wndHeader, -2, &m_hdiColumn);
|
|
|
|
GetWindowRect(m_rcDropTarget1);
|
|
m_pReportCtrl->m_wndHeader.GetWindowRect(m_rcDropTarget2);
|
|
}
|
|
|
|
m_iDropIndex = -1;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
UINT CReportColumnListCtrl::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 CReportColumnListCtrl::CancelDrag(CPoint pt)
|
|
{
|
|
m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, FALSE, -1);
|
|
|
|
if(m_pDragWnd != NULL)
|
|
{
|
|
m_pDragWnd->DestroyWindow();
|
|
m_pDragWnd = NULL;
|
|
}
|
|
}
|
|
|
|
void CReportColumnListCtrl::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_iDropIndex >= 0)
|
|
m_pReportCtrl->ActivateColumn(m_iColumn, m_iDropIndex);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportEditCtrl
|
|
|
|
CReportEditCtrl::CReportEditCtrl(INT iItem, INT iSubItem)
|
|
{
|
|
m_bEndEdit = FALSE;
|
|
|
|
m_iItem = iItem;
|
|
m_iSubItem = iSubItem;
|
|
|
|
m_nLastKey = VK_RETURN;
|
|
}
|
|
|
|
CReportEditCtrl::~CReportEditCtrl()
|
|
{
|
|
}
|
|
|
|
void CReportEditCtrl::PostNcDestroy()
|
|
{
|
|
CEdit::PostNcDestroy();
|
|
delete this;
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CReportEditCtrl, CEdit)
|
|
//{{AFX_MSG_MAP(CReportEditCtrl)
|
|
ON_WM_KILLFOCUS()
|
|
ON_WM_GETDLGCODE()
|
|
ON_WM_CHAR()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportEditCtrl operations
|
|
|
|
void CReportEditCtrl::EndEdit()
|
|
{
|
|
CString str;
|
|
|
|
if(m_bEndEdit)
|
|
return;
|
|
|
|
m_bEndEdit = TRUE;
|
|
GetWindowText(str);
|
|
|
|
NMRVITEMEDIT 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 = (LPCTSTR)str;
|
|
|
|
CWnd* pWnd = GetOwner();
|
|
if(pWnd != NULL)
|
|
pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie);
|
|
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
m_bEndEdit = FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportEditCtrl message handlers
|
|
|
|
void CReportEditCtrl::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
CWnd::OnKillFocus(pNewWnd);
|
|
EndEdit();
|
|
}
|
|
|
|
UINT CReportEditCtrl::OnGetDlgCode()
|
|
{
|
|
return DLGC_WANTALLKEYS;
|
|
}
|
|
|
|
void CReportEditCtrl::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if(nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
|
|
{
|
|
m_nLastKey = nChar;
|
|
|
|
GetParent()->SetFocus();
|
|
return;
|
|
}
|
|
|
|
CEdit::OnChar(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
BOOL CReportEditCtrl::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if(pMsg->message == WM_SYSCHAR)
|
|
return TRUE;
|
|
|
|
return CEdit::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportComboCtrl
|
|
|
|
CReportComboCtrl::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_KILLFOCUS()
|
|
ON_WM_GETDLGCODE()
|
|
ON_CONTROL_REFLECT(CBN_KILLFOCUS, OnKillfocus)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportComboCtrl operations
|
|
|
|
void CReportComboCtrl::EndEdit()
|
|
{
|
|
CString str;
|
|
|
|
if(m_bEndEdit)
|
|
return;
|
|
|
|
m_bEndEdit = TRUE;
|
|
GetWindowText(str);
|
|
|
|
NMRVITEMEDIT 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 = (LPCTSTR)str;
|
|
|
|
CWnd* pWnd = GetOwner();
|
|
if(pWnd != NULL)
|
|
pWnd->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmrvie);
|
|
|
|
PostMessage(WM_CLOSE, 0, 0);
|
|
m_bEndEdit = FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportComboCtrl message handlers
|
|
|
|
void CReportComboCtrl::OnKillFocus(CWnd* pNewWnd)
|
|
{
|
|
CWnd::OnKillFocus(pNewWnd);
|
|
|
|
if(IsChild(pNewWnd))
|
|
return;
|
|
|
|
EndEdit();
|
|
}
|
|
|
|
UINT CReportComboCtrl::OnGetDlgCode()
|
|
{
|
|
return DLGC_WANTALLKEYS;
|
|
}
|
|
|
|
BOOL CReportComboCtrl::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if(pMsg->message == WM_CHAR &&
|
|
(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();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportTipCtrl
|
|
|
|
CReportTipCtrl::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_dwLastLButtonDown = ULONG_MAX;
|
|
m_dwDblClickMsecs = GetDoubleClickTime();
|
|
}
|
|
|
|
CReportTipCtrl::~CReportTipCtrl()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CReportTipCtrl, CWnd)
|
|
//{{AFX_MSG_MAP(CReportTipCtrl)
|
|
ON_WM_MOUSEMOVE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CReportTipCtrl message handlers
|
|
|
|
BOOL CReportTipCtrl::Create(CReportCtrl* pReportCtrl)
|
|
{
|
|
ASSERT_VALID(pReportCtrl);
|
|
|
|
DWORD dwStyle = WS_BORDER|WS_POPUP;
|
|
DWORD dwExStyle = WS_EX_TOOLWINDOW|WS_EX_TOPMOST;
|
|
m_pReportCtrl = pReportCtrl;
|
|
|
|
return CreateEx(dwExStyle, REPORTTIPCTRL_CLASSNAME, NULL, dwStyle,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
NULL, NULL, NULL );
|
|
}
|
|
|
|
BOOL CReportTipCtrl::Show(CRect rectText, LPCTSTR lpszText, CFont* pFont)
|
|
{
|
|
ASSERT(::IsWindow(GetSafeHwnd()));
|
|
|
|
if(rectText.IsRectEmpty())
|
|
return FALSE;
|
|
|
|
if(IsWindowVisible())
|
|
return FALSE;
|
|
|
|
if(GetFocus() == NULL)
|
|
return FALSE;
|
|
|
|
m_rectText.top = -1;
|
|
m_rectText.left = -1;
|
|
m_rectText.right = rectText.Width()+1;
|
|
m_rectText.bottom = rectText.Height();
|
|
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 + 2*m_pReportCtrl->m_iSpacing;
|
|
|
|
BOOL bResult = FALSE;
|
|
if(rectDisplay.right > rectText.right)
|
|
{
|
|
SetWindowPos(
|
|
&wndTop,
|
|
rectDisplay.left, rectDisplay.top,
|
|
rectDisplay.Width(), rectDisplay.Height(),
|
|
SWP_SHOWWINDOW|SWP_NOACTIVATE
|
|
);
|
|
|
|
dc.SetBkMode(TRANSPARENT);
|
|
dc.TextOut(m_pReportCtrl->m_iSpacing-1, 0, lpszText);
|
|
|
|
SetCapture();
|
|
|
|
bResult = TRUE;
|
|
}
|
|
|
|
dc.SelectObject(pFontDC);
|
|
return bResult;
|
|
}
|
|
|
|
void CReportTipCtrl::Hide()
|
|
{
|
|
if (!::IsWindow(GetSafeHwnd()))
|
|
return;
|
|
|
|
if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
|
|
ReleaseCapture();
|
|
|
|
ShowWindow(SW_HIDE);
|
|
}
|
|
|
|
void CReportTipCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if(!m_rectText.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-through
|
|
|
|
case 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);
|
|
}
|