// XTPReportRecordItem.cpp : implementation of the CXTPReportRecordItem 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 #include "Common/XTPDrawHelpers.h" #include "Common/XTPMarkupRender.h" #include "Common/XTPResourceManager.h" #include "Common/XTPPropExchange.h" #include "Common/XTPCustomHeap.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSmartPtrInternalT.h" #include "Common/XTPColorManager.h" #include "XTPReportDefines.h" #include "XTPReportRow.h" #include "XTPReportRecords.h" #include "XTPReportColumns.h" #include "XTPReportColumn.h" #include "XTPReportControl.h" #include "XTPReportPaintManager.h" #include "XTPReportHyperlink.h" #include "XTPReportRecord.h" #include "XTPReportRecordItem.h" #include "XTPReportRecordItemConstraint.h" #include "XTPReportInplaceControls.h" #include "XTPReportRecordItemControls.h" #include "XTPReportBorder.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif ////////////////////////////////////////////////////////////////////////// // XTP_REPORTRECORDITEM_ARGS XTP_REPORTRECORDITEM_ARGS::XTP_REPORTRECORDITEM_ARGS() { pControl = NULL; pRow = NULL; pColumn = NULL; pItem = NULL; rcItem.SetRectEmpty(); } XTP_REPORTRECORDITEM_ARGS::XTP_REPORTRECORDITEM_ARGS( CXTPReportControl *pControl, CXTPReportRow *pRow, CXTPReportColumn *pColumn) { ASSERT(pControl && pRow && pColumn); this->pControl = pControl; this->pRow = pRow; this->pColumn = pColumn; this->pItem = pRow->GetRecord()->GetItem(pColumn); this->rcItem = pRow->GetItemRect(pItem); } XTP_REPORTRECORDITEM_ARGS::~XTP_REPORTRECORDITEM_ARGS() { } void XTP_REPORTRECORDITEM_ARGS::AddRef() { CMDTARGET_ADDREF(pRow); CMDTARGET_ADDREF(pColumn); CMDTARGET_ADDREF(pItem); } void XTP_REPORTRECORDITEM_ARGS::Release() { if (pRow) pRow->InternalRelease(); if (pColumn) pColumn->InternalRelease(); if (pItem) pItem->InternalRelease(); } const XTP_REPORTRECORDITEM_ARGS& XTP_REPORTRECORDITEM_ARGS::operator=(const XTP_REPORTRECORDITEM_ARGS& src) { pControl = src.pControl; pRow = src.pRow; pColumn = src.pColumn; pItem = src.pItem; rcItem = src.rcItem; return *this; } CXTPReportInplaceButtons::CXTPReportInplaceButtons() { } ////////////////////////////////////////////////////////////////////////// // CXTPReportRecordItem IMPLEMENT_SERIAL(CXTPReportRecordItem, CCmdTarget, VERSIONABLE_SCHEMA | _XTP_SCHEMA_CURRENT) CXTPReportRecordItem::CXTPReportRecordItem() : m_pMergeItem(NULL) , m_checkState(xtpReportCheckStateUnchecked) , m_pControl(NULL) , m_pRecord (NULL) , m_pBorder (NULL) { static const CString g_strFormatStringDef = _T("%s"); m_strFormatString = g_strFormatStringDef; m_strFormula.Empty(); m_bEditable = TRUE; m_pFontCaption = NULL; m_bBoldText = FALSE; m_clrText = XTP_REPORT_COLOR_DEFAULT; m_clrBackground = XTP_REPORT_COLOR_DEFAULT; m_nIconIndex = XTP_REPORT_NOICON; m_dwData = 0; m_nSortPriority = -1; m_nGroupPriority = -1; m_Alignment = (XTPReportColumnIconAlignment)(-1); m_bHasCheckbox = FALSE; m_bCanEditCheckboxItem = FALSE; m_bTristateCheckbox = FALSE; m_pEditOptions = NULL; m_pItemControls = NULL; m_pFocusedItemControl = NULL; m_bItemControlUnderMouse = FALSE; m_pItemControlHookWnd = NULL; m_bFocusable = TRUE; m_pHyperlinks = NULL; m_pMarkupUIElement = NULL; m_rcGlyph.SetRectEmpty(); } CXTPReportRecordItem::~CXTPReportRecordItem() { if (m_pItemControlHookWnd) { m_pItemControlHookWnd->DestroyWindow(); delete m_pItemControlHookWnd; m_pItemControlHookWnd = NULL; } CMDTARGET_RELEASE(m_pEditOptions); CMDTARGET_RELEASE(m_pItemControls); CMDTARGET_RELEASE(m_pHyperlinks); XTPMarkupReleaseElement(m_pMarkupUIElement); } double CXTPReportRecordItem::StringToDouble(CString strText) { TCHAR* locale = _tsetlocale(LC_NUMERIC, NULL); if (locale == NULL || _tcscmp(locale, _T("C")) == 0) // Not set { strText.Replace(',', '.'); } double res = atof(XTP_CT2CA(strText)); return res; } void CXTPReportRecordItem::ParseBBCode(CString &strText) { GetHyperlinks()->RemoveAll(); ////////////////////////////////////////////////////////////////////////// // Left [url=address]name[/url] Right ////////////////////////////////////////////////////////////////////////// const CString sUrlTagOpen = _T("[url"); const CString sUrlTagClose = _T("[/url]"); int nOpenTagStart = strText.Find(sUrlTagOpen); int nOpenTagEnd; int nCloseTagStart; int nCloseTagEnd; while (-1 != nOpenTagStart) { nOpenTagEnd = strText.Find(_T("]"), nOpenTagStart); CString sLeft = strText.Left(nOpenTagStart); nCloseTagStart = strText.Find(sUrlTagClose); CString sName = strText.Mid(nOpenTagEnd+1, nCloseTagStart-nOpenTagEnd-1); nCloseTagEnd = nCloseTagStart + sUrlTagClose.GetLength(); CString sRight = strText.Right(strText.GetLength()-nCloseTagEnd); strText = sLeft + sName + sRight; GetHyperlinks()->Add(new CXTPReportHyperlink(nOpenTagStart, nCloseTagStart-nOpenTagEnd-1)); nOpenTagStart = strText.Find(sUrlTagOpen); } } void CXTPReportRecordItem::SetCaption(LPCTSTR lpszCaption) { CString strCaption(lpszCaption); if (!m_strFormula.IsEmpty() && m_pRecord != NULL) { COLORREF clrSum = RGB(255,0,0); COLORREF clrSubSum = RGB(0,0,255); if (m_pControl) { clrSum = m_pControl->GetPaintManager()->m_clrFormulaSum; clrSubSum = m_pControl->GetPaintManager()->m_clrFormulaSubSum; } //CODE FOR RECALC double d(0.0); int m(0), M(0), n(0), N(0); CString s, t, u, v; CString sFormula(m_strFormula); int pos = sFormula.Find(_T("SUMSUB(")); //pattern SUMSUB(R#C#:R#C#) or * instead of # - means all row or column if (pos > -1 && m_pRecord->GetChilds() != NULL) { int mMax = m_pRecord->GetChilds()->GetCount(); int nMax = m_pRecord->GetItemCount(); sFormula.Replace(_T(" "), _T("")); sFormula = sFormula.Mid(pos + 7); pos = sFormula.Find(_T(":")); if (pos > -1) { s = sFormula.Left(pos); t = sFormula.Mid(pos + 1); pos = s.Find(_T("C")); if (pos > -1) { u = s.Left(pos); s = s.Mid(pos + 1); u.Replace(_T("R"), _T("")); if (u == _T("*")) m = 0; else m = _ttoi(u); if (s == _T("*")) n = 0; else n = _ttoi(s); pos = t.Find(_T("C")); if (pos > -1) { u = t.Left(pos); t = t.Mid(pos + 1); u.Replace(_T("R"), _T("")); if (u == _T("*")) M = mMax; else M = _ttoi(u); t.Replace(_T(")"), _T("")); if (t == _T("*")) N = nMax; else N = _ttoi(t); CXTPReportRecord* pRec = NULL; CXTPReportRecordItem* pItem = NULL; if (mMax > 0) { for (int row = m; row < M; row++) { for (int col = n; col < N; col++) { if (row < mMax) { pRec = m_pRecord->GetChilds()->GetAt(row); if (pRec) { if (col < pRec->GetItemCount()) { pItem = pRec->GetItem(col); if (pItem && pItem != this) //no circular ref!) { s = pItem->GetCaption(NULL); d += StringToDouble(s); } } } } } } CString sFmt = GetFormatString(); if (sFmt.IsEmpty() || sFmt == _T("%s")) sFmt = _T("%f"); else if (sFmt == _T("%d")) sFmt = _T("%.0f"); strCaption.Format(sFmt, d); SetTextColor(clrSubSum ); } } } } } sFormula = m_strFormula; pos = sFormula.Find(_T("SUM(")); //pattern SUM(R#C#:R#C#) or * instead of # - means all row or column if (pos > -1 && m_pRecord->GetRecords() != NULL) { int mMax = m_pRecord->GetRecords()->GetCount(); int nMax = m_pRecord->GetItemCount(); sFormula.Replace(_T(" "), _T("")); sFormula = sFormula.Mid(pos + 4); pos = sFormula.Find(_T(":")); if (pos > -1) { s = sFormula.Left(pos); t = sFormula.Mid(pos + 1); pos = s.Find(_T("C")); if (pos > -1) { u = s.Left(pos); s = s.Mid(pos + 1); u.Replace(_T("R"), _T("")); if (u == _T("*")) m = 0; else m = _ttoi(u); if (s == _T("*")) n = 0; else n = _ttoi(s); pos = t.Find(_T("C")); if (pos > -1) { u = t.Left(pos); t = t.Mid(pos + 1); u.Replace(_T("R"), _T("")); if (u == _T("*")) M = mMax; else M = _ttoi(u); t.Replace(_T(")"), _T("")); if (t == _T("*")) N = nMax; else N = _ttoi(t); CXTPReportRecord* pRec = NULL; CXTPReportRecordItem* pItem = NULL; if (m_pRecord->GetRecords()) { for (int row = m; row < M; row++) { for (int col = n; col < N; col++) { if (row < mMax) { pRec = m_pRecord->GetRecords()->GetAt(row); if (pRec) { if (col < pRec->GetItemCount()) { pItem = pRec->GetItem(col); if (pItem && pItem != this) //no circular ref! { s = pItem->GetCaption(NULL); d += StringToDouble(s); } } } } } } CString sFmt = GetFormatString(); if (sFmt.IsEmpty() || sFmt == _T("%s")) sFmt = _T("%f"); else if (sFmt == _T("%d")) sFmt = _T("%.0f"); strCaption.Format(sFmt, d); SetTextColor(clrSum ); } } } } } } //else if (m_strFormula.IsEmpty()) //{ // CString sFmt = GetFormatString(); // if (sFmt.Find(_T("%")) > -1) // { // if (sFmt.Find(_T("d")) > -1) // strCaption.Format(sFmt, _ttoi(strCaption)); // else if (sFmt.Find(_T("f")) > -1 || sFmt.Find(_T("g")) > -1) // strCaption.Format(sFmt, _tstof(strCaption)); // else // strCaption.Format(sFmt, strCaption); // } //} if (m_strCaption == strCaption) return; m_strCaption = strCaption; XTPMarkupReleaseElement(m_pMarkupUIElement); if (m_pRecord == NULL) return; CXTPMarkupContext* pMarkupContext = m_pRecord->GetMarkupContext(); if (pMarkupContext) m_pMarkupUIElement = XTPMarkupParseText(pMarkupContext, strCaption); else if (m_pRecord->m_pRecords) //extra source of markup { pMarkupContext = m_pRecord->m_pRecords->GetMarkupContext(); if (pMarkupContext) m_pMarkupUIElement = XTPMarkupParseText(pMarkupContext, strCaption); } } void CXTPReportRecordItem::DoMouseButtonClick() { mouse_event(GetSystemMetrics(SM_SWAPBUTTON) ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); mouse_event(GetSystemMetrics(SM_SWAPBUTTON) ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); } void CXTPReportRecordItem::GetCaptionRect(XTP_REPORTRECORDITEM_ARGS* pDrawArgs, CRect& rcItem) { ASSERT(pDrawArgs->pControl); if (!pDrawArgs->pControl) return; m_pControl = pDrawArgs->pControl; CXTPReportPaintManager* pPaintManager = pDrawArgs->pControl->GetPaintManager(); if (GetIconIndex() != XTP_REPORT_NOICON) { if (GetAlignment() != -1 && (GetAlignment() & xtpColumnIconRight) != 0) rcItem.right -= pPaintManager->DrawBitmap(NULL, pDrawArgs->pControl, rcItem, GetIconIndex()); else rcItem.left += pPaintManager->DrawBitmap(NULL, pDrawArgs->pControl, rcItem, GetIconIndex()); } if (m_bHasCheckbox) rcItem.left += 15; if (m_pItemControls && m_pItemControls->GetSize()) { for (int i = 0; i < m_pItemControls->GetSize() && rcItem.Width() > 0; i++) { int nWidth = m_pItemControls->GetAt(i)->GetSize().cx; nWidth = nWidth < 0 ? rcItem.Width() : nWidth; if (m_pItemControls->GetAt(i)->GetAlignment() == xtpItemControlRight) rcItem.right -= nWidth; else rcItem.left += nWidth; } } // Adjust for new lock icon BOOL bShowLock = !IsEditable() && pPaintManager->m_bShowLockIcon; if (bShowLock && !pDrawArgs->pControl->IsIconView()) //to prevent reaction on always read-only IconColumn / NumberColumn { rcItem.left += 18; } } void CXTPReportRecordItem::DrawCheckBox(XTP_REPORTRECORDITEM_DRAWARGS* pDrawArgs, CRect& rcItem) { BOOL bEditable = IsEditable() && (pDrawArgs->pColumn == NULL || pDrawArgs->pColumn->IsEditable()); CDC *pDC = pDrawArgs->pDC; XTPReportGlyph eState = xtpReportGlyphInvalid; if ( bEditable && !IsChecked()) { eState = xtpReportGlyphEnabledUnchecked; } else if ( bEditable && IsChecked()) { eState = xtpReportGlyphEnabledChecked; } else if (!bEditable && !IsChecked()) { eState = xtpReportGlyphDisabledUnchecked; } else if (!bEditable && IsChecked()) { eState = xtpReportGlyphDisabledChecked; } if (m_bTristateCheckbox && GetCheckedState() == xtpReportCheckStateIndeterminate) { eState = xtpReportGlyphEnabledTristate; } CXTPReportPaintManager *pPaintManager = pDrawArgs->pControl->GetPaintManager(); int nIconAlign = pDrawArgs->nTextAlign & xtpColumnIconMask; int nIconAlignV = nIconAlign & 0x0F000000; int nIconAlignH = nIconAlign & 0x00F00000; m_rcGlyph = rcItem; CSize sizeGlyph = pPaintManager->DrawGlyph(NULL, m_rcGlyph, eState); CRect rcGlyph(m_rcGlyph); // horizontal alignment switch (nIconAlignH) { case xtpColumnIconRight: rcGlyph.left = rcItem.right - sizeGlyph.cx - 2; // shift text box to the left rcItem.right -= (2 + sizeGlyph.cx); break; case xtpColumnIconCenter: rcGlyph.left = rcItem.CenterPoint().x - sizeGlyph.cx / 2 - 1; rcGlyph.right = rcGlyph.left + sizeGlyph.cx; break; // left text box as is - draw on image... case xtpColumnIconLeft: default: // shift text box to the right rcItem.left += 2 + sizeGlyph.cx; rcGlyph.left += 2; rcGlyph.right = rcItem.left - 1; break; } // vertical alignment switch (nIconAlignV) { case xtpColumnIconTop: rcGlyph.bottom = rcItem.top + sizeGlyph.cy + 2; break; case xtpColumnIconBottom: rcGlyph.top = rcItem.bottom - sizeGlyph.cy - 2; break; } // draw the glyph pPaintManager->DrawGlyph(pDC, rcGlyph, eState); m_rcGlyph = rcGlyph; //to restrict click on Glyph area only } void CXTPReportRecordItem::OnDrawCaption( XTP_REPORTRECORDITEM_DRAWARGS *pDrawArgs, XTP_REPORTRECORDITEM_METRICS *pMetrics) { ASSERT(pDrawArgs->pItem == this); CXTPReportPaintManager *pPaintManager = pDrawArgs->pControl->GetPaintManager(); BOOL bForceMarkUp(FALSE); if (pPaintManager) bForceMarkUp = pPaintManager->m_bForceDynamicMarkupForCell; //THIS CONDITION - IsVirtualMode() [Rev 7687 Oct 2008] PREVENTS MARKUP in Non-Virtual mode //if (pDrawArgs->pControl->IsVirtualMode() && pDrawArgs->pControl->GetMarkupContext()) //if (pDrawArgs->pControl->GetMarkupContext() // && !m_pMarkupUIElement) - rev 9113 //if (pDrawArgs->pControl->IsVirtualMode() // && pDrawArgs->pControl->GetMarkupContext() && !m_pMarkupUIElement) - rev 9114 // FIXED BACK! Only for virtual mode! Developer have to set Caption of Item to have markup // FIXED AGAIN WITH SPECIAL Flag to use if ((pDrawArgs->pControl->IsVirtualMode() || bForceMarkUp) && pDrawArgs->pControl->GetMarkupContext() && !m_pMarkupUIElement) { CXTPMarkupUIElement* pMarkupUIElement = XTPMarkupParseText(pDrawArgs->pControl->GetMarkupContext(), pMetrics->strText); if (pMarkupUIElement) { CRect rcItem = pDrawArgs->rcItem; rcItem.DeflateRect(2, 1, 2, 0); XTPMarkupSetDefaultFont(XTPMarkupElementContext(pMarkupUIElement), (HFONT)pMetrics->pFont->GetSafeHandle(), pMetrics->clrForeground); XTPMarkupMeasureElement(pMarkupUIElement, rcItem.Width(), INT_MAX); XTPMarkupRenderElement(pMarkupUIElement, pDrawArgs->pDC->GetSafeHdc(), &rcItem); XTPMarkupReleaseElement(pMarkupUIElement); return; } } if (m_pMarkupUIElement) { CRect rcItem = pDrawArgs->rcItem; rcItem.DeflateRect(2, 1, 2, 0); XTPMarkupSetDefaultFont(XTPMarkupElementContext(m_pMarkupUIElement), (HFONT)pMetrics->pFont->GetSafeHandle(), pMetrics->clrForeground); XTPMarkupMeasureElement(m_pMarkupUIElement, rcItem.Width(), INT_MAX); XTPMarkupRenderElement(m_pMarkupUIElement, pDrawArgs->pDC->GetSafeHdc(), &rcItem); } else { if (pPaintManager) { pPaintManager->DrawItemCaption(pDrawArgs, pMetrics); } } } void CXTPReportRecordItem::OnDrawControls(XTP_REPORTRECORDITEM_DRAWARGS* pDrawArgs, CRect& rcItem) { ASSERT(pDrawArgs->pItem == this); if (!m_pItemControls) return; for (int i = 0; i < m_pItemControls->GetSize() && rcItem.Width(); i++) { pDrawArgs->pControl->GetPaintManager()->DrawItemControl(pDrawArgs, m_pItemControls->GetAt(i), rcItem); } } int CXTPReportRecordItem::Draw(XTP_REPORTRECORDITEM_DRAWARGS *pDrawArgs) { ASSERT(pDrawArgs->pControl); if (!pDrawArgs->pControl) return 0; else m_pControl = pDrawArgs->pControl; CDC* pDC = pDrawArgs->pDC; CRect& rcItem = pDrawArgs->rcItem; CXTPReportPaintManager* pPaintManager = pDrawArgs->pControl->GetPaintManager(); XTP_REPORTRECORDITEM_METRICS* pMetrics = new XTP_REPORTRECORDITEM_METRICS(); pMetrics->strText = GetCaption(pDrawArgs->pColumn); pDrawArgs->pRow->GetItemMetrics(pDrawArgs, pMetrics); ASSERT(pMetrics->pFont); ASSERT(pMetrics->clrForeground != XTP_REPORT_COLOR_DEFAULT); if (pMetrics->clrBackground != XTP_REPORT_COLOR_DEFAULT) { pDC->FillSolidRect(rcItem, pMetrics->clrBackground); } int nItemGlyphs = rcItem.left; // draw tree inside item rect (see also HitTest function) if (pDrawArgs->pColumn && pDrawArgs->pColumn->IsTreeColumn()) { int nTreeDepth = pDrawArgs->pRow->GetTreeDepth() - pDrawArgs->pRow->GetGroupLevel(); if (nTreeDepth > 0) nTreeDepth++; BOOL bHasChildren = TRUE; if (pDrawArgs->pControl->IsVirtualMode()) { bHasChildren = (pMetrics->nVirtRowFlags & xtpVirtRowHasChildren) > 0; if (!bHasChildren) pDrawArgs->pRow->m_rcCollapse = CRect(NULL); if (pDrawArgs->pColumn == pDrawArgs->pControl->GetColumns()->GetIndentColumn()) pDrawArgs->nTextAlign = DT_LEFT; //to make compact tree presentation } else { bHasChildren = pDrawArgs->pRow->HasChildren(); } rcItem.left += pDrawArgs->pControl->GetIndent(nTreeDepth); if (pPaintManager->m_nBaseParentRecordIndent != 0) { if ((pDrawArgs->pRow->GetParentRow() != NULL ? pDrawArgs->pRow->GetParentRow()->IsGroupRow() : FALSE) && pDrawArgs->pRow->HasChildren() && (nTreeDepth == 0)) rcItem.left += pPaintManager->m_nBaseParentRecordIndent; if ((pDrawArgs->pRow->GetParentRow() != NULL ? !pDrawArgs->pRow->GetParentRow()->IsGroupRow() : FALSE) && (nTreeDepth > 0) && pDrawArgs->pControl->GetColumns()->GetGroupsOrder()->GetCount() > 0) rcItem.left += pPaintManager->m_nBaseParentRecordIndent; } // EXTRA TREE INDENT if (pPaintManager->m_bBaseTreeIndent) { rcItem.left += pPaintManager->m_nTreeIndent; } CRect rcBitmap(rcItem); CSize sizeBitmap = pPaintManager->DrawCollapsedBitmap(NULL, pDrawArgs->pRow, rcBitmap); pPaintManager->DrawTreeStructure(pDrawArgs, pMetrics, rcItem, sizeBitmap); int nIconAlign = pDrawArgs->nTextAlign & xtpColumnIconMask; // horizontal alignment switch (nIconAlign) { case xtpColumnIconRight: rcBitmap.left = rcBitmap.right - sizeBitmap.cx - 2; break; case xtpColumnIconLeft: rcBitmap.right = rcBitmap.left + sizeBitmap.cx + 2; break; } // vertical alignment switch (nIconAlign) { case xtpColumnIconTop: rcBitmap.bottom = rcBitmap.top + sizeBitmap.cy + 2; break; case xtpColumnIconBottom: rcBitmap.top = rcBitmap.bottom - sizeBitmap.cy - 2; break; } int nTreeTextIndent = 0; if (bHasChildren) { sizeBitmap = pPaintManager->DrawCollapsedBitmap(pDC, pDrawArgs->pRow, rcBitmap); if (!pDC->IsPrinting()) { pDrawArgs->pRow->SetCollapseRect(rcBitmap); } nTreeTextIndent = pPaintManager->m_nTreeTextIndentRowParent; } else { nTreeTextIndent = pPaintManager->m_nTreeTextIndentRowChildren; } rcItem.left = rcBitmap.left; rcItem.left += sizeBitmap.cx; rcItem.left += nTreeTextIndent; } pDC->SetTextColor(pMetrics->clrForeground); CFont* pOldFont = (CFont*)pDC->SelectObject(pMetrics->pFont); if (pMetrics->clrBackground != XTP_REPORT_COLOR_DEFAULT) { pDC->SetBkColor(pMetrics->clrBackground); } else { pDC->SetBkColor(pPaintManager->m_clrControlBack); } // Draw checkbox if (m_bHasCheckbox) { DrawCheckBox(pDrawArgs, rcItem); } BOOL bShowLock = !IsEditable() && pDrawArgs->pControl->GetPaintManager()->m_bShowLockIcon; // Do the draw bitmap pDC, rcItem, GetIconIndex() if (bShowLock && !pDrawArgs->pControl->IsIconView()) //to prevent reaction on always read-only IconColumn / NumberColumn { rcItem.left++; if (pDrawArgs->pControl->GetPaintManager()->m_bUseShellIcon) //variant without resources { pPaintManager->DrawShellIcon(pDC, rcItem, xtpReportShellIconLock); } else //variant with resources { pPaintManager->DrawGlyph(pDC, rcItem, xtpReportGlyphItemLocked); } rcItem.left += 17; } else if (pMetrics->nItemIcon != XTP_REPORT_NOICON || GetIconIndex() != XTP_REPORT_NOICON) { pPaintManager->DrawItemBitmap(pDrawArgs, rcItem, pMetrics->nItemIcon != XTP_REPORT_NOICON ? pMetrics->nItemIcon : GetIconIndex()); } else { CXTPReportRecordItemEditOptions* pEditOptions = GetEditOptions(pDrawArgs->pColumn); if (pEditOptions && pEditOptions->arrInplaceButtons.GetSize() > 0) { CXTPReportInplaceButton *pButton = pEditOptions->GetButton(0); if (pButton && pButton->IsInsideCellButton()) { CRect rc(rcItem); rc.left = rc.right - 17;//like CXTPReportInplaceButton::m_nWidth if (pPaintManager->IsFixedInplaceButtonHeight()) rc.bottom = min(rc.bottom, rc.top + 19); //like CXTPReportInplaceButton::m_nFixedHeight BOOL bShift(FALSE); //to keep focused frame not touched rc.top++; rc.bottom -= 2; rc.left--; if (pButton->GetID() == XTP_ID_REPORT_COMBOBUTTON) rc.right--; if (pButton->GetID() == XTP_ID_REPORT_COMBOBUTTON) bShift = pPaintManager->DrawInplaceComboButton(pDC, &rc); else if (pButton->GetID() == XTP_ID_REPORT_EXPANDBUTTON) bShift = pPaintManager->DrawInplaceExpandButton(pDC, &rc); else if (pButton->GetID() == XTP_ID_REPORT_SPINBUTTON) bShift = pPaintManager->DrawInplaceSpinButton(pDC, &rc); if (bShift) pDrawArgs->rcItem.right -= 17; } } } nItemGlyphs = (rcItem.left - nItemGlyphs); OnDrawControls(pDrawArgs, rcItem); if (rcItem.Width() > 2) { OnDrawCaption(pDrawArgs, pMetrics); } int nItemTextWidth = nItemGlyphs + 7; if (m_pMarkupUIElement) { nItemTextWidth += XTPMarkupMeasureElement(m_pMarkupUIElement, rcItem.Width() - 4, INT_MAX).cx; } 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()) { nItemTextWidth = max(wd, pDC->GetTextExtent(sFirst).cx + 7); } } pDC->SelectObject(pOldFont); pMetrics->InternalRelease(); return nItemTextWidth; } CXTPReportRecordItemControl* CXTPReportRecordItem::HitTest(CPoint ptPoint) { if (!(m_pItemControls && m_pItemControls->GetSize())) return NULL; for (int i = 0; i < m_pItemControls->GetSize(); i++) { CRect rcControl = m_pItemControls->GetAt(i)->GetRect(); if (rcControl.PtInRect(ptPoint)) return m_pItemControls->GetAt(i); } return NULL; } BOOL CXTPReportRecordItem::OnLButtonDown(XTP_REPORTRECORDITEM_CLICKARGS* pClickArgs) { CXTPReportRecordItemControl* pItemControl = HitTest(pClickArgs->ptClient); if (!pItemControl) return FALSE; pItemControl->OnLButtonDown(pClickArgs); // create item control window if (m_pItemControlHookWnd == NULL) { m_pItemControlHookWnd = new CXTPReportRecordItemControlHookWnd(pClickArgs); m_pItemControlHookWnd->Create(AfxRegisterWndClass(0), _T(""), WS_CHILD, pItemControl->GetRect(), pClickArgs->pControl, 0); m_pItemControlHookWnd->SetCapture(); } // redraw control pClickArgs->pControl->RedrawControl(); return TRUE; } BOOL CXTPReportRecordItem::OnLButtonUp(XTP_REPORTRECORDITEM_CLICKARGS* pClickArgs) { //>>attempt for 23588 issue case CXTPSmartPtrInternalT xSafety(this, TRUE); //>>attempt for 23588 issue case if (m_pItemControlHookWnd && m_pFocusedItemControl) { ReleaseCapture(); pClickArgs->pControl->ScreenToClient(&pClickArgs->ptClient); m_pFocusedItemControl->OnLButtonUp(pClickArgs); pClickArgs->pControl->RedrawControl(); // destroy item control window m_pItemControlHookWnd->DestroyWindow(); delete m_pItemControlHookWnd; m_pItemControlHookWnd = NULL; return TRUE; } CXTPReportRecordItemControl* pItemControl = HitTest(pClickArgs->ptClient); if (!pItemControl) return FALSE; pItemControl->OnLButtonUp(pClickArgs); pClickArgs->pControl->RedrawControl(); return TRUE; } void CXTPReportRecordItem::OnClick(XTP_REPORTRECORDITEM_CLICKARGS* pClickArgs) { if (!pClickArgs || !pClickArgs->pControl) return; if (OnLButtonUp(pClickArgs)) //old version (10) did not have this call return; InternalAddRef(); CMDTARGET_ADDREF(pClickArgs->pColumn); CMDTARGET_ADDREF(pClickArgs->pControl); CXTPReportRow* pRow = pClickArgs->pRow; CMDTARGET_ADDREF(pRow); BOOL bCheckBoxClicked = FALSE; CXTPReportControl* pControl = pClickArgs->pControl; if (IsEditable() && m_bHasCheckbox && (pClickArgs->pColumn == NULL || pClickArgs->pColumn->IsEditable()) && OnRequestEdit(pClickArgs)) { // adjust vertical coordinates if virtual mode if (pControl->IsVirtualMode()) { m_rcGlyph.top = pClickArgs->rcItem.top; m_rcGlyph.bottom = pClickArgs->rcItem.bottom; } // check whether we're clicking glyph area if (m_rcGlyph.PtInRect(pClickArgs->ptClient) && m_rcGlyph.PtInRect(pControl->m_mouseDownState.ptMouse)) { if (pControl->IsAutoCheckItems()) { if (!m_bTristateCheckbox) { SetChecked(!IsChecked()); } else { SetCheckedState((GetCheckedState() + 1) % xtpReportCheckStateCount); } } pControl->RedrawControl(); pControl->SendMessageToParent(pClickArgs->pRow, this, pClickArgs->pColumn, XTP_NM_REPORT_CHECKED, &pClickArgs->ptClient); bCheckBoxClicked = TRUE; } } if (!bCheckBoxClicked && IsAllowEdit(pClickArgs)) { if (pControl->IsEditOnDelayClick()) { if ( pControl->GetLastRqstEditCol() != pClickArgs->pColumn->GetItemIndex() || pControl->GetLastRqstEditRow() != pClickArgs->pRow->GetIndex()) { pControl->EnsureStopLastRqstTimer(); pControl->SetLastRqstEdit(pClickArgs->pRow->GetIndex(), pClickArgs->pColumn->GetItemIndex()); } else if(!pControl->GetDelayEditTimer()) { // Start the timer for this request. pControl->StartDelayEditTimer(); } } if (pControl->IsEditOnClick()) { pControl->EditItem(pClickArgs); CPoint pt(pClickArgs->ptClient); pControl->ClientToScreen(&pt); CXTPReportInplaceEdit* pEdit = DYNAMIC_DOWNCAST(CXTPReportInplaceEdit, CWnd::FromHandle(WindowFromPoint(pt))); if (pEdit && pEdit->GetItem() == this) { CXTPReportRecordItemEditOptions* pEditOptions = GetEditOptions(pClickArgs->pColumn); if (pEditOptions->m_bSelectTextOnEdit) pEdit->SetSel(0, -1); else DoMouseButtonClick(); } } } pClickArgs->pControl->SendMessageToParent(pClickArgs->pRow, this, pClickArgs->pColumn, NM_CLICK, &pClickArgs->ptClient); // Determine Hyperlink Click int nHyperlink = HitTestHyperlink(pClickArgs->ptClient); int mHyperlink = HitTestHyperlink(pControl->m_mouseDownState.ptMouse); if (nHyperlink >= 0 && mHyperlink >= 0) pClickArgs->pControl->SendMessageToParent(pClickArgs->pRow, this, pClickArgs->pColumn, XTP_NM_REPORT_HYPERLINK, &pClickArgs->ptClient, nHyperlink); CMDTARGET_RELEASE(pRow); CMDTARGET_RELEASE(pClickArgs->pColumn); CMDTARGET_RELEASE(pClickArgs->pControl); InternalRelease(); } int CXTPReportRecordItem::HitTestHyperlink(CPoint ptClick) { int nHitTest = -1; int nHyperlinks = GetHyperlinksCount(); CXTPReportHyperlink *pHyperlink; for (int nHyperlink = 0; nHyperlink < nHyperlinks; nHyperlink++) { pHyperlink = GetHyperlinkAt(nHyperlink); ASSERT(pHyperlink); if (pHyperlink && pHyperlink->m_rcHyperSpot.PtInRect(ptClick)) { ASSERT(-1 == nHitTest); nHitTest = nHyperlink; } } return nHitTest; } void CXTPReportRecordItem::OnDblClick(XTP_REPORTRECORDITEM_CLICKARGS *pClickArgs) { if (!pClickArgs || !pClickArgs->pControl) return; if (OnLButtonDown(pClickArgs)) //old version (10) did not have this call return; CXTPReportControl *pControl = pClickArgs->pControl; if (IsAllowEdit(pClickArgs) && !pControl->IsEditOnClick() && pControl->IsEditOnDoubleClick() && pControl->GetInplaceEdit()->GetItem() != this) { pControl->EditItem(pClickArgs); CPoint pt(pClickArgs->ptClient); pControl->ClientToScreen(&pt); CXTPReportInplaceEdit* pEdit = DYNAMIC_DOWNCAST(CXTPReportInplaceEdit, CWnd::FromHandle(WindowFromPoint(pt))); if (pEdit && pEdit->GetItem() == this) { CXTPReportRecordItemEditOptions* pEditOptions = GetEditOptions(pClickArgs->pColumn); if (pEditOptions->m_bSelectTextOnEdit) pEdit->SetSel(0, -1); else DoMouseButtonClick(); } } pControl->SendMessageToParent(pClickArgs->pRow, this, pClickArgs->pColumn, NM_DBLCLK, &pClickArgs->ptClient, -1); } void CXTPReportRecordItem::OnMouseMove(UINT nFlags, CPoint point, CXTPReportControl* pControl) { int nHyperlink = HitTestHyperlink(point); if (nHyperlink >= 0) { SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND)); return; } CXTPReportRecordItemControl* pItemControl = HitTest(point); if (m_pItemControlHookWnd && m_pFocusedItemControl && (nFlags & MK_LBUTTON)) { pControl->ScreenToClient(&point); if (m_bItemControlUnderMouse && !m_pFocusedItemControl->GetRect().PtInRect(point)) { m_pFocusedItemControl->OnMouseLeave(nFlags, point); m_bItemControlUnderMouse = FALSE; } else if (!m_bItemControlUnderMouse && m_pFocusedItemControl->GetRect().PtInRect(point)) { m_pFocusedItemControl->OnMouseEnter(nFlags, point); m_bItemControlUnderMouse = TRUE; } else m_pFocusedItemControl->OnMouseMove(nFlags, point); if (pControl != NULL && !pControl->IsEditMode()) pControl->RedrawControl(); return; } if (pItemControl) { if (pItemControl != m_pFocusedItemControl) { if (m_pFocusedItemControl) { m_pFocusedItemControl->OnMouseLeave(nFlags, point); m_bItemControlUnderMouse = FALSE; } pItemControl->OnMouseEnter(nFlags, point); m_bItemControlUnderMouse = TRUE; } pItemControl->OnMouseMove(nFlags, point); if (pControl != NULL && !pControl->IsEditMode()) pControl->RedrawControl(); } else { if (m_pFocusedItemControl) { m_pFocusedItemControl->OnMouseLeave(nFlags, point); m_bItemControlUnderMouse = FALSE; if (pControl != NULL && !pControl->IsEditMode()) pControl->RedrawControl(); } } m_pFocusedItemControl = pItemControl; } void CXTPReportRecordItem::SetFont(CFont* pFont) { m_pFontCaption = pFont; } void CXTPReportRecordItem::SetBold(BOOL bBold) { m_bBoldText = bBold; } void CXTPReportRecordItem::SetTextColor(COLORREF clrText) { m_clrText = clrText; } COLORREF CXTPReportRecordItem::GetTextColor() { return m_clrText; } void CXTPReportRecordItem::SetBackgroundColor(COLORREF clrBackground) { m_clrBackground = clrBackground; } COLORREF CXTPReportRecordItem::GetBackgroundColor() { return m_clrBackground; } int CXTPReportRecordItem::Compare(CXTPReportColumn* pColumn, CXTPReportRecordItem* pItem) { if (!pItem) return 0; if (m_nSortPriority != -1 || pItem->m_nSortPriority != -1) return m_nSortPriority - pItem->m_nSortPriority; return m_pRecord->GetRecords()->Compare(GetCaption(pColumn), pItem->GetCaption(pColumn)); } CFont* CXTPReportRecordItem::GetFont() { return m_pFontCaption; } CString CXTPReportRecordItem::GetGroupCaption(CXTPReportColumn* pColumn) { if (!m_strGroupCaption.IsEmpty()) return m_strGroupCaption; int nID = GetGroupCaptionID(pColumn); if (nID > 0) { CString str; if (str.LoadString(nID)) return str; } if (m_pMarkupUIElement || pColumn->GetMarkupUIElement()) return GetCaption(pColumn); return pColumn->GetCaption() + _T(": ") + GetCaption(pColumn); } int CXTPReportRecordItem::CompareGroupCaption(CXTPReportColumn* pColumn, CXTPReportRecordItem* pItem) { if (m_nGroupPriority != -1) return m_nGroupPriority - pItem->m_nGroupPriority; if (!m_strGroupCaption.IsEmpty()) return m_pRecord->GetRecords()->Compare(m_strGroupCaption, pItem->m_strGroupCaption); int nID = GetGroupCaptionID(pColumn); if (nID > 0) return nID - pItem->GetGroupCaptionID(pColumn); return Compare(pColumn, pItem); } int CXTPReportRecordItem::GetGroupCaptionID(CXTPReportColumn* /*pColumn*/) { return m_nGroupPriority; } void CXTPReportRecordItem::GetItemMetrics(XTP_REPORTRECORDITEM_DRAWARGS* pDrawArgs, XTP_REPORTRECORDITEM_METRICS* pItemMetrics) { if (m_clrBackground != XTP_REPORT_COLOR_DEFAULT) pItemMetrics->clrBackground = m_clrBackground; if (m_clrText != XTP_REPORT_COLOR_DEFAULT) pItemMetrics->clrForeground = m_clrText; if (m_pFontCaption != NULL) pItemMetrics->pFont = m_pFontCaption; else if (m_bBoldText) pItemMetrics->pFont = &pDrawArgs->pControl->GetPaintManager()->m_fontBoldText; if (m_Alignment != (XTPReportColumnIconAlignment)(-1)) pItemMetrics->nColumnAlignment = m_Alignment; } int CXTPReportRecordItem::GetIndex() const { return m_pRecord ? m_pRecord->IndexOf(this) : -1; } CXTPReportColumn* CXTPReportRecordItem::GetColumn() { if (m_pControl) { int nItemIndex = GetIndex(); CXTPReportColumns* pCols = m_pControl->GetColumns(); if (pCols) return pCols->Find(nItemIndex); } return NULL; } BOOL CXTPReportRecordItem::IsEditable() const { if (this == NULL) return FALSE; if (!m_pRecord) return FALSE; return m_pRecord ? m_pRecord->m_bEditable && m_bEditable && IsFocusable() : FALSE; } BOOL CXTPReportRecordItem::IsFocusable() const { if (this == NULL) return FALSE; return m_bFocusable; } BOOL CXTPReportRecordItem::GetCanEditCheckboxItem() const { if (this == NULL) return FALSE; return m_bCanEditCheckboxItem; } void CXTPReportRecordItem::SetCanEditCheckboxItem(BOOL bSet) { m_bCanEditCheckboxItem = bSet; } void CXTPReportRecordItem::OnBeginEdit(XTP_REPORTRECORDITEM_ARGS* pItemArgs) { ASSERT(pItemArgs); if (!pItemArgs) return; if (IsEditable() && OnRequestEdit(pItemArgs)) { CXTPReportControl* pControl = pItemArgs->pControl; CXTPReportInplaceEdit* pEdit = pControl->GetInplaceEdit(); CRect rcCaption(pItemArgs->rcItem); GetCaptionRect(pItemArgs, rcCaption); CXTPReportRecordItemEditOptions* pEditOptions = GetEditOptions(pItemArgs->pColumn); ASSERT(pEditOptions); CXTPReportInplaceButtons* pInpaceButtons = &pEditOptions->arrInplaceButtons; CRect rcButtons(pItemArgs->rcItem); CXTPClientRect rcControl(pItemArgs->pControl); int i; // calculate right-aligned item controls width int nControlsWidthRight = 0; if (m_pItemControls && m_pItemControls->GetSize() > 0) { for (i = 0; m_pItemControls && i < m_pItemControls->GetSize(); i++) { CXTPReportRecordItemControl* pControl = m_pItemControls->GetAt(i); if (pControl->GetAlignment() == xtpItemControlRight) nControlsWidthRight += pControl->GetRect().Width(); else pItemArgs->rcItem.left += pControl->GetRect().Width(); } } // calculate inplace buttons widths int nButtonsWidthIn = 0, nButtonsWidthOut = 0; for (i = 0; i < pInpaceButtons->GetSize(); i++) { CXTPReportInplaceButton* pButton = pInpaceButtons->GetAt(i); if (pButton->IsInsideCellButton()) nButtonsWidthIn += pButton->GetWidth(); else nButtonsWidthOut += pButton->GetWidth(); } // adjust buttons rect if (rcButtons.right + nButtonsWidthOut > rcControl.right) rcButtons.right = rcControl.right - nButtonsWidthOut; rcButtons.left = min(rcButtons.right, pItemArgs->rcItem.right - nControlsWidthRight); // create buttons for (i = 0; i < pInpaceButtons->GetSize(); i++) { CXTPReportInplaceButton* pButton = pInpaceButtons->GetAt(i); pButton->Create(pItemArgs, rcButtons); pControl->GetInplaceButtons()->Add(pButton); } // adjust item rect pItemArgs->rcItem.right = rcButtons.left; if (pEditOptions->m_bAllowEdit) { if (m_bHasCheckbox && !m_bCanEditCheckboxItem) return; else pEdit->Create(pItemArgs); } if (!pEditOptions->m_bAllowEdit && pInpaceButtons->GetSize() > 0) { CXTPReportInplaceButton *pButton = pInpaceButtons->GetAt(0); OnInplaceButtonDown(pButton); } XTP_NM_REPORTRECORDITEM nm; ::ZeroMemory(&nm, sizeof(nm)); nm.pItem = this; nm.pRow = pItemArgs->pRow; nm.pColumn = pItemArgs->pColumn; pControl->SendNotifyMessage(XTP_NM_REPORT_BEGINEDIT, (NMHDR*)&nm); } } void CXTPReportRecordItem::OnCancelEdit(CXTPReportControl *pControl, BOOL bApply) { if (NULL == pControl) return; CXTPReportInplaceButtons* pInpaceButtons = pControl->GetInplaceButtons(); for (int i = 0; i < pInpaceButtons->GetSize(); i++) { CXTPReportInplaceButton* pButton = pInpaceButtons->GetAt(i); if (pButton->GetSafeHwnd()) pButton->DestroyWindow(); if (pButton) { pButton->SetItemArgs(0); } } pInpaceButtons->RemoveAll(); CXTPReportInplaceList* pInpaceList = pControl->GetInplaceList(); if (pInpaceList->GetSafeHwnd()) pInpaceList->DestroyWindow(); CXTPReportInplaceEdit* pEdit = pControl->GetInplaceEdit(); if (pEdit == NULL) return; if (pEdit->GetSafeHwnd()) { if (bApply && pEdit->GetItem() == this) OnValidateEdit((XTP_REPORTRECORDITEM_ARGS*) pEdit); pEdit->HideWindow(); pEdit->SetItemArgs(0); pEdit->DestroyWindow(); } } void CXTPReportRecordItem::OnConstraintChanged(XTP_REPORTRECORDITEM_ARGS* pItemArgs, CXTPReportRecordItemConstraint* pConstraint) { OnEditChanged(pItemArgs, pConstraint->m_strConstraint); } BOOL CXTPReportRecordItem::OnEditChanging(XTP_REPORTRECORDITEM_ARGS* pItemArgs, CString& rstrNewText) { UNREFERENCED_PARAMETER(pItemArgs); UNREFERENCED_PARAMETER(rstrNewText); return TRUE; } void CXTPReportRecordItem::OnEditChanged(XTP_REPORTRECORDITEM_ARGS* pItemArgs, LPCTSTR szText) { if (pItemArgs) { int r = pItemArgs->pRow->GetIndex(); int i = pItemArgs->pItem->GetIndex(); CXTPReportRecord* pRec = pItemArgs->pRow->GetRecord(); if (pRec) pRec->UpdateRecordField(r, i, szText); } } void CXTPReportRecordItem::OnValidateEdit(XTP_REPORTRECORDITEM_ARGS* pItemArgs) { ASSERT(pItemArgs); if (!pItemArgs) return; CXTPReportControl* pControl = pItemArgs->pControl; CXTPReportInplaceEdit* pEdit = pControl->GetInplaceEdit(); XTP_REPORTRECORDITEM_ARGS args = *pItemArgs; if (pEdit->GetSafeHwnd() && pEdit->GetItem() == this) { args.AddRef(); BOOL bRedraw = FALSE; CMDTARGET_RELEASE(pEdit->pItem); //pEdit->pItem = NULL; if (GetEditOptions(args.pColumn)->m_bConstraintEdit) { if (pEdit->m_pSelectedConstraint) { OnConstraintChanged(&args, pEdit->m_pSelectedConstraint); bRedraw = TRUE; } } else { CString strValue; pEdit->GetWindowText(strValue); CString sOldValue = GetCaption(args.pColumn); if (sOldValue != strValue || pControl->IsVirtualMode()) { OnEditChanged(&args, strValue); bRedraw = TRUE; } //else if (GetCaption(args.pColumn) != strValue) //<<>> //{ // OnEditChanged(&args, strValue); // bRedraw = TRUE; //} } if (bRedraw) { pControl->RedrawControl(); pControl->SendMessageToParent(args.pRow, this, args.pColumn, XTP_NM_REPORT_VALUECHANGED, 0); } else { OnEditCanceled(pItemArgs); pControl->SendMessageToParent(args.pRow, this, args.pColumn, XTP_NM_REPORT_EDIT_CANCELED, 0); } pEdit->SetItemArgs(0); args.Release(); } } BOOL CXTPReportRecordItem::IsAllowEdit(XTP_REPORTRECORDITEM_ARGS *pItemArgs) { BOOL bIsAllowEdit = pItemArgs->pControl->IsAllowEdit(); if (m_pRecord) { // Header record if (m_pRecord->m_pRecords == pItemArgs->pControl->GetHeaderRecords()) { bIsAllowEdit = pItemArgs->pControl->IsHeaderRowsAllowEdit(); } // Footer record else if (m_pRecord->m_pRecords == pItemArgs->pControl->GetFooterRecords()) { bIsAllowEdit = pItemArgs->pControl->IsFooterRowsAllowEdit(); } } bIsAllowEdit = bIsAllowEdit && IsEditable(); if (pItemArgs->pColumn) { bIsAllowEdit = bIsAllowEdit && pItemArgs->pColumn->IsEditable(); } else { if (m_pEditOptions) { bIsAllowEdit = bIsAllowEdit && m_pEditOptions->m_bAllowEdit; } } return bIsAllowEdit; } BOOL CXTPReportRecordItem::OnRequestEdit(XTP_REPORTRECORDITEM_ARGS* pItemArgs) { CXTPReportControl* pControl = pItemArgs->pControl; XTP_NM_REPORTREQUESTEDIT nm; ::ZeroMemory(&nm, sizeof(nm)); nm.bCancel = FALSE; nm.pItem = this; nm.pRow = pItemArgs->pRow; nm.pColumn = pItemArgs->pColumn; pControl->SendNotifyMessage(XTP_NM_REPORT_REQUESTEDIT, (NMHDR*)&nm); return !nm.bCancel; } BOOL CXTPReportRecordItem::OnChar(XTP_REPORTRECORDITEM_ARGS *pItemArgs, UINT nChar) { CXTPReportControl* pControl = pItemArgs->pControl; if ((nChar == VK_SPACE) && IsEditable() && m_bHasCheckbox && (pItemArgs->pColumn == NULL || pItemArgs->pColumn->IsEditable()) && OnRequestEdit(pItemArgs)) { if (pControl->IsAutoCheckItems()) { if (!m_bTristateCheckbox) SetChecked(!IsChecked()); else SetCheckedState((GetCheckedState() + 1) % 3); } pControl->RedrawControl(); pControl->SendMessageToParent(pItemArgs->pRow, this, pItemArgs->pColumn, XTP_NM_REPORT_CHECKED, NULL); return TRUE; } if (IsAllowEdit(pItemArgs)) { // ^^ causes CXTPReportRecordItem::OnChar do be called twice BOOL bSameItem = pItemArgs->pItem == pControl->GetActiveItem(); if (!bSameItem) { pControl->EditItem(pItemArgs); } CXTPReportInplaceEdit *pEdit = pControl->GetInplaceEdit(); if (pEdit->GetSafeHwnd() && pEdit->GetItem() == this) { if (!bSameItem) { pEdit->SetFocus(); pEdit->SetSel(0, -1); } if (VK_TAB != nChar) { pEdit->SendMessage(WM_CHAR, nChar); } } return TRUE; } return FALSE; } CXTPReportRecordItemEditOptions* CXTPReportRecordItem::GetEditOptions(CXTPReportColumn* pColumn) { if (m_pEditOptions) return m_pEditOptions; if (pColumn) return pColumn->GetEditOptions(); return m_pEditOptions = new CXTPReportRecordItemEditOptions(); } CXTPReportRecordItemControls* CXTPReportRecordItem::GetItemControls() { if (!m_pItemControls) m_pItemControls = new CXTPReportRecordItemControls(this); return m_pItemControls; } void CXTPReportRecordItem::OnInplaceButtonDown(CXTPReportInplaceButton* pButton) { CXTPReportControl* pControl = pButton->pControl; XTP_NM_REPORTINPLACEBUTTON nm; ::ZeroMemory(&nm, sizeof(nm)); nm.pButton = pButton; nm.pItem = this; if (pControl->SendNotifyMessage(XTP_NM_REPORT_INPLACEBUTTONDOWN, (NMHDR*)&nm) == TRUE) return; if (pButton->GetID() == XTP_ID_REPORT_COMBOBUTTON) { CXTPReportInplaceList* pList = pControl->GetInplaceList(); XTP_REPORTRECORDITEM_ARGS itemArgs = *pButton; if (!itemArgs.pColumn && !itemArgs.pControl && !itemArgs.pItem && !itemArgs.pRow) return; ASSERT(itemArgs.pItem == this); CXTPWindowRect rcButton(pButton); pControl->ScreenToClient(&rcButton); itemArgs.rcItem.right = rcButton.right; itemArgs.rcItem.bottom = rcButton.bottom; CXTPReportRecordItemEditOptions* pEditOptions = GetEditOptions(itemArgs.pColumn); pList->m_Items2Show = pButton->m_Items2Show; if (pEditOptions->GetConstraints()->GetCount() > 0) pList->Create(&itemArgs, pEditOptions->GetConstraints()); } else if (pButton->GetID() == XTP_ID_REPORT_SPINBUTTON) { XTP_REPORTRECORDITEM_ARGS itemArgs = *pButton; ASSERT(itemArgs.pItem == this); CXTPReportInplaceEdit* pEdit = pControl->GetInplaceEdit(); if (itemArgs.pRow && itemArgs.pColumn && pEdit->GetSafeHwnd() && pEdit->GetItem() == this) { CString strValue; pEdit->GetWindowText(strValue); int nValue = _ttoi(strValue); int nValue2 = nValue + pButton->m_nSpinIncrement; nValue2 = max(nValue2, pButton->m_nSpinMin); nValue2 = min(nValue2, pButton->m_nSpinMax); if (nValue2 != nValue) { strValue.Format(_T("%d"), nValue2); BOOL bCommit = OnEditChanging(&itemArgs, strValue); if (bCommit) pEdit->SetWindowText(strValue); pControl->RedrawControl(); //pControl->SendMessageToParent(itemArgs.pRow, this, itemArgs.pColumn, XTP_NM_REPORT_VALUECHANGED, 0); } } } } CXTPReportHyperlinks* CXTPReportRecordItem::GetHyperlinks() { if (!m_pHyperlinks) m_pHyperlinks = new CXTPReportHyperlinks(); return m_pHyperlinks; } void CXTPReportRecordItem::DoPropExchange(CXTPPropExchange* pPX) { PX_DWord(pPX, _T("TextColor"), (DWORD&)m_clrText, XTP_REPORT_COLOR_DEFAULT); PX_DWord(pPX, _T("BackgroundColor"), (DWORD&)m_clrBackground, XTP_REPORT_COLOR_DEFAULT); PX_Bool(pPX, _T("BoldText"), m_bBoldText, FALSE); PX_String(pPX, _T("Format"), m_strFormatString, _T("%s")); PX_Bool(pPX, _T("Editable"), m_bEditable, TRUE); PX_Int(pPX, _T("IconIndex"), m_nIconIndex, XTP_REPORT_NOICON); PX_Int(pPX, _T("SortPriority"), m_nSortPriority, -1); PX_Int(pPX, _T("GroupPriority"), m_nGroupPriority, -1); PX_String(pPX, _T("GroupCaption"), m_strGroupCaption, _T("")); PX_Bool(pPX, _T("Focusable"), m_bFocusable, TRUE); PX_Int(pPX, _T("Checked"), m_checkState, 0); PX_Bool(pPX, _T("HasCheckbox"), m_bHasCheckbox, FALSE); PX_Bool(pPX, _T("TristateCheckbox"), m_bTristateCheckbox, FALSE); ULONGLONG ullData = m_dwData; PX_UI8(pPX, _T("Data"), ullData, 0); m_dwData = (DWORD_PTR)ullData; PX_String(pPX, _T("Tooltip"), m_strTooltip, _T("")); if (pPX->GetSchema() > _XTP_SCHEMA_98) { PX_String(pPX, _T("Caption"), m_strCaption, _T("")); } // Hyperlinks CXTPPropExchangeSection secHyperlinks(pPX->GetSection(_T("Hyperlinks"))); CXTPReportHyperlinks arHyperlinks; if (pPX->IsStoring() && m_pHyperlinks) { arHyperlinks.CopyFrom(m_pHyperlinks); } arHyperlinks.DoPropExchange(&secHyperlinks); if (pPX->IsLoading()) { if (arHyperlinks.GetSize()) { if (GetHyperlinks()) GetHyperlinks()->CopyFrom(&arHyperlinks); } else if (m_pHyperlinks) { m_pHyperlinks->RemoveAll(); } } // Item controls CXTPReportRecordItemControls arItemControls; if (pPX->IsStoring() && m_pItemControls) arItemControls.CopyFrom(m_pItemControls); if (pPX->GetSchema() >= _XTP_SCHEMA_1200) { CXTPPropExchangeSection secItemControls(pPX->GetSection(_T("ItemControls"))); arItemControls.DoPropExchange(&secItemControls); } if (pPX->IsLoading()) { if (arItemControls.GetSize()) { if (GetItemControls()) GetItemControls()->CopyFrom(&arItemControls); } else if (m_pItemControls) { m_pItemControls->RemoveAll(); } } // Update Markup data if (pPX->IsLoading()) { XTPMarkupReleaseElement(m_pMarkupUIElement); CXTPMarkupContext* pMarkupContext = m_pRecord ? m_pRecord->GetMarkupContext() : NULL; if (pMarkupContext) { m_pMarkupUIElement = XTPMarkupParseText(pMarkupContext, m_strCaption); } } } INT_PTR CXTPReportRecordItem::OnToolHitTest(CPoint /*point*/, TOOLINFO* /*pTI*/) { return -1; } void CXTPReportRecordItem::Merge(CXTPReportRecordItem *pMergeItem) { m_pMergeItem = pMergeItem; } CXTPReportRecordItem *CXTPReportRecordItem::GetMergeItem() const { return m_pMergeItem; } BOOL CXTPReportRecordItem::IsMerged() const { return (NULL != m_pMergeItem); } int CXTPReportRecordItem::AddHyperlink(CXTPReportHyperlink* pHyperlink) { return GetHyperlinks() ? (int)GetHyperlinks()->Add(pHyperlink) : -1; } int CXTPReportRecordItem::GetHyperlinksCount() const { return m_pHyperlinks ? (int)m_pHyperlinks->GetSize() : 0; } CXTPReportHyperlink* CXTPReportRecordItem::GetHyperlinkAt(int nHyperlink) const { return m_pHyperlinks ? m_pHyperlinks->GetAt(nHyperlink) : NULL; } void CXTPReportRecordItem::RemoveHyperlinkAt(int nHyperlink) { if (m_pHyperlinks) m_pHyperlinks->RemoveAt(nHyperlink); } BOOL CXTPReportRecordItem::CreateBorder() { if (NULL == m_pBorder) { m_pBorder = new CXTPReportBorder(); } return (NULL != m_pBorder); } BOOL CXTPReportRecordItem::DestroyBorder() { if (NULL != m_pBorder) { delete m_pBorder; m_pBorder = NULL; } return (NULL == m_pBorder); } CXTPReportBorder* CXTPReportRecordItem::GetBorder() const { return m_pBorder; }