You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7816 lines
179 KiB
C++

// XTPReportControl.cpp : implementation of the CXTPReportControl class.
//
// This file is a part of the XTREME REPORTCONTROL MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPSystemHelpers.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPPropExchange.h"
#include "Common/XTPToolTipContext.h"
#include "Common/XTPResourceManager.h"
#include "Common/XTPMarkupRender.h"
#include "Common/XTPCustomHeap.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPColorManager.h"
#include "XTPReportDefines.h"
#include "Behavior/XTPReportBehavior.h"
#include "XTPReportRows.h"
#include "XTPReportSelectedRows.h"
#include "XTPReportTip.h"
#include "XTPReportRecordItem.h"
#include "XTPReportRecord.h"
#include "XTPReportRecords.h"
#include "XTPReportHeader.h"
#include "XTPReportColumn.h"
#include "XTPReportColumns.h"
#include "XTPReportRow.h"
#include "XTPReportControl.h"
#include "XTPReportPaintManager.h"
#include "XTPReportNavigator.h"
#include "XTPReportSubListControl.h"
#include "XTPReportGroupRow.h"
#include "XTPReportInplaceControls.h"
#include "XTPReportRecordItemControls.h"
#include "XTPReportHyperlink.h"
#include "XTPReportRecordItemRange.h"
#include "XTPReportSection.h"
#include "XTPReportSections.h"
#include "XTPReportBorder.h"
#include "XTPReportThickness.h"
#include "XTPReportHitTestInfo.h"
#include "XTPReportADO.h"
#include "XTPReportDataManager.h"
#include "ItemTypes/XTPReportRecordItemPreview.h"
#include "ItemTypes/XTPReportRecordItemVariant.h"
#include "ItemTypes/XTPReportRecordItemIcon.h"
#include "ItemTypes/XTPReportRecordItemText.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define XTP_REPORT_HSCROLL_STEP 7
#define XTP_REPORT_VSCROLL_STEP 7
#define XTP_REPORT_AUTO_SCROLL_TIMER_ID 7
#define XTP_REPORT_AUTO_SCROLL_TIMER_RESOLUTION_MS 200
#define XTP_REPORT_DELAY_CLICK_TIMER_ID 10
#define XTP_REPORT_DELAYEDIT_CLICK_TIMER_ID 20
#define XTP_REPORT_CB_RECORDS_DATA_VER 1
#ifndef _UNICODE
#define XTP_CF_TEXT_T CF_TEXT
#else
#define XTP_CF_TEXT_T CF_UNICODETEXT
#endif
//////////////////////////////////////////////////////////////////////////
XTP_IMPLEMENT_HEAP_ALLOCATOR(CXTPReportDataAllocator, FALSE)
XTP_IMPLEMENT_HEAP_ALLOCATOR(CXTPReportRowAllocator, FALSE)
// to allocate in app default heap
XTP_IMPLEMENT_HEAP_ALLOCATOR(CXTPReportAllocatorDefault, FALSE)
class CXTPReportRow_Batch : public CXTPBatchAllocObjT<CXTPReportRow, CXTPReportRow_BatchData> {};
class CXTPReportGroupRow_Batch : public CXTPBatchAllocObjT<CXTPReportGroupRow, CXTPReportGroupRow_BatchData> {};
XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA(CXTPReportRow_BatchData, CXTPReportRow_Batch, FALSE)
XTP_IMPLEMENT_BATCH_ALLOC_OBJ_DATA(CXTPReportGroupRow_BatchData, CXTPReportGroupRow_Batch, FALSE)
//===========================================================================
HGLOBAL XTPAllocStrInGlobalMem(const CString& strText)
{
int nLen = (strText.GetLength() + 1) * sizeof(TCHAR);
UINT nAllocFlags = GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT;
HGLOBAL hText = ::GlobalAlloc(nAllocFlags, nLen);
if (hText != NULL)
{
LPTSTR lptstrCopy = (TCHAR*)GlobalLock(hText);
STRCPY_S(lptstrCopy, strText.GetLength() + 1, (LPCTSTR)strText);
GlobalUnlock(hText);
}
return hText;
}
//===========================================================================
BOOL CXTPReportControl::UseReportCustomHeap()
{
ASSERT(CXTPReportDataAllocator::ms_dwRefs == 0 || CXTPReportDataAllocator::ms_bUseCustomHeap);
ASSERT(CXTPReportRowAllocator::ms_dwRefs == 0 || CXTPReportRowAllocator::ms_bUseCustomHeap);
if (CXTPReportDataAllocator::ms_dwRefs == 0)
CXTPReportDataAllocator::ms_bUseCustomHeap = TRUE;
if (CXTPReportRowAllocator::ms_dwRefs == 0)
CXTPReportRowAllocator::ms_bUseCustomHeap = TRUE;
return CXTPReportDataAllocator::ms_bUseCustomHeap &&
CXTPReportRowAllocator::ms_bUseCustomHeap;
}
BOOL CXTPReportControl::UseRowBatchAllocation()
{
ASSERT(CXTPReportRow_BatchData::IsDataEmpty() || CXTPReportRow_BatchData::m_bBatchAllocationEnabled);
ASSERT(CXTPReportGroupRow_BatchData::IsDataEmpty() || CXTPReportGroupRow_BatchData::m_bBatchAllocationEnabled);
if (CXTPReportRow_BatchData::IsDataEmpty())
CXTPReportRow_BatchData::m_bBatchAllocationEnabled = TRUE;
if (CXTPReportGroupRow_BatchData::IsDataEmpty())
CXTPReportGroupRow_BatchData::m_bBatchAllocationEnabled = TRUE;
return CXTPReportRow_BatchData::m_bBatchAllocationEnabled &&
CXTPReportGroupRow_BatchData::m_bBatchAllocationEnabled;
}
void CXTPReportControl::FreeRowBatchExtraData()
{
CXTPReportRow_Batch::FreeExtraData();
CXTPReportGroupRow_Batch::FreeExtraData();
}
CArray<CXTPReportControlLocale::XTP_TIMESPEC, CXTPReportControlLocale::XTP_TIMESPEC&>
CXTPReportControlLocale::s_arMappedSpecs;
//////////////////////////////////////////////////////////////////////////
// CReportDropTarget
class CXTPReportControl::CReportDropTarget : public COleDropTarget
{
public:
virtual DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
{
CXTPReportControl* pReport = DYNAMIC_DOWNCAST(CXTPReportControl, pWnd);
if (!pReport)
return DROPEFFECT_NONE;
return pReport->OnDragOver(pDataObject, dwKeyState, point, 0);
}
virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
{
CXTPReportControl* pReport = DYNAMIC_DOWNCAST(CXTPReportControl, pWnd);
if (!pReport)
return DROPEFFECT_NONE;
return pReport->OnDragOver(pDataObject, dwKeyState, point, 2);
}
virtual void OnDragLeave(CWnd* pWnd)
{
CXTPReportControl* pReport = DYNAMIC_DOWNCAST(CXTPReportControl, pWnd);
if (pReport)
pReport->OnDragOver(NULL, 0, CPoint(-1, -1), 1);
}
virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point)
{
CXTPReportControl* pReport = DYNAMIC_DOWNCAST(CXTPReportControl, pWnd);
if (pReport)
return pReport->OnDrop(pDataObject, dropEffect, point);
return FALSE;
}
};
/////////////////////////////////////////////////////////////////////////////
void XTPStrSplit(LPCTSTR pcszString, LPCTSTR pcszSeparator, CStringArray& rarStrings)
{
rarStrings.RemoveAll();
int nSeparatorLen = (int)_tcslen(pcszSeparator);
CString strString(pcszString);
CString strItem;
int nIndex_start = 0;
// parse data
BOOL bBreak = FALSE;
do
{
int nIndex = strString.Find(pcszSeparator, nIndex_start);
if (nIndex >= 0)
{
strItem = strString.Mid(nIndex_start, nIndex - nIndex_start);
}
else
{
strItem = strString.Mid(nIndex_start);
bBreak = TRUE;
}
//---------------------------------------
rarStrings.Add(strItem);
nIndex_start = nIndex + nSeparatorLen;
}
while (!bBreak);
}
CString XTPStrMake(const CStringArray& arStrings, LPCTSTR pcszSeparator)
{
CString strString;
int nCount = (int)arStrings.GetSize();
for (int i = 0; i < nCount; i++)
{
if (i > 0)
strString += pcszSeparator;
strString += arStrings[i];
}
return strString;
}
// CXTPReportControl
IMPLEMENT_DYNCREATE(CXTPReportControl, CWnd)
BEGIN_MESSAGE_MAP(CXTPReportControl, CWnd)
//{{AFX_MSG_MAP(CXTPReportControl)
// Window
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_ENABLE()
ON_WM_TIMER()
ON_WM_NCHITTEST_EX()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
// Mouse
ON_WM_MOUSEMOVE()
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_CONTEXTMENU()
ON_WM_SETCURSOR()
// Key events
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_WM_SYSKEYDOWN()
ON_WM_SYSKEYUP()
// Scrolling
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_CAPTURECHANGED()
ON_WM_SYSCOLORCHANGE()
ON_WM_GETDLGCODE()
ON_WM_STYLECHANGED()
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
ON_MESSAGE(WM_GETOBJECT, OnGetObject)
ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE_VOID(XTP_WM_MARKUPREDRAW, RedrawControl)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CXTPReportControl::CXTPReportControl()
: m_bCreated (FALSE)
, m_bLockExpand(FALSE)
, m_bEditOnClick (TRUE)
, m_bEditOnDelayClick (FALSE)
, m_bEditOnDoubleClick(TRUE)
, m_bPinFooterRows (FALSE)
, m_bPinFooterRowsPrinted(TRUE)
, m_bDoubleBuffering (TRUE)
, m_nFixedColumnsCount(0)
, m_pSectionHeader(NULL)
, m_pSectionBody (NULL)
, m_pSectionFooter(NULL)
, m_pSectionScroll(NULL)
, m_dwLastMouseMessage(WM_NULL)
, m_scrollModeH(xtpReportScrollModeSmooth)
, m_scrollModeV(xtpReportScrollModeBlock)
, m_nScrollOffsetH(0)
, m_nScrollStepH(XTP_REPORT_HSCROLL_STEP)
, m_nScrollStepV(XTP_REPORT_VSCROLL_STEP)
, m_pMarkupContext(NULL)
{
RegisterWindowClass();
m_pBehavior = new CXTPReportBehavior(xtpReportBehaviorCodejockDefault);
m_pTip = new CXTPReportTip();
m_nLockUpdateCount = 0;
m_nRowsPerWheel = GetMouseScrollLines();
m_pSections = new CXTPReportSections(this);
m_pSectionHeader = m_pSections->GetAt(xtpReportSectionHeader);
m_pSectionBody = m_pSections->GetAt(xtpReportSectionBody);
m_pSectionFooter = m_pSections->GetAt(xtpReportSectionFooter);
m_pSectionScroll = m_pSectionBody; // Default scroll section
m_pSectionFooter->GetBorder()->GetBorderThickness()->SetTop(1);
m_pSectionHeader->SetHeightMode(xtpReportSectionHeightModeAuto);
m_pSectionBody ->SetHeightMode(xtpReportSectionHeightModeExpand);
m_pSectionFooter->SetHeightMode(xtpReportSectionHeightModeAuto);
m_pSectionHeader->SetDividerPosition(xtpReportSectionDividerPositionBottom);
m_pSectionFooter->SetDividerPosition(xtpReportSectionDividerPositionTop);
m_pSectionHeader->SetDividerStyle(xtpReportFixedRowsDividerThin);
m_pSectionFooter->SetDividerStyle(xtpReportFixedRowsDividerThin);
// Allow group
m_pSectionHeader->AllowGroup(FALSE);
m_pSectionBody ->AllowGroup(TRUE);
m_pSectionFooter->AllowGroup(FALSE);
// Allow sort
m_pSectionHeader->AllowSort(FALSE);
m_pSectionBody ->AllowSort(TRUE);
m_pSectionFooter->AllowSort(FALSE);
// Allow filter
m_pSectionHeader->AllowFilter(FALSE);
m_pSectionBody ->AllowFilter(TRUE);
m_pSectionFooter->AllowFilter(FALSE);
m_pSectionBody->SetVisible(TRUE);
m_pRows = m_pSectionBody->GetRows();
m_pColumns = new CXTPReportColumns(this);
m_pReportHeader = new CXTPReportHeader(this, m_pColumns);
//ICON_VIEW_MODE RELATED <<
m_bIconView = FALSE;
m_iIconWidth = 0;
m_iIconHeight = 0;
m_iIconWidthSpacing = 0;
m_iIconHeightSpacing = 0;
m_iIconViewColumn = -1;
m_iIconViewRowsPerLine = 0;
m_bUseIconColumnForNum = FALSE;
m_iColumnForNumPrev = -1;
m_iColumnForNum = -1;
m_bPrevFocusSubItems = FALSE;
m_bPrevHeaderAutoSize = FALSE;
m_iIconPropNum = 0;
m_iIconNum = 0;
m_pPrevVisible = NULL;
m_pPrevGroupsOrder = NULL;
m_nPrevTreeIndent = 0;
m_bIconColumnIndexNotValid = FALSE;
m_bPrevHeaderRows = FALSE;
m_bPrevFooterRows = FALSE;
m_bPrevHeaderShow = FALSE;
m_bPrevFooterShow = FALSE;
m_bRClickDrag = FALSE;
//ICON_VIEW_MODE RELATED >>
m_pPaintManager = new CXTPReportPaintManager();
m_pPaintManager->SetReportControl(this);
m_pNavigatorReport = new CXTPReportNavigator(this);
m_pNavigatorIcon = new CXTPReportIconNavigator(this);
m_pNavigator = m_pNavigatorReport;
//m_nSelectionLastBlockStartRow = -1;
m_bKeepSelectionAfterSort = TRUE;
m_bUnrestrictedDragDrop = FALSE;
m_bFreeHeightMode = FALSE;
m_nDefaultRowFreeHeight = 20;
m_uiDelayEditTimer = NULL;
m_uiDelayEditMaxTime = GetDoubleClickTime() + 50;
m_iLastRqstEditRow = -1;
m_iLastRqstEditCol = -1;
m_uRqstEditTimer = 0;
m_mouseMode = xtpReportMouseNothing;
m_bWasShiftKey = FALSE;
m_bSortedDragDrop = FALSE;
m_bNoNeedSortedDragDrop = TRUE;
m_bInternalMove = FALSE;
m_bTrapTabKey = FALSE;
m_pSelectedRows = new CXTPReportSelectedRows(this);
m_bStrictBestFit = FALSE;
m_bChanged = TRUE;
m_bRefreshIndexes = FALSE;
m_bGroupByEnabled = FALSE;
m_bHeaderVisible = TRUE;
m_bFooterVisible = FALSE;
m_bBlockSelection = TRUE;
m_bMultiSelectionMode = FALSE;
m_bShowTooltips = TRUE;
m_bSkipGroupsFocus = TRUE;
m_bSelectionExcludeGroupRows = TRUE;
m_pImageManager = new CXTPImageManager();
m_pFocusedColumn = NULL;
m_pActiveItem = NULL;
m_bEnsureFocusedRowVisible = TRUE;
m_bFocusSubItems = FALSE;
m_bPreviewAllowEdit = FALSE;
m_bInitialSelectionEnable = TRUE;
m_bRowFocusVisible = TRUE;
m_bAutoCheckItems = TRUE;
m_bShowIconWhenEditing = TRUE;
m_pInplaceEdit = new CXTPReportInplaceEdit();
m_pInplaceButtons = new CXTPReportInplaceButtons();
m_pInplaceList = new CXTPReportInplaceList();
m_rcGroupByArea.SetRectEmpty();
m_rcHeaderArea.SetRectEmpty();
m_rcFooterArea.SetRectEmpty();
m_bMovePivot = FALSE;
m_bForcePagination = FALSE;
m_nDisableReorderColumnsCount = 0;
m_pHotRow = NULL;
m_pHotExpandButtonRow = NULL;
m_pHotHyperlink = NULL;
m_nOLEDropMode = 0;
m_nOLEDropAbove = FALSE;
m_bVScrollBarVisible = FALSE;
m_bHScrollBarVisible = FALSE;
m_bPrepareDrag = FALSE;
m_ptDrag = CPoint(0, 0);
m_pToolTipContext = new CXTPToolTipContext;
m_pCachedToolTipInfo = new XTP_NM_REPORTTOOLTIPINFO;
m_cfReport = NULL;
m_pDropTarget = new CReportDropTarget;
m_bDragMode = FALSE;
m_bInternalDrag = FALSE;
m_dwDragDropFlags = 0;
m_dwDropMarkerFlags = xtpReportDropBetween; // Default to how it has always been.
m_pSelectedRowsBeforeDrag = NULL;
m_nDropPos = -1;
m_pDropRecords = NULL;
m_bFastDeselectMode = FALSE;
m_bAdjustLayoutRunning = FALSE;
m_uAutoScrollTimerID = 0;
m_bSortRecordChilds = FALSE;
m_pRowsCompareFunc = NULL;
m_ptrVirtualEditingRow = NULL;
m_bFilterHiddenColumns = FALSE;
m_nRecordsTreeFilterMode = xtpReportFilterTreeSimple;
m_hbmpWatermark = NULL;
m_WatermarkTransparency = 100;
m_WatermarkAlignment = xtpReportWatermarkStretch;
m_nEnsureVisibleRowIdx = m_nEnsureVisibleColumnIdx = -1;
m_pDataManager = NULL;
m_nAutoVScrollTimerResolution = XTP_REPORT_AUTO_SCROLL_TIMER_RESOLUTION_MS;
m_bMarkupEnabled = FALSE;
m_bDesktopTrackerMode = FALSE;
m_bStrictFiltering = FALSE;
m_pTip->m_pReportControl = this;
EnableAutomation();
}
CXTPReportControl::~CXTPReportControl()
{
if (::IsWindow(m_pTip->GetSafeHwnd()))
m_pTip->DestroyWindow();
EditItem(NULL);
ResetContent(FALSE);
EnableMarkup(FALSE);
m_UaSelected.RemoveAll();
CMDTARGET_RELEASE(m_pSelectedRows);
CMDTARGET_RELEASE(m_pColumns);
CMDTARGET_RELEASE(m_pPaintManager);
CMDTARGET_RELEASE(m_pNavigatorReport);
CMDTARGET_RELEASE(m_pNavigatorIcon);
CMDTARGET_RELEASE(m_pImageManager);
CMDTARGET_RELEASE(m_pReportHeader);
CMDTARGET_RELEASE(m_pToolTipContext);
SAFE_DELETE(m_pCachedToolTipInfo);
SAFE_DELETE(m_pInplaceEdit);
SAFE_DELETE(m_pInplaceButtons);
SAFE_DELETE(m_pInplaceList);
CMDTARGET_RELEASE(m_pDropTarget);
CMDTARGET_RELEASE(m_pSelectedRowsBeforeDrag);
CMDTARGET_RELEASE(m_ptrVirtualEditingRow);
CMDTARGET_RELEASE(m_pDropRecords);
if (m_hbmpWatermark)
::DeleteObject(m_hbmpWatermark);
//ICON_VIEW_MODE RELATED <<
CMDTARGET_RELEASE(m_pPrevVisible);
CMDTARGET_RELEASE(m_pPrevGroupsOrder);
//ICON_VIEW_MODE RELATED >>
CMDTARGET_RELEASE(m_pDataManager);
SAFE_DELETE(m_pBehavior);
SAFE_DELETE(m_pTip);
SAFE_DELETE(m_pSections);
}
BOOL CXTPReportControl::RegisterWindowClass(HINSTANCE hInstance)
{
return XTPDrawHelpers()->RegisterWndClass(hInstance, XTPREPORTCTRL_CLASSNAME, CS_DBLCLKS);
}
void CXTPReportControl::ResetContent(BOOL bUpdateControl)
{
EditItem(NULL);
m_pSectionBody->ResetContent();
if (m_pSelectedRows)
m_pSelectedRows->Clear();
if (bUpdateControl)
{
AdjustIndentation();
AdjustScrollBars();
RedrawControl();
}
}
void CXTPReportControl::SetReportHeader(CXTPReportHeader *pReportHeader)
{
if (NULL != pReportHeader)
{
m_pReportHeader->InternalRelease();
m_pReportHeader = pReportHeader;
AdjustLayout();
}
}
void CXTPReportControl::SetImageManager(CXTPImageManager *pImageManager)
{
if (NULL != pImageManager)
{
m_pImageManager->InternalRelease();
m_pImageManager = pImageManager;
}
}
void CXTPReportControl::SetImageList(CImageList *pImageList)
{
for (int i=0; i<pImageList->GetImageCount(); i++)
{
HICON hIcon = pImageList->ExtractIcon(i);
m_pImageManager->SetIcon(hIcon, i);
DestroyIcon(hIcon);
}
}
void CXTPReportControl::SetPaintManager(CXTPReportPaintManager *pPaintManager)
{
if (NULL != pPaintManager)
{
m_pPaintManager->SetReportControl(NULL);
m_pPaintManager->InternalRelease();
m_pPaintManager = pPaintManager;
m_pPaintManager->SetReportControl(this);
AdjustLayout();
AdjustScrollBars();
}
}
int CXTPReportControl::GetIndent(int nLevel) const
{
return max(0, (nLevel - 1) * m_pPaintManager->m_nTreeIndent);
}
void CXTPReportControl::SetTreeIndent(int nIndent)
{
m_pPaintManager->m_nTreeIndent = nIndent;
}
void CXTPReportControl::BeginUpdate()
{
m_nLockUpdateCount++;
m_bRefreshIndexes = FALSE;
}
void CXTPReportControl::EndUpdate()
{
SetChanged();
m_nLockUpdateCount--;
if (m_nLockUpdateCount == 0)
{
if (m_bRefreshIndexes)
{
m_bRefreshIndexes = FALSE;
_RefreshIndexes();
}
RedrawControl();
}
}
void CXTPReportControl::RedrawControl()
{
SetChanged();
if (m_nLockUpdateCount == 0 && GetSafeHwnd())
Invalidate(FALSE);
}
void CXTPReportControl::UpdateSubList()
{
CXTPReportHeader* pHeader = GetReportHeader();
if (pHeader && pHeader->m_pSubList &&
(pHeader->m_pSubList->GetReportCtrl() == this))
{
pHeader->m_pSubList->UpdateList();
}
}
void CXTPReportControl::_DoCollapse(CXTPReportRow* pRow)
{
ASSERT(NULL != pRow);
int nCount = 0;
if (NULL != pRow && NULL != pRow->m_pSection)
{
pRow->m_pSection->_DoCollapse(pRow);
}
if (nCount > 0)
{
m_pSelectedRows->_OnCollapsed(pRow->GetIndex(), nCount);
}
AdjustLayout();
RedrawControl();
}
void CXTPReportControl::_DoExpand(CXTPReportRow* pRow)
{
int nIndex = pRow->m_nIndex;
int nCount = _DoExpand(nIndex, pRow);
if (nCount > 0)
{
m_pSelectedRows->_OnExpanded(nIndex, nCount);
CXTPReportRows *pRows = pRow->GetSection()->GetRows();
if (pRows->m_nFocusedRow > nIndex)
{
pRows->m_nFocusedRow += nCount;
}
}
}
int CXTPReportControl::_DoExpand(int nIndex, CXTPReportRow *pRow)
{
ASSERT(NULL != pRow);
int nExpand = 0;
if (NULL != pRow && NULL != pRow->m_pSection)
{
nExpand = pRow->m_pSection->_DoExpand(nIndex, pRow);
}
AdjustLayout();
RedrawControl();
return nExpand;
}
void CXTPReportControl::RefreshIndexes(BOOL bAdjustLayout, BOOL bReverseOrder)
{
m_pSections->RefreshIndexes(bAdjustLayout, bReverseOrder);
}
void CXTPReportControl::_RefreshIndexes(BOOL bAdjustLayout, BOOL bReverseOrder)
{
if (m_nLockUpdateCount != 0)
{
m_bRefreshIndexes = TRUE;
return;
}
RefreshIndexes(bAdjustLayout, bReverseOrder);
}
CLIPFORMAT CXTPReportControl::EnableDragDrop(LPCTSTR lpszClipboardFormat, DWORD dwFlags, DWORD dwDropMarkerFlags)
{
if (m_dwDragDropFlags != 0)
{
if (m_pDropTarget)
m_pDropTarget->Revoke();
}
m_dwDragDropFlags = dwFlags;
m_dwDropMarkerFlags = dwDropMarkerFlags;
m_cfReport = NULL;
if (m_dwDragDropFlags != 0)
{
if (m_pDropTarget)
{
m_cfReport = (CLIPFORMAT)::RegisterClipboardFormat(lpszClipboardFormat);
m_pDropTarget->Revoke(); // to ensure kill previous registration.
m_pDropTarget->Register(this);
}
}
return m_cfReport;
}
BOOL CXTPReportControl::ApplyFilter(CXTPReportRecord *pRecord, CString strFilterText, BOOL bIncludePreview)
{
// not filtered if filter text is empty
if (!pRecord)
return FALSE;
if (pRecord->IsFiltered())
return TRUE;
if (strFilterText.IsEmpty())
return FALSE;
BOOL bFilterSimple = GetRecordsTreeFilterMode() == xtpReportFilterTreeSimple;
if (!bFilterSimple && pRecord->HasChildren() && pRecord->GetChilds())
{
CXTPReportRecords* pChildren = pRecord->GetChilds();
int nCount = pChildren->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPReportRecord* pR = pChildren->GetAt(i);
if (!ApplyFilter(pR, strFilterText, bIncludePreview))
return FALSE;
}
}
if (GetRecordsTreeFilterMode() == xtpReportFilterTreeByEndChildrenOnly
&& pRecord->HasChildren())
return TRUE;
return _ApplyFilter(pRecord, strFilterText, bIncludePreview);
}
BOOL CXTPReportControl::_ApplyFilter(CXTPReportRecord* pRecord, CString strFilterText, BOOL bIncludePreview)
{
// not filtered if filter text is empty
if (!pRecord)
return FALSE;
if (pRecord->IsFiltered())
return TRUE;
if (strFilterText.IsEmpty())
return FALSE;
BOOL bFilterHidden = IsFilterHiddenColumns();
// process each token in the filter string
TCHAR szSeps[] = _T(" \t");
TCHAR szSepsStrict[] = _T("\t");
TCHAR *szToken, *lpszContext = 0;
//int nCurPos = 0;
if (m_bStrictFiltering)
szToken = STRTOK_S(strFilterText.GetBuffer(strFilterText.GetLength()), szSepsStrict, &lpszContext);
else
szToken = STRTOK_S(strFilterText.GetBuffer(strFilterText.GetLength()), szSeps, &lpszContext);
while (szToken != NULL)
{
CString strToken(szToken);
strToken.MakeLower();
BOOL bTokenFound = FALSE;
// enumerate all visible columns
int nColumnsCount = m_pColumns->GetCount();
for (int nCol = 0; nCol < nColumnsCount; nCol++)
{
CXTPReportColumn* pCol = m_pColumns->GetAt(nCol);
if (pCol && (pCol->IsVisible() || bFilterHidden) && pCol->IsFilterable())
{
CXTPReportRecordItem* pItem = pRecord->GetItem(pCol);
if (pItem)
{
CString sItemText = pItem->GetCaption(pCol);
// case-insensitive search
sItemText.MakeLower();
bTokenFound = sItemText.Find(strToken) != -1;
if (bTokenFound)
{
// stop search current token - passed
break;
}
}
}
}
// also check preview text
if (bIncludePreview && !bTokenFound && pRecord->GetItemPreview())
{
CString sItemText = pRecord->GetItemPreview()->GetCaption(NULL);
// case-insensitive search
sItemText.MakeLower();
bTokenFound = sItemText.Find(strToken) != -1;
}
// Token not found - filter this record
if (!bTokenFound)
{
return TRUE;
}
// get next token
if (m_bStrictFiltering)
szToken = STRTOK_S(NULL, szSepsStrict, &lpszContext);
else
szToken = STRTOK_S(NULL, szSeps, &lpszContext);
}
return FALSE;
}
void CXTPReportControl::Populate()
{
EditItem(NULL);
BeginUpdate();
m_pSelectedRows->Clear();
m_pSectionHeader->Populate(FALSE);
m_pSectionBody ->Populate(FALSE);
m_pSectionFooter->Populate(FALSE);
AdjustIndentation();
AdjustLayout();
AdjustScrollBars();
UpdateSubList();
if (GetRows()->m_nFocusedRow == -1)
{
SetTopRow(0);
if (GetRows()->GetCount() > 0)
{
GetRows()->m_nFocusedRow = 0;
if (IsSelectionEnabled() && IsInitialSelectionEnabled())
{
CXTPReportRow* pFirst = m_pRows->GetAt(0);
if (pFirst)
{
if (!IsSkipGroupsFocusEnabled() || !pFirst->IsGroupRow())
m_pSelectedRows->Select(pFirst);
else
{
while (pFirst->IsGroupRow())
{
if (pFirst->HasChildren())
pFirst = pFirst->GetChilds()->GetAt(0);
}
m_pSelectedRows->Select(pFirst);
}
}
}
}
}
else
{
EnsureVisible(GetFocusedRow());
}
if (m_pFocusedColumn == NULL && m_bFocusSubItems)
{
m_pFocusedColumn = m_pColumns->GetFirstVisibleColumn();
//------------ Forum proposal 2009 June 19 ---------------------------- <<
if (GetRows())
{
CXTPReportRow* pRow = GetRows()->GetAt(GetTopRowIndex());
if (pRow)
m_pFocusedColumn = GetNextFocusableColumn(pRow, 0, 1);
}
//------------ Forum proposal 2009 June 19 ---------------------------- >>
}
EndUpdate();
if (GetBehavior()->Notifications->Populate->bSelectionChanged)
{
if (m_pSelectedRows->IsChanged())
{
OnSelectionChanged();
m_pSelectedRows->SetChanged(FALSE);
}
}
}
void CXTPReportControl::AdjustIndentation()
{
GetReportHeader()->m_nIndentLevel = m_pColumns->GetGroupsOrder()->GetCount();
}
CXTPReportColumn* CXTPReportControl::AddColumn(CXTPReportColumn* pColumn)
{
ASSERT(pColumn);
m_pColumns->Add(pColumn);
return pColumn;
}
void CXTPReportControl::DrawNoItems(CDC* pDC, const CRect& rcClient)
{
pDC->SetTextColor(GetPaintManager()->m_clrWindowText);
CString strNoItems = GetPaintManager()->m_strNoItems;
if (!strNoItems.IsEmpty())
{
CRect rcText(rcClient);
rcText.DeflateRect(5, 5, 5, 5);
CXTPFontDC font(pDC, &GetPaintManager()->m_fontText);
UINT uFlags = DT_CENTER | DT_TOP | DT_NOPREFIX | DT_WORDBREAK |
DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | DT_EDITCONTROL;
XTPMarkupDrawText(GetMarkupContext(), pDC->GetSafeHdc(), strNoItems, rcText, uFlags);
}
}
int CXTPReportControl::DrawRows(CDC *pDC, CRect &rcClient, int y, CXTPReportRows *pRows, int nTopRow, int nColumnFrom, int nColumnTo, int *pnHeight)
{
const BOOL bIsPrinting = pDC->IsPrinting();
CXTPReportRecordMergeItems mergeItems;
CXTPReportScreenRows *pScreenRows = pRows->GetScreenRows();
pScreenRows->Clear();
pScreenRows->SetSize(0, 100);
CXTPReportHeader *pHeader = GetReportHeader();
CRgn rgnClip;
int nRow = nTopRow; // Row index
if (NULL != pHeader->GetNextVisibleColumn(-1, xtpReportColumnDirectionRight))
{
int nRowCount = pRows->GetCount(); // Number of rows in the rows collection
int nRowWidth = 0;
int nRowHeight = 0;
if (bIsPrinting)
{
nRowWidth = rcClient.Width();
}
else
{
nRowWidth = pHeader->GetWidth();
}
//////////////////////////////////////////////////////////////////////////
// Draw non-merged items
//////////////////////////////////////////////////////////////////////////
#if 1
int nFreezeRight = 0;
if (GetFreezeColumnsCount() > 0)
{
CXTPReportColumn *pColumn = GetColumns()->GetAt(GetFreezeColumnsCount()-1);
if (NULL != pColumn)
{
nFreezeRight = pColumn->GetRect().right;
}
}
for (nRow=nTopRow; nRow<nRowCount; nRow++)
{
CXTPReportRow *pRow = pRows->GetAt(nRow);
ASSERT(pRow);
if (NULL != pRow)
{
nRowHeight = pRow->GetHeight(pDC, nRowWidth);
// Test if row is outside of client rectangle
if (bIsPrinting)
{
// Clipped rows are printed on the next page
if (y + nRowHeight > rcClient.bottom)
{
break;
}
}
else
{
// Clipped rows are drawn
if (y > rcClient.bottom)
{
break;
}
}
// Rectangles in Windows don't include the right and bottom edge.
CRect rcRow(rcClient.left, y, rcClient.left + nRowWidth, y + nRowHeight);
int nLeftOffset = 0;
if (!pDC->IsPrinting())
{
nLeftOffset = m_nScrollOffsetH;
}
// Draw row
pRow->Draw(pDC, rcRow, rcClient, nLeftOffset, mergeItems, nColumnFrom, nColumnTo);
y += nRowHeight;
CXTPReportRow *pScreenRow = NULL;
if (IsVirtualMode())
{
pScreenRow = CreateRow();
pScreenRow->InitRow(pRow);
}
else
{
pScreenRow = pRow;
pScreenRow->InternalAddRef();
}
pScreenRows->InsertAt(pScreenRows->GetSize(), pScreenRow);
}
} // for (nRow)
#endif
//////////////////////////////////////////////////////////////////////////
// Draw merged items
//////////////////////////////////////////////////////////////////////////
#if 1
VERIFY(rgnClip.CreateRectRgn(nFreezeRight, rcClient.top, rcClient.right, rcClient.bottom));
if (!pDC->IsPrinting())
{
pDC->SelectClipRgn(&rgnClip, RGN_COPY);
}
POSITION pos = mergeItems.GetStartPosition();
while (pos)
{
CXTPReportRecordItem *pItem;
CXTPReportRecordMergeItem mergeItem;
mergeItems.GetNextAssoc(pos, pItem, mergeItem);
CXTPReportRecordItemRange range;
CRect rcItem;
while (mergeItem.FindRange(range, rcItem))
{
//rcItem.left = GetColumns()->GetAt(range.m_nColumnFrom)->GetRect().left;
//rcItem.right = GetColumns()->GetAt(range.m_nColumnTo )->GetRect().right;
//rcItem.top = pRows->GetAt(range.m_nRecordFrom)->GetRect().top;
//rcItem.bottom = pRows->GetAt(range.m_nRecordTo )->GetRect().bottom;
CRect rcGrid(rcItem);
rcItem.DeflateRect(0,0,1,1);
XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
drawArgs.pDC = pDC;
drawArgs.pControl = this;
drawArgs.pColumn = GetColumns()->GetAt(range.m_nColumnFrom);
drawArgs.pRow = pRows->GetAt(range.m_nRecordFrom);
drawArgs.rcItem = rcItem;
drawArgs.nTextAlign = drawArgs.pColumn->GetAlignment();
drawArgs.pItem = pItem;
pItem->Draw(&drawArgs);
drawArgs.pRow->DrawItemGrid(pDC, drawArgs.pColumn, rcGrid);
}
}
if (!pDC->IsPrinting())
{
pDC->SelectClipRgn(NULL, RGN_COPY);
}
VERIFY(rgnClip.DeleteObject());
#endif
}
//////////////////////////////////////////////////////////////////////////
// Fill the rest of space with empty grid
//////////////////////////////////////////////////////////////////////////
if (GetPaintManager()->IsDrawGridForEmptySpace() && y < rcClient.bottom)
{
VERIFY(rgnClip.CreateRectRgn(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom));
if (!pDC->IsPrinting())
{
pDC->SelectClipRgn(&rgnClip, RGN_COPY);
}
CRect rcEmpty(rcClient);
rcEmpty.top = y;
DrawDefaultGrid(pDC, rcEmpty, GetPaintManager()->m_nRowHeight, m_nScrollOffsetH); //always use standard row height
if (!pDC->IsPrinting())
{
pDC->SelectClipRgn(NULL, RGN_COPY);
}
VERIFY(rgnClip.DeleteObject());
}
if (0 == pRows->GetCount())
{
DrawNoItems(pDC, rcClient);
}
if (NULL != pnHeight)
{
*pnHeight = y - rcClient.top;
}
return nRow;
}
void CXTPReportControl::DrawIconView(CDC *pDC, CRect &rcClient)
{
CXTPReportRecordMergeItems mergeItems;
int nHeaderWidth = GetReportHeader()->GetWidth();
int nRowCount = m_pRows->GetCount();
int y = rcClient.top;
m_iIconViewRowsPerLine = GetNumRowsOnLine(nHeaderWidth);
int x = rcClient.left;
int iLastMainRow = m_pSectionBody->GetScrollIndexV();
while(iLastMainRow % m_iIconViewRowsPerLine)
{
iLastMainRow++;
}
for (int i = iLastMainRow; i < nRowCount; i++)
{
CXTPReportRow* pRow = m_pRows->GetAt(i);
ASSERT(pRow);
if (!pRow)
continue;
if (y > rcClient.bottom)
break;
if (pRow->GetIndex() % m_iIconViewRowsPerLine)
{
x += m_iIconWidthSpacing;
CRect rcRow(x, y, x + m_iIconWidthSpacing,
y + m_iIconHeightSpacing);
pRow->Draw(pDC, rcRow, GetReportRectangle(), 0, mergeItems, 0, GetColumns()->GetCount());
}
else
{
x = rcClient.left;
if (iLastMainRow != pRow->GetIndex())
{
y += m_iIconHeightSpacing;
iLastMainRow = pRow->GetIndex();
}
CRect rcRow(x, y, x + m_iIconWidthSpacing,
y + m_iIconHeightSpacing);
pRow->Draw(pDC, rcRow, GetReportRectangle(), 0, mergeItems, 0, GetColumns()->GetCount());
}
CXTPReportRow* pScreenRow = NULL;
if (IsVirtualMode())
{
pScreenRow = CreateRow();
pScreenRow->InitRow(pRow);
pScreenRow->SetExpanded(pRow->IsExpanded());
pScreenRow->m_rcCollapse = pRow->m_rcCollapse;
}
else
{
pScreenRow = pRow;
pScreenRow->InternalAddRef();
}
CXTPReportScreenRows *pScreenRows = GetRows()->GetScreenRows();
pScreenRows->InsertAt(pScreenRows->GetSize(), pScreenRow);
}
}
void CXTPReportControl::OnSelectionChanged()
{
SetLastRqstEdit(-1, -1);
//m_iLastRqstEditCol = -1;
//m_iLastRqstEditRow = -1;
SendNotifyMessage(XTP_NM_REPORT_SELCHANGED);
if (m_pSelectedRows)
m_pSelectedRows->SetChanged(FALSE);
}
BOOL CXTPReportControl::OnFocusChanging(CXTPReportRow* pNewRow, CXTPReportColumn* pNewCol)
{
XTP_NM_REPORTREQUESTEDIT nm;
::ZeroMemory(&nm, sizeof(nm));
nm.bCancel = FALSE;
nm.pRow = pNewRow ? pNewRow : GetFocusedRow();
nm.pColumn = pNewCol ? pNewCol : GetFocusedColumn();
nm.pItem = nm.pRow && nm.pColumn ? (nm.pRow->GetRecord() ? nm.pRow->GetRecord()->GetItem(nm.pColumn) : NULL) : NULL;
SendNotifyMessage(XTP_NM_REPORT_FOCUS_CHANGING, (NMHDR*)&nm);
return !nm.bCancel;
}
void CXTPReportControl::GetItemMetrics(
XTP_REPORTRECORDITEM_DRAWARGS *pDrawArgs,
XTP_REPORTRECORDITEM_METRICS *pMetrics)
{
XTP_NM_REPORTITEMMETRICS nmData;
nmData.pDrawArgs = pDrawArgs;
nmData.pItemMetrics = pMetrics;
SendNotifyMessage(XTP_NM_REPORT_GETITEMMETRICS, (NMHDR*) &nmData);
}
BOOL CXTPReportControl::SetFocusedColumn(CXTPReportColumn* pColumn)
{
if (m_pFocusedColumn != pColumn)
{
if (m_bFocusSubItems && pColumn)
{
if (!OnFocusChanging(NULL, pColumn))
return FALSE;
}
m_pFocusedColumn = pColumn;
if (m_pFocusedColumn && m_bFocusSubItems)
{
CRect rc(m_pFocusedColumn->GetRect());
if (rc.right >= m_pSectionBody->GetRect().Width())
{
SetScrollOffsetH(m_nScrollOffsetH + min(rc.left, rc.right - m_pSectionBody->m_rcSection.Width()));
}
else
{
int nFreezeColumnWidth = 0;
int nFreezeColumnsCount = GetFreezeColumnsCount();
if (nFreezeColumnsCount > 0)
{
for (int i = 0; (i < m_pColumns->GetCount()) && (nFreezeColumnsCount > 0); i++)
{
CXTPReportColumn* pColumnCheck = m_pColumns->GetAt(i);
if (pColumnCheck == m_pFocusedColumn)
{
nFreezeColumnWidth = 0;
break;
}
if (pColumnCheck && pColumnCheck->IsVisible())
{
nFreezeColumnsCount--;
nFreezeColumnWidth = pColumnCheck->GetRect().right;
}
}
}
if (rc.left - nFreezeColumnWidth <= 0 && m_nScrollOffsetH != 0)
{
SetScrollOffsetH(m_nScrollOffsetH + rc.left - nFreezeColumnWidth);
}
}
}
if (m_bFocusSubItems)
OnSelectionChanged();
}
return TRUE;
}
BOOL CXTPReportControl::SetFocusedRow(CXTPReportRow* pRow, BOOL bShiftKey, BOOL bControlKey)
{
return SetFocusedRow(TRUE, pRow, bShiftKey, bControlKey);
}
BOOL CXTPReportControl::SetFocusedRow(CXTPReportRow* pRow, BOOL bControlKey)
{
return SetFocusedRow(TRUE, pRow, FALSE, bControlKey);
}
int CXTPReportControl::_GetFocusedRowType() const
{
int nFocusedRowType = -1;
if (GetRows()->GetFocusedRowIndex() != -1)
{
nFocusedRowType = xtpRowTypeBody;
}
if (GetHeaderRows()->GetFocusedRowIndex() != -1)
{
nFocusedRowType = xtpRowTypeHeader;
}
if (GetFooterRows()->GetFocusedRowIndex() != -1)
{
nFocusedRowType = xtpRowTypeFooter;
}
return nFocusedRowType;
}
int CXTPReportControl::_GetFocusedRowIndex() const
{
int nFocusedRowIndex = -1;
if (GetRows()->GetFocusedRowIndex() != -1)
{
nFocusedRowIndex = GetRows()->GetFocusedRowIndex();
}
if (GetHeaderRows()->GetFocusedRowIndex() != -1)
{
nFocusedRowIndex = GetHeaderRows()->GetFocusedRowIndex();
}
if (GetFooterRows()->GetFocusedRowIndex() != -1)
{
nFocusedRowIndex = GetFooterRows()->GetFocusedRowIndex();
}
return nFocusedRowIndex;
}
BOOL CXTPReportControl::_SetFocusedRow(CXTPReportRow *pRow)
{
//////////////////////////////////////////////////////////////////////////
// Current focused row
//////////////////////////////////////////////////////////////////////////
int nFocusedRowType = _GetFocusedRowType();
int nFocusedRowIndex = _GetFocusedRowIndex();
//////////////////////////////////////////////////////////////////////////
// New focused row
//////////////////////////////////////////////////////////////////////////
int nRowType = -1;
int nRowIndex = -1;
if (NULL != pRow)
{
nRowType = pRow->GetType();
nRowIndex = pRow->GetIndex();
}
//////////////////////////////////////////////////////////////////////////
// Notify OnFocusChanging
//////////////////////////////////////////////////////////////////////////
BOOL bApply = TRUE;
if (nFocusedRowType != nRowType ||
nFocusedRowIndex != nRowIndex)
{
if (NULL != pRow)
{
pRow->InternalAddRef();
bApply = OnFocusChanging(pRow, NULL);
if (1 == pRow->m_dwRef)
{
// Removed
bApply = FALSE;
}
pRow->InternalRelease();
}
}
//////////////////////////////////////////////////////////////////////////
// Set new focused row
//////////////////////////////////////////////////////////////////////////
GetRows()->SetFocusedRowIndex(-1);
GetFooterRows()->SetFocusedRowIndex(-1);
GetHeaderRows()->SetFocusedRowIndex(-1);
if (NULL != pRow && bApply)
{
switch (pRow->GetType())
{
case xtpRowTypeBody:
GetRows()->SetFocusedRowIndex(pRow->GetIndex());
break;
case xtpRowTypeHeader:
GetHeaderRows()->SetFocusedRowIndex(pRow->GetIndex());
break;
case xtpRowTypeFooter:
GetFooterRows()->SetFocusedRowIndex(pRow->GetIndex());
break;
}
}
return bApply;
}
BOOL CXTPReportControl::_SetSelectedRow(CXTPReportRow *pRow, int nFocusedRowIndex, BOOL bShiftKey, BOOL bControlKey)
{
BOOL bEnableSelection = FALSE;
if (NULL != pRow)
{
bEnableSelection = pRow->GetSection()->IsSelectionEnabled();
}
if (bEnableSelection)
{
if (m_bBlockSelection)
{
if (bShiftKey && nFocusedRowIndex != -1)
{
int nSelRow = pRow->GetIndex();
m_pSelectedRows->SelectBlock(nFocusedRowIndex, nSelRow, bControlKey);
}
else if (!bControlKey)
{
m_pSelectedRows->Select(pRow);
}
}
else
{
m_pSelectedRows->Select(pRow);
}
}
return TRUE;
}
BOOL CXTPReportControl::SetFocusedRow(BOOL bEnsureVisible, CXTPReportRow *pRow, BOOL bShiftKey, BOOL bControlKey)
{
int nFocusedRowIndex = _GetFocusedRowIndex(); // Current focused row
EditItem(NULL);
BeginUpdate();
_SetFocusedRow(pRow); // Null pointer clears focus
_SetSelectedRow(pRow, nFocusedRowIndex, bShiftKey, bControlKey); // Null pointer clears selection
if (bEnsureVisible && (NULL != pRow))
{
EnsureVisible(pRow); // Null pointer not allowed
}
EndUpdate();
if (m_pSelectedRows->IsChanged())
{
OnSelectionChanged();
}
return TRUE;
}
void CXTPReportControl::SetScrollOffsetH(int nOffset)
{
if (nOffset < 0)
{
nOffset = 0;
}
if (nOffset != m_nScrollOffsetH)
{
m_nScrollOffsetH = nOffset;
AdjustScrollBarH(TRUE, SIF_PAGE | SIF_POS); // Only update page and position
// Send notification
XTP_NM_REPORTSCROLL msg;
msg.nSection = m_pSectionScroll->GetIndex();
msg.nPosition = nOffset;
SendNotifyMessage(XTP_NM_REPORT_HSCROLL, &msg);
}
}
void CXTPReportControl::SetScrollOffsetV(int nOffset)
{
if (nOffset < 0)
{
nOffset = 0;
}
if (nOffset != m_pSectionScroll->GetScrollOffsetV())
{
m_pSectionScroll->SetScrollOffsetV(nOffset);
AdjustScrollBarV(TRUE, SIF_PAGE | SIF_POS); // Only update page and position
// Send notification
XTP_NM_REPORTSCROLL msg;
msg.nSection = m_pSectionScroll->GetIndex();
msg.nPosition = nOffset;
SendNotifyMessage(XTP_NM_REPORT_VSCROLL, &msg);
}
}
void CXTPReportControl::SetTopRow(int nIndex)
{
if (nIndex < 0)
{
nIndex = 0;
}
if (nIndex != GetTopRowIndex())
{
if (IsIconView())
{
// Must get first row on the same line.
while(nIndex % GetRowsPerLine())
{
nIndex--;
}
}
m_pSectionScroll->SetScrollIndexV(nIndex);
}
}
void CXTPReportControl::EnsureVisible(CXTPReportRow *pRow)
{
if (NULL != pRow)
{
if (NULL == GetSafeHwnd())
{
m_nEnsureVisibleRowIdx = pRow->GetIndex();
}
else
{
CXTPReportSection *pSection = pRow->GetSection();
ASSERT(NULL != pSection);
if (NULL != pSection)
{
if (pSection->GetRect().IsRectNull())
{
m_nEnsureVisibleRowIdx = pRow->GetIndex();
}
else
{
CClientDC dc(this);
pSection->EnsureVisible(&dc, pRow);
}
}
}
}
}
void CXTPReportControl::EnsureVisible(CXTPReportColumn* pCheckColumn)
{
int nCheckIndex = pCheckColumn ? pCheckColumn->GetIndex() : -1;
if (nCheckIndex == -1 || !pCheckColumn->m_bVisible || nCheckIndex >= m_pColumns->GetCount())
return;
if (m_pSectionBody->m_rcSection.Height() <= 0)
{
m_nEnsureVisibleRowIdx = nCheckIndex;
return;
}
CRect rc(pCheckColumn->GetRect());
if (rc.right >= m_pSectionBody->m_rcSection.Width())
{
SetScrollOffsetH(m_nScrollOffsetH + min(rc.left, rc.right - m_pSectionBody->m_rcSection.Width()));
}
else
{
int nFreezeColumnWidth = 0;
int nFreezeColumnsCount = GetFreezeColumnsCount();
if (nFreezeColumnsCount > 0)
{
for (int i = 0; (i < m_pColumns->GetCount()) && (nFreezeColumnsCount > 0); i++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(i);
if (pColumn == pCheckColumn)
{
nFreezeColumnWidth = 0;
break;
}
if (pColumn && pColumn->IsVisible())
{
nFreezeColumnsCount--;
nFreezeColumnWidth = pColumn->GetRect().right;
}
}
}
if (rc.left - nFreezeColumnWidth <= 0 && m_nScrollOffsetH != 0)
{
SetScrollOffsetH(m_nScrollOffsetH + rc.left - nFreezeColumnWidth);
}
}
}
BOOL CXTPReportControl::HitTest(CPoint pt, CXTPReportHitTestInfo *pInfo) const
{
if (NULL == pInfo)
{
return FALSE;
}
pInfo->m_pColumn = NULL;
pInfo->m_pRow = NULL;
pInfo->m_pItem = NULL;
pInfo->m_pBlock = NULL;
pInfo->m_htCode = xtpReportHitTestUnknown;
pInfo->m_iTrackPosition = 0;
if (m_rcHeaderArea.PtInRect(pt))
{
pInfo->m_htCode = xtpReportHitTestHeader;
pInfo->m_pColumn = GetReportHeader()->HitTest(pt);
}
else if (m_rcGroupByArea.PtInRect(pt))
{
pInfo->m_htCode = xtpReportHitTestGroupBox;
int nColumn = GetReportHeader()->FindGroupByColumn(pt, TRUE);
pInfo->m_pColumn = GetColumns()->GetGroupsOrder()->GetAt(nColumn);
}
else if (m_pSections->GetRect().PtInRect(pt))
{
const CXTPReportSection *pSection = m_pSections->HitTest(pt);
if (NULL != pSection)
{
switch(pSection->GetRowType())
{
case xtpRowTypeBody:
pInfo->m_htCode = xtpReportHitTestBodyRows;
break;
case xtpRowTypeHeader:
pInfo->m_htCode = xtpReportHitTestHeaderRows;
break;
case xtpRowTypeFooter:
pInfo->m_htCode = xtpReportHitTestFooterRows;
break;
}
}
pInfo->m_pRow = HitTest(pt);
if (NULL != pInfo->m_pRow)
{
pInfo->m_pItem = pInfo->m_pRow->HitTest(pt, NULL, &pInfo->m_pColumn);
}
}
return TRUE;
}
CXTPReportRow* CXTPReportControl::HitTest(CPoint pt) const
{
CXTPReportRow *pRow = NULL;
CXTPReportSection *pSection = m_pSections->HitTest(pt);
if (NULL != pSection)
{
pRow = pSection->GetRows()->GetScreenRows()->HitTest(pt);
}
return pRow;
}
int CXTPReportControl::GetReportAreaRows(int nStartRow, BOOL bMoveDown)
{
int nDirection = bMoveDown ? +1 : -1;
int top = m_pSectionBody->m_rcSection.top;
CClientDC dc(this);
int nHeaderWidth = GetReportHeader()->GetWidth();
int i = nStartRow;
if (IsIconView())
{
// Find the first row, to account for the height of the row we are in.
while(i % GetRowsPerLine() != 0)
{
i--;
}
}
for (; (i < m_pRows->GetCount() && i >= 0); i += nDirection)
{
CXTPReportRow* pRow = m_pRows->GetAt(i);
ASSERT(pRow);
if (!pRow)
continue;
int rowHeight = pRow->GetHeight(&dc, nHeaderWidth);
if (top + rowHeight > m_pSectionBody->m_rcSection.bottom)
return bMoveDown ? i - nStartRow - 1 : nStartRow - i - 1;
top += rowHeight;
}
//return bMoveDown ? m_pRows->GetCount() - nStartRow : nStartRow;
return bMoveDown ? m_pRows->GetCount() - nStartRow - 1: nStartRow; //-this is better way!
}
void CXTPReportControl::AdjustLayout()
{
/*
------------------------------
| Group by |
------------------------------
| Header |
------------------------------
| Sections |
------------------------------
| Footer |
------------------------------
*/
if (NULL == GetSafeHwnd())
return;
CXTPClientRect rcClient(this);
CClientDC dc(this);
if (rcClient.IsRectEmpty())
{
// Avoid unnecessary layout calculations during creation
return;
}
ASSERT(!m_bAdjustLayoutRunning);
if (m_bAdjustLayoutRunning) //guard to prevent the recursion similar to OnSize function
{
return;
}
m_bAdjustLayoutRunning = TRUE;
int nHeaderWidth = m_rcHeaderArea.Width();
CXTPReportHeader *pHeader = GetReportHeader();
int nHeightGroupBy = 0;
int nHeightHeader = 0;
int nHeightSections = 0;
int nHeightFooter = 0;
if (NULL != pHeader && m_bGroupByEnabled)
{
nHeightGroupBy = pHeader->GetGroupByHeight();
}
if (m_bHeaderVisible)
{
nHeightHeader = GetPaintManager()->GetHeaderHeight(this, &dc);
}
if (m_bFooterVisible)
{
nHeightFooter = GetPaintManager()->GetFooterHeight(this, &dc);
}
// Group by rect
m_rcGroupByArea.SetRect(0, 0, rcClient.Width(), nHeightGroupBy);
// Header
m_rcHeaderArea.SetRect(0, m_rcGroupByArea.bottom, rcClient.Width(), m_rcGroupByArea.bottom + nHeightHeader);
// Sections
nHeightSections = rcClient.Height() - nHeightGroupBy - nHeightHeader - nHeightFooter;
CRect rcSections(0, m_rcHeaderArea.bottom, rcClient.Width(), m_rcHeaderArea.bottom+nHeightSections);
m_pSections->AdjustLayout(&dc, rcSections);
// Footer
m_rcFooterArea.SetRect(0, rcClient.Height() - nHeightFooter, rcClient.Width(), rcClient.Height());
if (nHeaderWidth != m_rcHeaderArea.Width() && pHeader)
{
pHeader->AdjustColumnsWidth(m_rcHeaderArea.Width());
}
m_bAdjustLayoutRunning = FALSE;
}
CScrollBar* CXTPReportControl::GetScrollBarCtrl(int nBar) const
{
if (DYNAMIC_DOWNCAST(CView, GetParent()))
return GetParent()->GetScrollBarCtrl(nBar);
return NULL;
}
void CXTPReportControl::RedrawScrollBar(int nBar)
{
CScrollBar *pScrollBar = GetScrollBarCtrl(nBar);
if (NULL != pScrollBar)
{
SAFE_INVALIDATE(pScrollBar);
}
else
{
if (NULL != m_hWnd)
{
SendMessage(WM_NCPAINT);
}
}
}
void CXTPReportControl::GetColumnTotalSize(int &nTotalCount, int &nTotalWidth) const
{
nTotalCount = 0;
nTotalWidth = 0;
for (int nColumn=0; nColumn<GetColumns()->GetCount(); nColumn++)
{
const CXTPReportColumn *pColumn = GetColumns()->GetAt(nColumn);
if (pColumn->IsVisible())
{
nTotalCount += 1;
nTotalWidth += pColumn->GetWidth();
}
}
}
void CXTPReportControl::GetColumnOutOfViewSize(int &nOutOfViewCount, int &nOutOfViewWidth) const
{
int nLeft = 0;
int nRight = 0;
nOutOfViewCount = 0;
nOutOfViewWidth = 0;
for (int nColumn=0; nColumn<GetColumns()->GetCount(); nColumn++)
{
const CXTPReportColumn *pColumn = GetColumns()->GetAt(nColumn);
if (pColumn->IsVisible())
{
nRight = nLeft + pColumn->GetWidth();
if (nRight > GetReportRectangle().right)
{
nOutOfViewCount += 1;
nOutOfViewWidth += pColumn->GetWidth() - max(0, GetReportRectangle().right-nLeft);
}
nLeft = nRight;
}
}
}
void CXTPReportControl::GetColumnScrollSize(int nOutOfViewWidth, int &nScrollCount, int &nScrollWidth) const
{
nScrollCount = 0;
nScrollWidth = 0;
for (int nColumn=0; nColumn<GetColumns()->GetCount(); nColumn++)
{
const CXTPReportColumn *pColumn = GetColumns()->GetAt(nColumn);
if (pColumn->IsVisible() && !pColumn->IsFrozen())
{
if (nOutOfViewWidth > nScrollWidth)
{
nScrollCount += 1;
nScrollWidth += pColumn->GetWidth();
}
}
}
}
void CXTPReportControl::AdjustScrollBarH(BOOL bUpdate, UINT nMask)
{
if (bUpdate)
{
EditItem(NULL);
BeginUpdate();
}
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
// Get current values
GetScrollInfo(SB_HORZ, &si, SIF_ALL);
if (xtpReportScrollModeBlockCount == m_scrollModeH ||
xtpReportScrollModeBlockSize == m_scrollModeH)
{
const CXTPReportColumns *pColumns = GetColumns();
int nTotalCount, nTotalWidth;
GetColumnTotalSize(nTotalCount, nTotalWidth);
int nOutOfViewCount, nOutOfViewWidth;
GetColumnOutOfViewSize(nOutOfViewCount, nOutOfViewWidth);
int nScrollCount, nScrollWidth;
GetColumnScrollSize(nOutOfViewWidth, nScrollCount, nScrollWidth);
if (xtpReportScrollModeBlockCount == m_scrollModeH)
{
if (SIF_RANGE & nMask) si.nMin = 0;
if (SIF_RANGE & nMask) si.nMax = nTotalCount - 1;
if (SIF_PAGE & nMask) si.nPage = nTotalCount - nScrollCount;
if (SIF_POS & nMask) si.nPos = pColumns->GetAtOffset(m_nScrollOffsetH, TRUE);
}
if (xtpReportScrollModeBlockSize == m_scrollModeH)
{
if (SIF_RANGE & nMask) si.nMin = 0;
if (SIF_RANGE & nMask) si.nMax = nTotalWidth - 1;
if (SIF_PAGE & nMask) si.nPage = nTotalWidth - nScrollWidth;
if (SIF_POS & nMask) si.nPos = m_nScrollOffsetH;
}
}
if (xtpReportScrollModeSmooth == m_scrollModeH)
{
// Update requested values
if (SIF_RANGE & nMask) si.nMin = 0;
if (SIF_RANGE & nMask) si.nMax = GetReportHeader()->GetWidth() - 1;
if (SIF_PAGE & nMask) si.nPage = m_pSectionBody->GetRect().Width();
if (SIF_POS & nMask) si.nPos = m_nScrollOffsetH;
}
if (xtpReportScrollModeSmooth == m_scrollModeH ||
xtpReportScrollModeBlockSize == m_scrollModeH)
{
si.nPage = min(si.nPage, UINT(si.nMax)+1);
// Adjust scroll offset when increasing the section size
if ((si.nPos > 0) && (si.nPos + int(si.nPage) - 1 > si.nMax))
{
m_nScrollOffsetH = si.nMax - si.nPage + 1;
si.nPos = m_nScrollOffsetH;
}
}
// Set new values
si.fMask = nMask;
SetScrollInfo(SB_HORZ, &si); // Note: Causes an OnSize message
// si.nMax is -1 for no rows
BOOL bEnabled = (-1 != si.nMax) && (UINT(si.nMax) >= UINT(si.nPage));
CWnd::EnableScrollBarCtrl(SB_HORZ, bEnabled);
::EnableScrollBar(m_hWnd, SB_HORZ, (bEnabled && IsWindowEnabled()) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
if (m_bHScrollBarVisible != bEnabled)
{
m_bHScrollBarVisible = bEnabled;
}
if (bUpdate)
{
EndUpdate();
}
}
int CXTPReportControl::GetPageRowCount(CDC *pDC) const
{
int nCount = m_pRows->GetCount() - 1;
int nLinesCount = nCount;
int nHeight = m_pSectionBody->GetRect().Height();
int nWidth = m_pSectionBody->GetRect().Width();
for (; nLinesCount >= 0; nLinesCount--)
{
nHeight -= m_pRows->GetAt(nLinesCount)->GetHeight(pDC, nWidth);
if (nHeight < 0)
{
if (nLinesCount != nCount)
nLinesCount += IsIconView() ? GetRowsPerLine() : 1; // Want the next row, in icon view, that is an addition of an entire row.
break;
}
}
nLinesCount = max(nLinesCount, 0);
return nLinesCount;
}
void CXTPReportControl::AdjustScrollBarV(BOOL bUpdate, UINT nMask)
{
CClientDC dc(this);
if (bUpdate)
{
EditItem(NULL);
BeginUpdate();
}
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
// Get current values
GetScrollInfo(SB_VERT, &si, SIF_ALL);
if (xtpReportScrollModeBlockCount == m_scrollModeV ||
xtpReportScrollModeBlockSize == m_scrollModeV)
{
int nMax = m_pSectionBody->GetRows()->GetCount() - 1;
int nPage = GetPageRowCount(&dc);
// Update requested values
if (SIF_RANGE & nMask) si.nMin = 0;
if (SIF_RANGE & nMask) si.nMax = nMax;
if (SIF_PAGE & nMask) si.nPage = nMax - nPage + 1;
if (SIF_POS & nMask) si.nPos = GetTopRowIndex();
si.nPage = min(si.nPage, UINT(si.nMax)+1);
// Adjust scroll offset when increasing the section size
if ((si.nPos > 0) && (si.nPos + int(si.nPage) - 1 > si.nMax))
{
si.nPos = si.nMax - si.nPage + 1;
m_pSectionScroll->SetScrollIndexV(si.nPos);
}
}
if (xtpReportScrollModeSmooth == m_scrollModeV)
{
// Update requested values
if (SIF_RANGE & nMask) si.nMin = 0;
if (SIF_RANGE & nMask) si.nMax = m_pSectionScroll->GetRowsHeight(&dc) - 1;
if (SIF_PAGE & nMask) si.nPage = m_pSectionScroll->GetRect().Height();
if (SIF_POS & nMask) si.nPos = m_pSectionScroll->GetScrollOffsetV();
si.nPage = min(si.nPage, UINT(si.nMax)+1);
// Adjust scroll offset when increasing the section size
if ((si.nPos > 0) && (si.nPos + int(si.nPage) - 1 > si.nMax))
{
si.nPos = si.nMax - si.nPage + 1;
m_pSectionScroll->SetScrollOffsetV(si.nPos);
}
}
// Set new values
si.fMask = nMask;
SetScrollInfo(SB_VERT, &si); // Note: Causes an OnSize message
// si.nMax is -1 for no rows
BOOL bEnabled = (-1 != si.nMax) && (UINT(si.nMax) >= UINT(si.nPage));
CWnd::EnableScrollBarCtrl(SB_VERT, bEnabled);
::EnableScrollBar(m_hWnd, SB_VERT, (bEnabled && IsWindowEnabled()) ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
if (m_bVScrollBarVisible != bEnabled)
{
m_bVScrollBarVisible = bEnabled;
}
if (bUpdate)
{
EndUpdate();
}
}
void CXTPReportControl::UpdateScrollBarV()
{
AdjustScrollBarV(TRUE, SIF_PAGE | SIF_POS); // Only update page and position
// Send notification
XTP_NM_REPORTSCROLL msg;
msg.nSection = m_pSectionScroll->GetIndex();
switch(m_scrollModeV)
{
case xtpReportScrollModeSmooth:
msg.nPosition = m_pSectionScroll->GetScrollOffsetV();
break;
case xtpReportScrollModeBlockCount:
case xtpReportScrollModeBlockSize:
msg.nPosition = m_pSectionScroll->GetScrollIndexV();
break;
}
SendNotifyMessage(XTP_NM_REPORT_VSCROLL, &msg);
}
void CXTPReportControl::AdjustScrollBars()
{
if (GetSafeHwnd() == NULL)
return;
EditItem(NULL);
int nHeight = m_pSectionBody->GetRect().Height();
if (nHeight <= 0)
return;
BeginUpdate();
AdjustScrollBarH(FALSE, SIF_ALL);
AdjustScrollBarV(FALSE, SIF_ALL);
EndUpdate();
}
void CXTPReportControl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar)
{
if (pScrollBar != NULL)
{
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
return;
}
if (!m_bIconView)
{
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
GetScrollInfo(SB_VERT, &si, SIF_ALL);
const int nLimit = si.nMax - si.nPage + 1; // GetScrollLimit
if (xtpReportScrollModeSmooth == m_scrollModeV)
{
int nScrollOffsetV = m_pSectionScroll->GetScrollOffsetV();
switch (nSBCode)
{
case SB_LINEUP: // 0
nScrollOffsetV = max(nScrollOffsetV - m_nScrollStepV, 0);
break;
case SB_LINEDOWN: // 1
nScrollOffsetV = min(nScrollOffsetV + m_nScrollStepV, nLimit);
break;
case SB_PAGEUP: // 2
nScrollOffsetV = max(nScrollOffsetV - int(si.nPage), 0);
break;
case SB_PAGEDOWN: // 3
nScrollOffsetV = min(nScrollOffsetV + int(si.nPage), nLimit);
break;
case SB_THUMBPOSITION: // 4
case SB_THUMBTRACK: // 5
nScrollOffsetV = si.nTrackPos;
break;
case SB_TOP: // 6
nScrollOffsetV = 0;
break;
case SB_BOTTOM: // 7
nScrollOffsetV = nLimit;
break;
case SB_ENDSCROLL: // 8
break;
}
if (-1 != nScrollOffsetV)
{
SetScrollOffsetV(nScrollOffsetV);
}
} // smooth
if (xtpReportScrollModeBlockCount == m_scrollModeV ||
xtpReportScrollModeBlockSize == m_scrollModeV)
{
int nPos = -1;
switch (nSBCode)
{
case SB_LINEUP: // 0
nPos = max(si.nPos - 1, 0);
break;
case SB_LINEDOWN: // 1
nPos = min(si.nPos + 1, nLimit);
break;
case SB_PAGEUP: // 2
nPos = max(si.nPos - max(1, GetReportAreaRows(si.nPos, FALSE)), 0);
break;
case SB_PAGEDOWN: // 3
nPos = min(si.nPos + max(1, GetReportAreaRows(si.nPos, TRUE)), nLimit);
break;
case SB_THUMBPOSITION: // 4
case SB_THUMBTRACK: // 5
nPos = si.nTrackPos;
break;
case SB_TOP: // 6
nPos = 0;
break;
case SB_BOTTOM: // 7
nPos = nLimit;
break;
case SB_ENDSCROLL: // 8
break;
}
if (-1 != nPos)
{
SetTopRow(nPos);
}
}
}
else
{
int nCurPos = GetTopRowIndex();
CXTPReportColumn* pColumn = GetColumns()->Find(m_iIconViewColumn);
if (!pColumn)
{
CXTPReportControl::OnVScroll(nSBCode, nPos, pScrollBar);
return;
}
// decide what to do for each diffrent scroll event
switch (nSBCode)
{
case SB_TOP:
nCurPos = 0; break;
case SB_BOTTOM:
nCurPos = GetScrollLimit(SB_VERT); break;
case SB_LINEUP:
nCurPos = max(nCurPos - m_iIconViewRowsPerLine, 0); break;
case SB_LINEDOWN:
nCurPos = min(nCurPos + m_iIconViewRowsPerLine, GetScrollLimit(SB_VERT)); break;
case SB_PAGEUP:
nCurPos = max(nCurPos - GetReportAreaRows(nCurPos, FALSE), 0); break;
case SB_PAGEDOWN:
nCurPos = min(nCurPos + GetReportAreaRows(nCurPos, TRUE), GetScrollLimit(SB_VERT)); break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
{
SCROLLINFO si;
ZeroMemory(&si, sizeof(SCROLLINFO));
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_TRACKPOS;
if (!GetScrollInfo(SB_VERT, &si))
return;
nCurPos = si.nTrackPos;
}
break;
}
SetTopRow(nCurPos);
}
}
void CXTPReportControl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar)
{
if (pScrollBar != NULL)
{
CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
return;
}
int nCurPos = m_nScrollOffsetH;
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
GetScrollInfo(SB_HORZ, &si, SIF_ALL);
const int nLimit = si.nMax - si.nPage + 1; // GetScrollLimit
if (xtpReportScrollModeSmooth == m_scrollModeH)
{
switch (nSBCode)
{
case SB_LINEUP: // 0
nCurPos = max(nCurPos - m_nScrollStepH, 0);
break;
case SB_LINEDOWN: // 1
nCurPos = min(nCurPos + m_nScrollStepH, nLimit);
break;
case SB_PAGEUP: // 2
nCurPos = max(nCurPos - m_pSectionBody->GetRect().Width(), 0);
break;
case SB_PAGEDOWN: // 3
nCurPos = min(nCurPos + m_pSectionBody->m_rcSection.Width(), nLimit);
break;
case SB_THUMBPOSITION: // 4
case SB_THUMBTRACK: // 5
nCurPos = si.nTrackPos;
break;
case SB_TOP: // 6
nCurPos = 0;
break;
case SB_BOTTOM: // 7
nCurPos = nLimit;
break;
case SB_ENDSCROLL: // 8
break;
}
}
if (xtpReportScrollModeBlockCount == m_scrollModeH)
{
CXTPReportColumn *pPrev = NULL, *pCurr = NULL, *pNext = NULL;
int nScrollPos = 0, nScrollMax = 0;
GetReportHeader()->GetFullColScrollInfo(pPrev, pCurr, pNext, nScrollPos, nScrollMax);
int nOutOfViewCount, nOutOfViewWidth;
GetColumnOutOfViewSize(nOutOfViewCount, nOutOfViewWidth);
int nScrollCount, nScrollWidth;
GetColumnScrollSize(nOutOfViewWidth, nScrollCount, nScrollWidth);
switch (nSBCode)
{
case SB_LINEUP: // 0
case SB_PAGEUP: // 2
{
if (NULL != pPrev)
{
nCurPos = max(nCurPos - pPrev->GetWidth(), 0);
}
break;
}
case SB_LINEDOWN: // 1
case SB_PAGEDOWN: // 3
{
if (NULL != pCurr)
{
nCurPos = min(nCurPos + pCurr->GetWidth(), nScrollWidth);
}
break;
}
case SB_THUMBPOSITION: // 4
case SB_THUMBTRACK: // 5
{
nCurPos = GetColumns()->GetOffset(si.nTrackPos);
break;
}
case SB_TOP: // 6
nCurPos = 0;
break;
case SB_BOTTOM: // 7
nCurPos = nScrollWidth;
break;
case SB_ENDSCROLL: // 8
break;
}
}
if (xtpReportScrollModeBlockSize == m_scrollModeH)
{
CXTPReportColumn *pPrev = NULL, *pCurr = NULL, *pNext = NULL;
int nScrollPos = 0, nScrollMax = 0;
GetReportHeader()->GetFullColScrollInfo(pPrev, pCurr, pNext, nScrollPos, nScrollMax);
switch (nSBCode)
{
case SB_LINEUP: // 0
case SB_PAGEUP: // 2
{
if (NULL != pPrev)
{
nCurPos = max(nCurPos - pPrev->GetWidth(), 0);
}
break;
}
case SB_LINEDOWN: // 1
case SB_PAGEDOWN: // 3
{
if (NULL != pCurr)
{
nCurPos = min(nCurPos + pCurr->GetWidth(), nLimit);
}
break;
}
case SB_THUMBPOSITION: // 4
case SB_THUMBTRACK: // 5
{
int nColumn = GetColumns()->GetAtOffset(si.nTrackPos, TRUE);
nCurPos = GetColumns()->GetOffset(nColumn);
break;
}
case SB_TOP: // 6
nCurPos = 0;
break;
case SB_BOTTOM: // 7
nCurPos = nLimit;
break;
case SB_ENDSCROLL: // 8
break;
}
}
SetScrollOffsetH(nCurPos);
}
HBITMAP CXTPReportControl::GetWatermarkBitmap() const
{
return m_hbmpWatermark;
}
BOOL CXTPReportControl::SetWatermarkBitmap(HBITMAP hBitmap, BYTE Transparency)
{
m_WatermarkTransparency = Transparency;
// remove old watermark bitmap if one is
if (m_hbmpWatermark)
{
::DeleteObject(m_hbmpWatermark);
m_hbmpWatermark = NULL;
}
if (hBitmap)
{
// add new watermark bitmap
BITMAP bmSrc;
if (!CBitmap::FromHandle(hBitmap)->GetBitmap(&bmSrc))
return FALSE;
BOOL bAlphaBitmap = bmSrc.bmBitsPixel == 32;
// create an alpha bitmap if the bitmap supplied isn't an alpha one
if (!bAlphaBitmap)
{
m_hbmpWatermark = ::CreateBitmap(bmSrc.bmWidth, bmSrc.bmHeight, bmSrc.bmPlanes, 32, NULL);
ASSERT(m_hbmpWatermark);
if (!m_hbmpWatermark)
return FALSE;
CXTPCompatibleDC memWatermarkDC(NULL, m_hbmpWatermark);
CXTPCompatibleDC memScrDC(NULL, hBitmap);
memWatermarkDC.BitBlt(0, 0, bmSrc.bmWidth, bmSrc.bmHeight, &memScrDC, 0, 0, SRCCOPY);
}
else
{
m_hbmpWatermark = CXTPImageManagerIcon::CopyAlphaBitmap(hBitmap);
}
if (!m_hbmpWatermark)
return FALSE;
if (!CBitmap::FromHandle(m_hbmpWatermark)->GetBitmap(&m_bmWatermark))
{
::DeleteObject(m_hbmpWatermark);
m_hbmpWatermark = NULL;
return FALSE;
}
}
return TRUE;
}
BOOL CXTPReportControl::SetWatermarkBitmap(LPCTSTR szPath, BYTE Transparency)
{
m_WatermarkTransparency = Transparency;
// if path is empty, remove watermark bitmap
if (_tcslen(szPath) == 0)
{
::DeleteObject(m_hbmpWatermark);
m_hbmpWatermark = NULL;
}
else
{
// remove old watermark bitmap if one is
if (m_hbmpWatermark)
{
::DeleteObject(m_hbmpWatermark);
m_hbmpWatermark = NULL;
}
// add new watermark bitmap
BOOL bAlphaBitmap = FALSE;
m_hbmpWatermark = CXTPImageManagerIcon::LoadBitmapFromFile(szPath, &bAlphaBitmap);
if (!m_hbmpWatermark)
return FALSE;
if (!CBitmap::FromHandle(m_hbmpWatermark)->GetBitmap(&m_bmWatermark))
{
::DeleteObject(m_hbmpWatermark);
m_hbmpWatermark = NULL;
return FALSE;
}
// create an alpha bitmap if the bitmap supplied isn't an alpha one
if (!bAlphaBitmap)
{
CXTPCompatibleDC memWatermarkDC(NULL, m_hbmpWatermark);
CXTPImageManagerIcon::DrawAlphaBitmap(&memWatermarkDC, m_hbmpWatermark, CPoint(0, 0), CSize(m_bmWatermark.bmWidth, m_bmWatermark.bmHeight));
}
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
// CXTPReportControl message handlers
void CXTPReportControl::Paint(CDC *pDC)
{
OnDraw(pDC);
// Update flag
SetChanged(FALSE);
if (!IsWindowEnabled() && GetPaintManager()->m_bGrayIfDisable)
{
CXTPClientRect rcClient(this);
XTPImageManager()->DisableBitmap(*pDC, rcClient, RGB(250, 250, 250), RGB(128, 128, 128));
}
}
void CXTPReportControl::EnableDoubleBuffering(BOOL bEnable)
{
m_bDoubleBuffering = bEnable;
// Delete buffer
if (!m_bDoubleBuffering && NULL != m_bmpCache.GetSafeHandle())
{
m_bmpCache.DeleteObject();
}
}
void CXTPReportControl::OnPaint()
{
CPaintDC dc(this); // device context for painting
CXTPClientRect rcClient(this);
// ensure visible row and column if first started
if (m_nEnsureVisibleRowIdx >= 0)
{
CXTPReportRow *pRow = GetRows()->GetAt(m_nEnsureVisibleRowIdx);
if (NULL != pRow)
{
EnsureVisible(pRow);
}
m_nEnsureVisibleRowIdx = -1;
}
if (m_nEnsureVisibleColumnIdx >= 0)
{
EnsureVisible(GetColumns()->GetAt(m_nEnsureVisibleColumnIdx));
m_nEnsureVisibleColumnIdx = -1;
}
// start counting drawing time
#ifdef XTP_DEBUG
LARGE_INTEGER iStartCount;
QueryPerformanceCounter(&iStartCount);
#endif
if (m_bDoubleBuffering)
{
// Update cached bitmap
if (m_nLockUpdateCount == 0 && (IsChanged() || NULL == m_bmpCache.GetSafeHandle()))
{
m_bmpCache.DeleteObject();
CDC memDC;
if (memDC.CreateCompatibleDC(&dc))
{
if (m_bmpCache.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()))
{
CBitmap *pOldBitmap = memDC.SelectObject(&m_bmpCache);
Paint(&memDC);
memDC.SelectObject(pOldBitmap);
}
}
}
}
// Draw cached bitmap if available
if (NULL != m_bmpCache.GetSafeHandle())
{
CXTPCompatibleDC memDC(&dc, &m_bmpCache);
dc.BitBlt(0, 0, rcClient.right, rcClient.bottom, &memDC, 0, 0, SRCCOPY);
}
// Draw directly to device context
else
{
Paint(&dc);
}
// count drawing time
#ifdef XTP_DEBUG
LARGE_INTEGER iEndCount;
QueryPerformanceCounter(&iEndCount);
XTP_TRACE(_T("Draw counter ticks: %d\n"), iEndCount.LowPart-iStartCount.LowPart);
#endif
}
void CXTPReportControl::DrawWatermark(CDC *pDC, CRect rcWatermark, CRect rcClient)
{
if (m_hbmpWatermark)
{
CRect rcDst(rcWatermark);
CRect rcSrc(0, 0, m_bmWatermark.bmWidth, m_bmWatermark.bmHeight);
// no stretch
if (!(GetWatermarkAlignment() & xtpReportWatermarkStretch))
{
if (rcSrc.Width() > rcDst.Width())
{
rcSrc.right = rcSrc.left + rcDst.Width();
}
else
{
rcDst.right = rcDst.left + rcSrc.Width();
}
if (rcSrc.Height() > rcDst.Height())
{
rcSrc.bottom = rcSrc.top + rcDst.Height();
}
else
{
rcDst.bottom = rcDst.top + rcSrc.Height();
}
}
// enlarge only
if ((GetWatermarkAlignment() & xtpReportWatermarkStretch) &&
(GetWatermarkAlignment() & xtpReportWatermarkEnlargeOnly))
{
if (rcSrc.Width() > rcDst.Width())
{
rcSrc.right = rcSrc.left + rcDst.Width();
}
if (rcSrc.Height() > rcDst.Height())
{
rcSrc.bottom = rcSrc.top + rcDst.Height();
}
}
// shrink only
if ((GetWatermarkAlignment() & xtpReportWatermarkStretch) &&
(GetWatermarkAlignment() & xtpReportWatermarkShrinkOnly))
{
if (rcSrc.Width() < rcDst.Width())
{
rcDst.right = rcDst.left + rcSrc.Width();
}
if (rcSrc.Height() < rcDst.Height())
{
rcDst.bottom = rcDst.top + rcSrc.Height();
}
}
// preserve aspect ratio
if ((GetWatermarkAlignment() & xtpReportWatermarkStretch) &&
(GetWatermarkAlignment() & xtpReportWatermarkPreserveRatio))
{
if (rcDst.Width() > (rcDst.Height() * rcSrc.Width() / rcSrc.Height()))
{
rcDst.right = rcDst.left + rcDst.Height() * rcSrc.Width() / rcSrc.Height();
}
if (rcDst.Height() > (rcDst.Width() * rcSrc.Height() / rcSrc.Width()))
{
rcDst.bottom = rcDst.top + rcDst.Width() * rcSrc.Height() / rcSrc.Width();
}
}
// horizontal
switch (GetWatermarkAlignment() & xtpReportWatermarkHmask)
{
// center
case xtpReportWatermarkCenter :
rcDst.OffsetRect((rcWatermark.Width() - rcDst.Width()) / 2, 0);
break;
// right
case xtpReportWatermarkRight :
rcDst.OffsetRect(rcWatermark.Width() - rcDst.Width(), 0);
break;
// left
default :
break;
}
// vertical
switch (GetWatermarkAlignment() & xtpReportWatermarkVmask)
{
// center
case xtpReportWatermarkVCenter :
rcDst.OffsetRect(0, (rcWatermark.Height() - rcDst.Height()) / 2);
break;
// bottom
case xtpReportWatermarkBottom:
rcDst.OffsetRect(0, rcWatermark.Height() - rcDst.Height());
break;
// top
default :
break;
}
CXTPCompatibleDC memWatermarkDC(pDC, m_hbmpWatermark);
if (GetWatermarkAlignment() & xtpReportWatermarkStretch)
{
CBitmap bmpWatermark;
bmpWatermark.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height());
CXTPCompatibleDC dcWatermark(pDC, &bmpWatermark);
dcWatermark.FillSolidRect(&rcClient, RGB(255, 255, 255));
dcWatermark.SetStretchBltMode(HALFTONE);
dcWatermark.StretchBlt(rcDst.left, rcDst.top, rcDst.Width(), rcDst.Height(), &memWatermarkDC, 0, 0, rcSrc.Width(), rcSrc.Height(), SRCCOPY);
XTPImageManager()->AlphaBlend2(*pDC, rcClient, dcWatermark, rcClient, m_WatermarkTransparency);
}
else
{
XTPImageManager()->AlphaBlend2(*pDC, rcDst, memWatermarkDC, rcSrc, m_WatermarkTransparency);
}
}
}
LRESULT CXTPReportControl::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
{
CDC* pDC = CDC::FromHandle((HDC)wParam);
if (pDC)
{
if (m_bmpCache.GetSafeHandle() == 0)
OnDraw(pDC);
else
{
CXTPCompatibleDC memDC(pDC, &m_bmpCache);
CXTPClientRect rc(this);
pDC->BitBlt(0, 0, rc.right, rc.bottom, &memDC, 0, 0, SRCCOPY);
}
}
return TRUE;
}
BOOL CXTPReportControl::OnEraseBkgnd(CDC *pDC)
{
UNREFERENCED_PARAMETER(pDC);
return TRUE; // Don't erase the background.
}
void CXTPReportControl::OnDraw(CDC *pDC)
{
CXTPClientRect rcClient(this);
pDC->SetBkMode(TRANSPARENT);
if (GetExStyle() & WS_EX_RTLREADING)
{
pDC->SetTextAlign(TA_RTLREADING);
}
// Fill background
pDC->FillSolidRect(rcClient, GetPaintManager()->GetControlBackColor(this));
// Draw watermark
DrawWatermark(pDC, m_pSections->GetRect(), rcClient);
// Draw header
CXTPReportHeader *pHeader = GetReportHeader();
if (NULL != pHeader)
{
CRect rcHeader = m_rcHeaderArea;
rcHeader.right = rcHeader.left + pHeader->GetWidth();
pHeader->Draw(pDC, rcHeader, m_nScrollOffsetH); // draw header
pHeader->DrawGroupByControl(pDC, m_rcGroupByArea); // draw group by box
}
if (m_bIconView)
{
DrawIconView(pDC, m_pSectionBody->m_rcSection);
}
else
{
m_pSections->Draw(pDC);
}
CRect rcFooter = m_rcFooterArea;
if (rcFooter.Height() > 0)
pHeader->DrawFooter(pDC, rcFooter, m_nScrollOffsetH);
BOOL bForce(FALSE);
BOOL bDrawBetween = FALSE;
int yForce(-1);
if (m_bDragMode && GetPaintManager() && !IsIconView())
{
bForce = GetPaintManager()->m_bForceShowDropMarker;
CPoint ptMouse;
if (::GetCursorPos(&ptMouse))
{
ScreenToClient(&ptMouse);
EnsureStartAutoVertScroll();
if (m_dwDropMarkerFlags & xtpReportDropBetween)
{
CXTPReportRow* pHitRow = HitTest(ptMouse);
if (pHitRow && pHitRow->GetRecord())
{
if(bForce
|| !(m_dwDropMarkerFlags & xtpReportDropSelect)
|| (m_pSelectedRows->GetCount() == 0
&& (ptMouse.y <= (pHitRow->GetRect().top + 4)
|| ptMouse.y >= (pHitRow->GetRect().bottom - 4))))
{
bDrawBetween = TRUE;
BOOL bAbove = TRUE;
if (pHitRow->GetRect().CenterPoint().y < ptMouse.y)
bAbove = FALSE;
if (bAbove)
yForce = pHitRow->GetRect().top - 1;
else
yForce = pHitRow->GetRect().bottom - 1;
}
}
}
}
}
if (bDrawBetween)
{
if (m_nDropPos != -1 && GetPaintManager()->m_bUseDropMarker)
{
DrawDropMarker(pDC);
}
else if (bForce && yForce > 0 && GetPaintManager()->m_bUseDropMarker)
{
DrawExtDropMarker(pDC, yForce);
}
}
// update flag
SetChanged(FALSE);
}
void CXTPReportControl::DrawDropMarker(CDC *pDC)
{
if (m_nDropPos == 0 && GetRows()->GetCount() == 0)
{
m_nDropPos = m_pSectionBody->m_rcSection.top;
}
else if (m_nDropPos < m_pSectionBody->m_rcSection.top - 1 ||
m_nDropPos > m_pSectionBody->m_rcSection.bottom)
{
return;
}
CRect rc(m_pSectionBody->m_rcSection.left, m_nDropPos, m_pSectionBody->m_rcSection.right, m_nDropPos + 1);
pDC->FillSolidRect(rc, GetPaintManager()->m_clrHotDivider);
CXTPPenDC pen(*pDC, GetPaintManager()->m_clrHotDivider);
CXTPBrushDC brush(*pDC, GetPaintManager()->m_clrHotDivider);
int x = rc.left;
int y = m_nDropPos;
POINT ptsLeftArrow[] =
{
{x, y - 2},
{x + 2, y - 2},
{x + 2, y - 5},
{x + 7, y },
{x + 2, y + 5},
{x + 2, y + 2},
{x, y + 2}
};
pDC->Polygon(ptsLeftArrow, 7);
x = rc.right - 1;
POINT ptsRightArrow[] =
{
{x, y - 2},
{x - 2, y - 2},
{x - 2, y - 5},
{x - 7, y },
{x - 2, y + 5},
{x - 2, y + 2},
{x, y + 2}
};
pDC->Polygon(ptsRightArrow, 7);
}
void CXTPReportControl::DrawExtDropMarker(CDC* pDC, int y)
{
CRect rc(m_pSectionBody->m_rcSection.left, y, m_pSectionBody->m_rcSection.right, y + 1);
pDC->FillSolidRect(rc, GetPaintManager()->m_clrHotDivider);
CXTPPenDC pen(*pDC, GetPaintManager()->m_clrHotDivider);
CXTPBrushDC brush(*pDC, GetPaintManager()->m_clrHotDivider);
int x = rc.left;
POINT ptsLeftArrow[] =
{
{x, y - 2},
{x + 2, y - 2},
{x + 2, y - 5},
{x + 7, y},
{x + 2, y + 5},
{x + 2, y + 2},
{x, y + 2}
};
pDC->Polygon(ptsLeftArrow, 7);
x = rc.right - 1;
POINT ptsRightArrow[] =
{
{x, y - 2},
{x - 2, y - 2},
{x - 2, y - 5},
{x - 7, y},
{x - 2, y + 5},
{x - 2, y + 2},
{x, y + 2}
};
pDC->Polygon(ptsRightArrow, 7);
}
BOOL CXTPReportControl::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID, CCreateContext *pContext)
{
return CXTPReportControl::Create(XTPREPORTCTRL_CLASSNAME, NULL, dwStyle, rect, pParentWnd, nID, pContext);
}
BOOL CXTPReportControl::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID, CCreateContext *pContext)
{
m_bCreated = TRUE;
return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}
void CXTPReportControl::PreSubclassWindow()
{
CWnd::PreSubclassWindow();
// DDX_Control subclasses the window and OnCreate and OnSize will not be called
if (!m_bCreated)
{
AdjustLayout();
AdjustScrollBars();
}
}
int CXTPReportControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (0 != CWnd::OnCreate(lpCreateStruct))
{
// CWnd creation failed
return -1;
}
return 0;
}
void CXTPReportControl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
BeginUpdate();
EditItem(NULL);
AdjustLayout();
AdjustScrollBars();
EndUpdate();
}
/////////////////////////////////////////////////////////////////////////////
// Left button
/////////////////////////////////////////////////////////////////////////////
void CXTPReportControl::OnButton(UINT nFlags, CPoint point,
CXTPReportBehaviorRowMouseButton* pBehavior)
{
UNREFERENCED_PARAMETER(nFlags);
XTPReportInputState inputState;
// Get input states
inputState.ptMouse = point;
inputState.bKeyControl = (::GetKeyState(VK_CONTROL) < 0) || m_bMultiSelectionMode;
inputState.bKeyShift = (::GetKeyState(VK_SHIFT) < 0);
inputState.nRow = -1;
inputState.bSelected = FALSE;
// Click arguments
XTP_REPORTRECORDITEM_CLICKARGS clickArgs;
clickArgs.pControl = this;
clickArgs.ptClient = point;
clickArgs.pColumn = NULL;
clickArgs.pRow = NULL;
clickArgs.pItem = NULL;
// Find clicked row
clickArgs.pRow = HitTest(point);
CXTPSmartPtrInternalT<CCmdTarget> ptrRowLock(clickArgs.pRow, TRUE);
if (NULL != clickArgs.pRow)
{
inputState.nRow = clickArgs.pRow->GetIndex();
inputState.bSelected = clickArgs.pRow->IsSelected();
// Find clicked item and column
clickArgs.pItem = clickArgs.pRow->HitTest(point, &clickArgs.rcItem, &clickArgs.pColumn);
}
// Store state
if (xtpReportMouseEventButtonDown == pBehavior->m_event)
{
m_mouseDownState = inputState;
}
CXTPReportBehaviorRowModifier *pModifier = NULL;
if (m_mouseDownState.bKeyShift) pModifier = pBehavior->Shift; // Shift
else if (m_mouseDownState.bKeyControl) pModifier = pBehavior->Control; // Control
else pModifier = pBehavior->None; // No modifier
// Current focused row index
const int nFocusedRowIndex = _GetFocusedRowIndex();
if (xtpReportMouseEventButtonDown == pBehavior->m_event)
{
SetFocus();
// If an item is currently edited, this need to be ended first.
// EditItem(NULL) sends a XTP_NM_REPORT_VALUECHANGED message
// and the user may modify the rows.
EditItem(NULL);
}
// Notify header
CXTPReportHeader *pHeader = GetReportHeader();
if (NULL != pHeader)
{
if (xtpReportMouseButtonLeft == pBehavior->m_button)
{
if (xtpReportMouseEventButtonDown == pBehavior->m_event)
{
pHeader->OnLButtonDown(point);
}
if (xtpReportMouseEventButtonUp == pBehavior->m_event)
{
pHeader->OnLButtonUp(nFlags, point);
}
}
}
if (NULL != clickArgs.pRow)
{
BOOL bHandled = FALSE;
// Notify row
if (xtpReportMouseButtonLeft == pBehavior->m_button)
{
if (xtpReportMouseEventButtonDown == pBehavior->m_event)
{
bHandled = clickArgs.pRow->OnLButtonDown(&clickArgs);
}
if (xtpReportMouseEventButtonUp == pBehavior->m_event)
{
bHandled = clickArgs.pRow->OnLButtonUp(&clickArgs);
}
}
// Notify inplace control
if (NULL != clickArgs.pItem)
{
}
if (!bHandled && clickArgs.pRow->GetSection()->IsAllowAccess())
{
BeginUpdate();
// Begin drag
if (pBehavior->bDragBegin)
{
m_ptDrag = point;
m_bPrepareDrag = TRUE;
}
// End drag
if (pBehavior->bDragEnd)
{
// Stop dragging
m_bPrepareDrag = FALSE;
// Stop auto scrolling
EnsureStopAutoVertScroll();
}
BOOL bKeepSelection = FALSE;
BOOL bKeepFocus = FALSE;
BOOL bDeferredDeselection = FALSE;
BOOL bFocused = TRUE;
const BOOL bSelected = clickArgs.pRow->IsSelected();
if (bSelected)
{
if (pModifier->bKeepSelection)
{
bKeepSelection = TRUE;
}
if (pModifier->bKeepFocus)
{
bKeepFocus = TRUE;
}
}
// Focus column
if (pBehavior->bFocusColumn && m_bFocusSubItems)
{
if (clickArgs.pItem && clickArgs.pItem->IsFocusable())
{
bFocused = SetFocusedColumn(clickArgs.pColumn);
}
else
{
bFocused = SetFocusedColumn(NULL);
}
}
// Focus row
if ((pModifier->bFocusRow || pModifier->bFocusRowTemporarily) && !bKeepFocus)
{
bFocused = _SetFocusedRow(clickArgs.pRow);
}
// Deferred deselection
if (m_mouseDownState.bKeyControl &&
m_mouseDownState.bSelected &&
m_mouseDownState.nRow == clickArgs.pRow->GetIndex() && xtpReportMouseEventButtonUp == pBehavior->m_event)
{
bDeferredDeselection = TRUE;
}
// Select row(s)
if ((pModifier->bSelectRow && !bKeepSelection) || bDeferredDeselection)
{
if (pModifier->bMultipleSelection)
{
_SetSelectedRow(clickArgs.pRow, nFocusedRowIndex, inputState.bKeyShift, inputState.bKeyControl);
if (IsSelectionEnabled() && IsMultipleSelection() && !inputState.bKeyShift && inputState.bKeyControl)
{
m_pSelectedRows->Invert(clickArgs.pRow);
}
}
else
{
_SetSelectedRow(clickArgs.pRow, nFocusedRowIndex, FALSE, FALSE);
}
}
// Ensure visible
if (pBehavior->bEnsureVisible)
{
EnsureVisible(clickArgs.pRow);
}
// Row click
if (pBehavior->bClick)
{
clickArgs.pRow->OnClick(point);
if (pBehavior->bCheckSelectedRows && clickArgs.pItem)
{
SetSelectionState(clickArgs.pItem->GetIndex(), clickArgs.pItem->GetCheckedState());
}
}
EndUpdate();
} // !bHandled
}
else if (m_bFastDeselectMode)
{
if (!inputState.bKeyControl && !inputState.bKeyShift)
{
m_pSelectedRows->Clear();
}
}
// Context menu
if (pBehavior->bContextMenu)
{
if (NULL != m_pSections->HitTest(point))
{
CXTPReportColumn *pColumn = NULL;
CXTPReportRecordItem *pItem = NULL;
if (NULL != clickArgs.pRow)
{
//clickArgs.pRow->HitTest(point, NULL, &pColumn);
clickArgs.pRow->OnContextMenu(point);
}
else
{
ClientToScreen(&point);
SendMessageToParent(clickArgs.pRow, pItem, pColumn, NM_RCLICK, &point);
}
}
}
// Restore focus
if (pModifier->bFocusRowTemporarily)
{
CXTPReportRow *pRow = NULL;
pRow = GetRows()->GetAt(nFocusedRowIndex);
BeginUpdate();
_SetFocusedRow(pRow);
EndUpdate();
}
if (m_pSelectedRows->IsChanged())
{
//TRACE(_T("OnSelectionChanged\n"));
OnSelectionChanged();
}
}
void CXTPReportControl::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDown(nFlags, point);
m_dwLastMouseMessage = WM_LBUTTONDOWN;
OnButton(nFlags, point, m_pBehavior->Row->MouseDown->Left);
}
void CXTPReportControl::OnLButtonUp(UINT nFlags, CPoint point)
{
//TRACE(_T("CXTPReportControl::OnLButtonUp\n"));
CWnd::OnLButtonUp(nFlags, point);
/*
The Windows window manager sends an unwanted WM_LBUTTONDOWN message if
the window is maximized with a double-click on the caption bar.
Window messages for double-click:
- WM_LBUTTONDOWN
- WM_LBUTTONUP
- WM_LBUTTONDBLCLK
- WM_LBUTTONUP
*/
if (WM_LBUTTONDOWN == m_dwLastMouseMessage ||
WM_LBUTTONDBLCLK == m_dwLastMouseMessage ||
xtpReportMouseNothing != GetMouseMode())
{
m_dwLastMouseMessage = WM_LBUTTONUP;
OnButton(nFlags, point, m_pBehavior->Row->MouseUp->Left);
}
}
void CXTPReportControl::OnLButtonDblClk(UINT nFlags, CPoint ptDblClick)
{
CWnd::OnLButtonDblClk(nFlags, ptDblClick);
m_dwLastMouseMessage = WM_LBUTTONDBLCLK;
EditItem(NULL);
// Information for delay editing
EnsureStopDelayEditTimer();
SetLastRqstEdit(-1, -1);
// columns processing
CXTPReportHeader *pHeader = GetReportHeader();
if (NULL != pHeader)
{
pHeader->OnLButtonDblClk(ptDblClick);
}
// rows processing
CXTPReportRow *pRow = HitTest(ptDblClick);
if (NULL != pRow)
{
pRow->OnDblClick(ptDblClick);
}
else // just notify parent
{
SendMessageToParent(NULL, NULL, NULL, NM_DBLCLK, &ptDblClick);
}
}
/////////////////////////////////////////////////////////////////////////////
// Right button
/////////////////////////////////////////////////////////////////////////////
void CXTPReportControl::OnRButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnRButtonDown(nFlags, point);
OnButton(nFlags, point, m_pBehavior->Row->MouseDown->Right);
}
void CXTPReportControl::OnRButtonUp(UINT nFlags, CPoint point)
{
CWnd::OnRButtonUp(nFlags, point);
if (!IsWindow(m_hWnd)) // Can be destroyed in WM_CONTEXTMENU
return;
OnButton(nFlags, point, m_pBehavior->Row->MouseUp->Right);
}
LRESULT CXTPReportControl::OnNcHitTest(CPoint point)
{
LRESULT ht = CWnd::OnNcHitTest(point);
if (ht != HTCLIENT)
return ht;
DWORD dwStyle = GetStyle();
if ((dwStyle & (WS_VSCROLL | WS_HSCROLL)) == 0)
return ht;
CXTPWindowRect rcWindow(this);
if (dwStyle & WS_VSCROLL)
{
if (IsLayoutRTL() || !!(GetWindowLong(m_hWnd, GWL_EXSTYLE) & WS_EX_LEFTSCROLLBAR))
{
CRect rc(rcWindow.left, rcWindow.top, GetSystemMetrics(SM_CXVSCROLL), rcWindow.bottom - (dwStyle & WS_HSCROLL ? GetSystemMetrics(SM_CYHSCROLL) : 0));
if (rc.PtInRect(point))
return HTVSCROLL;
}
else
{
CRect rc(rcWindow.right- GetSystemMetrics(SM_CXVSCROLL), rcWindow.top,
rcWindow.right, rcWindow.bottom - (dwStyle & WS_HSCROLL ? GetSystemMetrics(SM_CYHSCROLL) : 0));
if (rc.PtInRect(point))
return HTVSCROLL;
}
}
if (dwStyle & WS_HSCROLL)
{
CRect rc(rcWindow.left, rcWindow.bottom - GetSystemMetrics(SM_CYHSCROLL),
rcWindow.right - (dwStyle & WS_VSCROLL ? GetSystemMetrics(SM_CXVSCROLL) : 0), rcWindow.bottom);
if (rc.PtInRect(point))
return HTHSCROLL;
}
return ht;
}
void CXTPReportControl::OnContextMenu(CWnd *pWnd, CPoint pos)
{
UNREFERENCED_PARAMETER(pWnd);
if (GetMouseMode() != xtpReportMouseNothing)
return;
CPoint ptClient = pos;
ScreenToClient(&ptClient);
// call context menu handler for report header if clicked inside
if (m_rcHeaderArea.PtInRect(ptClient) ||
m_rcGroupByArea.PtInRect(ptClient))
{
CXTPReportHeader *pHeader = GetReportHeader();
if (pHeader)
pHeader->OnContextMenu(ptClient);
return;
}
// Context menu key
if (pos == CPoint(-1, -1))
{
CXTPReportRow *pFocusedRow = GetFocusedRow();
if (pFocusedRow)
{
// Menu position below row
ptClient = CPoint(
pFocusedRow->GetRect().left,
pFocusedRow->GetRect().bottom
);
pFocusedRow->OnContextMenu(ptClient);
}
else
{
pos = m_pSectionBody->m_rcSection.TopLeft();
ClientToScreen(&pos);
SendMessageToParent(NULL, NULL, NULL, NM_RCLICK, &pos);
}
}
}
CXTPReportColumn* CXTPReportControl::GetNextFocusableColumn(CXTPReportRow* pRow, int nColumnIndex, int nDirection)
{
if (!pRow->GetRecord())
return NULL;
for (;;)
{
CXTPReportColumn* pColumn = GetReportHeader()->GetNextVisibleColumn(nColumnIndex, nDirection);
if (!pColumn)
return NULL;
CXTPReportRecordItem* pItem = pRow->GetRecord()->GetItem(pColumn);
if (pItem && pItem->IsFocusable())
return pColumn;
nColumnIndex = pColumn->GetIndex();
}
}
BOOL CXTPReportControl::OnPreviewKeyDown(UINT& rnChar, UINT nRepCnt, UINT nFlags)
{
XTP_NM_REPORTPREVIEWKEYDOWN nmParams;
::ZeroMemory(&nmParams, sizeof(nmParams));
nmParams.nChar = rnChar;
nmParams.nRepCnt = nRepCnt;
nmParams.nFlags = nFlags;
nmParams.bCancel = FALSE;
SendNotifyMessage(XTP_NM_REPORT_PREVIEWKEYDOWN, (NMHDR*)&nmParams);
rnChar = nmParams.nChar;
return !nmParams.bCancel;
}
void CXTPReportControl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
BOOL bControlKeyOnly = (::GetKeyState(VK_CONTROL) < 0);
BOOL bControlKey = (::GetKeyState(VK_CONTROL) < 0) || m_bMultiSelectionMode;
BOOL bShiftKey = (::GetKeyState(VK_SHIFT) < 0);
CXTPReportRow* pFocusedRow = GetFocusedRow();
CXTPDrawHelpers::KeyToLayout(this, nChar);
int nRows = GetRows()->GetCount();
int nHeadRows = GetHeaderRows()->GetCount();
int nFootRows = GetFooterRows()->GetCount();
// Increase reference Count for pFocusedRow to be sure it won't be destroyed inside function.
CXTPSmartPtrInternalT<CCmdTarget> ptrRowLock(pFocusedRow, TRUE);
if (nRows > 0
|| nHeadRows > 0
|| nFootRows > 0)
switch (nChar)
{
case VK_F5:
Recalc(bShiftKey);
break;
case VK_ADD:
{
if (bControlKeyOnly)
{
if (!IsLockExpand())
{
ExpandAll();
}
}
else if ( pFocusedRow &&
pFocusedRow->HasChildren() &&
!pFocusedRow->IsExpanded() &&
!pFocusedRow->IsLockExpand())
{
pFocusedRow->SetExpanded(TRUE);
}
}
break;
case VK_SUBTRACT:
{
if (bControlKeyOnly)
{
if (!IsLockExpand())
{
CollapseAll();
}
}
else if ( pFocusedRow &&
pFocusedRow->HasChildren() &&
pFocusedRow->IsExpanded() &&
!pFocusedRow->IsLockExpand())
{
pFocusedRow->SetExpanded(FALSE);
}
}
break;
case VK_LEFT:
if (m_bIconView)
{
GetNavigator()->MoveLeft(bShiftKey, bControlKey);
}
else
{
/**
[0] if FocusSubItems we need check first if we can move one column left. if not - "fall down" for cases [1][2][3]
[1] If a row without children has the focus, focus shall be put on the parent row
[2] If a row with expanded children has the focus, children shall be collapsed
[3] If a row with collapsed children has the focus, focus shall be put on the parent row
*/
if (pFocusedRow)
{
if (m_bFocusSubItems && m_pFocusedColumn)
{
CXTPReportColumn* pColumn = GetNextFocusableColumn(pFocusedRow, m_pFocusedColumn->GetIndex(), -1);
if (pColumn)
{
SetFocusedColumn(pColumn);
SetFocusedRow(GetFocusedRow());
break;
}
}
/* [1], Row without children */
if (!pFocusedRow->HasChildren())
{
CXTPReportRow *pParent = pFocusedRow->GetParentRow();
if (NULL != pParent)
{
SetFocusedRow(pParent);
}
else
{
GetNavigator()->MoveUp(bShiftKey, bControlKey);
}
}
/* [2][3] Row with children */
else // if (pFocusedRow->HasChildren())
{
/* [2] Row with expanded children */
if (pFocusedRow->IsExpanded())
{
if (!pFocusedRow->IsLockExpand())
{
pFocusedRow->SetExpanded(FALSE);
}
else
{
GetNavigator()->MoveUp(bShiftKey, bControlKey);
}
}
/* [3] Row with collapsed children */
else
{
CXTPReportRow* pParent = pFocusedRow->GetParentRow();
// if we don't have parent just go up, like Outlook.
if (NULL != pParent)
{
SetFocusedRow(pParent);
}
else
{
GetNavigator()->MoveUp(bShiftKey, bControlKey);
}
}
}
}
}
break;
case VK_RIGHT:
if (m_bIconView)
{
GetNavigator()->MoveRight(bShiftKey, bControlKey);
break;
}
else
{
/**
[0] if FocusSubItems we need check first if we can move one column right. if not - "fall down" for cases [1][2][3]
[1] If a row with expanded children has the focus, focus shall be put on first children
[2] If a row with collapsed children has the focus, children shall be expanded
[3] If a row with no children has the focus, we go down like Outlook
*/
if (pFocusedRow)
{
if (m_bFocusSubItems && m_pFocusedColumn)
{
CXTPReportColumn* pColumn = GetNextFocusableColumn(pFocusedRow, m_pFocusedColumn->GetIndex(), +1);
if (pColumn)
{
SetFocusedColumn(pColumn);
SetFocusedRow(GetFocusedRow());
break;
}
}
if (pFocusedRow->HasChildren())
{
/* [1] Row with expanded children */
if (pFocusedRow->IsExpanded())
{
CXTPReportRows *pChildRows = pFocusedRow->GetChilds();
CXTPReportRow *pChildRow = pChildRows->GetAt(0);
SetFocusedRow(pChildRow);
}
/* [2] Row with collapsed children */
else
{
if (!pFocusedRow->IsLockExpand())
{
pFocusedRow->SetExpanded(TRUE, bControlKeyOnly);
}
else
{
GetNavigator()->MoveDown(bShiftKey, bControlKey);
}
}
}
else
{
GetNavigator()->MoveDown(bShiftKey, bControlKey);
}
}
}
break;
case VK_DOWN:
GetNavigator()->MoveDown(bShiftKey, bControlKey);
break;
case VK_UP:
GetNavigator()->MoveUp(bShiftKey, bControlKey);
break;
case VK_HOME:
GetNavigator()->MoveFirstRow(bShiftKey, FALSE);
break;
case VK_END:
GetNavigator()->MoveLastRow(bShiftKey, FALSE);
break;
case VK_NEXT:
GetNavigator()->MovePageDown(bShiftKey, FALSE);
break;
case VK_PRIOR:
GetNavigator()->MovePageUp(bShiftKey, FALSE);
break;
case VK_RETURN:
if (pFocusedRow && pFocusedRow->HasChildren() && !pFocusedRow->IsLockExpand())
{
pFocusedRow->SetExpanded(!pFocusedRow->IsExpanded());
}
break;
case VK_ESCAPE:
if (m_mouseMode != xtpReportMouseNothing)
GetReportHeader()->CancelMouseMode();
break;
case VK_F2:
GetNavigator()->BeginEdit();
break;
case VK_SPACE:
if (IsSelectionEnabled() && bControlKey && pFocusedRow)
{
if (pFocusedRow->IsSelected())
m_pSelectedRows->Remove(pFocusedRow);
else
m_pSelectedRows->Add(pFocusedRow);
OnSelectionChanged();
//OnSelectionChanged set Selection flag m_bChanged = FALSE;
}
break;
case 'A':
if (IsSelectionEnabled() && !bShiftKey && bControlKeyOnly && IsMultipleSelection())
{
if (IsVirtualMode())
{
GetNavigator()->MoveToRow(0);
GetNavigator()->MoveToRow(GetRecords()->GetCount() - 1, TRUE);
}
else
{
_SelectRows(GetRecords());
}
RedrawControl();
}
break;
}
NMKEY nmgv;
nmgv.nVKey = nChar;
nmgv.uFlags = nFlags;
SendNotifyMessage(NM_KEYDOWN, (NMHDR*)&nmgv);
}
//ICON_VIEW_MODE RELATED <<
void CXTPReportControl::SetNavigator(CXTPReportNavigator* pNavigator)
{
if (pNavigator)
{
CMDTARGET_RELEASE(m_pNavigator);
m_pNavigator = pNavigator;
}
}
void CXTPReportControl::SetIconViewToDefaults()
{
m_bIconView = FALSE;
m_iIconWidth = 0;
m_iIconHeight = 0;
m_iIconWidthSpacing = 0;
m_iIconHeightSpacing = 0;
m_iIconViewColumn = -1;
m_iIconViewRowsPerLine = 0;
m_bUseIconColumnForNum = FALSE;
m_iColumnForNum = -1;
m_bPrevFocusSubItems = FALSE;
m_bPrevHeaderAutoSize = FALSE;
m_iIconPropNum = 0;
m_iIconNum = 0;
m_pPrevVisible = NULL;
m_pPrevGroupsOrder = NULL;
m_nPrevTreeIndent = 0;
m_bIconColumnIndexNotValid = FALSE;
m_bPrevHeaderRows = FALSE;
m_bPrevFooterRows = FALSE;
m_bPrevHeaderShow = FALSE;
m_bPrevFooterShow = FALSE;
m_bRClickDrag = FALSE;
}
void CXTPReportControl::SetIconColumn(CXTPReportColumn* pColumn)
{
ASSERT(pColumn);
m_iIconViewColumn = pColumn ? pColumn->GetItemIndex() : -1;
}
void CXTPReportControl::CreateIconColumn(BOOL bUseColumnForNum, int nWidth)
{
if (GetColumns())
{
if (!m_bUseIconColumnForNum)
m_bUseIconColumnForNum = bUseColumnForNum;
if (m_iIconViewColumn == -1)
{
int iCnt = GetColumns()->GetCount();
if (GetRecords())
{
int iCnt0 = iCnt;
if (GetRecords()->GetAt(0))
iCnt = max(iCnt, GetRecords()->GetAt(0)->GetItemCount());
if (iCnt > iCnt0)
for (int iIc = 0; iIc < iCnt - iCnt0; iIc++)
AddColumn(new CXTPReportColumn(iIc,_T(""), 0, FALSE,XTP_REPORT_NOICON,FALSE,FALSE));
}
CXTPReportColumn* pIconCol = AddColumn(new CXTPReportColumn(iCnt, _T(""), 0));
pIconCol->SetVisible(FALSE);
if (m_bUseIconColumnForNum)
{
pIconCol->SetCaption(_T("#"));
pIconCol->SetVisible(TRUE);
pIconCol->SetHeaderAlignment(DT_CENTER);
pIconCol->SetWidth(nWidth);
if (GetColumns()->GetGroupsOrder()->GetCount() > 0 && nWidth < 30)
nWidth = 30;
GetPaintManager()->m_RecordNumberWidth = nWidth;
pIconCol->AllowRemove(FALSE);
pIconCol->EnableResize(FALSE);
//pIconCol->SetAutoSize(FALSE);
pIconCol->SetAllowDrag(FALSE);
pIconCol->SetEditable(FALSE);
pIconCol->SetGroupable(FALSE);
pIconCol->SetSortable(FALSE);
}
m_iIconViewColumn = pIconCol->GetIndex();
m_iColumnForNum = m_iIconViewColumn;
}
}
}
void CXTPReportControl::AssignIconViewPropNumAndIconNum(int nCol, int nIcon,
BOOL bUseColumnForNum, int nWidth)
{
BOOL bAlreadyUsed = m_bUseIconColumnForNum;
m_bIconColumnIndexNotValid = TRUE;
CreateIconColumn(bUseColumnForNum, nWidth);
m_bIconColumnIndexNotValid = FALSE;
if (!bAlreadyUsed && bUseColumnForNum)
{
m_bUseIconColumnForNum = bUseColumnForNum;
if (m_iIconViewColumn > -1)
{
CXTPReportColumn* pIconCol = GetColumns()->GetAt(m_iIconViewColumn);
if (m_bUseIconColumnForNum)
{
pIconCol->SetCaption(_T("#"));
pIconCol->SetVisible(TRUE);
pIconCol->SetHeaderAlignment(DT_CENTER);
pIconCol->SetWidth(nWidth);
if (GetColumns()->GetGroupsOrder()->GetCount() > 0 && nWidth < 30)
nWidth = 30;
GetPaintManager()->m_RecordNumberWidth = nWidth;
pIconCol->AllowRemove(FALSE);
pIconCol->EnableResize(FALSE);
pIconCol->SetEditable(FALSE);
pIconCol->SetGroupable(FALSE);
pIconCol->SetSortable(FALSE);
}
}
}
if (nCol > -1)
m_iIconPropNum = nCol;
if (nIcon > -1)
m_iIconNum = nIcon;
if (!bAlreadyUsed && m_iColumnForNum > -1 && bUseColumnForNum)
GetColumns()->ChangeColumnOrder(0, m_iColumnForNum);
}
//ICON_VIEW_MODE RELATED >>
void CXTPReportControl::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
}
void CXTPReportControl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
m_bWasShiftKey = (GetKeyState(VK_SHIFT) < 0);
CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
}
void CXTPReportControl::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CWnd::OnSysKeyUp(nChar, nRepCnt, nFlags);
}
void CXTPReportControl::OnChar(UINT nChar, UINT nRepCntr, UINT nFlags)
{
NMCHAR nmgv;
ZeroMemory(&nmgv, sizeof(NMCHAR));
nmgv.ch = nChar;
SendNotifyMessage(NM_CHAR, (NMHDR*)&nmgv);
CXTPReportRow* pFocusedRow = GetFocusedRow();
if (pFocusedRow && (nChar == VK_TAB))
{
if (m_bFocusSubItems)
{
CXTPSmartPtrInternalT<CCmdTarget> ptrRowLock(pFocusedRow, TRUE);
EditItem(NULL);
BOOL bBack = (GetKeyState(VK_SHIFT) < 0);
GetNavigator()->MoveLeftRight(bBack);
if (IsAllowEdit() && m_bEditOnClick && !m_bTrapTabKey)
{
GetNavigator()->BeginEdit();
}
}
return;
}
if (m_pFocusedColumn && pFocusedRow && pFocusedRow->GetRecord()
&& (nChar != VK_RETURN) && (nChar != VK_ESCAPE))
{
XTP_REPORTRECORDITEM_ARGS itemArgs(this, pFocusedRow, m_pFocusedColumn);
if (itemArgs.pItem && itemArgs.pItem->OnChar(&itemArgs, nChar))
return;
}
CWnd::OnChar(nChar, nRepCntr, nFlags);
}
void CXTPReportControl::OnCaptureChanged(CWnd* pWnd)
{
if (m_mouseMode != xtpReportMouseNothing)
GetReportHeader()->CancelMouseMode();
CWnd::OnCaptureChanged(pWnd);
}
void CXTPReportControl::OnEnable(BOOL bEnable)
{
UNREFERENCED_PARAMETER(bEnable);
AdjustScrollBars();
}
UINT CXTPReportControl::GetMouseScrollLines()
{
UINT nScrollLines = 3; // default value
if (XTPSystemVersion()->IsWin95())
{
HKEY hKey;
if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), 0, KEY_QUERY_VALUE, &hKey))
{
TCHAR szData[128];
DWORD dwKeyDataType;
DWORD dwDataBufSize = sizeof(szData);
if (ERROR_SUCCESS == ::RegQueryValueEx(hKey, _T("WheelScrollLines"), NULL, &dwKeyDataType, (LPBYTE) &szData, &dwDataBufSize))
{
nScrollLines = _tcstoul(szData, NULL, 10);
}
::RegCloseKey(hKey);
}
}
// win98 or greater
else
{
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
}
return nScrollLines;
}
BOOL CXTPReportControl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (!m_bVScrollBarVisible)
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
UINT uiMsg;
int nScrollsCount = 0;
// calculate what should be sent
if (m_nRowsPerWheel == -1)
{
// A m_nRowsPerWheel value less than 0 indicates that the mouse wheel scrolls whole pages, not just lines.
int nPagesScrolled = zDelta / 120;
uiMsg = nPagesScrolled > 0 ? SB_PAGEUP : SB_PAGEDOWN;
nScrollsCount = nPagesScrolled > 0 ? nPagesScrolled : -nPagesScrolled;
}
else
{
int nRowsScrolled = m_nRowsPerWheel * zDelta / 120;
uiMsg = nRowsScrolled > 0 ? SB_LINEUP : SB_LINEDOWN;
nScrollsCount = nRowsScrolled > 0 ? nRowsScrolled : -nRowsScrolled;
}
BeginUpdate();
// send scroll messages
for (int i = 0; i < nScrollsCount; i++)
{
OnVScroll(uiMsg, 0, NULL);
}
EndUpdate();
UpdateWindow();
return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}
void CXTPReportControl::OnMouseLeave()
{
OnMouseMove(0, CPoint(-1, -1));
}
void CXTPReportControl::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd::OnMouseMove(nFlags, point);
CXTPReportHeader *pHeader = GetReportHeader();
CXTPReportColumn *pColumn = NULL;
CXTPReportRow *pRow = NULL;
CXTPReportRecordItem *pItem = NULL;
if (NULL != pHeader)
{
pHeader->OnMouseMove(nFlags, point);
}
CXTPReportRow* pHotExpandButtonRow = NULL;
CXTPReportHyperlink *pHotHyperlink = NULL;
if (GetMouseMode() == xtpReportMouseNothing)
{
pRow = HitTest(point);
if (NULL != pRow)
{
pRow->OnMouseMove(nFlags, point);
// Hyperlink hit test
pItem = pRow->HitTest(point);
if (NULL != pItem)
{
pColumn = pItem->GetColumn();
int nHyperlink = pItem->HitTestHyperlink(point);
if (nHyperlink >= 0)
{
pHotHyperlink = pItem->GetHyperlinks()->GetAt(nHyperlink);
}
}
if (m_bShowTooltips && nFlags == 0)
{
pRow->ShowToolTip(point, m_pTip);
}
}
if (pRow && pRow->IsGroupRow() && m_pPaintManager->m_columnStyle == xtpReportColumnResource)
{
if (pRow->m_rcCollapse.PtInRect(point))
{
pHotExpandButtonRow = pRow;
}
}
if (m_pHotRow != pRow)
{
TRACKMOUSEEVENT tme =
{
sizeof(TRACKMOUSEEVENT), TME_LEAVE, GetSafeHwnd(), 0
};
_TrackMouseEvent (&tme);
m_pHotRow = pRow;
}
// If mouse moved some since down...
if (m_bPrepareDrag && (labs (point.x - m_ptDrag.x) > 3 ||
labs (point.y - m_ptDrag.y) > 3))
{
// Prevent duplicate
m_bPrepareDrag = FALSE;
// Begin a drag operation
OnBeginDrag(m_ptDrag, nFlags);
}
}
if (m_pHotHyperlink != pHotHyperlink)
{
m_pHotHyperlink = pHotHyperlink;
RedrawControl();
}
if (m_pHotExpandButtonRow != pHotExpandButtonRow)
{
m_pHotExpandButtonRow = pHotExpandButtonRow;
RedrawControl();
}
SendMessageToParent(pRow, pItem, pColumn, XTP_NM_REPORT_MOUSEMOVE, &point);
}
class CXTPReportDropSource : public COleDropSource
{
public:
CXTPReportDropSource(CXTPReportControl *pControl)
: m_pControl(pControl)
{
}
virtual SCODE GiveFeedback(DROPEFFECT dropEffect)
{
SCODE sCode = NOERROR;
XTP_NM_REPORTGIVEFEEDBACK giveFeedback;
giveFeedback.dropEffect = dropEffect;
giveFeedback.bDragStarted = m_bDragStarted;
LRESULT lResult = m_pControl->SendNotifyMessage(XTP_NM_REPORT_GIVEFEEDBACK, &giveFeedback);
if (0 != lResult)
{
sCode = S_OK;
}
else
{
sCode = COleDropSource::GiveFeedback(dropEffect);
}
return sCode;
}
protected:
CXTPReportControl *m_pControl;
};
void CXTPReportControl::OnBeginDrag(CPoint point)
{
OnBeginDrag(point, 0);
}
void CXTPReportControl::OnBeginDrag(CPoint point, UINT nFlags)
{
if (SendMessageToParent(NULL, NULL, NULL, LVN_BEGINDRAG, &point))
return;
//R-DD <<
if ((nFlags & MK_RBUTTON) && SendMessageToParent(NULL, NULL, NULL, LVN_BEGINRDRAG, &point))
return;
//R-DD >>
if (m_cfReport == NULL)
return;
CXTPReportSelectedRows* pSelectedRows = GetSelectedRows();
if (!pSelectedRows)
return;
if ((m_dwDragDropFlags & xtpReportAllowDrag) == 0)
return;
if (pSelectedRows->m_nRowType == xtpRowTypeHeader ||
pSelectedRows->m_nRowType == xtpRowTypeFooter)
return;
int nCount = pSelectedRows->GetCount();
for (int i = nCount - 1; i >= 0; i--)
{
CXTPReportRow* pRow = pSelectedRows->GetAt(i);
if (pRow->IsGroupRow())
{
pRow->SetExpanded(TRUE);
pRow->SelectChilds();
}
}
int nRowsCount = pSelectedRows->GetCount();
if (nRowsCount < 1)
return;
// minimize memory reallocs to improve performance
UINT nAveRecordsSize = 1500; // bytes
UINT nGrowBytes = ((nRowsCount * nAveRecordsSize) / 4096 + 1) * 4096;
UINT nAllocFlags = GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT;
CSharedFile fileRecords(nAllocFlags, nGrowBytes);
BOOL bSucceed = FALSE;
//------------------------------------------------------------------------
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
CXTPReportRecords* pDragRecords = new CXTPReportRecords(TRUE);
if (!_GetSelectedRows(pDragRecords))
{
CMDTARGET_RELEASE(pDragRecords);
return;
}
try
{
CArchive ar(&fileRecords, CArchive::store);
CXTPPropExchangeArchive px(ar);
bSucceed = _WriteRecordsData(&px, pDragRecords);
ar.Close(); // perform Flush() and detach from file
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnBeginDrag() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnBeginDrag() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnBeginDrag() - Unhandled Exception!\n"));
}
if (!bSucceed)
{
CMDTARGET_RELEASE(pDragRecords);
return;
}
HGLOBAL hGlobal = fileRecords.Detach();
m_bDragMode = TRUE;
m_bInternalDrag = TRUE;
DROPEFFECT dropEffectMask =
((m_dwDragDropFlags & xtpReportAllowDragCopy) ? DROPEFFECT_COPY : 0) +
((m_dwDragDropFlags & xtpReportAllowDragMove) ? DROPEFFECT_MOVE : 0);
COleDataSource* pds = new COleDataSource();
XTP_NM_REPORTDRAGDROP nmData;
ZeroMemory(&nmData, sizeof(nmData));
nmData.pRecords = pDragRecords;
nmData.pDataSource = pds; // Data Source - issue 22675
if (SendNotifyMessage(XTP_NM_REPORT_BEGINDRAG, (NMHDR*) &nmData) == -1)
{
CMDTARGET_RELEASE(pDragRecords);
CMDTARGET_RELEASE(m_pSelectedRowsBeforeDrag)
m_bDragMode = FALSE;
m_bInternalDrag = FALSE;
pds->InternalRelease();
return;
}
pds->CacheGlobalData(m_cfReport, hGlobal);
if (!(m_dwDragDropFlags & xtpReportDontDropAsText))
{
// Get As Text
CString strDropText = _GetSelectedRowsVisibleColsText();
HGLOBAL hDropText = XTPAllocStrInGlobalMem(strDropText);
if (hDropText)
pds->CacheGlobalData(XTP_CF_TEXT_T, hDropText);
}
CXTPReportDropSource dropSource(this);
DROPEFFECT dropEffect = pds->DoDragDrop(dropEffectMask, NULL, &dropSource);
m_bDragMode = FALSE;
m_bInternalDrag = FALSE;
if ((m_dwDropMarkerFlags & xtpReportDropSelect)
&& m_pSelectedRowsBeforeDrag)
{
// Must remember the selected items before drag.
m_pSelectedRows->Clear();
for (int i = 0; i < m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks.GetSize(); i++)
m_pSelectedRows->m_arrSelectedBlocks.Add(m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks[i]);
CMDTARGET_RELEASE(m_pSelectedRowsBeforeDrag);
}
nmData.dropEffect = dropEffect;
SendNotifyMessage(XTP_NM_REPORT_DRAGDROP_COMPLETED, (NMHDR*) &nmData);
if ((dropEffect == DROPEFFECT_MOVE) && (dropEffectMask & DROPEFFECT_MOVE))
{
Cut();
}
CMDTARGET_RELEASE(pDragRecords);
EnsureStopAutoVertScroll();
pds->InternalRelease();
}
DROPEFFECT CXTPReportControl::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point, int nState)
{
DROPEFFECT dropEffect = DROPEFFECT_MOVE;
BOOL bAbove = TRUE;
CXTPReportRecord* pTargetRecord = NULL;
int nTargetRow = -1;
if (nState == 0)
{
// Must get the selected rows before the selection changes.
if(m_dwDropMarkerFlags & xtpReportDropSelect)
{
// Must remember the selected items before drag.
m_pSelectedRowsBeforeDrag = new CXTPReportSelectedRows(this);
for (int i=0; i<m_pSelectedRows->m_arrSelectedBlocks.GetSize(); i++)
{
m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks.Add(m_pSelectedRows->m_arrSelectedBlocks[i]);
}
}
}
if ((dwKeyState & MK_CONTROL) == MK_CONTROL)
{
dropEffect = DROPEFFECT_COPY;
}
if (!m_nOLEDropMode)
{
if (m_cfReport == NULL)
dropEffect = DROPEFFECT_NONE;
if ((m_dwDragDropFlags & xtpReportAllowDrop) == 0)
dropEffect = DROPEFFECT_NONE;
XTP_NM_REPORTDRAGDROP nmData;
nmData.dropEffect = dropEffect;
nmData.pDataObject = pDataObject;
nmData.pt = point;
//R-DD <<
nmData.dwKeyState = dwKeyState;
//R-DD >>
int iValid = (int) SendNotifyMessage(XTP_NM_REPORT_HASVALIDDROPTYPE, (NMHDR*) &nmData);
m_nOLEDropAbove = nmData.bAbove;
if ((dropEffect != DROPEFFECT_NONE)
&& (!pDataObject || (!pDataObject->IsDataAvailable(m_cfReport) && iValid != 1)))
dropEffect = DROPEFFECT_NONE;
}
int nDropPos = m_nDropPos;
m_nDropPos = -1;
if (dropEffect != DROPEFFECT_NONE)
{
EnsureStartAutoVertScroll();
// DoAutoVertScrollIfNeed(m_ptDrag, point);
m_bNoNeedSortedDragDrop = (GetColumns()->GetSortOrder()->GetCount() == 0
&& GetColumns()->GetGroupsOrder()->GetCount() == 0);
if (m_bNoNeedSortedDragDrop || m_bSortedDragDrop)
{
CXTPReportRow *pRow = HitTest(point);
if (pRow && pRow->GetRecord())
{
if (pRow->GetRect().CenterPoint().y < point.y)
bAbove = FALSE;
if (bAbove)
m_nDropPos = pRow->GetRect().top == 0 ? 0 : pRow->GetRect().top - 1;
//m_nDropPos = pRow->GetRect().top - 1;
else
m_nDropPos = pRow->GetRect().bottom - 1;
pTargetRecord = pRow->GetRecord();
nTargetRow = pRow->GetIndex();
if (((m_dwDropMarkerFlags & xtpReportDropSelect)
&& (m_dwDropMarkerFlags & xtpReportDropBetween)
&& point.y > (pRow->GetRect().top + 3)
&& point.y < (pRow->GetRect().bottom - 3))
|| ((m_dwDropMarkerFlags & xtpReportDropSelect)
&& point.y > pRow->GetRect().top
&& point.y < pRow->GetRect().bottom))
{
XTP_NM_REPORTDRAGDROP nmData;
nmData.dropEffect = dropEffect;
nmData.pDataObject = pDataObject;
nmData.pTargetRecord = pTargetRecord;
nmData.nTargetRow = nTargetRow;
nmData.pt = point;
//R-DD <<
nmData.dwKeyState = dwKeyState;
//R-DD >>
int iValid = (int) SendNotifyMessage(XTP_NM_REPORT_VALIDDROPTARGET, (NMHDR*) &nmData);
if (iValid == 1)
m_pSelectedRows->Select(pRow);
else
m_pSelectedRows->Clear();
m_nOLEDropAbove = nmData.bAbove;
}
else if(m_dwDropMarkerFlags & xtpReportDropSelect)
{
m_pSelectedRows->Clear();
}
}
else
{
if ((m_nDropPos > m_pSectionBody->m_rcSection.top - 1 || m_nDropPos < m_pSectionBody->m_rcSection.bottom - 1))
m_nDropPos = point.y;
if (GetRows()->GetCount() == 0)
m_nDropPos = 0;
if (m_dwDropMarkerFlags & xtpReportDropSelect)
m_pSelectedRows->Clear();
}
if (m_nDropPos == 0 && GetRows()->GetCount() == 0)
m_nDropPos = m_pSectionBody->m_rcSection.top;
else if ((m_nDropPos < m_pSectionBody->m_rcSection.top - 1 || m_nDropPos > m_pSectionBody->m_rcSection.bottom - 1))
dropEffect = DROPEFFECT_NONE;
}
}
if (nState == 0)
{
// entering, get report records
CMDTARGET_RELEASE(m_pDropRecords);
CFile* pFile = m_cfReport ? pDataObject->GetFileData(m_cfReport) : NULL;
if (pFile)
{
m_pDropRecords = new CXTPReportRecords();
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
try
{
CArchive ar(pFile, CArchive::load);
CXTPPropExchangeArchive px(ar);
if (!_ReadRecordsFromData(&px, *m_pDropRecords))
{
m_pDropRecords->RemoveAll();
}
ar.Close(); // detach from file
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnDragOver() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnDragOver() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnDragOver() - Unhandled Exception!\n"));
}
delete pFile;
}
m_bDragMode = TRUE;
}
else if (nState == 1)
{
// leaving, release drop records
CMDTARGET_RELEASE(m_pDropRecords);
if ((m_dwDropMarkerFlags & xtpReportDropSelect)
&& m_pSelectedRowsBeforeDrag)
{
// Must remember the selected items before drag.
m_pSelectedRows->Clear();
for (int i = 0; i < m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks.GetSize(); i++)
m_pSelectedRows->m_arrSelectedBlocks.Add(m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks[i]);
CMDTARGET_RELEASE(m_pSelectedRowsBeforeDrag);
}
m_bDragMode = FALSE;
}
COleDataSource* pds = new COleDataSource();
XTP_NM_REPORTDRAGDROP nmData;
nmData.pRecords = m_pDropRecords;
nmData.pTargetRecord = pTargetRecord;
nmData.nTargetRow = nTargetRow;
nmData.bAbove = bAbove;
nmData.dropEffect = dropEffect;
nmData.pt = point;
nmData.nState = nState;
nmData.pDataSource = pds; // Data Source - issue 22675
nmData.pDataObject = pDataObject;
//R-DD <<
nmData.dwKeyState = dwKeyState;
//R-DD >>
m_nOLEDropAbove = nmData.bAbove;
SendNotifyMessage(XTP_NM_REPORT_DRAGOVER, (NMHDR*) &nmData);
m_nOLEDropAbove = nmData.bAbove;
if (nState != 1
&& nmData.dropEffect == DROPEFFECT_NONE
&& (m_dwDropMarkerFlags & xtpReportDropSelect))
m_pSelectedRows->Clear();
if (m_nDropPos != nDropPos)
RedrawControl();
pds->InternalRelease();
return nmData.dropEffect;
}
BOOL CXTPReportControl::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
{
CMDTARGET_RELEASE(m_pDropRecords);
EnsureStopAutoVertScroll();
m_bDragMode = FALSE;
if (m_nDropPos == -1)
return FALSE;
CUpdateContext updateContext(this);
int nDropPos = m_nDropPos;
m_nDropPos = -1;
if (dropEffect != DROPEFFECT_COPY
&& dropEffect != DROPEFFECT_MOVE)
return FALSE;
//if (IsVirtualMode()) return FALSE;
int nTargetRow = -1;
if ((m_dwDropMarkerFlags & xtpReportDropSelect)
&& m_pSelectedRows->GetCount() == 1)
nTargetRow = m_pSelectedRows->GetAt(0)->GetIndex();
XTP_NM_REPORTDRAGDROP nmData;
nmData.dropEffect = dropEffect;
nmData.pDataObject = pDataObject;
nmData.pt = point;
int iValid = (int) SendNotifyMessage(XTP_NM_REPORT_HASVALIDDROPTYPE, (NMHDR*) &nmData);
m_nOLEDropAbove = nmData.bAbove;
if (iValid != -1 && nmData.dropEffect == DROPEFFECT_NONE)
{
// Drop handled or not allowed.
if ((m_dwDropMarkerFlags & xtpReportDropSelect)
&& m_pSelectedRowsBeforeDrag)
{
// Must remember the selected items before drag.
m_pSelectedRows->Clear();
for (int i = 0; i < m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks.GetSize(); i++)
m_pSelectedRows->m_arrSelectedBlocks.Add(m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks[i]);
CMDTARGET_RELEASE(m_pSelectedRowsBeforeDrag);
}
return FALSE;
}
if ((m_dwDropMarkerFlags & xtpReportDropSelect)
&& m_pSelectedRowsBeforeDrag)
{
// Must remember the selected items before drag.
m_pSelectedRows->Clear();
for (int i = 0; i < m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks.GetSize(); i++)
m_pSelectedRows->m_arrSelectedBlocks.Add(m_pSelectedRowsBeforeDrag->m_arrSelectedBlocks[i]);
CMDTARGET_RELEASE(m_pSelectedRowsBeforeDrag);
}
if (!pDataObject || (!pDataObject->IsDataAvailable(m_cfReport) && iValid != 1))
return FALSE;
if ((m_dwDragDropFlags & xtpReportAllowDrop) == 0)
return FALSE;
int nInsert = GetRecords()->GetCount();
BOOL bAbove = TRUE;
CXTPReportRecord* pTargetRecord = NULL;
CXTPReportRecord* pOriginalTargetRecord = NULL;
CXTPReportRow* pRow = HitTest(point);
if (pRow)
{
if (pRow->GetRect().CenterPoint().y < point.y)
bAbove = FALSE;
pTargetRecord = pRow->GetRecord();
if (pTargetRecord)
{
if (m_bUnrestrictedDragDrop)
pOriginalTargetRecord = pTargetRecord;
while (pTargetRecord->GetParentRecord() != NULL)
pTargetRecord = pTargetRecord->GetParentRecord();
nInsert = pTargetRecord->GetIndex();
if (!m_bNoNeedSortedDragDrop
&& m_bSortedDragDrop && nInsert != -1
&& m_pSectionBody->m_UaSorted.GetSize() > nInsert)
nInsert = m_pSectionBody->m_UaSorted.GetAt(nInsert);
if (!bAbove)
nInsert++;
}
}
m_bInternalMove = FALSE;
if (m_bInternalDrag && dropEffect == DROPEFFECT_MOVE)
{
m_bInternalMove = TRUE;
if (nDropPos == -1)
return FALSE;
BOOL bRedraw = FALSE;
if (!m_bNoNeedSortedDragDrop && m_bSortedDragDrop && GetColumns()->GetGroupsOrder()->GetCount() == 0)
{
ReleaseSorted();
bRedraw = TRUE;
}
CXTPReportRecords* pDropRecords = new CXTPReportRecords(TRUE);
if (!iValid && (!_GetSelectedRows(pDropRecords)
|| pDropRecords->GetCount() == GetRows()->GetCount()))
{
CMDTARGET_RELEASE(pDropRecords);
return FALSE;
}
if (bRedraw)
{
Populate();
RedrawControl();
}
nmData.pRecords = pDropRecords;
nmData.pTargetRecord = pTargetRecord;
nmData.nTargetRow = nTargetRow;
if (m_bUnrestrictedDragDrop)
nmData.pTargetRecord = pOriginalTargetRecord;
nmData.bAbove = bAbove;
nmData.dropEffect = dropEffect;
nmData.pDataObject = pDataObject;
//nmData.bReturnValue = TRUE; //James proposal (wrong!)
nmData.bReturnValue = FALSE;
m_nOLEDropAbove = nmData.bAbove;
CMDTARGET_ADDREF(pTargetRecord);
if (SendNotifyMessage(XTP_NM_REPORT_DROP, (NMHDR*) &nmData) == -1)
{
CMDTARGET_RELEASE(pDropRecords);
CMDTARGET_RELEASE(pTargetRecord);
return nmData.bReturnValue;
}
if (!IsVirtualMode())
{
if (!pTargetRecord == NULL)
nInsert = pTargetRecord->GetIndex();
else
nInsert = GetRows()->GetCount();
if (!bAbove)
nInsert++;
GetRecords()->Move(nInsert, pDropRecords);
Populate();
_SelectRows(pDropRecords);
RedrawControl();
}
m_nOLEDropAbove = nmData.bAbove;
SendNotifyMessage(XTP_NM_REPORT_RECORDS_DROPPED, (NMHDR*) &nmData);
CMDTARGET_RELEASE(pDropRecords);
CMDTARGET_RELEASE(pTargetRecord);
return nmData.bReturnValue;
}
CXTPReportRecords* pDropRecords = NULL;
if (pDataObject->IsDataAvailable(m_cfReport))
{
CFile* pFile = pDataObject->GetFileData(m_cfReport);
if (pFile)
{
pDropRecords = new CXTPReportRecords();
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
try
{
CArchive ar(pFile, CArchive::load);
CXTPPropExchangeArchive px(ar);
if (!_ReadRecordsFromData(&px, *pDropRecords))
{
pDropRecords->RemoveAll();
}
ar.Close(); // detach from file
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnDrop() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnDrop() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPReportControl::OnDrop() - Unhandled Exception!\n"));
}
delete pFile;
}
}
nmData.pRecords = pDropRecords;
nmData.pTargetRecord = pTargetRecord;
if (m_bUnrestrictedDragDrop)
nmData.pTargetRecord = pOriginalTargetRecord;
nmData.nTargetRow = nTargetRow;
nmData.bAbove = bAbove;
nmData.dropEffect = dropEffect;
nmData.pDataObject = pDataObject;
nmData.bReturnValue = TRUE;
m_nOLEDropAbove = nmData.bAbove;
if (SendNotifyMessage(XTP_NM_REPORT_DROP, (NMHDR*) &nmData) == -1)
{
CMDTARGET_RELEASE(pDropRecords);
return nmData.bReturnValue;
}
m_nOLEDropAbove = nmData.bAbove;
if (!IsVirtualMode() && pDropRecords)
{
// Add and Populate records
int nRecordsCount = pDropRecords->GetCount();
if (nRecordsCount > 0)
{
// Add
for (int i = 0; i < nRecordsCount; i++)
{
CXTPReportRecord* pRecord = pDropRecords->GetAt(i);
if (pRecord)
{
CMDTARGET_ADDREF(pRecord);
GetRecords()->InsertAt(nInsert, pRecord);
nInsert++;
}
}
Populate();
_SelectRows(pDropRecords);
RedrawControl();
SendNotifyMessage(XTP_NM_REPORT_RECORDS_DROPPED, (NMHDR*) &nmData);
}
}
else
{
SendNotifyMessage(XTP_NM_REPORT_RECORDS_DROPPED, (NMHDR*) &nmData);
}
CMDTARGET_RELEASE(pDropRecords);
//return TRUE;
return nmData.bReturnValue;
}
void CXTPReportControl::ReleaseSorted()
{
int nSortCnt = GetColumns()->GetSortOrder()->GetCount();
if (nSortCnt > 0)
{
GetColumns()->GetSortOrder()->Clear();
CXTPReportRecord* pDropRec;
int N = (int) m_pSectionBody->m_UaSorted.GetSize();
for (int J = 0; J < N; J++)
{
pDropRec = GetRows()->GetAt(J)->GetRecord();
if (pDropRec)
{
CXTPReportRecords* pDropRecs = new CXTPReportRecords(TRUE);
pDropRecs->Add(pDropRec);
GetRecords()->Move(J, pDropRecs);
delete pDropRecs;
}
}
}
if (GetColumns()->GetGroupsOrder()->GetCount() > 0)
GetColumns()->GetGroupsOrder()->Clear();
m_bNoNeedSortedDragDrop = TRUE;
m_bSortedDragDrop = TRUE;
}
void CXTPReportControl::OnTimer(UINT_PTR uTimerID)
{
if (m_uAutoScrollTimerID == uTimerID)
{
CPoint ptMouse;
if (::GetCursorPos(&ptMouse))
{
ScreenToClient(&ptMouse);
DoAutoVertScrollIfNeed(m_ptDrag, ptMouse);
}
}
if (m_uRqstEditTimer == uTimerID)
{
m_iLastRqstEditRow = -1;
m_iLastRqstEditCol = -1;
}
// Information for delay editing.
if (m_uiDelayEditTimer == uTimerID)
{
EnsureStopDelayEditTimer();
ASSERT(!IsEditMode());
if ( m_iLastRqstEditRow != -1
&& m_iLastRqstEditCol != -1
&& m_iLastRqstEditRow < GetRows()->GetCount()
&& IsEditOnDelayClick())
{
XTP_REPORTRECORDITEM_ARGS args(this, GetRows()->GetAt(m_iLastRqstEditRow), GetColumns()->Find(m_iLastRqstEditCol));
EditItem(&args);
StartLastRqstTimer();
}
}
CWnd::OnTimer(uTimerID);
}
void CXTPReportControl::EnsureStopAutoVertScroll()
{
if (m_uAutoScrollTimerID)
{
KillTimer(m_uAutoScrollTimerID);
m_uAutoScrollTimerID = 0;
}
}
void CXTPReportControl::EnsureStartAutoVertScroll()
{
if (0 == m_uAutoScrollTimerID)
{
m_uAutoScrollTimerID = SetTimer(XTP_REPORT_AUTO_SCROLL_TIMER_ID, m_nAutoVScrollTimerResolution, NULL);
}
}
void CXTPReportControl::SetAutoVScrollTimerResolution(UINT nNewTimerResolution)
{
if (nNewTimerResolution == m_nAutoVScrollTimerResolution)
return;
BOOL bStartTimer = (m_uAutoScrollTimerID != 0);
EnsureStopAutoVertScroll();
m_nAutoVScrollTimerResolution = nNewTimerResolution;
if (bStartTimer)
EnsureStartAutoVertScroll();
}
void CXTPReportControl::DoAutoVertScrollIfNeed(CPoint ptClick, CPoint pt)
{
enum XTPReportControlDirection
{
xtpReportControlDirectionNone = 0,
xtpReportControlDirectionUp = -1,
xtpReportControlDirectionDown = 1
};
CXTPReportScreenRows *pScreenRows = GetRows()->GetScreenRows();
if (0 == pScreenRows->GetSize())
{
EnsureStopAutoVertScroll();
return;
}
CXTPReportRow *pRowUp = pScreenRows->GetAt(0);
CXTPReportRow *pRowDown = pScreenRows->GetAt(pScreenRows->GetSize() - 1);
if (NULL == pRowUp || NULL == pRowDown)
{
EnsureStopAutoVertScroll();
return;
}
XTPReportControlDirection nDirection = xtpReportControlDirectionNone;
CRect rcUp = m_pSectionBody->m_rcSection;
CRect rcDown = m_pSectionBody->m_rcSection;
rcUp.bottom = m_pSectionBody->m_rcSection.top + 20; //while dragging item
rcDown.top = m_pSectionBody->m_rcSection.bottom - 20;
if (rcUp.PtInRect(pt))
{
nDirection = xtpReportControlDirectionUp;
}
if (rcDown.PtInRect(pt))
{
nDirection = xtpReportControlDirectionDown;
}
if (xtpReportControlDirectionNone == nDirection || m_bDragMode &&
((xtpReportControlDirectionDown == nDirection && pt.y - ptClick.y < 3) ||
(xtpReportControlDirectionUp == nDirection && ptClick.y - pt.y < 3)))
{
EnsureStopAutoVertScroll();
return;
}
SCROLLINFO si;
si.cbSize = sizeof(SCROLLINFO);
GetScrollInfo(SB_VERT, &si, SIF_ALL);
const int nScrollFactor = 2; // Factor to speed up smooth scrolling
if (xtpReportControlDirectionUp == nDirection && si.nPos > 0)
{
m_nScrollStepV *= nScrollFactor;
OnVScroll(SB_LINEUP, 0, NULL);
m_nScrollStepV /= nScrollFactor;
EnsureStartAutoVertScroll();
}
else if (xtpReportControlDirectionDown == nDirection && si.nPos + int(si.nPage) - 1 < si.nMax)
{
m_nScrollStepV *= nScrollFactor;
OnVScroll(SB_LINEDOWN, 0, NULL);
m_nScrollStepV /= nScrollFactor;
EnsureStartAutoVertScroll();
}
else
{
EnsureStopAutoVertScroll();
}
}
BOOL CXTPReportControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (nHitTest == HTCLIENT)
{
switch (m_mouseMode)
{
case xtpReportMouseOverColumnDivide:
SetCursor(GetReportHeader()->m_hResizeCursor);
return TRUE;
}
}
return CWnd::OnSetCursor(pWnd, nHitTest, message);
}
LRESULT CXTPReportControl::SendNotifyMessage(UINT nMessage, NMHDR *pNMHDR) const
{
if (!IsWindow(m_hWnd))
return 0;
NMHDR nmhdr;
if (pNMHDR == NULL)
pNMHDR = &nmhdr;
pNMHDR->hwndFrom = GetSafeHwnd();
pNMHDR->idFrom = GetDlgCtrlID();
pNMHDR->code = nMessage;
CWnd *pOwner = GetOwner();
if (pOwner && IsWindow(pOwner->m_hWnd))
return pOwner->SendMessage(WM_NOTIFY, pNMHDR->idFrom, (LPARAM)pNMHDR);
else
return 0;
}
LRESULT CXTPReportControl::SendMessageToParent(CXTPReportRow* pRow, CXTPReportRecordItem* pItem, CXTPReportColumn* pColumn, UINT nMessage, CPoint* pPoint, int nHyperlink) const
{
if (!IsWindow(m_hWnd))
return 0;
XTP_NM_REPORTRECORDITEM nmgv;
nmgv.pItem = pItem;
nmgv.pColumn = pColumn;
nmgv.pRow = pRow;
nmgv.nHyperlink = nHyperlink;
nmgv.pt.x = 0;
nmgv.pt.y = 0;
if (pPoint)
nmgv.pt = *pPoint;
return SendNotifyMessage(nMessage, (NMHDR*)&nmgv);
}
void CXTPReportControl::DoPropExchange(CXTPPropExchange *pPX)
{
/*
9.8.1 (_XTP_SCHEMA_98)
10.1.0 (_XTP_SCHEMA_1000)
10.2.0 (_XTP_SCHEMA_1000)
10.3.0 (_XTP_SCHEMA_1030)
10.3.1 (_XTP_SCHEMA_1030)
10.4.0 (_XTP_SCHEMA_1040)
10.4.1 (_XTP_SCHEMA_1041)
10.4.2 (_XTP_SCHEMA_1041)
- [Columns]
- ShowGroupBox
- FreezeColumnsCount
- [Header]
11.1.0 (_XTP_SCHEMA_1100)
11.1.2 (_XTP_SCHEMA_1100)
12.0.1 (_XTP_SCHEMA_1200)
12.1.0 (_XTP_SCHEMA_1210)
13.0.0 (_XTP_SCHEMA_1210)
- [Columns]
- ShowGroupBox
- FreezeColumnsCount
- FullColumnScrolling >= _XTP_SCHEMA_1100
- HScrollStep >= _XTP_SCHEMA_1100
- [Header]
13.1.0 (_XTP_SCHEMA_1210)
- [Columns]
- ShowGroupBox
- FreezeColumnsCount
- FullColumnScrolling >= _XTP_SCHEMA_1100
- HScrollStep >= _XTP_SCHEMA_1100
- [Header]
- ShowIconView
13.2.0 (_XTP_SCHEMA_1310)
- [Columns]
- ShowGroupBox
- FullColumnScrolling >= _XTP_SCHEMA_1100
- HScrollStep >= _XTP_SCHEMA_1100
- FreezeColumnsCount !! Order changed !!
- FreezeColumnsAbs >= _XTP_SCHEMA_1310
- MovePivot >= _XTP_SCHEMA_1310
- ForcePagination >= _XTP_SCHEMA_1310
- StrictBestFit >= _XTP_SCHEMA_1310
- SelectionExcludeGroupRows >= _XTP_SCHEMA_1310
- DesktopTrackerMode >= _XTP_SCHEMA_1310
- [Header]
- ShowIconView
*/
//ICON_VIEW_MODE RELATED <<
BeginUpdate();
BOOL bCurIconView = IsIconView();
BOOL bSetBackToIconView = bCurIconView;
if (bSetBackToIconView)
SetIconView(FALSE);
//ICON_VIEW_MODE RELATED >>
TRY
{
pPX->ExchangeSchemaSafe();
CXTPPropExchangeSection secColumns(pPX->GetSection(_T("Columns")));
m_pColumns->DoPropExchange(&secColumns);
PX_Bool(pPX, _T("ShowGroupBox"), m_bGroupByEnabled, FALSE);
if (pPX->GetSchema() >= _XTP_SCHEMA_1100)
{
BOOL bFullColumnScrolling = IsFullColumnScrolling();
PX_Bool(pPX, _T("FullColumnScrolling"), bFullColumnScrolling, FALSE);
PX_Int (pPX, _T("HScrollStep"), m_nScrollStepH, XTP_REPORT_HSCROLL_STEP);
if (pPX->IsLoading())
{
SetFullColumnScrolling(bFullColumnScrolling);
}
}
if (pPX->GetSchema() >= _XTP_SCHEMA_1310)
{
// The order of "FreezeColumnsCount" has been changed with 13.2.0
int nFreezeColumnsCount = GetFreezeColumnsCount();
BOOL bFreezeColumnsAbs = FALSE;
PX_Int (pPX, _T("FreezeColumnsCount"), nFreezeColumnsCount, 0);
PX_Bool(pPX, _T("FreezeColumnsAbs"), bFreezeColumnsAbs, FALSE); // Removed
PX_Bool(pPX, _T("MovePivot"), m_bMovePivot, FALSE);
PX_Bool(pPX, _T("ForcePagination"), m_bForcePagination, FALSE);
PX_Bool(pPX, _T("StrictBestFit"), m_bStrictBestFit, FALSE);
PX_Bool(pPX, _T("SelectionExcludeGroupRows"), m_bSelectionExcludeGroupRows, TRUE);
PX_Bool(pPX, _T("DesktopTrackerMode"), m_bDesktopTrackerMode, FALSE);
if (pPX->IsLoading())
{
SetFreezeColumnsCount(nFreezeColumnsCount);
}
}
CXTPPropExchangeSection secHeader(pPX->GetSection(_T("Header")));
GetReportHeader()->DoPropExchange(&secHeader);
if (pPX->IsLoading())
{
GetReportHeader()->OnColumnsChanged(xtpReportColumnOrderChanged | xtpReportColumnPropExchange, NULL);
Populate();
}
}
CATCH(CArchiveException, e)
{
ASSERT(FALSE);
}
END_CATCH
//ICON_VIEW_MODE RELATED <<
TRY
{
pPX->ExchangeSchemaSafe();
PX_Bool(pPX, _T("ShowIconView"), bCurIconView);
if (pPX->IsLoading() && bCurIconView)
SetIconView(bCurIconView);
}
CATCH(CArchiveException, e)
{
}
END_CATCH
if (pPX->IsStoring() && bSetBackToIconView)
SetIconView(TRUE);
EndUpdate();
//ICON_VIEW_MODE RELATED >>
}
//ICON_VIEW_MODE RELATED <<
void CXTPReportControl::SetIconView(BOOL bIconView /* = TRUE */)
{
if (m_iIconViewColumn == -1) //No Icon Column Set
{
m_bIconView = FALSE;
return;
}
if (m_bIconView == bIconView)
return;
CXTPReportColumn* pColumn = NULL;
m_UaSelected.RemoveAll();
CXTPReportSelectedRows* pSel = GetSelectedRows();
for (int i = 0; i < pSel->GetCount(); i++)
{
if (pSel->GetAt(i))
m_UaSelected.Add(pSel->GetAt(i)->GetIndex());
}
if (bIconView)
{
m_pNavigator = m_pNavigatorIcon;
if (!m_pPrevGroupsOrder)
m_pPrevGroupsOrder = new CXTPReportColumnOrder(GetColumns());
if (!m_pPrevVisible)
m_pPrevVisible = new CXTPReportColumnOrder(GetColumns());
if (m_pPrevGroupsOrder)
{
m_pPrevGroupsOrder->Clear();
CXTPReportColumnOrder* pCurrentColumnOrder = GetColumns()->GetGroupsOrder();
if (pCurrentColumnOrder->GetCount())
{
for (int i = 0; i < GetColumns()->GetCount(); i++)
{
pColumn = pCurrentColumnOrder->GetAt(i);
if (pColumn)
{
m_pPrevGroupsOrder->Add(pColumn);
pColumn->SetVisible(FALSE);
}
}
pCurrentColumnOrder->Clear();
Populate();
}
}
if (m_pPrevVisible)
{
m_pPrevVisible->Clear();
for (int i = 0; i < GetColumns()->GetCount(); i++)
{
pColumn = GetColumns()->GetAt(i);
if (pColumn && pColumn->IsVisible())
{
m_pPrevVisible->Add(pColumn);
pColumn->SetVisible(FALSE);
}
}
}
m_iIconWidth = GetSystemMetrics(SM_CXICON);
m_iIconHeight = GetSystemMetrics(SM_CYICON);
m_iIconWidthSpacing = GetSystemMetrics(SM_CXICONSPACING) + 5;
m_iIconHeightSpacing = GetSystemMetrics(SM_CYICONSPACING);
m_iIconHeightSpacing = max(m_iIconHeightSpacing, (((CXTPReportPaintManager* ) GetPaintManager())->m_nRowHeight << 1) + m_iIconHeight);
pColumn = GetColumns()->Find(m_iIconViewColumn);
if (pColumn)
{
pColumn->SetVisible(TRUE);
if (pColumn->IsResizable())
GetPaintManager()->m_RecordNumberWidth = pColumn->GetWidth();
pColumn->SetWidth(m_iIconWidth);
pColumn->SetEditable(TRUE);
}
m_bPrevHeaderShow = IsHeaderVisible();
m_bPrevFooterShow = IsFooterVisible();
ShowHeader(FALSE);
ShowFooter(FALSE);
m_bPrevFocusSubItems = IsFocusSubItems();
m_bPrevHeaderAutoSize = GetReportHeader()->IsAutoColumnSizing();
// This is not needed since we only have one column and it screws up the selection.
FocusSubItems(FALSE);
GetReportHeader()->SetAutoColumnSizing(TRUE);
m_bPrevHeaderRows = IsHeaderRowsVisible();
m_bPrevFooterRows = IsFooterRowsVisible();
ShowHeaderRows(FALSE);
ShowFooterRows(FALSE);
// Need this so the scrollbar is correct at the beginning.
m_iIconViewRowsPerLine = GetNumRowsOnLine(GetReportHeader()->GetWidth());
m_nPrevTreeIndent = GetPaintManager()->m_nTreeIndent;
GetPaintManager()->m_nTreeIndent = 0;
m_bPrevPreviewMode = IsPreviewMode();
GetPaintManager()->EnablePreviewMode(FALSE);
}
else
{
m_pNavigator = m_pNavigatorReport;
GetPaintManager()->m_nTreeIndent = m_nPrevTreeIndent;
GetReportHeader()->SetAutoColumnSizing(m_bPrevHeaderAutoSize);
pColumn = GetColumns()->Find(m_iIconViewColumn);
if (pColumn)
{
if (m_bUseIconColumnForNum)
{
if (m_iColumnForNum > -1)
{
if (m_pPrevGroupsOrder
&& m_pPrevGroupsOrder->GetCount() > 0
&& GetPaintManager()->m_RecordNumberWidth < 30)
GetPaintManager()->m_RecordNumberWidth = 30;
pColumn->SetWidth(GetPaintManager()->m_RecordNumberWidth);
pColumn->SetMinWidth(GetPaintManager()->m_RecordNumberWidth);
pColumn->SetVisible(TRUE);
}
else
pColumn->SetVisible(FALSE);
pColumn->SetHeaderAlignment(DT_CENTER);
pColumn->SetEditable(FALSE);
}
else
{
pColumn->SetVisible(FALSE);
pColumn->SetWidth(0);
}
}
if (m_pPrevVisible)
{
for (int i = 0; i < m_pPrevVisible->GetCount(); i++)
{
pColumn = m_pPrevVisible->GetAt(i);
if (pColumn)
{
pColumn->SetVisible(TRUE);
if (pColumn->GetWidth() == 0)
pColumn->SetWidth(pColumn->GetMinWidth());
}
}
}
if (m_pPrevGroupsOrder)
{
for (int i = 0; i < m_pPrevGroupsOrder->GetCount(); i++)
{
pColumn = m_pPrevGroupsOrder->GetAt(i);
if (pColumn)
{
GetColumns()->GetGroupsOrder()->Add(pColumn);
pColumn->SetVisible(TRUE);
}
}
Populate();
}
ShowHeader(m_bPrevHeaderShow);
ShowFooter(m_bPrevFooterShow);
if (m_bPrevFocusSubItems)
FocusSubItems(m_bPrevFocusSubItems);
ShowHeaderRows(m_bPrevHeaderRows);
ShowFooterRows(m_bPrevFooterRows);
GetPaintManager()->EnablePreviewMode(m_bPrevPreviewMode);
}
BOOL bOldFirst(TRUE);
for (int ii = 0; ii < m_UaSelected.GetSize(); ii++)
{
int j = (int) m_UaSelected.GetAt(ii);
if (j == 0)
bOldFirst = FALSE;
if (j > -1)
{
if (GetRows()->GetAt(j))
GetRows()->GetAt(j)->SetSelected(TRUE);
}
}
if (bOldFirst)
{
if (GetRows()->GetAt(0))
GetRows()->GetAt(0)->SetSelected(FALSE);
}
m_bIconView = bIconView;
AdjustScrollBars();
}
int CXTPReportControl::GetNumRowsOnLine(int iTotalWidth) const
{
return max(iTotalWidth / m_iIconWidthSpacing, 1);
}
//ICON_VIEW_MODE RELATED >>
void CXTPReportControl::SerializeState(CArchive& ar)
{
CXTPPropExchangeArchive px(ar);
DoPropExchange(&px);
}
void CXTPReportControl::CollapseAll()
{
CXTPReportRows *pRows = GetRows();
BeginUpdate();
m_UaSelected.RemoveAll();
CXTPReportSelectedRows *pSelelectedRows = GetSelectedRows();
for (int i=0; i<pSelelectedRows->GetCount(); i++)
{
const CXTPReportRow *pRow = pSelelectedRows->GetAt(i);
if (NULL != pRow)
{
m_UaSelected.Add(pRow->GetIndex());
}
}
for (int j=pRows->GetCount()-1; j>=0; j--)
{
pRows->GetAt(j)->SetExpanded(FALSE);
}
EndUpdate();
EnsureVisible(GetFocusedRow());
pSelelectedRows->Clear(TRUE);
}
void CXTPReportControl::ExpandAll(BOOL bRecursive)
{
CXTPReportRows *pRows = m_pSectionBody->GetRows();
if (pRows->GetCount() == 0)
return;
BeginUpdate();
for (int i = pRows->GetCount() - 1; i >= 0; i--)
{
CXTPReportRow* pRow = pRows->GetAt(i);
if (pRow)
pRow->SetExpanded(TRUE, bRecursive);
}
BOOL bOldFirst(TRUE);
for (int j = 0; j < m_UaSelected.GetSize(); j++)
{
int jj = (int) m_UaSelected.GetAt(j);
if (jj == 0)
bOldFirst = FALSE;
CXTPReportRow* pRow = pRows->GetAt(jj);
if (pRow)
pRow->SetSelected(TRUE);
}
int nTopRowIndex = GetTopRowIndex();
if (bOldFirst && nTopRowIndex >= 0 && nTopRowIndex < pRows->GetCount())
pRows->GetAt(nTopRowIndex)->SetSelected(FALSE);
EndUpdate();
EnsureVisible(GetFocusedRow());
}
void CXTPReportControl::SetMouseMode(XTPReportMouseMode nMode)
{
XTP_TRACE(_T("SetMouseMode: Switching from %d to %d\n"), m_mouseMode, nMode);
m_mouseMode = nMode;
}
void CXTPReportControl::RelayToolTipEvent(UINT message)
{
if (m_pTip->GetSafeHwnd() && m_pTip->IsWindowVisible())
{
CPoint pt;
GetCursorPos(&pt);
if (!m_pTip->GetHoverRect().PtInRect(pt))
{
m_pTip->SetTooltipText(NULL);
m_pTip->Activate(FALSE, FALSE);
}
switch (message)
{
case WM_MOUSEWHEEL:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSELEAVE:
m_pTip->Activate(FALSE, FALSE);
}
}
}
BOOL CXTPReportControl::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
static BOOL bRelay = FALSE;
if (m_pTip->GetSafeHwnd() && m_pTip->IsWindowVisible() && !bRelay)
{
bRelay = TRUE;
RelayToolTipEvent(message);
bRelay = FALSE;
}
if (m_pToolTipContext && m_bShowTooltips)
{
m_pToolTipContext->FilterToolTipMessage(this, message, wParam, lParam);
}
if (GetMarkupContext())
{
CPoint ptMouse(0);
GetCursorPos(&ptMouse);
ScreenToClient(&ptMouse);
BOOL bRelay = FALSE;
CXTPReportRow* pRow = HitTest(ptMouse);
if (pRow)
{
CXTPReportRecordItem* pItem = pRow->HitTest(ptMouse);
if (pItem && pItem->GetMarkupUIElement())
{
bRelay = TRUE;
if (XTPMarkupRelayMessage(pItem->GetMarkupUIElement(), message, wParam, lParam, pResult))
return TRUE;
}
//13.2.2 <<
//enable markup mouse move for groups
else if (pRow->IsGroupRow())
{
bRelay = TRUE;
if (XTPMarkupRelayMessage(((CXTPReportGroupRow*) pRow)->m_pMarkupUIElement, message, wParam, lParam, pResult))
return TRUE;
}
//13.2.2 >>
}
if (!bRelay)
{
if (XTPMarkupRelayMessage(GetMarkupContext(), message, wParam, lParam, pResult))
return TRUE;
}
}
return CWnd::OnWndMsg(message, wParam, lParam, pResult);
}
void CXTPReportControl::OnSysColorChange()
{
CWnd::OnSysColorChange();
m_pPaintManager->RefreshMetrics();
RedrawControl();
}
UINT CXTPReportControl::OnGetDlgCode()
{
return (m_bFocusSubItems ? DLGC_WANTTAB : 0) | DLGC_WANTARROWS | DLGC_WANTCHARS;
}
void CXTPReportControl::OnSetFocus(CWnd* pOldWnd)
{
CWnd::OnSetFocus(pOldWnd);
RedrawControl();
}
void CXTPReportControl::OnKillFocus (CWnd* pNewWnd)
{
CWnd::OnKillFocus(pNewWnd);
EnsureStopAutoVertScroll();
RedrawControl();
}
int CXTPReportControl::GetHeaderIndent() const
{
return GetIndent(GetReportHeader()->m_nIndentLevel);
}
CXTPReportRow* CXTPReportControl::CreateRow()
{
return new CXTPReportRow_Batch();
}
CXTPReportGroupRow* CXTPReportControl::CreateGroupRow()
{
return new CXTPReportGroupRow_Batch();
}
CXTPReportRow* CXTPReportControl::CreateHeaderFooterRow()
{
return new CXTPHeapObjectT<CXTPReportRow, CXTPReportAllocatorDefault>;
}
void CXTPReportControl::ShowIconWhenEditing(BOOL bShow)
{
m_bShowIconWhenEditing = bShow;
}
BOOL CXTPReportControl::IsShowIconWhenEditing()
{
return m_bShowIconWhenEditing;
}
void CXTPReportControl::EditItem(XTP_REPORTRECORDITEM_ARGS *pItemArgs)
{
CXTPReportRecordItem *pItem = pItemArgs ? pItemArgs->pItem : NULL;
if (NULL == m_pActiveItem && NULL == pItem)
{
// Nothing do to
return;
}
if (m_pActiveItem != NULL)
{
m_pActiveItem->OnCancelEdit(this, TRUE);
m_pActiveItem = NULL;
if (!m_bFocusSubItems)
SetFocusedColumn(NULL);
}
CMDTARGET_RELEASE(m_ptrVirtualEditingRow);
if (pItem && pItemArgs && pItemArgs->pRow)
{
if (!HasFocus())
SetFocus();
if (!IsVirtualMode())
{
AdjustScrollBars();
RedrawControl();
UpdateWindow();
}
if (IsVirtualMode())
{
int nRowIndex = pItemArgs->pRow->GetIndex();
//EnsureVisible(pItemArgs->pRow);
RedrawControl();
UpdateWindow();
pItemArgs->pRow = NULL; // RedrawControl delete and re-create new screen rows
BOOL bMapped = FALSE;
CXTPReportScreenRows *pScreenRows = GetRows()->GetScreenRows();
for (int i = 0; i <pScreenRows->GetSize(); i++)
{
CXTPReportRow* pRow = pScreenRows->GetAt(i);
if (pRow->GetIndex() == nRowIndex)
{
pItemArgs->pRow = pRow;
bMapped = TRUE;
ASSERT(m_ptrVirtualEditingRow == NULL);
m_ptrVirtualEditingRow = pRow;
CMDTARGET_ADDREF(m_ptrVirtualEditingRow);
break;
}
}
ASSERT(bMapped);
if (!bMapped)
return;
}
else if (GetFocusedRow() != pItemArgs->pRow)
{
SetFocusedRow(pItemArgs->pRow);
UpdateWindow();
}
pItemArgs->rcItem = pItemArgs->pRow->GetItemRect(pItem);
pItemArgs->rcItem.left += (pItemArgs->rcItem.left == 0 ? GetHeaderIndent() : 0);
if (m_bShowIconWhenEditing && pItemArgs->pColumn)
{
XTP_REPORTRECORDITEM_METRICS* pMetrics = new XTP_REPORTRECORDITEM_METRICS();
XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
drawArgs.pControl = this;
drawArgs.pColumn = pItemArgs->pColumn;
drawArgs.rcItem = pItemArgs->pColumn->GetRect();
drawArgs.nTextAlign = pItem->GetAlignment() == -1 ? 0 : pItem->GetAlignment();
drawArgs.pRow = pItemArgs->pRow;
drawArgs.pItem = pItemArgs->pItem;
pItemArgs->pRow->GetItemMetrics(&drawArgs, pMetrics);
int nIcon = pMetrics->nItemIcon;
nIcon = (nIcon != XTP_REPORT_NOICON) ? nIcon : pItem->GetIconIndex();
if (nIcon != XTP_REPORT_NOICON)
{
if ((drawArgs.nTextAlign & xtpColumnIconRight) != 0)
pItemArgs->rcItem.right -= GetPaintManager()->DrawBitmap(NULL, this, pItemArgs->rcItem, nIcon);
else
pItemArgs->rcItem.left += GetPaintManager()->DrawBitmap(NULL, this, pItemArgs->rcItem, nIcon);
}
CMDTARGET_RELEASE(pMetrics);
}
if (pItem->GetHasCheckbox() && pItem->GetCanEditCheckboxItem())
pItemArgs->rcItem.left += 15;
if (SetFocusedColumn(pItemArgs->pColumn))
{
m_pActiveItem = pItem;
pItem->OnBeginEdit(pItemArgs);
if (!IsEditMode()) // Need to actually cancel the edit - old version (10) did not have this call
EditItem(NULL);
}
// Fix selection
if (GetInplaceEdit()->GetSafeHwnd()
&& GetInplaceEdit()->GetItem() == pItem)
{
CXTPReportRecordItemEditOptions* pEditOptions = pItem->GetEditOptions(pItemArgs->pColumn);
if (pEditOptions && pEditOptions->m_bSelectTextOnEdit)
{
GetInplaceEdit()->SetSel(0, -1);
}
else
{
CString str;
GetInplaceEdit()->GetWindowText(str);
GetInplaceEdit()->SetSel(str.GetLength(), str.GetLength());
}
}
}
RedrawControl();
}
BOOL CXTPReportControl::HasFocus() const
{
const CWnd* pFocusWnd = GetFocus();
if (!pFocusWnd)
return FALSE;
return (pFocusWnd->GetSafeHwnd() == m_hWnd)
|| (pFocusWnd->GetParent()->GetSafeHwnd() == m_hWnd)
|| (pFocusWnd->GetOwner()->GetSafeHwnd() == m_hWnd);
}
void CXTPReportControl::ReleaseItem(int nIndex)
{
CXTPReportRecords *pRecords = GetRecords();
int i(0);
if (IsVirtualMode() && pRecords->GetCount())
{
CXTPReportRecord* pRecord = pRecords->GetAt(0);
pRecord->m_arrItems[nIndex]->InternalRelease();
pRecord->m_arrItems.RemoveAt(nIndex);
}
else
{
for (i = 0; i < pRecords->GetCount(); i++)
{
CXTPReportRecord* pRecord = pRecords->GetAt(i);
pRecord->m_arrItems[nIndex]->InternalRelease();
pRecord->m_arrItems.RemoveAt(nIndex);
}
}
CXTPReportColumns* pColumns = GetColumns();
CXTPReportColumn* pColumnToRemove = NULL;
int nColumnsCount = pColumns->GetCount();
for (i = 0; i < nColumnsCount; i++)
{
CXTPReportColumn* pColumn = pColumns->GetAt(i);
if (pColumn->m_nItemIndex > nIndex)
pColumn->m_nItemIndex--;
else if (pColumn->m_nItemIndex == nIndex)
pColumnToRemove = pColumn;
}
if (pColumnToRemove)
pColumns->Remove(pColumnToRemove);
}
void CXTPReportControl::SetVirtualMode(CXTPReportRecord* pVirtualRecord, int nCount, int nFields)
{
CXTPReportRecords *pRecords = GetRecords();
if (pRecords)
{
if (pVirtualRecord)
{
int nItems = pVirtualRecord->GetItemCount();
if (nItems == 0 && nFields > 0)
for (int i = 0; i < nFields; i++)
pVirtualRecord->AddItem(new CXTPReportRecordItem());
}
else
{
pVirtualRecord = new CXTPReportRecord();
if (nFields > 0)
for (int i = 0; i < nFields; i++)
pVirtualRecord->AddItem(new CXTPReportRecordItem());
}
if (m_iIconViewColumn > -1)
{
int nItems = pVirtualRecord->GetItemCount();
CXTPReportRecordItem* pLastItem = pVirtualRecord->GetItem(nItems - 1);
if (!pLastItem->IsKindOf(RUNTIME_CLASS(CXTPReportRecordItemIcon)))
pVirtualRecord->AddItem(new CXTPReportRecordItemIcon());
}
pRecords->SetVirtualMode(pVirtualRecord, nCount);
}
}
BOOL CXTPReportControl::IsVirtualMode() const
{
CXTPReportRecords *pRecords = GetRecords();
return pRecords ? pRecords->IsVirtualMode() : FALSE;
}
CXTPReportRow* CXTPReportControl::GetFocusedRow() const
{
return m_pSections->GetFocusedRow();
}
void CXTPReportControl::OnStyleChanged(int nStyleType, LPSTYLESTRUCT lpStyleStruct)
{
CWnd::OnStyleChanged(nStyleType, lpStyleStruct);
RedrawControl();
}
CXTPToolTipContext* CXTPReportControl::GetToolTipContext() const
{
return m_pToolTipContext;
}
INT_PTR CXTPReportControl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
// check child windows first by calling CControlBar
INT_PTR nHit = CWnd::OnToolHitTest(point, pTI);
if (nHit != -1)
return nHit;
nHit = GetReportHeader()->OnToolHitTest(point, pTI);
if (nHit != -1)
return nHit;
CXTPReportRow* pRow = HitTest(point);
if (pRow)
nHit = pRow->OnToolHitTest(point, pTI);
return nHit;
}
void CXTPReportControl::SetLayoutRTL(BOOL bRightToLeft)
{
if (!XTPSystemVersion()->IsLayoutRTLSupported())
return;
if (!m_hWnd)
return;
if (bRightToLeft)
{
ModifyStyleEx(0, WS_EX_LAYOUTRTL);
}
else
{
ModifyStyleEx(WS_EX_LAYOUTRTL, 0);
}
GetImageManager()->DrawReverted(bRightToLeft);
GetInplaceEdit()->DestroyWindow();
AdjustLayout();
if (GetParent())
{
CRect rc;
GetParent()->GetClientRect(&rc);
GetParent()->SetWindowPos(NULL, 0, 0, rc.Width() + 1, rc.Height(), SWP_NOMOVE | SWP_NOZORDER);
}
}
BOOL CXTPReportControl::IsLayoutRTL()
{
if (!XTPSystemVersion()->IsLayoutRTLSupported())
return FALSE;
if (!m_hWnd)
return FALSE;
return !!(GetWindowLong(m_hWnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL);
}
//////////////////////////////////////////////////////////////////////////
// Clipboard operations
BOOL CXTPReportControl::CanCopy()
{
// Check whether are there any selected rows to be copied
CXTPReportSelectedRows* pSelRows = GetSelectedRows();
if ((pSelRows != NULL) && (pSelRows->GetCount() > 0))
return TRUE;
return FALSE;
}
BOOL CXTPReportControl::CanCut()
{
//Old VirtualMode
if (IsVirtualMode())
return FALSE;
return CanCopy();
}
BOOL CXTPReportControl::CanPaste()
{
CLIPFORMAT uCF_Records = (CLIPFORMAT)::RegisterClipboardFormat(XTPREPORTCTRL_CF_RECORDS);
BOOL bCan = FALSE;
COleDataObject odj;
if (odj.AttachClipboard())
{
bCan = odj.IsDataAvailable(CF_TEXT)
|| odj.IsDataAvailable(CF_UNICODETEXT)
|| odj.IsDataAvailable(uCF_Records) ;
}
return bCan;
}
void CXTPReportControl::Cut()
{
CWaitCursor _WC;
Copy();
if (IsVirtualMode())
return;
// Delete selected rows
CXTPInternalCollectionT<CXTPReportRow> arSelectedRows;
_GetSelectedRows(NULL, &arSelectedRows);
int nSelRowsCount = (int) arSelectedRows.GetSize();
int nFirstSelRow = INT_MAX;
for (int i = nSelRowsCount - 1; i >= 0 ; i--)
{
CXTPReportRow* pRow = arSelectedRows.GetAt(i, FALSE);
if (pRow)
{
nFirstSelRow = min(nFirstSelRow, pRow->GetIndex());
VERIFY(RemoveRowEx(pRow, FALSE));
}
arSelectedRows.RemoveAt(i);
}
if (GetSelectedRows())
{
GetSelectedRows()->Clear();
if (nFirstSelRow != INT_MAX)
{
GetRows()->m_nFocusedRow = min(nFirstSelRow, GetRows()->GetCount() - 1);
if (GetFocusedRow())
{
SetFocusedRow(GetFocusedRow());
GetSelectedRows()->Add(GetFocusedRow());
}
}
}
AdjustScrollBars();
RedrawControl();
}
// We support text format with \t dividers for record items and
// \r\n dividers for records (simple tab-separated text).
// Such format is also supported by Excel and some other applications.
void CXTPReportControl::Copy()
{
CWaitCursor _WC;
int nRowsCount = 1;
if (GetSelectedRows())
nRowsCount = GetSelectedRows()->GetCount();
// minimize memory reallocs to improve performance
UINT nAveRecordsSize = 1500; // bytes
UINT nGrowBytes = ((nRowsCount * nAveRecordsSize) / 4096 + 1) * 4096;
UINT nAllocFlags = GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT;
CSharedFile fileRecords(nAllocFlags, nGrowBytes);
BOOL bIsRecordsData = FALSE;
//------------------------------------------------------------------------
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
try
{
CArchive ar(&fileRecords, CArchive::store);
CXTPPropExchangeArchive px(ar);
bIsRecordsData = _WriteSelectedRowsData(&px);
ar.Close(); // perform Flush() and detach from file
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::Copy() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::Copy() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPReportControl::Copy() - Unhandled Exception!\n"));
}
CString strClipText = _GetSelectedRowsVisibleColsText();
CLIPFORMAT uCF_Records = (CLIPFORMAT)::RegisterClipboardFormat(XTPREPORTCTRL_CF_RECORDS);
// Put prepared text into the clipboard
if (OpenClipboard())
{
::EmptyClipboard();
// 1 - Text
HGLOBAL hText = XTPAllocStrInGlobalMem(strClipText);
if (hText != NULL)
{
::SetClipboardData(XTP_CF_TEXT_T, hText);
}
// 2 - Blob data
if (bIsRecordsData)
{
HGLOBAL hData = fileRecords.Detach();
::GlobalUnlock(hData); // unlock data
::SetClipboardData(uCF_Records, hData);
}
::CloseClipboard();
}
}
void CXTPReportControl::Paste()
{
CWaitCursor _WC;
CLIPFORMAT uCF_Records = (CLIPFORMAT)::RegisterClipboardFormat(XTPREPORTCTRL_CF_RECORDS);
CXTPReportRecords arRecords;
BOOL bTryPasteFromText = TRUE;
// Retrieve text from the clipboard
if (!OpenClipboard())
return;
if (::IsClipboardFormatAvailable(uCF_Records))
{
HGLOBAL hPasteData = ::GetClipboardData(uCF_Records);
if (hPasteData)
{
bTryPasteFromText = FALSE;
const int cErrTextSize = 1024;
TCHAR szErrText[cErrTextSize + 1];
CSharedFile fileSahred;
fileSahred.SetHandle(hPasteData, FALSE);
CArchive ar(&fileSahred, CArchive::load);
try
{
CXTPPropExchangeArchive px(ar);
if (!_ReadRecordsFromData(&px, arRecords))
{
arRecords.RemoveAll();
}
}
catch(CArchiveException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::Paste() - %s\n"), szErrText);
}
pE->Delete();
}
catch(CFileException* pE)
{
if (pE->GetErrorMessage(szErrText, cErrTextSize))
{
TRACE(_T("EXCEPTION: CXTPReportControl::Paste() - %s\n"), szErrText);
}
pE->Delete();
}
catch(...)
{
TRACE(_T("EXCEPTION: CXTPReportControl::Paste() - Unhandled Exception!\n"));
}
//*********
ar.Close(); // detach from file
fileSahred.Detach(); //detach from data
::GlobalUnlock(hPasteData); // unlock data
}
}
UINT uCF_TText = sizeof(TCHAR) == 2 ? CF_UNICODETEXT : CF_TEXT;
if (bTryPasteFromText && ::IsClipboardFormatAvailable(uCF_TText))
{
// Try to get text data from the clipboard
HGLOBAL hglbPaste = ::GetClipboardData(uCF_TText);
// Import Text data into the control
if (hglbPaste != NULL)
{
TCHAR* lpszClipboard = (TCHAR*)GlobalLock(hglbPaste);
if (!_ReadRecordsFromText(lpszClipboard, arRecords))
{
arRecords.RemoveAll();
}
::GlobalUnlock(hglbPaste);
}
}
::CloseClipboard();
if (IsVirtualMode())
return;
CUpdateContext updateContext(this);
// Add and Populate records
int nRecordsCount = arRecords.GetCount();
if (nRecordsCount > 0)
{
// Add
for (int i = 0; i < nRecordsCount; i++)
{
CXTPReportRecord* pRecord = arRecords.GetAt(i);
if (pRecord)
{
CMDTARGET_ADDREF(pRecord);
AddRecord(pRecord);
}
}
Populate();
// Select added records
_SelectRows(&arRecords);
}
}
// We support text format with \t dividers for record items and
// \r\n dividers for records (simple tab-separated text).
// Such format is also supported by Excel and some other applications.
CString CXTPReportControl::_GetSelectedRowsVisibleColsText()
{
CString strSelText;
CXTPReportColumns* pColumns = GetColumns();
if (NULL == pColumns)
return _T("");
const int nColumnCount = pColumns->GetVisibleColumnsCount();
// Iterate over the selected rows and prepare corresponding records text
CXTPReportSelectedRows* pSelectedRows = GetSelectedRows();
if ((pSelectedRows != NULL) && (pSelectedRows->GetCount() > 0))
{
POSITION pos = pSelectedRows->GetFirstSelectedRowPosition();
while (pos)
{
CXTPReportRow* pRow = pSelectedRows->GetNextSelectedRow(pos);
if (NULL == pRow)
break;
CXTPReportRecord* pRecord = pRow->GetRecord();
if (NULL == pRecord)
continue;
CStringArray arStrings;
for (int nCol = 0; nCol < nColumnCount; nCol++)
{
CXTPReportColumn* pColumn = pColumns->GetVisibleAt(nCol);
CXTPReportRecordItem* pItem = pRecord->GetItem(pColumn);
if (NULL == pItem)
continue;
arStrings.Add(pItem->GetCaption(pColumn));
}
BOOL bCanceled = OnBeforeCopyToText(pRecord, arStrings);
if (bCanceled)
continue;
strSelText += XTPStrMake(arStrings, _T("\t"));
strSelText += _T("\r\n");
}
}
return strSelText;
}
BOOL CXTPReportControl::_ReadRecordsFromText(LPCTSTR pcszText,
CXTPReportRecords& rarRecords)
{
//////////////////////////////////////////////////////////////////////////
// Insert retrieved text into the control
CStringArray arRecordsStrings;
XTPStrSplit(pcszText, _T("\r\n"), arRecordsStrings);
int nCount = (int) arRecordsStrings.GetSize();
for (int i = 0; i < nCount; i++)
{
CString strRecord = arRecordsStrings[i];
if (strRecord.IsEmpty())
continue;
CXTPReportRecord* pNewRec = _CreateRecodFromText(strRecord);
// Case: pNewRec = NULL - paste was handled by the user
if (pNewRec)
rarRecords.Add(pNewRec);
}
return TRUE;
}
CXTPReportRecord* CXTPReportControl::_CreateRecodFromText(LPCTSTR pcszRecord)
{
if (!GetColumns())
{
ASSERT(FALSE);
return NULL;
}
CStringArray arStrings;
// Read each field from the initial string and set visible field one by one
XTPStrSplit(pcszRecord, _T("\t"), arStrings);
CXTPReportRecord* pRecord = NULL;
BOOL bHandled = OnBeforePasteFromText(arStrings, &pRecord);
if (bHandled)
return pRecord;
#if _MFC_VER >= 0x0600 // Not supported by Visual Studio 5.0
if (!pRecord)
{
pRecord = new CXTPReportRecord();
if (!pRecord)
{
return NULL;
}
int nDataCount = (int) arStrings.GetSize();
// Fill record with all items
int nCount = GetColumns()->GetCount();
for (int i = 0; i < nCount; i++)
{
COleVariant varItem(_T(""));
CXTPReportRecordItem* pItem = new CXTPReportRecordItemVariant(varItem);
if (!pItem)
{
CMDTARGET_RELEASE(pRecord);
return NULL;
}
pRecord->AddItem(pItem);
}
// Iterate all visible columns and set text for each next
const int nColumnCount = GetColumns()->GetVisibleColumnsCount();
for (int nCol = 0; nCol < nColumnCount; nCol++)
{
COleVariant varItem(nCol < nDataCount ? (LPCTSTR)arStrings[nCol] : _T(""));
CXTPReportColumn* pColumn = GetColumns()->GetVisibleAt(nCol);
CXTPReportRecordItem* pItem = pRecord->GetItem(pColumn);
ASSERT(pItem);
if (NULL == pItem)
continue;
CXTPReportRecordItemVariant* pItemVar = DYNAMIC_DOWNCAST(CXTPReportRecordItemVariant, pItem);
ASSERT(pItemVar);
if (pItemVar)
{
pItemVar->m_oleValue = varItem;
}
}
}
#endif
return pRecord;
}
BOOL CXTPReportControl::_WriteRecordsData(CXTPPropExchange* pPX, CXTPReportRecords* pRecords)
{
if (!pRecords)
return FALSE;
long nSchema = XTP_REPORT_CB_RECORDS_DATA_VER;
PX_Long(pPX, _T("Version"), (long&)nSchema);
pPX->ExchangeLocale();
CXTPPropExchangeSection secRecords(pPX->GetSection(_T("ReportRecords")));
int nRecordsCount = (int)pRecords->GetCount();
CXTPPropExchangeEnumeratorPtr pEnumRecords(secRecords->GetEnumerator(_T("Record")));
POSITION posRecord = pEnumRecords->GetPosition((DWORD)nRecordsCount);
for (int i = 0; i < nRecordsCount; i++)
{
CXTPPropExchangeSection secRecord(pEnumRecords->GetNext(posRecord));
CXTPReportRecord* pRecord = pRecords->GetAt(i);
PX_Object(&secRecord, pRecord, RUNTIME_CLASS(CXTPReportRecord));
}
return TRUE;
}
void CXTPReportControl::_SelectChilds(CXTPReportRecords *pRecords)
{
ASSERT(NULL != pRecords);
CXTPReportRows *pRows = GetRows();
CXTPReportSelectedRows *pSelRows = GetSelectedRows();
for (int nRecord=0; nRecord<pRecords->GetCount(); nRecord++)
{
CXTPReportRecord *pRecord = pRecords->GetAt(nRecord);
ASSERT(NULL != pRecord);
if (NULL != pRecord)
{
CXTPReportRow *pRow = pRows->Find(pRecord);
if (NULL != pRow)
{
pSelRows->Add(pRow);
// Recursion
if (pRecord->HasChildren())
{
CXTPReportRecords *pChilds = pRecord->GetChilds();
if (NULL != pChilds)
{
_SelectChilds(pChilds);
}
}
}
}
}
}
void CXTPReportControl::_SelectRows(CXTPReportRecords *pRecords)
{
CXTPReportSelectedRows *pSelRows = GetSelectedRows();
pSelRows->Clear();
_SelectChilds(pRecords);
if (pSelRows->IsChanged())
{
OnSelectionChanged();
}
}
BOOL CXTPReportControl::_GetSelectedRows(CXTPReportRecords* pRecords,
CXTPInternalCollectionT<CXTPReportRow> *pRows)
{
ASSERT(!pRecords || pRecords->m_bArray == TRUE);
CXTPReportSelectedRows* pSelectedRows = GetSelectedRows();
if (!pSelectedRows
|| !pSelectedRows->GetCount()
|| (!pRecords && !pRows))
return FALSE;
POSITION pos = pSelectedRows->GetFirstSelectedRowPosition();
while (pos)
{
CXTPReportRow* pRow = pSelectedRows->GetNextSelectedRow(pos);
CXTPReportRecord* pRecord = pRow ? pRow->GetRecord() : NULL;
if (NULL == pRow)
break;
if (pRecord && pRecords)
pRecords->Add(pRecord);
if (pRow && pRows)
pRows->AddPtr(pRow, TRUE);
}
return TRUE;
}
BOOL CXTPReportControl::_WriteSelectedRowsData(CXTPPropExchange* pPX)
{
if (!pPX || !pPX->IsStoring())
{
ASSERT(FALSE);
return FALSE;
}
CXTPReportRecords* pSelectedRecords= new CXTPReportRecords(TRUE);
if (!_GetSelectedRows(pSelectedRecords) || !_WriteRecordsData(pPX, pSelectedRecords))
{
CMDTARGET_RELEASE(pSelectedRecords);
return FALSE;
}
CMDTARGET_RELEASE(pSelectedRecords);
return TRUE;
}
BOOL CXTPReportControl::_ReadRecordsFromData(CXTPPropExchange* pPX,
CXTPReportRecords& rarRecords)
{
rarRecords.RemoveAll();
if (!pPX || !pPX->IsLoading())
{
ASSERT(FALSE);
return FALSE;
}
CXTPPropExchangeSection secRecords(pPX->GetSection(_T("ReportRecords")));
long nSchema = 0;
PX_Long(pPX, _T("Version"), (long&)nSchema);
pPX->ExchangeLocale();
if (nSchema != XTP_REPORT_CB_RECORDS_DATA_VER)
{
ASSERT(FALSE);
return FALSE;
}
CXTPPropExchangeEnumeratorPtr pEnumRecords(secRecords->GetEnumerator(_T("Record")));
POSITION posRecord = pEnumRecords->GetPosition();
while (posRecord)
{
CXTPPropExchangeSection secRecord(pEnumRecords->GetNext(posRecord));
CXTPReportRecord* pRecord = NULL;
PX_Object(&secRecord, pRecord, RUNTIME_CLASS(CXTPReportRecord));
if (!pRecord)
AfxThrowArchiveException(CArchiveException::badClass);
CXTPReportRecord* pRecord2 = pRecord;
BOOL bCanceled = OnBeforePaste(&pRecord2);
if (bCanceled || pRecord2 != pRecord)
CMDTARGET_RELEASE(pRecord);
if (bCanceled)
continue;
rarRecords.Add(pRecord2);
}
return TRUE;
}
BOOL CXTPReportControl::OnBeforeCopyToText(CXTPReportRecord* pRecord, CStringArray& rarStrings)
{
XTP_NM_REPORT_BEFORE_COPYPASTE nmParams;
::ZeroMemory(&nmParams, sizeof(nmParams));
CXTPReportRecord* pRecordTmp = pRecord;
nmParams.ppRecord = &pRecordTmp;
nmParams.parStrings = &rarStrings;
LRESULT lResult = SendNotifyMessage(XTP_NM_REPORT_BEFORE_COPY_TOTEXT, (NMHDR*)&nmParams);
return lResult != 0;
}
BOOL CXTPReportControl::OnBeforePasteFromText(CStringArray& arStrings,
CXTPReportRecord** ppRecord)
{
XTP_NM_REPORT_BEFORE_COPYPASTE nmParams;
::ZeroMemory(&nmParams, sizeof(nmParams));
nmParams.parStrings = &arStrings;
nmParams.ppRecord = ppRecord;
LRESULT lResult = SendNotifyMessage(XTP_NM_REPORT_BEFORE_PASTE_FROMTEXT, (NMHDR*)&nmParams);
return lResult != 0;
}
BOOL CXTPReportControl::OnBeforePaste(CXTPReportRecord** ppRecord)
{
XTP_NM_REPORT_BEFORE_COPYPASTE nmParams;
::ZeroMemory(&nmParams, sizeof(nmParams));
nmParams.ppRecord = ppRecord;
LRESULT lResult = SendNotifyMessage(XTP_NM_REPORT_BEFORE_PASTE, (NMHDR*)&nmParams);
return lResult != 0;
}
int CXTPReportControl::OnGetColumnDataBestFitWidth(CXTPReportColumn* pColumn)
{
CXTPReportPaintManager* pPaintManager = GetPaintManager();
if (!pColumn || !pPaintManager)
{
ASSERT(FALSE);
return 0;
}
int nDataWidth = 0;
int nDataWidth0 = 0;
int nDataWidth1 = 0;
CXTPClientRect rcClient(this);
CBitmap bmp;
{
CClientDC dcClient(this);
bmp.CreateCompatibleBitmap(&dcClient, rcClient.Width(), rcClient.Height());
}
CXTPCompatibleDC dc(NULL, &bmp);
CXTPFontDC autoFont(&dc, pPaintManager->GetTextFont()); // to reset selected font on exit
if (pColumn->GetBestFitMode() == xtpColumnBestFitModeVisibleData
|| (pColumn->GetBestFitMode() == xtpColumnBestFitModeAllData && IsVirtualMode())
/* && pColumn->m_nMaxItemWidth == 0*/)
{
// calculate width for visible rows only
int nVisibleRows = GetReportAreaRows(GetTopRowIndex(), TRUE);
nDataWidth = OnGetItemsCaptionMaxWidth(&dc, GetRows(), pColumn,
GetTopRowIndex(), nVisibleRows);
}
else if (pColumn->GetBestFitMode() == xtpColumnBestFitModeAllData && !IsVirtualMode())
nDataWidth = OnGetItemsCaptionMaxWidth(&dc, GetRows(), pColumn);
else
return 0;
if (m_pSectionHeader->IsVisible() && GetHeaderRows()->GetCount() > 0)
nDataWidth0 = OnGetItemsCaptionMaxWidth(&dc, GetHeaderRows(), pColumn);
if (m_pSectionFooter->IsVisible() && GetFooterRows()->GetCount() > 0)
nDataWidth1 = OnGetItemsCaptionMaxWidth(&dc, GetFooterRows(), pColumn);
nDataWidth = max(nDataWidth, max(nDataWidth0, nDataWidth1));
return nDataWidth;
}
int CXTPReportControl::OnGetItemsCaptionMaxWidth(CDC* pDC, CXTPReportRows* pRows,
CXTPReportColumn* pColumn, int nStartRow, int nRowsCount)
{
CXTPReportPaintManager* pPaintManager = GetPaintManager();
if (!pDC || !pRows || !pColumn || !pPaintManager)
{
ASSERT(FALSE);
return 0;
}
XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
drawArgs.pDC = pDC;
drawArgs.pControl = this;
drawArgs.pColumn = pColumn;
drawArgs.rcItem = pColumn->GetRect();
XTP_REPORTRECORDITEM_METRICS* pMetrics = new XTP_REPORTRECORDITEM_METRICS();
int nGroupIndent = 0;
if (GetColumns()->GetVisibleAt(0) == pColumn)
nGroupIndent = GetHeaderIndent();
CSize sizeBitmap(0, 0);
int nMaxWidth = 0;
int nItemIndex = pColumn->GetItemIndex();
int nEndRow = pRows->GetCount();
if (nRowsCount > 0)
nEndRow = min(pRows->GetCount(), nStartRow + nRowsCount);
for (int i = max(0, nStartRow); i < nEndRow; i++)
{
CXTPReportRow* pRow = pRows->GetAt(i);
if (!pRow)
continue;
if (pRow && pRow->IsGroupRow())
continue;
CXTPReportRecord* pRec = pRow ? pRow->GetRecord() : NULL;
CXTPReportRecordItem* pItem = pRec ? pRec->GetItem(nItemIndex) : NULL;
if (!pItem)
continue;
// 1. Calculate Text
drawArgs.pRow = pRow;
drawArgs.pItem = pItem;
pMetrics->strText = pItem->GetCaption(pColumn);
pRow->GetItemMetrics(&drawArgs, pMetrics);
pDC->SelectObject(pMetrics->pFont);
int nWidth = 0;
if (pItem->GetMarkupUIElement())
{
nWidth = XTPMarkupMeasureElement(pItem->GetMarkupUIElement(), INT_MAX, 0).cx + 4;
}
else
{
CString sFirst(pMetrics->strText);
CString sLast;
int jPos = sFirst.Find(_T('\n'), 0);
int wd(0);
while (jPos > -1)
{
sLast = sFirst.Mid(jPos + 1);
sFirst = sFirst.Left(jPos - 1);
wd = max(wd, pDC->GetTextExtent(sFirst).cx + 7);
sFirst = sLast;
jPos = sFirst.Find(_T('\n'), 0);
}
if (!sFirst.IsEmpty())
nWidth = max(wd, pDC->GetTextExtent(sFirst).cx + 7);
// nWidth = pDC->GetTextExtent(pMetrics->strText).cx + 7;
}
// 2. Calculate Tree Indent
if (pColumn->IsTreeColumn())
{
int nTreeDepth = pRow->GetTreeDepth() - pRow->GetGroupLevel();
if (nTreeDepth > 0)
nTreeDepth++;
nWidth += GetIndent(nTreeDepth);
if (sizeBitmap.cx == 0 && sizeBitmap.cy == 0)
{
CRect rcBmp(0, 0, 100, 100);
sizeBitmap = pPaintManager->DrawCollapsedBitmap(NULL, pRow, rcBmp);
}
nWidth += sizeBitmap.cx + 2;
}
// 2.1 Calculate Group Indent
nWidth += nGroupIndent;
// 3. Calculate item Icon
int nIcon = pMetrics->nItemIcon;
nIcon = (nIcon != XTP_REPORT_NOICON) ? nIcon : pItem->GetIconIndex();
if (nIcon != XTP_REPORT_NOICON)
{
CXTPImageManagerIcon* pIcon = GetImageManager()->GetImage(nIcon, 0);
if (pIcon)
nWidth += pIcon->GetWidth() + 4;
}
if (pItem->GetHasCheckbox())
{
nWidth += 16;
}
// 4. Calculate item Controls
if (pItem->m_pItemControls)
{
int nControlsCount = pItem->m_pItemControls->GetSize();
for (int k = 0; k < nControlsCount; k++)
{
CXTPReportRecordItemControl* pCtrl = pItem->m_pItemControls->GetAt(k);
int nControlWidth = 0;
if (pCtrl)
nControlWidth = pCtrl->GetSize().cx;
if (nControlWidth < 0)
nControlWidth = 20;
nWidth += nControlWidth;
}
}
nMaxWidth = max(nMaxWidth, nWidth);
}
CMDTARGET_RELEASE(pMetrics);
return nMaxWidth;
}
BOOL CXTPReportControl::IsEditMode()
{
CXTPReportInplaceEdit* pEdit = GetInplaceEdit();
BOOL bEditMode = pEdit && pEdit->GetSafeHwnd() && pEdit->IsWindowVisible();
bEditMode |= GetInplaceList() && GetInplaceList()->GetSafeHwnd() && GetInplaceList()->IsWindowVisible();
return bEditMode;
}
int CXTPReportControl::GetRowsHeight(CXTPReportRows* pRows, int nTotalWidth, int nMaxHeight)
{
int nRowsHeight = 0;
CWindowDC dc (this);
for (int i = 0; i < pRows->GetCount(); ++i)
{
nRowsHeight += GetPaintManager()->GetRowHeight(&dc, pRows->GetAt(i), nTotalWidth);
if (nMaxHeight >= 0 && nRowsHeight > nMaxHeight)
return nRowsHeight;
}
return nRowsHeight;
}
void CXTPReportControl::DrawDefaultGrid(CDC* pDC, CRect rcClient, int nRowHeight, int nLeftOffset)
{
if (nRowHeight <= 0)
return;
int nFreezeCols = GetFreezeColumnsCount();
CRect rcClipBox = GetReportRectangle();
CRect rcRow;
rcRow = rcClient;
rcRow.left -= nLeftOffset;
rcRow.right -= nLeftOffset;
rcRow.bottom = rcClient.top + nRowHeight;
int nIndentWidth = GetHeaderIndent();
CXTPReportPaintManager* pPaintManager = GetPaintManager();
CXTPReportColumns arrVisibleColumns(this);
GetColumns()->GetVisibleColumns(arrVisibleColumns);
int nVisColCount = arrVisibleColumns.GetCount();
nFreezeCols = min(nFreezeCols, nVisColCount);
// fill the empty space
while (rcRow.top < rcClient.bottom)
{
CRect rcItem(rcRow.left, rcRow.top, rcRow.right, rcRow.bottom);
CRect rcIndent(nFreezeCols ? rcRow : rcRow); /////////////////////
rcIndent.right = rcIndent.left + nIndentWidth;
int xMinCol_0 = rcRow.left + nIndentWidth;
for (int nColumn = nVisColCount-1; nColumn >= 0; nColumn--)
{
BOOL bFreezeCol = nColumn < nFreezeCols;
int nColIdx = bFreezeCol ? nFreezeCols - 1 - nColumn : nColumn;
CXTPReportColumn* pColumn = arrVisibleColumns.GetAt(nColIdx);
ASSERT(pColumn && pColumn->IsVisible());
if (pColumn)
{
rcItem.left = pColumn->GetRect().left;
if (nColIdx == 0)
rcItem.left = max(xMinCol_0, rcItem.left);
rcItem.right = pColumn->GetRect().right;
if (!CRect().IntersectRect(rcClipBox, rcItem))
continue;
if (bFreezeCol)
{
CRect rcFreeze(rcItem);
rcFreeze.top +=1;
pDC->FillSolidRect(rcFreeze, pPaintManager->GetControlBackColor(this));
}
CRect rcGridItem(rcItem);
rcGridItem.left--;
pPaintManager->DrawGrid(pDC, xtpReportOrientationHorizontal, rcGridItem);
pPaintManager->DrawGrid(pDC, xtpReportOrientationVertical, rcGridItem);
if (nColIdx == nFreezeCols - 1)
pPaintManager->DrawFreezeColsDivider(pDC, rcGridItem, this);
}
}
if (nIndentWidth > 0) // draw indent column
pPaintManager->FillIndent(pDC, rcIndent);
rcRow.top += nRowHeight;
rcRow.bottom += nRowHeight;
}
}
BOOL CXTPReportControl::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
if (!OnPreviewKeyDown((UINT&)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam)) )
{
return TRUE;
}
}
return CWnd::PreTranslateMessage(pMsg);
}
BOOL CXTPReportControl::OnConstraintSelecting(CXTPReportRow* pRow, CXTPReportRecordItem* pItem, CXTPReportColumn* pColumn,
CXTPReportRecordItemConstraint* pConstraint)
{
XTP_NM_REPORTCONSTRAINTSELECTING nmConstraint;
::ZeroMemory(&nmConstraint, sizeof(nmConstraint));
nmConstraint.pRow = pRow;
nmConstraint.pColumn = pColumn;
nmConstraint.pItem = pItem;
nmConstraint.pConstraint = pConstraint;
LRESULT lResult = SendNotifyMessage(XTP_NM_REPORT_CONSTRAINT_SELECTING, (NMHDR*)&nmConstraint);
return lResult != 0;
}
const XTP_NM_REPORTTOOLTIPINFO& CXTPReportControl::OnGetToolTipInfo(CXTPReportRow* pRow, CXTPReportRecordItem* pItem, CString& rstrToolTipText)
{
::ZeroMemory(m_pCachedToolTipInfo, sizeof(XTP_NM_REPORTTOOLTIPINFO));
m_pCachedToolTipInfo->pRow = pRow;
m_pCachedToolTipInfo->pItem = pItem;
m_pCachedToolTipInfo->pstrText = &rstrToolTipText;
SendNotifyMessage(XTP_NM_REPORT_GETTOOLTIPINFO, (NMHDR*)m_pCachedToolTipInfo);
return *m_pCachedToolTipInfo;
}
CXTPReportDataManager* CXTPReportControl::GetDataManager()
{
if (!m_pDataManager)
m_pDataManager = new CXTPReportDataManager(this);
return m_pDataManager;
}
CRect CXTPReportControl::GetElementRect(int nElement) const
{
switch (nElement)
{
case xtpReportElementRectGroupByArea:
return m_rcGroupByArea;
case xtpReportElementRectHeaderArea:
return m_rcHeaderArea;
case xtpReportElementRectFooterArea:
return m_rcFooterArea;
case xtpReportElementRectHeaderRecordsArea:
return m_pSectionHeader->m_rcSection;
case xtpReportElementRectFooterRecordsArea:
return m_pSectionFooter->m_rcSection;
case xtpReportElementRectHeaderRecordsDividerArea:
return m_pSectionHeader->GetDividerRect();
case xtpReportElementRectFooterRecordsDividerArea:
return m_pSectionFooter->GetDividerRect();
default:
return m_pSectionBody->m_rcSection;
}
}
CXTPMarkupContext* CXTPReportControl::GetMarkupContext() const
{
return m_pMarkupContext;
}
void CXTPReportControl::EnableMarkup(BOOL bEnable)
{
if (m_bMarkupEnabled == bEnable)
return;
m_bMarkupEnabled = bEnable;
XTPMarkupReleaseContext(m_pMarkupContext);
m_pMarkupContext = NULL;
if (bEnable)
{
m_pMarkupContext = XTPMarkupCreateContext(m_hWnd);
}
m_pSections->SetMarkupContext(m_pMarkupContext);
}
LRESULT CXTPReportControl::OnGetObject(WPARAM wParam, LPARAM lParam)
{
if (((LONG)lParam) != OBJID_CLIENT)
return (LRESULT)Default();
LPUNKNOWN lpUnknown = GetInterface(&IID_IAccessible);
if (!lpUnknown)
return E_FAIL;
return LresultFromObject(IID_IAccessible, wParam, lpUnknown);
}
BEGIN_INTERFACE_MAP(CXTPReportControl, CCmdTarget)
INTERFACE_PART(CXTPReportControl, IID_IAccessible, ExternalAccessible)
END_INTERFACE_MAP()
CCmdTarget* CXTPReportControl::GetAccessible()
{
return this;
}
HRESULT CXTPReportControl::GetAccessibleParent(IDispatch* FAR* ppdispParent)
{
*ppdispParent = NULL;
if (GetSafeHwnd())
{
return AccessibleObjectFromWindow(GetSafeHwnd(), OBJID_WINDOW, IID_IDispatch, (void**)ppdispParent);
}
return E_FAIL;
}
HRESULT CXTPReportControl::GetAccessibleChildCount(long FAR* pChildCount)
{
if (pChildCount == 0)
{
return E_INVALIDARG;
}
*pChildCount = 1 + GetRows()->GetCount();
return S_OK;
}
HRESULT CXTPReportControl::GetAccessibleChild(VARIANT varChild, IDispatch* FAR* ppdispChild)
{
*ppdispChild = NULL;
int nChild = GetChildIndex(&varChild);
if (nChild <= 0)
{
return E_INVALIDARG;
}
if (nChild == 1)
{
*ppdispChild = GetReportHeader()->GetIDispatch(TRUE);
return S_OK;
}
CXTPReportRow* pRow = GetRows()->GetAt(nChild - 2);
if (!pRow)
{
return E_INVALIDARG;
}
*ppdispChild = pRow->GetIDispatch(TRUE);
return S_OK;
}
HRESULT CXTPReportControl::GetAccessibleName(VARIANT varChild, BSTR* pszName)
{
int nChild = GetChildIndex(&varChild);
if (nChild == CHILDID_SELF || nChild == -1)
{
CString strCaption;
GetWindowText(strCaption);
if (strCaption.IsEmpty()) strCaption = _T("Report");
*pszName = strCaption.AllocSysString();
return S_OK;
}
return E_INVALIDARG;
}
HRESULT CXTPReportControl::GetAccessibleRole(VARIANT varChild, VARIANT* pvarRole)
{
pvarRole->vt = VT_EMPTY;
int nChild = GetChildIndex(&varChild);
if (nChild == CHILDID_SELF)
{
pvarRole->vt = VT_I4;
pvarRole->lVal = ROLE_SYSTEM_TABLE;
return S_OK;
}
return E_INVALIDARG;
}
HRESULT CXTPReportControl::GetAccessibleState(VARIANT varChild, VARIANT* pvarState)
{
pvarState->vt = VT_I4;
pvarState->lVal = 0;
int nChild = GetChildIndex(&varChild);
if (nChild == CHILDID_SELF)
{
pvarState->lVal = STATE_SYSTEM_FOCUSABLE;
}
return S_OK;
}
HRESULT CXTPReportControl::AccessibleLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild)
{
*pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
if (!GetSafeHwnd())
return S_OK;
CRect rc;
GetWindowRect(&rc);
int nChild = GetChildIndex(&varChild);
if (nChild == 1)
{
rc = m_rcHeaderArea;
ClientToScreen(&rc);
}
if (nChild > 1)
{
CXTPReportRow* pRow = GetRows()->GetAt(nChild - 2);
if (pRow)
{
rc = pRow->GetRect();
ClientToScreen(&rc);
}
}
*pxLeft = rc.left;
*pyTop = rc.top;
*pcxWidth = rc.Width();
*pcyHeight = rc.Height();
return S_OK;
}
HRESULT CXTPReportControl::AccessibleHitTest(long xLeft, long yTop, VARIANT* pvarID)
{
if (pvarID == NULL)
return E_INVALIDARG;
pvarID->vt = VT_EMPTY;
if (!GetSafeHwnd())
return S_FALSE;
if (!CXTPWindowRect(this).PtInRect(CPoint(xLeft, yTop)))
return S_FALSE;
pvarID->vt = VT_I4;
pvarID->lVal = 0;
CPoint pt(xLeft, yTop);
ScreenToClient(&pt);
if (m_rcHeaderArea.PtInRect(pt))
{
pvarID->vt = VT_DISPATCH;
pvarID->pdispVal = GetReportHeader()->GetIDispatch(TRUE);
return S_OK;
}
CXTPReportRow* pRow = HitTest(pt);
if (pRow)
{
pvarID->vt = VT_DISPATCH;
pvarID->pdispVal = pRow->GetIDispatch(TRUE);
return S_OK;
}
return S_FALSE;
}
void CXTPReportControl::EnsureStopLastRqstTimer()
{
if (m_uRqstEditTimer)
{
KillTimer(m_uRqstEditTimer);
m_uRqstEditTimer = 0;
m_iLastRqstEditRow = -1;
m_iLastRqstEditCol = -1;
}
}
// Information for delay editing.
void CXTPReportControl::EnsureStopDelayEditTimer()
{
if (m_uiDelayEditTimer)
{
KillTimer(m_uiDelayEditTimer);
m_uiDelayEditTimer = NULL;
}
}
void CXTPReportControl::StartLastRqstTimer()
{
EnsureStopLastRqstTimer();
m_uRqstEditTimer = SetTimer(XTP_REPORT_DELAY_CLICK_TIMER_ID, 3000, NULL); // After 3 seconds, ignore this click.
}
// Information for delay editing.
void CXTPReportControl::StartDelayEditTimer()
{
EnsureStopDelayEditTimer();
m_uiDelayEditTimer = SetTimer(XTP_REPORT_DELAYEDIT_CLICK_TIMER_ID, m_uiDelayEditMaxTime, NULL); // Begin edit after a full double click is possible.
}
void CXTPReportControl::SetSelectionState(int index, int state)
{
CXTPReportSelectedRows* pSelectedRows = GetSelectedRows();
if (!pSelectedRows)
return;
CXTPReportRecordItem* pItem = NULL;
CXTPReportRecord* pRec = NULL;
for (int i = 0; i < pSelectedRows->GetCount(); i++)
{
if (pSelectedRows->GetAt(i))
{
pRec = pSelectedRows->GetAt(i)->GetRecord();
if (pRec)
{
if (index < pRec->GetItemCount())
{
pItem = pRec->GetItem(index);
if (pItem)
{
pItem->SetChecked(state == 1);
pItem->SetCheckedState(state);
}
}
}
}
}
RedrawControl();
}
void CXTPReportControl::Recalc(BOOL bAll)
{
EditItem(NULL);
if (!bAll && GetFocusedRow())
{
CXTPReportRecord* pRec = GetFocusedRow()->GetRecord();
if (pRec)
{
int N = pRec->GetItemCount();
CXTPReportRecordItem* pItem = NULL;
for (int i = 0; i < N; i++)
{
pItem = pRec->GetItem(i);
if (pItem)
{
if (!pItem->GetFormula().IsEmpty())
pItem->SetCaption(_T("x")); //it will call recalc for item
}
}
RedrawControl();
}
}
else if (GetRecords())
{
int n = GetRecords()->GetCount();
for (int j = 0; j < n; j++)
{
CXTPReportRecord* pRec = GetRecords()->GetAt(j);
if (pRec)
{
int N = pRec->GetItemCount();
CXTPReportRecordItem* pItem = NULL;
for (int i = 0; i < N; i++)
{
pItem = pRec->GetItem(i);
if (pItem)
{
if (!pItem->GetFormula().IsEmpty())
pItem->SetCaption(_T("x"));
}
}
RedrawControl();
}
}
int N = GetRows()->GetCount();
for (int I = 0; I < N; I++)
{
CXTPReportRow* pTRow = GetRows()->GetAt(I);
if (pTRow && pTRow->IsGroupRow())
{
CXTPReportGroupRow* pTgRow = (CXTPReportGroupRow*) pTRow;
if (!pTgRow->GetFormula().IsEmpty())
pTgRow->SetCaption(_T("x"));
}
}
RedrawControl();
}
}
BOOL CXTPReportControl::IsShowRowNumber()
{
if (m_iColumnForNum > -1)
{
if (m_bUseIconColumnForNum)
{
CXTPReportColumn* pIconCol = GetColumns()->Find(m_iColumnForNum);
if (pIconCol)
return pIconCol->IsVisible();
}
}
return FALSE;
}
void CXTPReportControl::ShowRowNumber(BOOL bSet)
{
if (bSet)
{
if (m_iColumnForNumPrev > -1)
m_iColumnForNum = m_iColumnForNumPrev;
if (m_iColumnForNum > -1)
{
if (m_bUseIconColumnForNum)
{
CXTPReportColumn* pIconCol = GetColumns()->Find(m_iColumnForNum);
if (pIconCol)
pIconCol->SetVisible(TRUE);
}
}
}
else
{
m_iColumnForNumPrev = m_iColumnForNum;
if (m_iColumnForNum > -1)
{
if (m_bUseIconColumnForNum && !m_bIconView)
{
CXTPReportColumn* pIconCol = GetColumns()->Find(m_iColumnForNum);
if (pIconCol)
pIconCol->SetVisible(FALSE);
}
}
m_iColumnForNum = -1;
}
RedrawControl();
}
int CXTPReportControl::GetFreezeColumnsCount() const
{
int nCount = 0;
BOOL bStop = FALSE;
const CXTPReportColumns *pColumns = GetColumns();
for (int nColumn=0; nColumn<pColumns->GetCount(); nColumn++)
{
const CXTPReportColumn *pColumn = pColumns->GetAt(nColumn);
ASSERT(NULL != pColumn);
if (pColumn->IsVisible())
{
if (pColumn->IsFrozen() && !bStop)
{
++nCount;
}
else
{
bStop = TRUE;
}
}
}
return nCount;
}
int CXTPReportControl::GetFreezeColumnsIndex() const
{
int nCount = GetFreezeColumnsCount();
int nIndex = -1;
for (int nColumn=0; nColumn<GetColumns()->GetCount(); nColumn++)
{
const CXTPReportColumn *pColumn = GetColumns()->GetAt(nColumn);
ASSERT(NULL != pColumn);
if (pColumn->IsVisible() && (nCount > 0))
{
nCount--;
nIndex = nColumn;
}
}
return nIndex;
}
void CXTPReportControl::SetFreezeColumnsCount(int nCount, BOOL bAdjust)
{
UNREFERENCED_PARAMETER(bAdjust);
for (int nColumn=0; nColumn<GetColumns()->GetCount(); nColumn++)
{
CXTPReportColumn *pColumn = GetColumns()->GetAt(nColumn);
if (NULL != pColumn)
{
pColumn->SetFrozen(nColumn < nCount);
}
}
RedrawControl();
#if 0
if (nCount >= 0 && nCount < m_pColumns->GetCount())
{
BOOL bCallView = FALSE;
if (GetPaintManager() != NULL && GetPaintManager()->m_bMoveScrollbarOnFixedColumnsIndent)
bCallView = TRUE;
m_nFreezeColumnsCount = nCount;
if (IsFullColumnScrolling())
SetFullColumnScrolling(IsFullColumnScrolling());
else if (bCallView && m_hWnd != NULL)
{
CXTPReportControl::OnHScroll(SB_TOP, 0, NULL);
RedrawControl();
UpdateWindow();
AdjustScrollBars();
}
if (bCallView)
{
CWnd* pParent = GetParent();
if (pParent)
{
CRect rc;
pParent->GetWindowRect(&rc);
int w = rc.Width();
int h = rc.Height();
if (bAdjust)
h -= 4;
if (DYNAMIC_DOWNCAST(CView, pParent))
((CView*) pParent)->SendMessage(WM_SIZE, 0, MAKELPARAM(w, h));
//pParent->SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height(), SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
}
}
else
m_nFreezeColumnsCount = 0;
#endif
}
void CXTPReportControl::SetDisableReorderColumnsCount(int nCount)
{
if (nCount >= 0 && nCount < m_pColumns->GetCount())
m_nDisableReorderColumnsCount = nCount;
else
m_nDisableReorderColumnsCount = 0;
}
CXTPReportRecordItem* CXTPReportControl::GetFocusedRecordItem() const
{
CXTPReportColumn* pCol = GetFocusedColumn();
CXTPReportRow* pRow = GetFocusedRow();
if (pCol && pRow && pRow->GetRecord())
return pRow->GetRecord()->GetItem(pCol);
return NULL;
}
BOOL CXTPReportControl::SetCellText(int row, int col, CString sText)
{
CXTPReportRow* pRow = GetRows()->GetAt(row);
if (pRow && pRow->GetRecord())
{
CXTPReportRecordItem* pItem = pRow->GetRecord()->GetItem(col);
if (pItem)
{
if (pItem->IsKindOf(RUNTIME_CLASS(CXTPReportRecordItemText)))
((CXTPReportRecordItemText*) pItem)->SetValue(sText);
pItem->SetCaption(sText);
return TRUE;
}
}
return FALSE;
}
BOOL CXTPReportControl::SetCellFormula(int row, int col, CString sFormula)
{
CXTPReportRow* pRow = GetRows()->GetAt(row);
if (pRow && pRow->GetRecord())
{
CXTPReportRecordItem* pItem = pRow->GetRecord()->GetItem(col);
if (pItem)
{
pItem->SetFormula(sFormula); //e.g. "SUM(R0*C2:R1*C5)"
pItem->SetFormatString(_T("%d"));
pItem->SetCaption(_T("x"));
pItem->SetEditable(FALSE);
return TRUE;
}
}
return FALSE;
}
void CXTPReportControl::UnselectGroupRows()
{
if (IsSkipGroupsFocusEnabled() && !IsVirtualMode())
{
for (int II = 0; II < GetRows()->GetCount(); II++)
{
CXTPReportRow* pRow = GetRows()->GetAt(II);
if (pRow)
{
if (pRow->IsGroupRow())
pRow->SetSelected(FALSE);
}
}
}
}
BOOL CXTPReportControl::IsFullColumnScrolling() const
{
if (GetReportHeader() && GetReportHeader()->IsAutoColumnSizing())
{
return FALSE;
}
else
{
return (xtpReportScrollModeBlock == m_scrollModeH);
}
}
//----------------------------------------------------------------------
IMPLEMENT_DYNAMIC(CXTPPromptDlg, CDialog)
CXTPPromptDlg::CXTPPromptDlg(CWnd* pParent) : CDialog()
{
UNREFERENCED_PARAMETER(pParent);
}
CXTPPromptDlg::~CXTPPromptDlg()
{
}
INT_PTR CXTPPromptDlg::DoModal()
{
BYTE DlgTempl[]=
{
0X01, 0X00, 0XFF, 0XFF, 0X00, 0X00, 0X00, 0X00, 0X80, 0X00, 0X00, 0X00, 0X48, 0X00, 0XC8, 0X80,
0X02, 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 0X01, 0X19, 0X00, 0X00, 0X00, 0X00, 0X00, 0X41, 0X00,
0X73, 0X00, 0X73, 0X00, 0X69, 0X00, 0X67, 0X00, 0X6E, 0X00, 0X20, 0X00, 0X4D, 0X00, 0X61, 0X00,
0X72, 0X00, 0X6B, 0X00, 0X65, 0X00, 0X72, 0X00, 0X20, 0X00, 0X4E, 0X00, 0X61, 0X00, 0X6D, 0X00,
0X65, 0X00, 0X00, 0X00, 0X08, 0X00, 0X90, 0X01, 0X00, 0X01, 0X4D, 0X00, 0X53, 0X00, 0X20, 0X00,
0X53, 0X00, 0X68, 0X00, 0X65, 0X00, 0X6C, 0X00, 0X6C, 0X00, 0X20, 0X00, 0X44, 0X00, 0X6C, 0X00,
0X67, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X80, 0X10, 0X81, 0X50,
0X02, 0X00, 0X02, 0X00, 0XCA, 0X00, 0X15, 0X00, 0XF1, 0X03, 0X00, 0X00, 0XFF, 0XFF, 0X81, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 0X00, 0X01, 0X50,
0XD0, 0X00, 0X04, 0X00, 0X32, 0X00, 0X0E, 0X00, 0X01, 0X00, 0X00, 0X00, 0XFF, 0XFF, 0X80, 0X00,
0X4F, 0X00, 0X4B, 0X00, 0X00, 0X00, 0X00, 0X00
};
InitModalIndirect((LPCDLGTEMPLATE)&DlgTempl, NULL);
return CDialog::DoModal();
}
void CXTPPromptDlg::OnOK()
{
if (GetDlgItem(1009))
GetDlgItem(1009)->GetWindowText(m_sName);
CDialog::OnOK();
}
BOOL CXTPPromptDlg::OnInitDialog()
{
CDialog::OnInitDialog();
if (GetDlgItem(1009))
GetDlgItem(1009)->SetWindowText(m_sName);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////
XTPReportScrollMode CXTPReportControl::GetScrollMode(XTPReportOrientation orientation) const
{
XTPReportScrollMode scrollMode;
switch(orientation)
{
case xtpReportOrientationHorizontal:
scrollMode = m_scrollModeH;
break;
case xtpReportOrientationVertical:
scrollMode = m_scrollModeV;
break;
default:
scrollMode = xtpReportScrollModeNone;
break;
}
return scrollMode;
}
void CXTPReportControl::SetScrollMode(
XTPReportOrientation orientation,
XTPReportScrollMode scrollMode)
{
switch(orientation)
{
case xtpReportOrientationHorizontal:
m_scrollModeH = scrollMode;
break;
case xtpReportOrientationVertical:
m_scrollModeV = scrollMode;
break;
case xtpReportOrientationAll:
m_scrollModeH = scrollMode;
m_scrollModeV = scrollMode;
break;
}
AdjustScrollBars();
}
void CXTPReportControl::SetGridStyle(BOOL bVertical, XTPReportGridStyle gridStyle)
{
m_pPaintManager->SetGridStyle(bVertical, gridStyle);
AdjustScrollBars();
}
XTPReportGridStyle CXTPReportControl::GetGridStyle(BOOL bVertical) const
{
return m_pPaintManager->GetGridStyle(bVertical);
}
COLORREF CXTPReportControl::SetGridColor(COLORREF clrGridLine)
{
return m_pPaintManager->SetGridColor(clrGridLine);
}
void CXTPReportControl::EnablePreviewMode(BOOL bIsPreviewMode)
{
m_pPaintManager->EnablePreviewMode(bIsPreviewMode);
}
BOOL CXTPReportControl::IsPreviewMode() const
{
return m_pPaintManager->IsPreviewMode();
}
void CXTPReportControl::ShadeGroupHeadings(BOOL bEnable)
{
if (m_pPaintManager)
m_pPaintManager->m_bShadeGroupHeadings = bEnable;
AdjustScrollBars();
}
BOOL CXTPReportControl::IsShadeGroupHeadingsEnabled() const
{
return m_pPaintManager ? m_pPaintManager->m_bShadeGroupHeadings : FALSE;
}
void CXTPReportControl::SetGroupRowsBold(BOOL bBold)
{
if (m_pPaintManager)
m_pPaintManager->m_bGroupRowTextBold = bBold;
}
BOOL CXTPReportControl::IsGroupRowsBold() const
{
return m_pPaintManager ? m_pPaintManager->m_bGroupRowTextBold : FALSE;
}
/////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////
void CXTPReportControl::InitialSelectionEnable(BOOL bEnable)
{
m_bInitialSelectionEnable = bEnable;
if (!m_bInitialSelectionEnable)
m_pSelectedRows->Clear();
}
CXTPReportSections *CXTPReportControl::GetSections() const
{
return m_pSections;
}