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++
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;
|
|
}
|