|
Why with a function like this one the elements doesn't become all checked?
if(!GetItemCount())
return;
int nIndex=0;//has to be the root
if(nIndex!=-1)
{
//do a GetHeadPosition
POSITION pos = GetRootHeadPosition();
while(pos != NULL)
{
CTreeItem *pParent = (CTreeItem*)GetNextRoot(pos);
CTreeItem *pItem = pParent;
CItemInfo* lp = GetData(pParent);
lp->SetCheck(true);
UpdateData(pParent,lp);
//GetNext ....loop through all children
for(;;)
{
CTreeItem *pCur = GetNext(pParent, pItem, TRUE, FALSE);
if(!IsChildOf(pParent, pCur))
break;
else
if(pCur==pItem)
break;
CItemInfo* lp = GetData(pCur);
lp->SetCheck(true);
UpdateData(pParent,lp);
pItem=pCur;
}
}//while
}//if
|
|
|
|
|
Add this method to 'CMySuperGrid', it's the ONLY way to correctly refresh updated datas ! Maybe it could then display your checked boxes...
'UpdateDate' change the datas without creating a new line, but did not refresh/update the changes to the screen.
void CMySuperGrid::Refresh()
{ // A bit slow on loooooong list...
CTreeItem* arbo;
POSITION pos;
int index;
//
index = 0;
//
pos = GetRootHeadPosition();
arbo = GetNextRoot(pos);
SetRedraw(0);
Collapse(arbo);
ExpandAll(arbo, index);
SetRedraw(1);
InvalidateRect(NULL);
UpdateWindow();
}
|
|
|
|
|
When creating a checked root item for example with the code below, it is not checked because the appropriate test is not done :
CItemInfo* lp = new CItemInfo();
... additive root item initialization
lp->SetCheck(1); // Checking the root item
... additive root item initialization
CTreeItem* pRoot = InsertRootItem(lp); // Insertion of the root item
The solution is to modify the original 'InsertRootItem' function into the 'supergridctrl.cpp' file as follow :
Look for the following lines in the 'InsertRootItem' function...
CListCtrl::InsertItem(&lvItem);
int nSize = lp->GetItemCount();
for(int i=0; i < nSize;i++)
Then just add between the 'CListCtrl' line and the 'int' line the following code :
if(lpInfo->GetCheck())
SetCheck(lvItem.iItem);
You should get something like this :
CListCtrl::InsertItem(&lvItem);
if(lpInfo->GetCheck())
SetCheck(lvItem.iItem);
int nSize = lp->GetItemCount();
for(int i=0; i < nSize;i++)
Now, if you 'lp->SetCheck(1)' before the 'InsertRootItem(lp)' you will get a correct checked root item.
It will now works a bit like the 'InsertItem' function above the 'InsertRootItem' function in the 'supergridctrl.cpp' file.
A problem in SuperGrid, just ask, I'm fond of
Kochise
PS : I'm currently working on the callback notify message bug that is NOT CComboBox compatible.
|
|
|
|
|
When you Dclick between two columns in order to focus them closer to the lenght of the text within, SuperGrid *ALWAYS* focus a bit too much and then you get *ALWAYS* a three doted text.
The solution is to correct the column width calculation into supergridctrl.cpp !
At line 370 and 400 you will find the column width calculation : 'rcItem.right - rcItem.left'
Just add 1 to get the correct width. So then you must get something like this...
Line 370 (just below //draw 1. item) :
pszText = MakeShortString(pDC, szBuff, rcItem.right - rcItem.left + 1, 2*OFFSET_FIRST);
Line 400 (in //draw subitems..) :
pszText=MakeShortString(pDC,szBuff,rcItem.right-rcItem.left + 1,2*OFFSET_OTHER);
Now when you Dclick between two columns, they narrow focus correctly !
Kochise
PS : Instead of changing these lines above, you could also directly modify the 'MakeShortString' function. For this, change every '< nColumnLen)' into '< nColumnLen + 1)'.
But the best is the give a correct value into the 'nColumnLen' entry parameter, so just modify the 'rcItem.right - rcItem.left' calculation into 'rcItem.right - rcItem.left + 1'.
|
|
|
|
|
OK everybody, forget the previous solution I given, it's just a lame code
Don't replace 'rcItem.right - rcItem.left' with 'rcItem.right - rcItem.left + 1' into the 'DrawItem' function, but replace every '< nColumnLen)' with '<= nColumnLen)' into the 'MakeShortString' function.
Note the equal sign that makes the difference !
Nothing more
Kochise
|
|
|
|
|
Well, that worked for the code before the subitem images were supported. Now, when you double-click on the column to get the column resized the code doesn't take into account the image size so you can end up with the column too short (e.g. "..."). Anybody fixed that?
|
|
|
|
|
I have some problem. I dynamically create CTestTreeDlg such as:
m_pDlg=new CTestTreeDlg();
m_pDlg->Create(IDD_DIALOG_SUPERGRID);
m_pDlg->ShowWindow(TRUE);
But when CTestTreeDlg is destroying i get ASSERT message.
My callstack is:
CImageList::FromHandlePermanent(HIMAGELIST h)
CImageList::RemoveImageList(int nImageList)
CImageList::OnNcDestroy()
------------------------------------------
I destroy CTestTreeDlg by "delete m_pDlg" operator...
May be i need to call smth. before?
If i use CTestTreeDlg locally, such as:
CTestTreeDlg test;
test.DoModal();
All work normally.
Thanks for all.
|
|
|
|
|
When adding lines, you create CObject objects in fact. Just deleting your CTestTreeDlg will not delete the created objects. Try 'm_Filter.DeleteAll()' where 'm_Filter' is the 'CMySuperGrid' or the derivated object from 'CSuperGridCtrl' you display into your 'CTestTreeDlg'. It should solve your problem.
Make always sure that everything was removed before deleting an object. Don't forget that destructors are hardly well coded to do that job, so do it 'by hand' as clean as possible. Not only initialisations are necessary.
Kochise
|
|
|
|
|
I'm using your SuperGrid project into one of mine, and having 2 combo on the same line, one is used to control the CStringList choice of the second combo. But selecting the first did not chance the choice of the second. How can I retreive automatically the choice once selected, then change the second combo list using, I guess, lp->SetControlType(lp->CONTROLTYPE::combobox, 3); then lp->SetListData(3, &list);.
Is there a message to know what changed and on which line (kinda callback function).
Kochise (kochise@caramail.com)
|
|
|
|
|
Problem solved, thanks to Eric DAVID !
Using ClassWizard, override the Windows' 'OnNotify' message (combo : Class name, list : Messages, button : Add function + Edit code).
Zen edit the code as follow :
BOOL 'your class'::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// TODO: Add your specialized code here and/or call the base class
LV_DISPINFO *pDispinfo=(LV_DISPINFO *)lParam;
if(pDispinfo->hdr.code == LVN_ENDLABELEDIT)
{ // If the message match
if(pDispinfo->item.iSubItem == 'your subitem')
{ // If the specified source column : WARNINGS about offsets (iItem & iSubItem), see below !!!
m_View.SetCombo(pDispinfo->item.iItem, 'your column to set/change', (CStringList*) combo);
}
}
return CView::OnNotify(wParam, lParam, pResult);
}
Note : (CMySuperGrid) m_View is a public member of 'your class'
Where 'SetCombo' is :
void CMySuperGrid::SetCombo(int nbobj, int nbcol, CStringList* combo)
{
CItemInfo* lp;
//
//
lp = GetData(GetTreeItem(nbobj)); // nbobj = 0 -> root
lp->SetControlType(lp->CONTROLTYPE::combobox, nbcol); // WARNING HERE : nbcol = 0 -> first column
lp->SetListData(nbcol, combo); // set the new CStringList combo
}
Interresting items are :
pDispinfo->item.iItem : Line number (root is 0)
pDispinfo->item.iSubItem : Column number (WARNING, tree is 0, first column 1 and so...)
pDispinfo->item.pszText : The new text
There is also a bug (thanks Eric DAVID), pDispinfo->item.lParam *ALWAYS* return 0 !
The correction is to modify the original 'CComboInListView::OnKillFocus' function as :
lvDispinfo.item.lParam = nIndex; // to return the CComboBox selected item index
Instead of :
lvDispinfo.item.lParam = GetItemData(GetCurSel());
Kochise
|
|
|
|
|
Hello, i have downloaded the Supergrid and when it run i don't see the images in the second, third, fourth.. columns. And the images are not in the resource file.
Thanks for all.
|
|
|
|
|
Hi,
How to use this in VB6 ? Do you hav ethe OCX version of this ?
Thanks
|
|
|
|
|
I want to modify positions of children.
Example:
"Root"
"child A"
"child B"
I move "B", before "A"
So it becomes:
"Root"
"child B"
"child A"
What I have to do?
|
|
|
|
|
I not tested it, but try this :
SetCurIndex((CTreeItem*) pChildA, (int) NodeToIndex((CTreeItem*) pChildB); // It might works, but 'NodeToIndex' is 'protected' so try instead '_NodeToIndex'
Otherwise, try using GetPrev and GetNext from ChildA, then change the pointers by hand...
Check into 'supergridctrl.h' to get some explanations about its functionalities !
Kochise
|
|
|
|
|
Example:
<root node="">
<child a="">
<child b="">
I move "B", and set it before "A"
<root node="">
<child b="">
<child a="">
How can I do this?
|
|
|
|
|
The control, as stated in documentation, does not support header drag n drop operations...
Any idea to implement header drag/drop operations ?
thanks in advance .
pif
|
|
|
|
|
how to get rid of the grid line?
|
|
|
|
|
in MySuperGrid.cpp there is a function call SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES); simply erase the LVS_EX_GRIDLINES
J_T_Biggs - 2002 Gorilla Software
|
|
|
|
|
I use the example program to add my project.And my project is a Dialog based program use another class named CTabCtrlSSL.It can use a dialog as propertypage .I add the Dialog demo to my program as one propertypage in tabctrl.but when i want delete one row use sendmessage function.it will delete two rows .why ?
|
|
|
|
|
I tried to create a supergrid in a dialog.
It works fine, but it seems the checkboxes are lost.
The demo project has the same problem when try to
display the grid in dialog. Any suggestions?
|
|
|
|
|
If you replace the initialization code to be the same as that used for the view it seems to work fine (although I haven't done much testing) and you can see the checkboxes.
The following is the patched OnCreate method for the dialog:
int CTestTreeDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
//m_List.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP, CRect(0,0,0,0),this,0x1001);
//m_List.InitializeGrid();
//m_List.SetExtendedStyle(0);
//m_List.ModifyStyleEx(0,WS_EX_CLIENTEDGE);
m_List.Create(WS_CHILD | WS_VISIBLE,CRect(0,0,0,0),this,0x100);
m_List.InitializeGrid();
return 0;
}
|
|
|
|
|
Hi, I've seen a newer code at http://codeguru.earthweb.com/listview/supergrid.shtml
But in the sources you tell us that you update more often here, but the more recent code is still at codeguru!!
|
|
|
|
|
Hi wanna do drag n drop with root items,
does anybody know how that works?
thanks in advance
|
|
|
|
|
I did use the Microsoft Drag and Drop classes. It works fine.
Below is an example of my Symbol Grid which is derived from CSuperGridCtrl.
You need do register the clippboard format You want to usein the ctor of CSymbolGrid:
CSymbolGrid::CSymbolGrid()
{
DragDropFormat = ::RegisterClipboardFormat(GLOBAL_CLIPBOARD_FORMAT);
}
void CSymbolGrid::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult)
{
CString lAddress,lLength;
int SelItem = GetSelectedItem();
GetSelAddress(lAddress);
GetSelLength(lLength);
// Create the drag&drop source and data objects
COleDropSource *pDropSource = new COleDropSource;
COleDataSource *pDataSource = new COleDataSource;
// now grab the data (here: the count and text)
// and serialize it into an clipboard archive
HGLOBAL hGlob;
try // to drag into a memory dump
{
CSharedFile file(GMEM_ZEROINIT|GMEM_DDESHARE|GMEM_MOVEABLE);
CArchive ar(&file, CArchive::store);
// "Serialize" your data object into the archive
// (yes, you may use YourObject.Serialize(ar) here!)
CPtrArray lptrArr;
OnAddVar(lptrArr);
WORD larrSize = lptrArr.GetSize();
ar << lAddress << lLength << larrSize;
ar.Close();
// put the file object into the data object
hGlob = file.Detach();
pDataSource->CacheGlobalData(DragDropFormat, hGlob);
pDataSource->DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY, NULL, pDropSource);
}
catch(...)
{
// exception while destructing the file
ASSERT(FALSE);
}
delete pDropSource;
delete pDataSource;
*pResult = 0;
}
In the Target Window You must also Register the ClipBoard Format.
For the Drop Target I use a derived class
class CViewDropTarget : public COleDropTarget
{
public:
CViewDropTarget();
virtual ~CViewDropTarget();
void SetClassPtr(CView *lptr) { ViewPtr = lptr; };
private:
CView *ViewPtr;
UINT DragDropFormat;
public:
CString Address; // Address we got by Drop operation
CString Length; // Length we got by Drop operation
protected:
virtual BOOL OnDrop( CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point );
virtual DROPEFFECT OnDragOver( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point );
};
CViewDropTarget::CViewDropTarget()
{
DragDropFormat = ::RegisterClipboardFormat(GLOBAL_CLIPBOARD_FORMAT);
ViewPtr=NULL;
}
CViewDropTarget::~CViewDropTarget()
{
}
DROPEFFECT CViewDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
CFile *pFile = pDataObject->GetFileData(DragDropFormat);
if (pFile != NULL)
{
// perhaps some point checking here?
delete pFile; // Is a must, because every time a Shared memory object is created,
// which must be deleted !
return DROPEFFECT_COPY; // data fits
}
else
return DROPEFFECT_NONE; // data won’t fit
}
BOOL CViewDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point )
{
CFile *pFile = pDataObject->GetFileData(DragDropFormat);
if (pFile != NULL)
{
// perhaps some point checking first?
try
{
CArchive ar(pFile, CArchive::load);
if (DragDropFormat != CF_TEXT)
{
// "Serialize" your data object from the archive
// (yes, you may use YourObject.Serialize(ar) here!)
ar >> Address >> Length;
}
ar.Close();
}
catch(...)
{
// exception in the destructor of ar
ASSERT(FALSE);
}
}
delete pFile; // Is a must, because every time a Shared memory object is created,
// which must be deleted !
// notify our view from a drop operation
SendMessage(ViewPtr->m_hWnd,WM_USER_DROP_MEM_DUMP,0,0);
return COleDropTarget::OnDrop(pWnd, pDataObject, dropEffect, point);
}
Create an Instance of this class in Your View
class CMyView : CView
{
private:
CViewDropTarget DropTarget
}
CMyView::CMyView()
{
DropTarget.SetClassPtr(this); // mark it as target for our sendmessage function
}
in the View ctor set the view ptr to make it for the class possible to send a message when
a drop operation has occured.
CMyView::OnInitialUpdate()
{
// register Your view as drop target
if( !DropTarget.Register(this) )
ASSERT(FALSE);
}
Thats all I think. It works great.
|
|
|
|
|
Hi,
How do i actually edit the items in listview? i don't want to just edit the most left first column, i need to be able to edit all the columns.
thanks a lot!
|
|
|
|
|