#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; iGetItemCount(); 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; iGetItemCount(); 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(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; }