396 lines
9.2 KiB
C++
396 lines
9.2 KiB
C++
#include "stdafx.h"
|
|
#include "SuperGridCtrlEx.h"
|
|
#include "ComboInListView.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
CSuperGridCtrlEx::CSuperGridCtrlEx()
|
|
{
|
|
m_bDrag = TRUE;
|
|
}
|
|
|
|
CSuperGridCtrlEx::~CSuperGridCtrlEx()
|
|
{
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CSuperGridCtrlEx, CSuperGridCtrl)
|
|
//{{AFX_MSG_MAP(CSuperGridCtrlEx)
|
|
ON_WM_CREATE()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
int CSuperGridCtrlEx::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CSuperGridCtrl::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//helper function to copy CItemInfo used when drag/drop you must override this this function to suit your own CItemInfo class
|
|
CItemInfo* CSuperGridCtrlEx::CopyData(CItemInfo* lpSrc)
|
|
{
|
|
ASSERT(lpSrc!=NULL);
|
|
CItemInfo* lpDest = new CItemInfo;
|
|
//well okay I put all the copy thing in one function, located in CItemInfo class,
|
|
//so you should check out this function, remember to modify this function each time you add new data to CItemInfo class.
|
|
lpDest->CopyObjects(lpSrc);
|
|
return lpDest;
|
|
}
|
|
|
|
//override, like red!
|
|
COLORREF CSuperGridCtrlEx::GetCellRGB()
|
|
{
|
|
return RGB(192,192,192);
|
|
}
|
|
|
|
//this is my override of GetIcon, override this to set what ever icon suits you
|
|
int CSuperGridCtrlEx::GetIcon(const CTreeItem* pItem)
|
|
{
|
|
if(pItem!=NULL)
|
|
{
|
|
int n = GetData(pItem)->GetImage();
|
|
if(n!=-1)
|
|
return n;
|
|
|
|
int iImage = 0;
|
|
if(ItemHasChildren(pItem))
|
|
{
|
|
IsCollapsed(pItem) ? iImage = 1/*close icon*/:iImage = 0;/*open icon*/
|
|
}
|
|
else
|
|
iImage = 2;//doc icon
|
|
return iImage;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//override called when OnLButtondown
|
|
void CSuperGridCtrlEx::OnControlLButtonDown(UINT nFlags, CPoint point, LVHITTESTINFO& ht)
|
|
{
|
|
//now I am sure I added a combobox some where, so check for this control
|
|
CTreeItem*pSelItem = GetTreeItem(ht.iItem);
|
|
if(pSelItem!=NULL)
|
|
{
|
|
CItemInfo* pInfo = GetData(pSelItem);
|
|
CItemInfo::CONTROLTYPE ctrlType;
|
|
if(pInfo->GetControlType(ht.iSubItem-1, ctrlType))
|
|
{
|
|
if(ctrlType== CItemInfo::combobox)
|
|
{
|
|
if(this->m_bEditStyle && pSelItem->m_bCanEditMe)
|
|
{
|
|
CStringList* list=NULL;
|
|
pInfo->GetListData(ht.iSubItem-1, list);
|
|
CComboBox * pList = ShowList(ht.iItem, ht.iSubItem, list);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(this->m_bEditStyle && pSelItem->m_bCanEditMe)
|
|
{
|
|
CSuperGridCtrl::OnControlLButtonDown(nFlags, point, ht);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CSuperGridCtrlEx::OnVkReturn()
|
|
{
|
|
BOOL bResult=FALSE;
|
|
int iItem = GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);
|
|
if( GetCurSubItem() != -1 && iItem != -1)
|
|
{
|
|
CTreeItem*pSelItem = GetTreeItem(iItem);
|
|
if(pSelItem!=NULL)
|
|
{
|
|
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
|
|
int iSubItem = Header_OrderToIndex(pHeader->m_hWnd, GetCurSubItem());
|
|
CItemInfo* pInfo = GetData(pSelItem);
|
|
CItemInfo::CONTROLTYPE ctrlType;
|
|
if(pInfo->GetControlType(iSubItem-1, ctrlType))
|
|
{
|
|
switch(ctrlType)
|
|
{
|
|
/*put in your own control here*/
|
|
case CItemInfo::datecontrol:break;
|
|
case CItemInfo::spinbutton:break;
|
|
case CItemInfo::dropdownlistviewwhatevercontrol:break;
|
|
case CItemInfo::combobox:
|
|
{
|
|
|
|
CStringList* list=NULL;
|
|
pInfo->GetListData(iSubItem-1, list);
|
|
CComboBox * pList = ShowList(iItem, iSubItem, list);
|
|
bResult=TRUE; //I'll handle it from here
|
|
}break;
|
|
default:break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
#define IDC_COMBOBOXINLISTVIEW 0x1235
|
|
CComboBox* CSuperGridCtrlEx::ShowList(int nItem, int nCol, CStringList *lstItems)
|
|
{
|
|
CString strFind = GetItemText(nItem, nCol);
|
|
|
|
//basic code start
|
|
CRect rect;
|
|
int offset = 0;
|
|
// Make sure that the item is visible
|
|
if( !EnsureVisible(nItem, TRUE)) return NULL;
|
|
GetSubItemRect(nItem, nCol, LVIR_BOUNDS, rect);
|
|
// Now scroll if we need to expose the column
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
|
|
{
|
|
CSize size;
|
|
size.cx = offset + rect.left;
|
|
size.cy = 0;
|
|
Scroll(size);
|
|
rect.left -= size.cx;
|
|
}
|
|
|
|
rect.left += offset;
|
|
rect.right = rect.left + GetColumnWidth(nCol);
|
|
if(rect.right > rcClient.right)
|
|
rect.right = rcClient.right;
|
|
//basic code end
|
|
|
|
rect.bottom += 10 * rect.Height();//dropdown area
|
|
|
|
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL|CBS_DROPDOWNLIST;
|
|
CComboBox *pList = new CComboInListView(nItem, nCol, lstItems);
|
|
pList->Create(dwStyle, rect, this, IDC_COMBOBOXINLISTVIEW);
|
|
pList->ModifyStyleEx(0,WS_EX_CLIENTEDGE);//can we tell at all
|
|
pList->SetHorizontalExtent(CalcHorzExtent(pList, lstItems));
|
|
pList->ShowDropDown();
|
|
pList->SelectString(-1, strFind.GetBuffer(1));
|
|
// The returned pointer should not be saved
|
|
return pList;
|
|
}
|
|
|
|
int CSuperGridCtrlEx::CalcHorzExtent(CWnd* pWnd, CStringList *pList)
|
|
{
|
|
int nExtent=0;
|
|
if(pWnd!=NULL)
|
|
{
|
|
CDC* pDC = pWnd->GetDC();
|
|
HFONT hFont = (HFONT)pWnd->SendMessage(WM_GETFONT); //why not pWnd->GetFont();..I like the send thing alot and
|
|
CFont *pFont = CFont::FromHandle(hFont); //this way I get to use this function..cool :)
|
|
if(pFont!=NULL) //ya what ever makes me happy,.right :}
|
|
{
|
|
CFont* pOldFont = pDC->SelectObject(pFont);
|
|
CSize newExtent;
|
|
POSITION pos = pList->GetHeadPosition();
|
|
while(pos != NULL)
|
|
{
|
|
CString str(pList->GetNext(pos));
|
|
newExtent = pDC->GetTextExtent(str);
|
|
newExtent.cx += 6;
|
|
if (newExtent.cx > nExtent)
|
|
{
|
|
nExtent = newExtent.cx;
|
|
}
|
|
}
|
|
pDC->SelectObject(pOldFont);
|
|
}
|
|
pWnd->ReleaseDC(pDC);
|
|
}
|
|
return nExtent;
|
|
}
|
|
|
|
CTreeItem* CSuperGridCtrlEx::Search(CString strItem,...)
|
|
{
|
|
if(!GetItemCount())
|
|
return NULL;
|
|
|
|
va_list args;
|
|
va_start(args, strItem);
|
|
int nCount=0;
|
|
|
|
for(;;)
|
|
{
|
|
LPCTSTR lpsz = va_arg(args, LPCTSTR);
|
|
if(lpsz==NULL)
|
|
break;
|
|
nCount++;
|
|
}
|
|
|
|
POSITION pos = GetRootHeadPosition();
|
|
while(pos != NULL)
|
|
{
|
|
CTreeItem *pParent = (CTreeItem*)GetNextRoot(pos);
|
|
CTreeItem *pItem = pParent;
|
|
CItemInfo* lp = GetData(pParent);
|
|
CString strData = lp->GetItemText();
|
|
if(strData==strItem)//must be a match before going further...suit you self
|
|
{
|
|
va_start(args, strItem);
|
|
int nResult=0;
|
|
for(int i=0; i<nCount;i++)
|
|
{
|
|
LPCTSTR lpsz = va_arg(args, LPCTSTR);
|
|
for(int nCol=0; nCol < lp->GetItemCount(); nCol++)
|
|
{
|
|
CString str = lp->GetSubItem(nCol);
|
|
if(!str.CompareNoCase(lpsz))
|
|
{
|
|
nResult++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
va_end(args);
|
|
if(nCount==nResult)//all args was found return node
|
|
return pParent;
|
|
}
|
|
|
|
//GetNext ....loop through all children
|
|
for(;;)
|
|
{
|
|
CTreeItem *pCur = GetNext(pParent, pItem, TRUE, FALSE/*regardless of the item are hidden or not, set to TRUE if only visible items must be included in the search*/);
|
|
if(!IsChildOf(pParent, pCur))
|
|
break;
|
|
else
|
|
if(pCur==pItem)
|
|
break;
|
|
CItemInfo* lp = GetData(pCur);
|
|
CString strData = lp->GetItemText();
|
|
if(strData==strItem)//must be a match before going further
|
|
{
|
|
va_start(args, strItem);
|
|
int nResult=0;
|
|
for(int i=0; i<nCount;i++)
|
|
{
|
|
LPCTSTR lpsz = va_arg(args, LPCTSTR);
|
|
for(int nCol=0; nCol < lp->GetItemCount(); nCol++)
|
|
{
|
|
CString str = lp->GetSubItem(nCol);
|
|
if(!str.CompareNoCase(lpsz))
|
|
{
|
|
nResult++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
va_end(args);
|
|
if(nCount==nResult)//all args was found return node
|
|
return pCur;
|
|
}
|
|
pItem=pCur;//next;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CSuperGridCtrlEx::SortData()
|
|
{
|
|
int nIndex = GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
|
|
if(nIndex==-1)
|
|
return;
|
|
|
|
CTreeItem *pItem = reinterpret_cast<CTreeItem*>(GetItemData(nIndex));
|
|
|
|
if(AfxMessageBox(_T("Sort all children(Yes)\nor just sort rootitems(No)"),MB_YESNO)==IDYES)
|
|
Sort(pItem, TRUE);
|
|
else
|
|
Sort(pItem, FALSE);
|
|
//do a simple refresh thing
|
|
if(ItemHasChildren(pItem))
|
|
{
|
|
SetRedraw(0);
|
|
Collapse(pItem);
|
|
Expand(pItem, nIndex);
|
|
SetRedraw(1);
|
|
}
|
|
}
|
|
|
|
//another search thing
|
|
CTreeItem* CSuperGridCtrlEx::SearchEx(CTreeItem *pStartPosition, CString strItem)
|
|
{
|
|
CItemInfo* lp = GetData(pStartPosition);
|
|
//if(lp->GetCheck()) another condition here maybe
|
|
CString strData = lp->GetItemText();
|
|
if(strData==strItem)
|
|
{
|
|
return pStartPosition;
|
|
}
|
|
|
|
const int nChildren = NumChildren(pStartPosition);
|
|
if (nChildren > 0)
|
|
{
|
|
POSITION pos = GetHeadPosition(pStartPosition);
|
|
while (pos)
|
|
{
|
|
CTreeItem *pChild = GetNextChild(pStartPosition, pos);
|
|
CItemInfo* lp = GetData(pChild);
|
|
CString strData = lp->GetItemText();
|
|
if(strData==strItem)
|
|
{
|
|
return pChild;
|
|
}
|
|
}
|
|
}
|
|
|
|
POSITION pos = GetHeadPosition(pStartPosition);
|
|
while (pos)
|
|
{
|
|
CTreeItem *pChild = GetNextChild(pStartPosition, pos);
|
|
CItemInfo* lp = GetData(pChild);
|
|
CString strData = lp->GetItemText();
|
|
if(strData==strItem)
|
|
{
|
|
return pChild;
|
|
}
|
|
|
|
pChild = SearchEx(pChild, strItem);
|
|
if(pChild!=NULL)
|
|
return pChild;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
BOOL CSuperGridCtrlEx::OnDeleteItem(CTreeItem* pItem, int nIndex)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
BOOL CSuperGridCtrlEx::OnItemExpanding(CTreeItem *pItem, int iItem)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
BOOL CSuperGridCtrlEx::OnItemExpanded(CTreeItem* pItem, int iItem)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
BOOL CSuperGridCtrlEx::OnCollapsing(CTreeItem *pItem)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
BOOL CSuperGridCtrlEx::OnItemCollapsed(CTreeItem *pItem)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
CImageList *CSuperGridCtrlEx::CreateDragImageEx(int nItem)
|
|
{
|
|
if(m_bDrag)
|
|
return CSuperGridCtrl::CreateDragImageEx(GetDragItem());
|
|
else
|
|
return NULL;
|
|
}
|
|
|