|
If using this control on a system with multiple displays, you will find problems adding items from the field chooser if the window is on a monitor with negative coordinates (i.e. to the left or above the primary display).
This is due to how it sends the coordinates to the header control allowing for the drawing of the red placement arrows, dropping the column in, etc.
m_iDropIndex = m_pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, TRUE, MAKELONG(pt.x,pt.y));
MAKELONG returns a long obviously. However the params being passed to the macro are both longs. MAKELONG needs shorts to work properly. If not fixed, the headercontrol will receive the message and not get correct values for negative coordinates when doing HIWORD and LOWORD.
Make the following changes in CReportSubItemListCtrl::Dragging(CPoint pt)
/* cast the values to shorts */
short x = (short)pt.x;
short y = (short)pt.y;
m_iDropIndex = pReportCtrl->m_wndHeader.SendMessage(HDM_SETHOTDIVIDER, TRUE, MAKELONG(x,y));
In CFlatHeaderCtrl::OnSetHotDivider(WPARAM wParam, LPARAM lParam)
do:
short x = (short)LOWORD(lParam);
short y = (short)HIWORD(lParam);
hdhti.pt.x = x;
hdhti.pt.y = y;
This should fix your problem. I was seeing values in the -200s being converted to +60,000s in this handler until I made the changes.
TMB
|
|
|
|
|
This code is in ReportCtrl.cpp, line 5108 (aproximatelly) :
CPen pen(PS_SOLID, 2, RGB(0xFF, 0, 0));
CPen* pPen = pDC->SelectObject(&pen);
if(bDisable == TRUE)
{
rect.DeflateRect(1, 1);
if( lprvi->iCheck >= 4 )
rect.OffsetRect(2, 0);
pDC->MoveTo(rect.left, rect.top);
pDC->LineTo(rect.right-1, rect.bottom-1);
pDC->MoveTo(rect.right-1, rect.top);
pDC->LineTo(rect.left, rect.bottom-1);
pDC->SelectObject(pPen);
}
This is error, because if conditional block is not processed,
the pen is not restored. Result is when you use checkbox,
grid lines in next function are drawed in not right color.
Change it to:
CPen pen(PS_SOLID, 2, RGB(0xFF, 0, 0));
CPen* pPen = pDC->SelectObject(&pen);
if(bDisable == TRUE)
{
rect.DeflateRect(1, 1);
if( lprvi->iCheck >= 4 )
rect.OffsetRect(2, 0);
pDC->MoveTo(rect.left, rect.top);
pDC->LineTo(rect.right-1, rect.bottom-1);
pDC->MoveTo(rect.right-1, rect.top);
pDC->LineTo(rect.left, rect.bottom-1);
}
pDC->SelectObject(pPen);
|
|
|
|
|
I'd like to use CReportView instead of CListView which creates VS2003 in MDI app wizard with chosen "windows explorer" window style. Some problem is here with redrawing CReportCtrl content. I simple paste content of ReportCrtlDemo OnInitialUpdate() into the same member in MDI app's view class. After code executes this, in wiew nothing displays, till I click on non-visible header. Then control header stay visible, when I try drag - it's possible, but background does not redraws, there is only redrawing field like it is dragged. Probably is needed to add some message handler for redrawing report control ? What to do with it ?
|
|
|
|
|
Problem with redrawing backgroung is solved,
but still here is some problem with activating control.
After content is drawed I must to call rc.PostMessage(WM_ACTIVATE, 2, 0) and rc.PostMessage(WM_ACTIVATETOPLEVEL, 2, 0).
Both I investigate with spy++ with demo application.
What I dod wrong ? IMHO it should not need to send these messages.
|
|
|
|
|
Hi,
I've added the Unicode macros to my app, and I started to get errors with this function, such that I cannot solve myself:
OnToolTipNotify(UINT nId, NMHDR *pNMHDR, LRESULT *pResult)
I tried replacing the code in the function to this, but it started crashing whenever I hovered over the list header.
<br />
void ConvertStringToWChar (LPCTSTR str, WCHAR *buffer)<br />
{<br />
for (int i=0; str[i]; i++)<br />
buffer[i] = (WCHAR)str[i];<br />
buffer[i] = 0;<br />
}<br />
<br />
BOOL CFlatHeaderCtrl::OnToolTipNotify(UINT nId, NMHDR *pNMHDR, LRESULT *pResult)<br />
{<br />
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;<br />
<br />
if(<br />
pNMHDR->idFrom == (UINT)FLATHEADER_TT_MAGIC &&<br />
!m_arrayHdrItemEx[m_iHotIndex].strToolTip.IsEmpty()<br />
) {<br />
WCHAR *lpszW = new WCHAR[MAX_PATH];<br />
ConvertStringToWChar (m_arrayHdrItemEx[m_iHotIndex].strToolTip, lpszW);<br />
wcscpy((WCHAR*)pTTT->lpszText, lpszW);<br />
delete[] lpszW;<br />
<br />
pTTT->lpszText = pTTT->szText;<br />
return TRUE;<br />
}<br />
else <br />
return FALSE;<br />
}<br />
Crash is in this line:
VERIFY(pToolTip->SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti)); (tooltip.cpp ln 427).
Please help!
Stilgar.
|
|
|
|
|
I have exactly the same problem, but have not found how to fix it.
pToolTip->SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti) returns FALSE, but this happens only if compiled in UNICODE mode (which I would like to use). In ASCII mode it works fine and TTN_NEEDTEXT message is sent back to the grid control like it should. In UNICODE build the TTN_NEEDTEXT message never come.
I hope somebody have solved this,
Tim
|
|
|
|
|
I found sollution!
The TOOLINFO struct have changed from VC6 to VC7.1 by addition of one extra field (void* lpReserved), which is not used. For some reason (bug) VC7.1 can not handle the new TOOLINFO.
But UNICODE tooltips worked for me at least with this work-around, by decreasing the size member of TOOLINFO struct to the old VC6 size:
pToolInfo->cbSize = sizeof(TOOLINFO) - sizeof(void*);
Big thanks goes to this link (Place where I found the answer for the problem):
http://www.codecomments.com/archive372-2005-4-464854.html
|
|
|
|
|
Is there an outlook like control that also supports "group by" functionality?
|
|
|
|
|
|
There are some problems if I compile the demo with VC7.
1. ReportCtrl.cpp(322) : error C2065: 'm_pchData' is unkown
Why is it unkown. Where is it.
2.BOOL CFlatHeaderCtrl::GetItemEx
HDITEMEX& hditemex = m_arrayHdrItemEx[iPos];
The compiler don't like the &. Without it run's.
And the main problem... I can't see the text and the icons.
With the VC6 it run's very good. With icons and text.
Can you help me?
Thanks Bjoern
|
|
|
|
|
Hi,
short answer:
m_pchData was a public member of CString. Now it's private or protected.
Use:
GetString();
2.
//15-09-03 error C2440: 'initializing' : cannot convert from 'const HDITEMEX' to 'HDITEMEX &'
//HDITEMEX& hditemex = m_arrayHdrItemEx[iPos];
HDITEMEX VarFromTemplate = m_arrayHdrItemEx[iPos];
HDITEMEX &hditemex = VarFromTemplate;
3. Sorry. everything looks fine. I cannot help you for this problem
Ciao
Siegmund
|
|
|
|
|
thank you for this really great class !
however, i have problems using it under winnt4.
m_wndTip.Create(this)
in function
BOOL CReportCtrl::Create()
returns FALSE and throws a memory-exception
there are no problems when i use it under windows 2000 or windows xp
|
|
|
|
|
I think there are solutions given in this thread.
Look here
|
|
|
|
|
There are some comments reporting problems with not updated selection maps when RVN_SELECTIONCHANGED is received.
Because I also had trouble with that issue I tried to rewrite the SelectRows method of CReportCtrl.
Notice that the behaviour of the message SELECTIONCHANGED is a little bit different:
There will only be one message for the first selected item.
No messages are sent when an item becomes unselected.
The new state of the first item is not sent as parameter (always the same).
I also publish this method to get reports about bugs. So be so kind and tell me if there are problems with this method, please.
Philipp Grohs
PS. I hope you understood what I tried to express in my poor school English.
void CReportCtrl::SelectRows(INT iFirst, INT iLast, BOOL bSelect, BOOL bKeepSelection, BOOL bInvert, BOOL bNotify)
{
if(m_dwStyle&RVS_SINGLESELECT){
iLast = iFirst;
bKeepSelection = FALSE;
}
if(m_iFocusRow > RVI_INVALID &&
iFirst != m_iFocusRow)
{
SetState(m_iFocusRow, 0, RVIS_FOCUSED);
RedrawRows(m_iFocusRow);
}
m_iFocusRow = iFirst;
SetState(iFirst, RVIS_FOCUSED, RVIS_FOCUSED);
if(iFirst > iLast){
iLast += iFirst;
iFirst = iLast - iFirst;
iLast -= iFirst;
}
if(!bKeepSelection && bSelect){
CList<POSITION, POSITION&> cRemList;
for(POSITION Pos = m_listSelection.GetHeadPosition(); Pos != NULL; ){
INT iItem = m_listSelection.GetAt(Pos);
INT iRow = GetRowFromItem(iItem);
UINT nOldState = 0;
UINT nNewState = 0;
nOldState = nNewState = GetState(iRow);
if((iRow < iFirst || iRow > iLast) &&
nOldState & RVIS_SELECTED)
{
nNewState &= ~RVIS_SELECTED;
if(nNewState != nOldState){
if(bNotify && Notify(RVN_SELECTIONCHANGING,
iItem, -1, nNewState) == TRUE)
{
continue;
}
cRemList.AddTail(Pos);
SetState(iRow, nNewState, RVIS_SELECTED);
RedrawRows(iRow);
}
}
m_listSelection.GetNext(Pos);
}
while(!cRemList.IsEmpty())
m_listSelection.RemoveAt(cRemList.RemoveHead());
}
if(bSelect){
for(INT iRow = iFirst; iRow <= iLast; iRow++){
INT iItem = GetItemFromRow(iRow);
UINT nOldState = 0;
UINT nNewState = 0;
nOldState = nNewState = GetState(iRow);
if(bInvert == TRUE)
nNewState ^= RVIS_SELECTED;
else nNewState |= RVIS_SELECTED;
if(nNewState != nOldState){
if(bNotify && Notify(RVN_SELECTIONCHANGING,
iItem, -1, nNewState) == TRUE)
{
continue;
}
POSITION Pos = m_listSelection.Find(iItem);
if((nNewState & RVIS_SELECTED) && Pos == NULL)
m_listSelection.AddTail(iItem);
else if(bInvert == TRUE)
m_listSelection.RemoveAt(Pos);
SetState(iRow, nNewState, RVIS_SELECTED);
RedrawRows(iRow);
}
}
}
if(bNotify)
Notify(RVN_SELECTIONCHANGED, GetItemFromRow(iFirst));
UpdateWindow();
}
|
|
|
|
|
there is a small bug when RVS_TREEMASK and RVS_FOCUSSUBITEMS are enabled:
<br />
void CReportCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)<br />
.<br />
.<br />
case VK_LEFT:<br />
.<br />
.<br />
<br />
iFirst = GetRowFromItem(m_iFocusRow);<br />
RedrawRows( iFirst );<br />
<br />
.<br />
.<br />
should be changed to
<br />
<br />
RedrawRows( m_iFocusRow );<br />
<br />
The same bug is in case VK_RIGHT.
Hope this is useful for you too.
With best regards
Frank Kobs
Palette CAD GmbH
|
|
|
|
|
Dear Maarten,
thanks for sharing this excellent written control! It's really what I was looking for.
As others mentioned, some sourcecode doc (at least some comments on the styles and properties) would have been good, but I will not complain. Better a good control without comments than a lousy control with comments
However, I have made some additions which someone might be useful: Drawing lines on the tree:
here is the code:
Inside void CReportCtrl::DrawRow() locate:
.
.
.
if(iColumn == 0 && lprvi->iIndent >= 0)
{
if(lprvi->nState&RVIS_TREEMASK)
{
rectItem.left -= m_iDefaultHeight;
DrawTreeBox(pDC, rectItem, lprvi->nState&RVIS_TREEOPENED);
rectItem.left += m_iDefaultHeight;
}
.
.
.
}
and add:
.
.
.
if(iColumn == 0 && lprvi->iIndent >= 0)
{
LPTREEITEM lpti = m_arrayItems[lprvi->iItem].lptiItem;
CRect rectTreeLines( rectItem );
for (int n=0;n<lprvi->iIndent;n++)
{
int nDrawMode = 0;
if (n == 0)
nDrawMode += 2;
ASSERT( lpti );
if (lpti && lpti->lptiSibling)
nDrawMode += 1;
rectTreeLines.left -= m_iDefaultHeight;
DrawTreeLines(pDC, rectTreeLines, nDrawMode );
lpti = lpti->lptiParent;
}
if(lprvi->nState&RVIS_TREEMASK)
{
rectItem.left -= m_iDefaultHeight;
DrawTreeBox(pDC, rectItem, lprvi->nState&RVIS_TREEOPENED);
rectItem.left += m_iDefaultHeight;
}
.
.
.
}
Finally code the DrawTreeLines function (don't forget to add it to header)
void CReportCtrl::DrawTreeLines(CDC* pDC, CRect rectBox, INT nDrawMode)
{
if(rectBox.right < rectBox.left)
return;
if (nDrawMode == 0)
return;
rectBox.right = rectBox.left + rectBox.Height();
CPoint point = rectBox.CenterPoint();
CPen pen(PS_SOLID, 1, RGB(192,192,192));
CPen* pPen = pDC->SelectObject(&pen);
switch (nDrawMode)
{
case 1:
pDC->MoveTo( point.x, rectBox.top );
pDC->LineTo( point.x, rectBox.bottom );
break;
case 2:
pDC->MoveTo( point.x, rectBox.top );
pDC->LineTo( point.x, point.y );
pDC->LineTo( rectBox.right, point.y );
break;
case 3:
pDC->MoveTo( point.x, rectBox.top );
pDC->LineTo( point.x, rectBox.bottom );
pDC->MoveTo( point.x, point.y );
pDC->LineTo( rectBox.right, point.y );
break;
default:
ASSERT( FALSE );
}
pDC->SelectObject(pPen);
}
Maybe some optimizations can be done but generally it seems to work.
With best regards,
Frank Kobs
Palette CAD GmbH
|
|
|
|
|
you have a little bug, you should replace :
for (int n=0;niIndent;n++)
by
for (int n=0;n < iIndent;n++)
thanks for your code !
|
|
|
|
|
Thanks for the fix - was obviously a typo!
Good to see that this code (even if it's old) is still useful for others!
With best regards,
Frank
|
|
|
|
|
Hi!
I created a dialog class and a member variable in my view.
in the OnCreate event i assigned the parent to the
CReportCtrl member variable (which I allready created):
m_wndContactsDetails.Create(IDD_FRMCONTACT, &m_wndReportCtrl);
I keep track on the expanded (previewed) item and on the OnRvnItemDrawPreview event I do:
m_wndContactsDetails.MoveWindow(&lpnmrvdp->rect);
in order to display the dialog in the preview area
all works well except in case I scroll the ReportCtrl down and the expanded item is the first - the dialog remains shown.
if instead I do the dc.DrawText function - it disappears correctly.
the problem never happens when scrolling up.
how do I solve this? Thanks.
|
|
|
|
|
|
Hi all,
I'm using the SuperGrid Report Control written by Maarten Hoeben and appreciate this software as very multifunctional and convinient as well. But since introduction we have experienced a little trouble with it. I'm wondering why the bug i'm going to describe below hasn't been reported yet.
Bug description:
The thing is, when you are resizing the header in the list control(CFlatHeaderCtrl class) too fast, the software starts recognizing your action in a incorrect way. Actualy, it places itself in the drag and drop mode as though you're going to change column's places. This is an ugly bug because after it is occured, the headers jump out of the grid and become independent from it. One has a little chance to get it in proper position again.
Suggested solution to eliminate the bug
In the class CFlatHeaderCtrl, there is a function called OnMouseMove. Everything one needs, is to check m_bResizing flag when the software means it should start in the drag'n drop mode. The Author already sets und resets that flag properly (I suppose ). Here's the code of the OnMouseMove routine where the bug is not present anymore:
void CFlatHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_bButtonDownOnItem && m_nClickFlags&MK_LBUTTON && m_iHotIndex>=0)
{
if(m_bResizing)
CHeaderCtrl::OnMouseMove(nFlags, point);
if(m_hdhtiHotItem.flags&HHT_ONHEADER)
{
if(m_bDragging)
{
..............
..............
}
else if(GetStyle()&HDS_DRAGDROP && m_bResizing == FALSE) // the only change (hanryz)
{
.............
.............
}
}
}
That's it.
The Author's opinion to this solution would be appreciated
So long.
|
|
|
|
|
This is a fantastic contribution with some great functionality.
However, I'm using it in my SDI app in a splitterwnd, when I switchview to a CFormView or other class and then try to go back to CReport it no longer appears leaving the last view still visible and still working.
Does this class lack a refresh view? or something?
I love the column sorting!
|
|
|
|
|
Working through this;
Apparently we need to send and have the following
ON_MESSAGE_VOID(WM_INITIALUPDATE, OnInitialUpdate)
void CMainFrame::OnConfig()
{
m_wndSplitter.ReplaceView(1,1,RUNTIME_CLASS(CSrsConf),CSize(0,26));
m_wndSplitter.GetPane(1,1)->SendMessage(WM_INITIALUPDATE);
}
This works with CFormViews but not CReportView, gives assert errors on line 3613 in ReportCtrl.cpp
ASSERT(lprvi->iSubItem < m_arraySubItems.GetSize());
|
|
|
|
|
Kind of works, after thinking about the error it was giving I thought, what if it can't add the lines 'cos the table is not there?
The bInit var was set to TRUE, stopping the creation of the table. I removed the 'static' keyword and everything works.... or does it?
BOOL bInit = FALSE;
Is this a bad idea? works for me anyway.
Dan
|
|
|
|
|
I changed
LPCTSTR lpsz = GetString();
but still get following error.
ReportCtrl.cpp
..\ReportCtrl\ReportCtrl.cpp(7229) : error C2360: initialization of 'points' is skipped by 'case' label
..\ReportCtrl\ReportCtrl.cpp(7185) : see declaration of 'points'
..\ReportCtrl\ReportCtrl.cpp(7230) : error C2360: initialization of 'points' is skipped by 'case' label
..\ReportCtrl\ReportCtrl.cpp(7185) : see declaration of 'points'
|
|
|
|
|