|
Hi. Your control is great, but im having a problem: it shows all icons as 16color items...
Does it work with icons with more than 16 colors?
Ive seen that the image list is with the "ILC_COLOR24" param, which means it should show with 24bit colors, but it isnt working...
Thanks in advanced...
|
|
|
|
|
Hi Miguel,
For some reason, when you load a 256 color bitmap into an ImageList, they use the half-tone pallette, creating an "ILC_COLOR8" ImageList.
To get around this, you need to create the ImageList in one step and then add the bitmap in a second step.
Here is a Sample of the function CMySuperGrid::OnCreate that I've fixed:
Replace the line:
if(!m_image.Create(IDB_FOLDER, 16, 1, RGB(0, 255, 255)))
return -1;
with:
// Create the ImageList with ILC_COLOR32 parameter.
// You could also use ILC_COLOR24 rather than ILC_COLOR32
if(!m_image.Create(16, 16, ILC_MASK | ILC_COLOR32, 0, 0))
return -1;
// Load your Bitmap
CBitmap bmp;
bmp.LoadBitmap(IDB_FOLDER);
// Set up your transparent color as appropriate
COLORREF rgbTransparentColor;
rgbTransparentColor = RGB(0, 255, 255);
// Add the bitmap into the image list
m_image.Add(&bmp, rgbTransparentColor);
modified 25-May-20 21:58pm.
|
|
|
|
|
CString GetCellText(int nbrow, int nbcol);
void SetCellText(int nbrow, int nbcol, CString pts);
void Refresh();
int IsObjectParent(int obindex);
BOOL IsObjectChild(int obparent, int obchild);
BOOL IsObjectSingle(int obindex);
CString CMySuperGrid::GetCellText(int nbrow, int nbcol)
{
CItemInfo* lp;
lp = GetData(GetTreeItem(nbrow));
return lp->GetSubItem(nbcol);
}
void CMySuperGrid::SetCellText(int nbrow, int nbcol, CString pts)
{
CItemInfo* lp;
lp = GetData(GetTreeItem(nbrow));
lp->SetSubItemText(nbcol, pts);
}
void CMySuperGrid::Refresh()
{
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();
}
int CMySuperGrid::IsObjectParent(int obindex)
{
CTreeItem* pSelItem;
pSelItem = GetTreeItem(obindex);
if(pSelItem != NULL)
{
return NumChildren(pSelItem);
}
else
{
return 0;
}
}
BOOL CMySuperGrid::IsObjectChild(int obparent, int obchild)
{
CTreeItem* pParentItem;
CTreeItem* pChildItem;
pParentItem = GetTreeItem(obparent);
pChildItem = GetTreeItem(obchild);
if(
(pParentItem != NULL)
&& (pChildItem != NULL)
)
{
return IsChildOf(pParentItem, pChildItem);
}
else
{
return FALSE;
}
}
BOOL CMySuperGrid::IsObjectSingle(int obindex)
{
CTreeItem* pSelItem;
pSelItem = GetTreeItem(obindex);
if(pSelItem != NULL)
{
return !(ItemHasChildren(pSelItem));
}
else
{
return FALSE;
}
}
|
|
|
|
|
Hi,
I found your control wonderful !! I just have a problem : is it possible to avoid the subitem texts to be editable... Does someone know for example if you can replace the edit control in list by a static control ??
Thanks by advance for the one who'll find a solution...
|
|
|
|
|
1) expand the CItemInfo::CONTROLTYPE enum with a new item: e.g.
<br />
enum CONTROLTYPE {edit, combobox, nonedit };<br />
2) set your list item to nonedit
<br />
lp->SetControlType( CItemInfo::CONTROLTYPE::nonedit );<br />
3) In you Eventhandler make something similar to this:
<br />
void MhRptGrid::OnControlLButtonDown(UINT nFlags, CPoint point, LVHITTESTINFO& ht)<br />
{<br />
CTreeItem *pSelItem = GetTreeItem(ht.iItem);<br />
<br />
<br />
if(pSelItem!=NULL)<br />
{ <br />
CItemInfo* pInfo = GetData(pSelItem);<br />
CItemInfo::CONTROLTYPE ctrlType;<br />
<br />
pInfo->GetControlType(ht.iSubItem-1, ctrlType);<br />
<br />
switch( ctrlType )<br />
{<br />
case pInfo->CONTROLTYPE::nonedit:<br />
TRACE( L"NonEdit clicked\n" );<br />
break;<br />
case pInfo->CONTROLTYPE::edit:<br />
TRACE( L"Edit clicked\n" );<br />
CSuperGridCtrl::OnControlLButtonDown(nFlags, point, ht);<br />
break;<br />
default:<br />
break;<br />
}<br />
}<br />
<br />
return;<br />
}<br />
Zynismus ist der geglückte Versuch die Welt zu verstehen.
Zwei Dinge sind unendlich. Das Universium und die menschliche Dummheit. Nur beim ersteren bin ich mir nicht sicher.
Albert Einstein
|
|
|
|
|
I create an item to be inserted and CItemInfo::SetCheck on that item to true... but Root Items are never checked intially for some reason.
It works fine when inserting child items (InsertItem)
I have looked briefly at the code but havent resolved this on my own yet... has anyone else experienced this problem?
|
|
|
|
|
Hi - Kochise allready solved this problem a few days ago in this Forum. You don´t have to search for it. I copy his fine solution to this answer:
FROM KOCHISE:
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.
END OF THE KOCHISE SOLUTION
btw: thanks for your answer on the Checkbox-drawing-problem...
Rafael
oops!
|
|
|
|
|
|
I have a list control that has LVS_EX_GRIDLINES style set. The problem is when the user clicks on the down or up arrow of the scroll bar in the list control the grid lines are getting drawn over the items. This messes up the whole list control display. This behavior is there only when I include the manifest file in the application’s resource file. This is done to enable my application to use ComCtl32.dll version 6. If I take out the manifest from the resource it works fine. I would really appreciate if any one can help me find a fix for this problem.
|
|
|
|
|
Hi,
I'm I. J. Bae
I heard your control and saw it. It has clean and smart image except sorting.
So I want to improve supergrid with drived your ctrl.
I already read article of "Enhancment of the SortEx method - S.Bonenfant (2000/02/03)" at codeguru site. But I don't know how can I use it...
Please, if you develop about sorting, could I know it?
Regards,
I. J. Bae
|
|
|
|
|
It would be awesome to have cell joining capabilities in the supergrid.
In a view that has different size (lengths) of data you could just
span over two cells instead of throwing the whole column out of whack.
This would enable row and column cell joining.
Mike
Mike "Badvox"
|
|
|
|
|
There is CSuperGridCtrl::InsertRootItem method, but it does not allow to insert root item between the others. This code solves the problem, please check it out.
Thanks,
Ek
CSuperGridCtrl::CTreeItem* CSuperGridCtrl::InsertRootItem(int nIndex, CItemInfo * lpInfo)
{
if(nIndex < 0 || nIndex > GetItemCount())
{
ASSERT(FALSE);
return NULL;
}
if(lpInfo==NULL)
lpInfo = new CItemInfo;
CTreeItem* pRoot = NULL;
pRoot = new CTreeItem();
CleanMe(pRoot);
UpdateData(pRoot, lpInfo);
SetIndent(pRoot, 1);
SetCurIndex(pRoot, nIndex);
SetParentItem(pRoot, NULL);
CItemInfo *lp = GetData(pRoot);
LV_ITEM lvItem;
lvItem.mask = LVIF_TEXT | LVIF_INDENT | LVIF_PARAM;
if(lp->GetImage() != -1)
{
lvItem.iImage = lp->GetImage();
lvItem.mask |= LVIF_IMAGE;
}
CString strItem = lp->GetItemText();
lvItem.pszText = strItem.GetBuffer(1);
lvItem.iItem = nIndex;
lvItem.lParam = (LPARAM)pRoot;
lvItem.iIndent = 1;
lvItem.iSubItem = 0;
CListCtrl::InsertItem(&lvItem);
int nSize = lp->GetItemCount();
for(int i=0; i < nSize;i++)
{
CString str = lp->GetSubItem(i);
lvItem.mask = LVIF_TEXT;
lvItem.iSubItem = i+1;
lvItem.pszText = str.GetBuffer(1);
SetItem(&lvItem);
}
int nStartIndex = 0;
POSITION pos = m_RootItems.GetHeadPosition();
POSITION prevPos = NULL;
for(; pos != NULL; nStartIndex++)
{
prevPos = pos;
CTreeItem *root = (CTreeItem*)m_RootItems.GetNext(pos);
if(nStartIndex == nIndex)
break;
}
m_RootItems.InsertBefore(prevPos, pRoot);
InternaleUpdateTree();
return pRoot;
}
|
|
|
|
|
How can we change the CHeaderCtrl background color??
prem
|
|
|
|
|
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
|
|
|
|
|