/////////////////////////////////////////////////////////////////////////////
//
//  File name: YYHGRID.CPP
//
//  Description: The implementation file for the class: CYYHGRID.
//
//  Author: Jerry Yan
//
//  Date:   04/96
//
//  Modification:
//      1. 07/29/95, Initial version of the class: CYYHGrid.
//
/////////////////////////////////////////////////////////////////////////////

           

#include "stdafx.h"
#include "yyhgrid.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
           

#define SM_PAINT (WM_USER+1)


/////////////////////////////////////////////////////////////////////////////
// CYYHGrid

IMPLEMENT_DYNCREATE(CYYHGrid, CWnd)

/////////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
/////////////////////////////////////////////////////////////////////////////

BOOL CYYHGrid::Create(CWnd* pParentWnd,DWORD dwStyle,CRect rect,UINT nID)
{
	if(pParentWnd!=NULL)
        ASSERT_VALID(pParentWnd);
    DWORD csStyle=CS_DBLCLKS;    
    dwStyle=dwStyle|WS_CHILD|WS_BORDER|WS_TABSTOP;
    if(!CWnd::Create(AfxRegisterWndClass(csStyle,AfxGetApp()->LoadCursor(IDC_ARROW),(HBRUSH)::GetStockObject(WHITE_BRUSH)),NULL,dwStyle,rect,pParentWnd,nID)) 
          return 0;
	return 1;	    
}  


BOOL CYYHGrid::DeleteContent()
{
	POSITION pos,pos1;
	CStringList *strList;
	//CString str;
	pos=m_ObList.GetHeadPosition();	
	while(pos!=NULL)
	{   
		pos1=pos;
		strList=(CStringList*)m_ObList.GetNext(pos);
		m_ObList.RemoveAt(pos1);
		delete strList;
	}	
	return 1;		
}

BOOL CYYHGrid::ResetContent(int level)
{
	
	if(m_nRows==0) return 0;
	if(level>=m_nRows) return 0;
	int count;
	CRect rect;
	POSITION pos,pos1;
	CStringList *strList;
	//CString str;
	pos=m_ObList.GetHeadPosition();	
//  strList=(CStringList*)m_ObList.GetNext(pos);
	while(pos!=NULL)
	{   
		strList=(CStringList*)m_ObList.GetNext(pos);
        pos1=strList->GetHeadPosition();
        strList->GetNext(pos1);
        if(pos1!=NULL) 
            strList->GetNext(pos1);
        while( (count=strList->GetCount() )>level){
            strList->RemoveTail(); 
            rect=RowToRect(count-1);
            rect.left=0;
            InvalidateRect(&rect);
        }    
//		delete strList;
	}	                   
	m_nRows=level;  
	if(m_nActiveRow>level-1) m_nActiveRow=level-1;    
	if(m_ptActiveCell.y>level-1) m_ptActiveCell=level-1;
//	Invalidate();
	UpdateWindow();
	return 1;		
}


CYYHGrid::CYYHGrid()
: m_nFont(14), m_ptFirst(0,0) ,m_nTextCenterMode(DT_CENTER)
{
    m_bEnable=0;
    if(m_bEnable)
    	m_pEdit=new CEdit;
	m_nFirstViewableCol=1; 
	m_hOldCur=NULL;  
	m_bCurSet=0;  
	m_nCols=0;m_nRows=0;
	m_nDefColWidth=100;
    m_nDefRowHeight=18;  
    m_ptActiveCell=CPoint(0,0);
    m_nActiveRow=0;
//    m_rectFocus.SetRectEmpty();
//    m_rectPreFocus.SetRectEmpty();   
    for(int nCol=0;nCol<10;nCol++)
    	m_nColWidth[nCol]=m_nDefColWidth;
    m_nColWidth[0]=70;
    m_nColWidth[1]=80;	
}

CYYHGrid::~CYYHGrid()
{  
    if(m_bEnable){
    	m_pEdit->DestroyWindow();
    	delete m_pEdit;
    }             
    DeleteContent();
}                        



void CYYHGrid::Resize(int cx, int cy)
{
    
    CRect rect;
    GetClientRect(&m_rectClient);
    rect=m_rectClient;
    rect.left-=m_nColWidth[0];
    rect.top-=m_nDefRowHeight;
    int x=0;
    for(int i=0;i<m_nCols;i++)
        x+=m_nColWidth[i];
//    m_nColWidth[m_nCols-1]+=max(0,cx-x);
    if(x > cx-m_nColWidth[0]) 
        m_szScroll.cx = x - cx;//+m_nColWidth[0];
    else m_szScroll.cx = 0;
    SetScrollRange(SB_HORZ, 0, m_szScroll.cx);

    if(m_nRows * m_nDefRowHeight > cy)    
        m_szScroll.cy = ((m_nRows * m_nDefRowHeight - cy)/m_nDefRowHeight+1)*m_nDefRowHeight;
    else m_szScroll.cy = 0;
    SetScrollRange(SB_VERT, 0, m_szScroll.cy);

    if(m_ptFirst.x!=0||m_ptFirst.y!=0)
    {	
    	ScrollWindow(m_ptFirst.x,0,&rect,&rect);
    	ScrollWindow(0,m_ptFirst.y,&rect,&rect);
        m_ptFirst.x=m_ptFirst.y=0;  
        m_nFirstViewableCol=1;
        Invalidate();
        UpdateWindow();
    }    
    SetScrollPos(SB_HORZ, m_ptFirst.x);
    SetScrollPos(SB_VERT, m_ptFirst.y);
    
}

BEGIN_MESSAGE_MAP(CYYHGrid, CWnd)
    //{{AFX_MSG_MAP(CYYHGrid)
    ON_MESSAGE(SM_PAINT,OnSmPaint)
    ON_WM_PAINT()
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_HSCROLL()
    ON_WM_VSCROLL()
    ON_WM_LBUTTONDOWN()
    ON_WM_GETMINMAXINFO()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_SETCURSOR()
	ON_WM_KEYDOWN()
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

LONG CYYHGrid::OnSmPaint(UINT,LONG)
{
	Invalidate();
	UpdateWindow();   
	return 1;
}

void CYYHGrid::OnPaint()
{
    CPaintDC dc(this); // device context for painting
//    CRect rectClient;
//    GetClientRect(&rectClient);
    if(m_nActiveRow>0)
       HighLightRow(&dc,m_nActiveRow);
    if(m_ptActiveCell.x!=0&&m_ptActiveCell.y!=0&&m_ptActiveCell.x>=m_nFirstViewableCol)   
       HighLightCell(&dc,m_ptActiveCell);
    
    if(m_nCols==0||m_nRows==0)
	{
	    dc.MoveTo(0,m_nDefRowHeight);
    	dc.LineTo(2*m_nDefColWidth+1,m_nDefRowHeight);
    	dc.MoveTo(0,2*m_nDefRowHeight+1);	
    	dc.LineTo(2*m_nDefColWidth+1,m_nDefRowHeight*2+1);
    
	    dc.MoveTo(m_nDefColWidth,0);
	    dc.LineTo(m_nDefColWidth,m_nDefRowHeight*2+1);
    	dc.MoveTo(2*m_nDefColWidth+1,0);
    	dc.LineTo(1+2*m_nDefColWidth,m_nDefRowHeight*2+1);
	}   
	else
	{   
/*		CRect  rect(0,0,rectClient.right,m_nDefRowHeight);
		::FillRect(dc.m_hDC,&rect,(HBRUSH)::GetStockObject(LTGRAY_BRUSH) );
		rect.right=m_nColWidth[0];
		rect.bottom=rectClient.bottom;
		::FillRect(dc.m_hDC,&rect,(HBRUSH)::GetStockObject(LTGRAY_BRUSH) );
*/		
		ASSERT(m_nCols==m_ObList.GetCount());
	    DrawGrid(&dc,m_nCols,m_nRows,m_nColWidth);
	    SetGrid(&dc);
	}   

    // Do not call CWnd::OnPaint() for painting messages
}
                    
int CYYHGrid::GetGridWidth()
{
	int t=m_nColWidth[0];
	for(int i=m_nFirstViewableCol;i<m_nCols;i++)
	    t+=m_nColWidth[i];
	return t;    
}                    
                    
void CYYHGrid::DrawGrid(CDC* pDC,int nCols,int nRows,int *nColWidth)
{
    int nWidth=GetGridWidth();
	CRect  rect(0,0,min(nWidth,m_rectClient.right),m_nDefRowHeight);
	::FillRect(pDC->m_hDC,&rect,(HBRUSH)::GetStockObject(LTGRAY_BRUSH) );
	rect.right=min(m_nColWidth[0],m_rectClient.right);
	rect.bottom=m_rectClient.bottom;
	::FillRect(pDC->m_hDC,&rect,(HBRUSH)::GetStockObject(LTGRAY_BRUSH) );
		
    pDC->MoveTo(m_nColWidth[0],0-m_ptFirst.y);
    pDC->LineTo(m_nColWidth[0],m_rectClient.bottom);
    CPen* pOldPen;                                             

    pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);  
   	pDC->MoveTo(0,m_rectClient.bottom);
   	pDC->LineTo(0,0);         
   	pDC->LineTo(m_rectClient.right,0);
   	pDC->SelectObject(pOldPen);
    
	int nGridWidth=m_nColWidth[0],nGridHeight=m_nDefRowHeight;         
    for(int i=1;i<nCols;i++)
    {
    	pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);  
    	pDC->MoveTo(nGridWidth-m_ptFirst.x+1,0);
    	pDC->LineTo(nGridWidth-m_ptFirst.x+1,m_nDefRowHeight);
    	pDC->SelectObject(pOldPen);
        nGridWidth+=nColWidth[i];
    	pDC->MoveTo(nGridWidth-m_ptFirst.x,0);
    	pDC->LineTo(nGridWidth-m_ptFirst.x,m_rectClient.bottom);
    }
    
   	pDC->MoveTo(0-m_ptFirst.x,m_nDefRowHeight);
	pDC->LineTo(min(m_rectClient.right,nGridWidth-m_ptFirst.x),m_nDefRowHeight);
	pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
    pDC->MoveTo(0,nGridHeight-m_ptFirst.y+1);
 	pDC->LineTo(m_nColWidth[0],min(m_rectClient.right,nGridHeight-m_ptFirst.y+1));
	pDC->SelectObject(pOldPen);
    for(i=1;i<nRows-1;i++)
    {	
    	nGridHeight+=m_nDefRowHeight;
    	if(nGridHeight-m_ptFirst.y>m_nDefRowHeight){
    	pDC->MoveTo(0-m_ptFirst.x,nGridHeight-m_ptFirst.y);
   		pDC->LineTo(min(m_rectClient.right,nGridWidth-m_ptFirst.x),nGridHeight-m_ptFirst.y);
		pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
    	pDC->MoveTo(0-m_ptFirst.x,nGridHeight-m_ptFirst.y+1);
   		pDC->LineTo(m_nColWidth[0],nGridHeight-m_ptFirst.y+1);
		pDC->SelectObject(pOldPen);
   		}
   	}	
   	while(m_rectClient.bottom-(nGridHeight-m_ptFirst.y)>0)
   	{
		nGridHeight+=m_nDefRowHeight;
		pDC->MoveTo(0-m_ptFirst.x,nGridHeight-m_ptFirst.y);
   		pDC->LineTo(min(nGridWidth-m_ptFirst.x,m_rectClient.right),nGridHeight-m_ptFirst.y);
		pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
    	pDC->MoveTo(0,nGridHeight-m_ptFirst.y+1);
   		pDC->LineTo(m_nColWidth[0],nGridHeight-m_ptFirst.y+1);
		pDC->SelectObject(pOldPen);
	}	   		
}                       

void CYYHGrid::Style3D(CDC* pDC,CRect rect)
{
	CPen* pOldPen;
	pOldPen=(CPen*)pDC->SelectStockObject(WHITE_PEN);
   	pDC->MoveTo(rect.left,rect.bottom);
	pDC->LineTo(rect.TopLeft()); 
	pDC->LineTo(rect.right,rect.top); 
	pDC->SelectObject(pOldPen);
}


void CYYHGrid::SetGrid(CDC *pDC)
{
	POSITION pos,pos0;
	CRect rect;                     
	int nCol,nRow=0; 
	int t=m_nColWidth[0];              
	CStringList* pList;
	CString  Str;                           
	CFont *pOldFont;
	pOldFont=(CFont*)pDC->SelectStockObject(ANSI_FIXED_FONT );      
	pDC->SetBkMode(TRANSPARENT);     
	pos0=m_ObList.GetHeadPosition();
	pList=(CStringList*)(m_ObList.GetNext(pos0));  
    if(!pList->IsEmpty()){
        pos=pList->GetHeadPosition(); 
        Str=pList->GetNext(pos);         
        rect.left=0;rect.top=0;
        rect.right=m_nColWidth[0];
        rect.bottom=m_nDefRowHeight;
        pDC->DrawText((Str),Str.GetLength(),&rect,m_nTextCenterMode);
        while(pos!=NULL){
           Str=pList->GetNext(pos);
           nRow++;
   		   if(!Str.IsEmpty())
   		   {   rect.left=0;
   		       rect.top=nRow*m_nDefRowHeight-m_ptFirst.y;
   			   rect.right=m_nColWidth[0];
   			   rect.bottom=rect.top+m_nDefRowHeight;
           	   if(rect.top>=m_nDefRowHeight-1)
           	   		pDC->DrawText((Str),Str.GetLength(),&rect,m_nTextCenterMode);
           	   if(pos==NULL) break;
//           	   Str=pList->GetNext(pos);
//           	   nRow++;
   			} 
   		}                    
    }
	
	for(nCol=1;nCol<m_nCols;nCol++) 
	{             
	   nRow=0; 
	   pList=(CStringList*)(m_ObList.GetNext(pos0));   
	   if(!pList->IsEmpty()){
	        pos=pList->GetHeadPosition(); 
	        Str=pList->GetNext(pos);
			rect.left=t-m_ptFirst.x;
	   		rect.top=0;
	   		rect.right=t+m_nColWidth[nCol]-m_ptFirst.x;
	   		rect.bottom=rect.top+m_nDefRowHeight;
           	if(rect.left<m_nColWidth[0])
           	   rect.left=m_nColWidth[0];
           	pDC->DrawText((Str),Str.GetLength(),&rect,m_nTextCenterMode);

	   	    while(pos!=NULL){
	   	    Str=pList->GetNext(pos);
           	nRow++;
	   		if(!Str.IsEmpty())
	   		{   
	   			rect.left=t-m_ptFirst.x;
	   			rect.top=nRow*m_nDefRowHeight-m_ptFirst.y;
	   			rect.right=t+m_nColWidth[nCol]-m_ptFirst.x;
	   			rect.bottom=rect.top+m_nDefRowHeight;
	   			if(rect.left<m_nColWidth[0])
           	   		rect.left=m_nColWidth[0];
           	   	if(rect.top>=m_nDefRowHeight-1)	
            	    pDC->DrawText((Str),Str.GetLength(),&rect,m_nTextCenterMode);
            	if(pos==NULL) break;
//            	Str=pList->GetNext(pos);
//            	nRow++;
       		}    
       		}
       }
	   t+=m_nColWidth[nCol];
	}  	              
 	pDC->SelectObject(pOldFont) ;
}                                                     


int CYYHGrid::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // TODO: Add your specialized creation code here
    if(m_bEnable)
    	m_pEdit->Create(WS_BORDER|WS_CHILD,CRect(0,0,0,0),this,9999);
    SetFocus();
    // Get font size          
    TEXTMETRIC tm;
    CDC * pDC = GetDC();
    //pDC->SelectStockObject(m_nFont);
    pDC->GetTextMetrics(&tm);
    ReleaseDC(pDC); 
    m_szFont.cy = tm.tmHeight + tm.tmExternalLeading;
    m_szFont.cx = tm.tmAveCharWidth;  
/*    
    SetCellText(0,0,"Mon");
    SetCellText(1,0,"Tus");
    SetCellText(2,0,"Wed");
    SetCellText(3,0,"Ths");
    SetCellText(4,0,"Fir");
    SetCellText(0,1,"Jan");
    SetCellText(0,2,"Feb");
    SetCellText(0,3,"Jan");
    SetCellText(0,4,"March");
    SetCellText(0,5,"May");  
    SetCellText(1,1,"Snow"); 
    SetCellText(2,2,"coding");
    SetCellText(1,2,"debuging");
    SetCellText(3,3,"backup");
    SetCellText(4,4,"server");
*/    
    return 0;
}

void CYYHGrid::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here
    Resize(cx, cy);
}

/////////////////////////////////////////////////////////////////////////////
void CYYHGrid::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//    CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
    // TODO: Add your message handler code here and/or call default
    CRect rect;
//    GetClientRect(&rect);     
    rect=m_rectClient;
    rect.top=0;
    rect.left=m_nColWidth[0];
    int i;                                
    switch(nSBCode) {
        case SB_LINELEFT:                 
            if(m_ptFirst.x <= 0)  return;  
            ASSERT(m_nFirstViewableCol!=1);
              i = m_nColWidth[m_nFirstViewableCol-1];
            m_ptFirst.x -= i;;   
            m_nFirstViewableCol--;
            ScrollWindow(i, 0,&rect,&rect);
            SetScrollPos(SB_HORZ, m_ptFirst.x);
            break;
        case SB_LINERIGHT:
            if(m_ptFirst.x >= m_szScroll.cx)    return;
               i =m_nColWidth[m_nFirstViewableCol] ;
            m_nFirstViewableCol++;     
            m_ptFirst.x += i;
            ScrollWindow(-i,0,&rect,&rect);
            SetScrollPos(SB_HORZ, m_ptFirst.x);
            break;     
        case SB_PAGELEFT: 
            if(m_ptFirst.x == 0)    return;
            ASSERT(m_nFirstViewableCol!=1);
            i = m_nColWidth[m_nFirstViewableCol-1];
            m_ptFirst.x -= i;;   
            m_nFirstViewableCol--;
            ScrollWindow(i, 0,&rect,&rect);
            SetScrollPos(SB_HORZ, m_ptFirst.x);
            break;
        case SB_PAGERIGHT:
            if(m_ptFirst.x >= m_szScroll.cx)    return;

            i =m_nColWidth[m_nFirstViewableCol] ;
            m_nFirstViewableCol++;    
//            else i = m_szScroll.cx - m_ptFirst.x;
            m_ptFirst.x += i;;

            ScrollWindow(-i, 0,&rect,&rect);
            SetScrollPos(SB_HORZ, m_ptFirst.x);
            break;
        case SB_THUMBPOSITION:           
        case SB_THUMBTRACK:
            if(int(nPos) == m_ptFirst.x) return;                
            
            int t=0;
            t=  nPos-m_ptFirst.x;
            if(abs(t)<m_nColWidth[m_nFirstViewableCol])
               return;
            if(t>0)
               while(t>=m_nColWidth[m_nFirstViewableCol])
               {
                 t-=m_nColWidth[m_nFirstViewableCol];
                 m_nFirstViewableCol++;
               }  
            else{
			   if(m_nFirstViewableCol<1) return;	
               while(t<-m_nColWidth[m_nFirstViewableCol-1])
               {
               	   t+=m_nColWidth[m_nFirstViewableCol-1];
               	   m_nFirstViewableCol--;       
               	   if(m_nFirstViewableCol<1) break;	
               }
            }   	   	   
            ScrollWindow(nPos-m_ptFirst.x-t,0,&rect,&rect);   
            m_ptFirst.x=nPos-t;

            SetScrollPos(SB_HORZ, m_ptFirst.x);
            break;
    } 
    CRect cliprect;
    GetParent()->GetUpdateRect(&cliprect);
    GetParent()->InvalidateRect(&cliprect);
    GetParent()->UpdateWindow();    
}

/////////////////////////////////////////////////////////////////////////////
void CYYHGrid::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    CRect rect; 
    rect=m_rectClient;
    int i;
    rect.left=0;
    rect.top=m_nDefRowHeight;
    switch(nSBCode) {
        case SB_LINEUP:
            if(m_ptFirst.y <= 0)  return;
			 i = m_nDefRowHeight;
            m_ptFirst.y -= i;      
            ScrollWindow(0, i,&rect, &rect);
            SetScrollPos(SB_VERT, m_ptFirst.y);
            break;
        case SB_LINEDOWN:    
            if(m_ptFirst.y >= m_szScroll.cy)    return;
            i =m_nDefRowHeight;
            m_ptFirst.y += i;;
            ScrollWindow(0,-i,&rect,&rect);
            SetScrollPos(SB_VERT, m_ptFirst.y);
            break;
        case SB_PAGEUP: 
            if(m_ptFirst.y == 0)    return;
//            if(m_ptFirst.y > m_nDefRowHeight)               
                i=m_nDefRowHeight;
//            else i = m_ptFirst.y;
            m_ptFirst.y -= i;      
            ScrollWindow(0,i ,&rect,&rect);
           
            SetScrollPos(SB_VERT, m_ptFirst.y);
            break;
        case SB_PAGEDOWN:
            if(m_ptFirst.y >= m_szScroll.cy)    return;
//            if(m_ptFirst.y <=m_szScroll.cy - m_nDefRowHeight) 
			i =m_nDefRowHeight;
//            else i = m_szScroll.cy - m_ptFirst.y;
            m_ptFirst.y += i;;
            ScrollWindow(0, -i,&rect,&rect);
            SetScrollPos(SB_VERT, m_ptFirst.y);
            break;
        case SB_THUMBPOSITION:           
        case SB_THUMBTRACK:
            if(int(nPos) == m_ptFirst.y) return;     
            int t=0;
            t=  nPos-m_ptFirst.y;
            if(abs(t)<m_nDefRowHeight)
               return; 
            t=t/m_nDefRowHeight*m_nDefRowHeight;   
            m_ptFirst.y=m_ptFirst.y+t;
            ScrollWindow( 0,t,&rect,&rect);   
            SetScrollPos(SB_VERT, m_ptFirst.y);
            break;
    }          
    CRect cliprect;
	GetParent()->GetUpdateRect(&cliprect);
    GetParent()->InvalidateRect(&cliprect);
    GetParent()->UpdateWindow();    
}   


int CYYHGrid::PointToRow(CPoint point)
{
//	int nRow;
	if(point.y<m_nDefRowHeight||point.x>GetGridWidth()) return 0;
	return  ( point.y+m_ptFirst.y)/m_nDefRowHeight;
}

CPoint CYYHGrid::PointToCell(CPoint point)
{
//	int nRow,nCol;
	CPoint pt=CPoint(0,0);
	if(point.y<m_nDefRowHeight) return pt;
	if(GetGridWidth()<point.x) return pt;
	int t=-m_ptFirst.x;
	while(t<point.x)
	{
		t+=m_nColWidth[pt.x];
		pt.x++;
	}
	pt.x--;	
	pt.y=( point.y+m_ptFirst.y)/m_nDefRowHeight;
	return  pt;
}


/////////////////////////////////////////////////////////////////////////////
void CYYHGrid::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    CClientDC dc(this);                  
    int WinCapH=::GetSystemMetrics(SM_CYCAPTION);	
	CRect rect;        
//	m_rectFocus.SetRectEmpty();
//	GetClientRect(&m_rectFocus);
	if(m_nDragCell!=-1) 
	{
		SetCapture();
		m_PrePoint=point;
		m_StartPoint=point;
		CDC* pDC=GetDC();  
		CRect rectFocus(point.x,0,point.x,3000);
		pDC->DrawFocusRect(&rectFocus);    
        ReleaseDC(pDC);
	}
	else 
	{  
	  CPoint pt;                                 
	  pt=PointToCell(point);     
//Add this line only for StackWindow of EP-SLD	  
	  if(pt.y>=m_nRows||pt.y==0) return;                
//////////////////////////////////////////////////////
	  if(0!=PointToRow(point)&&m_nActiveRow!=PointToRow(point) )
	  {
	   	 if(pt.x==0){ 
	   	    if(m_ptActiveCell!=CPoint(1,pt.y))
	   	    {   rect=CellToRect(m_ptActiveCell.x,m_ptActiveCell.x);
	   	    	InvalidateRect(&rect);
	   	    	m_ptActiveCell=CPoint(1,pt.y);
	   	    	rect=CellToRect(1,pt.y);
	   	    	InvalidateRect(&rect);
	   	    }	                                                  
	   	 }   
	   	 if(m_nActiveRow!=0)
	   	 {   rect=RowToRect(m_nActiveRow);
	   	     InvalidateRect(&rect);
	   	  }   
	   	 m_nActiveRow=PointToRow(point);
	   	 rect=RowToRect(m_nActiveRow);
	   	 InvalidateRect(&rect);
	  }
	  if(pt.x==0&&pt.y!=0)  pt.x=1;
	  if(pt.x!=0&&pt.y!=0&&pt.x<m_nCols&&m_ptActiveCell!=pt)
	  {
		if(m_bEnable){
		  if((m_pEdit->GetStyle())&WS_VISIBLE) 
		  {
	          CString str;
			  m_pEdit->GetWindowText(str);
    		  m_pEdit->ShowWindow(SW_HIDE);
    		  SetCellText(m_ptActiveCell.x,m_ptActiveCell.y,str.GetBuffer(str.GetLength()) );
    		  str.ReleaseBuffer();  
    		  if(m_szFont.cx*str.GetLength()>m_nColWidth[m_ptActiveCell.x])
    		     Invalidate();
           }
		}
		  rect=CellToRect(m_ptActiveCell.x,m_ptActiveCell.y);
		  InvalidateRect(&rect);
		  rect=CellToRect(pt.x,pt.y);
		  InvalidateRect(&rect);
		  m_ptActiveCell=pt;
//		  UpdateWindow();
	  }	
	}				    
	SetActiveWindow();
	SetFocus(); 
	UpdateWindow();
	CWnd::OnLButtonDown(nFlags, point);
}                                                              

/////////////////////////////////////////////////////////////////////////////

void CYYHGrid::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
    // TODO: Add your message handler code here and/or call default
    CWnd::OnGetMinMaxInfo(lpMMI);
    lpMMI->ptMinTrackSize.x = 150;    
}

void CYYHGrid::GetCellString(int nCol,int nRow,CString& str)
{
	POSITION pos;                    
	CStringList *p;
	pos=m_ObList.FindIndex(nCol);
	if(pos!=NULL)
	{   p=(CStringList*)(m_ObList.GetAt(pos) );
	    if( (pos=p->FindIndex(nRow))!=NULL)
	        str=p->GetAt(pos);
	    else str=""; 
	}
	else str="";      
}      
      
void CYYHGrid::SetCellText(int nCol,int nRow,char* lpstr)
{
    CString str;
    GetCellString(nCol,nRow,str);
    if( !strcmp((str),lpstr) ) return ;
    POSITION pos;
	CStringList *sl;
    CStringList* p;
	m_nCols=m_ObList.GetCount();
	while(m_nCols<nCol) 
	{
		m_ObList.AddTail(new CStringList);
		m_nCols++;
		m_nColWidth[m_nCols]=m_nDefColWidth;
		m_szScroll.cx+=m_nColWidth[m_nCols];
	}   
	if(nCol==m_nCols)
	{
		sl=new CStringList;
		for(int i=0;i<nRow-1;i++)
	       sl->AddTail(" ");
	    if(m_nRows<nRow+1) m_nRows=nRow+1;   	
	    sl->AddTail(lpstr); 
	    m_ObList.AddTail(sl);
    	m_nCols++;                          
	    m_nColWidth[m_nCols]=m_nDefColWidth;
	    m_szScroll.cx+=m_nColWidth[m_nCols];
	    SetScrollRange(SB_HORZ, 0, m_szScroll.cx);
	 }
	 else
	 {  pos=m_ObList.FindIndex(nCol);
	    p=(CStringList*)(m_ObList.GetAt(pos) );
		while(pos!=NULL&&p->GetCount()<nRow)		    
		{
	    	p->AddTail(" ");
	  	    	
		}
       	if((p)->GetCount()==nRow){
			p->AddTail(lpstr);
			if(m_nRows<nRow+1)
			{ 
			   m_szScroll.cy+=(nRow+1-m_nRows)*m_nDefRowHeight;
			   SetScrollRange(SB_VERT, 0, m_szScroll.cy);			   
			   m_nRows=nRow+1;    
			}   
		}
		else
		{   
		    
		    pos=m_ObList.FindIndex(nCol);
	        p=(CStringList*)(m_ObList.GetAt(pos) );
	   	    pos=(p)->FindIndex(nRow)	;
	   		p->GetAt(pos)=CString(lpstr);
		}                      

	 }	
	 if(m_nColWidth[nCol]!=0)
	  if(strlen(lpstr)*m_szFont.cx>(UINT)m_nColWidth[nCol])
      { m_nColWidth[nCol]=strlen(lpstr)*m_szFont.cx+5;
     	CRect rect(0,0,0,0) ;
  	    int t=0;
	    for(int i=0;i<nCol;i++)
	       t+=m_nColWidth[i];
	    rect.left=t-m_ptFirst.x-1;
	    rect.top=1;
	    rect.right=rect.left+m_nColWidth[nCol]-1;
	    rect.bottom=30000;
	   	InvalidateRect(&rect);
	  }  	   	    
	 InvalidateCell(nCol,nRow); 
}      

void CYYHGrid::InvalidateCell(int nCol,int nRow)
{
	CRect rect;
	if(nCol==0){
	   rect.left=1;
	   rect.top=nRow*m_nDefRowHeight-m_ptFirst.y+1;
	   rect.right=m_nColWidth[0]-1;
	   rect.bottom=rect.top+m_nDefRowHeight-1;
	}
	else if(nRow==0)
	{  
	   int t=0;
	   for(int i=0;i<nCol;i++)
	      t+=m_nColWidth[i];
	   rect.left=t-m_ptFirst.x+1;
	   rect.top=0+1;
	   rect.right=rect.left+m_nColWidth[nCol]-1;
	   rect.bottom=m_nDefRowHeight-1;           
	}   
	else
	{                       
	   int t=0;
	   for(int i=0;i<nCol;i++)
		   t+=m_nColWidth[i];
 	   rect.left=t-m_ptFirst.x+1;
	   rect.top=nRow*m_nDefRowHeight-m_ptFirst.y+1;
	   rect.right=t+m_nColWidth[nCol]-m_ptFirst.x-1;
	   rect.bottom=rect.top+m_nDefRowHeight-1;
	   if(rect.left<m_nColWidth[0])
          rect.left=m_nColWidth[0];
	}
	InvalidateRect(&rect);
//	UpdateWindow();	  
}
      
void CYYHGrid::OnLButtonUp(UINT nFlags, CPoint point) 
{
//	CRect rectClient;
//	GetClientRect(&rectClient);
	if(GetCapture()==this&&(m_nDragCell!=-1)){
		ReleaseCapture();
		CDC*pDC=GetDC(); 
		CPoint pS(m_PrePoint.x,0),pE(m_PrePoint.x,m_rectClient.bottom);
        CRect rectFocus(pS.x,pS.y,pE.x+1,pE.y);
        pDC->DrawFocusRect(&rectFocus);
		pS.x=0;
		for(int i=0;i<m_nDragCell;i++)
			pS.x+=m_nColWidth[i];
		pE.x=pS.x;
		pS.x=point.x;pE.x=pS.x;
        rectFocus.SetRect(pS.x,pS.y,pE.x+1,pE.y);
        pDC->DrawFocusRect(&rectFocus);
        pDC->MoveTo(pS);pDC->LineTo(pE); 
		ReleaseDC(pDC);
		m_nColWidth[m_nDragCell]+=point.x-m_StartPoint.x;
		if(m_bEnable)
		{
			if(m_ptActiveCell.x==m_nDragCell&&
		   		(m_pEdit->GetStyle()&WS_VISIBLE))
			{   CRect wrect;
				m_pEdit->GetWindowRect(&wrect); 
				ScreenToClient(&wrect); 
				wrect.right+=point.x-m_StartPoint.x;
		    	m_pEdit->MoveWindow(&wrect);        
		 	}   
		} 	
		if(m_nColWidth[m_nDragCell]<=0)
		   m_nColWidth[m_nDragCell]=0;
		Invalidate();
		UpdateWindow();
	}
	CWnd::OnLButtonUp(nFlags, point);
}

void CYYHGrid::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	int WinCapH=GetSystemMetrics(SM_CYCAPTION);	
//	CRect rectClient;
//	GetClientRect(&rectClient);
	if(GetCapture()==this){
		CPoint pS(m_PrePoint.x,0),pE(m_PrePoint.x,m_rectClient.bottom);
		CDC *pDC=GetDC();      

		CRect rectFocus(pS.x,pS.y,pE.x,pE.y);
		pDC->DrawFocusRect(&rectFocus);
		m_PrePoint=point;
		pS.x=point.x;pE.x=point.x;             
		rectFocus.SetRect(pS.x,pS.y,pE.x,pE.y);
		pDC->DrawFocusRect(&rectFocus);
		ReleaseDC(pDC);
	}
	else if((m_nDragCell=HitTest(point))!=-1){  
			  if(!m_bCurSet) 	
	          {   
	          	  m_hOldCur=::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE) );  
	              m_bCurSet=1;
	          }    
		   } 
	      else 
	      { 
//	        if(m_bCurSet)
//	        {   
	        	::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS) );  
	            m_bCurSet=0;
//	        }   	
	      }   
	          	
	CWnd::OnMouseMove(nFlags, point);
}
                  
int CYYHGrid::HitTest(CPoint point)
{
 	int nT=0;  
 	int wT=0;
// 	CRect rectClient;
// 	GetClientRect(&rectClient); 
// 	ScreenToClient(&point);
 	while(nT<m_nCols){
 	   wT+=m_nColWidth[nT];
 	   if(wT>=0){
 	   	  if( (point.x<wT-m_ptFirst.x+3)&&(point.x>wT-m_ptFirst.x-3) )
 	   	     if(m_nColWidth[nT+1]==0) return nT+1; 
 	   	     else return nT ;
	   	  else nT++;
	   }
	} 
	return -1;  
}	   

CRect CYYHGrid::RowToRect(int nRow)
{
// 	ASSERT(nRow>0);
 	CRect rect;
 	rect.left=m_nColWidth[0]+1;
 	rect.top=nRow*m_nDefRowHeight-m_ptFirst.y+2;
 	rect.bottom=rect.top+m_nDefRowHeight-1;
 	rect.right=GetGridWidth()-1;
	return rect;
}         


CRect CYYHGrid::CellToRect(int nCol,int nRow)
{
	CRect rect;                      
//	CRect rectClient;
//	GetClientRect(&rectClient);
 	int t=m_nColWidth[0];
 	rect.top=nRow*m_nDefRowHeight-m_ptFirst.y+1;
 	rect.bottom=rect.top+m_nDefRowHeight-1;
 	for(int i=m_nFirstViewableCol;i<nCol;i++)
 	    t+=m_nColWidth[i];
 	rect.left=t+1;
 	rect.right=t+m_nColWidth[nCol]-1; 
// 	if(nCol==m_nCols-1)
// 	rect.right=max(rect.right,rectClient.right);
 	return rect;
}
	   
void CYYHGrid::HighLightRow(CDC*pDC,int nRow)
{                                 
    CRect rect;
    rect=RowToRect(nRow);
    CBrush br(RGB(0,255,0));
    pDC->FillRect(&rect,&br); 
//Add this line only for StackWindow of EP_SLD    
    GetParent()->SendMessage(SM_UPDATELOCAL,0,0);
}                                         

void CYYHGrid::HighLightCell(CDC*pDC,CPoint pt)
{                                 
//    if(pt.x<m_nFirstViewableCol) return;
    CRect rect;
///    CRect rectClient;
//    GetClientRect(&rectClient);
    rect=CellToRect(pt.x,pt.y); 
    rect.top++;
    rect.left++;   
    CBrush br(RGB(255,0,0));
    pDC->FrameRect(&rect,&br);
}

                  
void CYYHGrid::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
  if(m_bEnable){
	CPoint pt;
	pt=PointToCell(point); 
	if(pt.x>=m_nCols||pt.x==0) return;
//Add this line only for StackWindow of EP-SLD
	if(pt.y>m_nRows) return;
/////////////////////////////////////////////////
	CString str;
	GetCellString(pt.x,pt.y,str);
	CRect rect;
	rect=CellToRect(pt.x,pt.y);
    m_pEdit->MoveWindow(&rect,FALSE);
	m_pEdit->SetWindowText((str)); 
	m_pEdit->ShowWindow(SW_SHOW); 
	m_pEdit->SetFocus();
  }
	CWnd::OnLButtonDblClk(nFlags, point);
}


BOOL CYYHGrid::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	// TODO: Add your message handler code here and/or call default
//	if(nHitTest==HTCLIENT ) SetCursor((HCURSSOR)0);
	
	return CWnd::OnSetCursor(pWnd, nHitTest, message);
}

void CYYHGrid::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: Add your message handler code here and/or call default
	int i;         
	CRect rect;
//	GetClientRect(&rectClient);
	rect=m_rectClient;
	switch(nChar){
	case VK_UP:
		if(m_nActiveRow<=1) return;
		else 
		{                         
			if(m_ptActiveCell.y==GetFirstViewableRow())
			{
	            rect.top=m_nDefRowHeight;
	            if(m_ptFirst.y <= 0)  return;
				 i = m_nDefRowHeight;
        	    m_ptFirst.y -= i;      
            	ScrollWindow(0, i,&rect, &rect);
            	SetScrollPos(SB_VERT, m_ptFirst.y);
			}
			if(m_nActiveRow!=0){
			rect=RowToRect(m_nActiveRow);
			InvalidateRect(&rect);
			}
			m_nActiveRow--; 
			m_ptActiveCell.y--;    
			if(m_nActiveRow!=0){
				rect=RowToRect(m_nActiveRow);
				InvalidateRect(&rect); 
			}
		}
		break;	
	case VK_DOWN:
		if(m_nActiveRow>=m_nRows-1) return;
		else 
		{                         
			if(m_ptActiveCell.y==GetLastViewableRow())
			{
	            rect.top=m_nDefRowHeight;
	            if(m_ptFirst.y >= m_szScroll.cy)    return;
    	        i =m_nDefRowHeight;
        	    m_ptFirst.y += i;;
            	ScrollWindow(0,-i,&rect,&rect);
            	SetScrollPos(SB_VERT, m_ptFirst.y);
			 }
			if(m_nActiveRow!=0){
			rect=RowToRect(m_nActiveRow);
			InvalidateRect(&rect);
			}
			m_nActiveRow++; 
			m_ptActiveCell.y++;    
			if(m_nActiveRow!=0){
			rect=RowToRect(m_nActiveRow);
			InvalidateRect(&rect);
			}
		}
		break;	
	case VK_LEFT:
		if(m_ptActiveCell.x<=1) return;
		else 
		{                         
			if(m_ptActiveCell.x==m_nFirstViewableCol)
			{
				rect.left=m_nColWidth[0];
	            if(m_ptFirst.x <= 0)  return;  
    	        ASSERT(m_nFirstViewableCol!=1);
        	    i = m_nColWidth[m_nFirstViewableCol-1];
            	m_ptFirst.x -= i;;   
            	m_nFirstViewableCol--;
            	ScrollWindow(i, 0,&rect,&rect);
            	SetScrollPos(SB_HORZ, m_ptFirst.x);
			 }
			rect=CellToRect(m_ptActiveCell.x,m_ptActiveCell.y);
			InvalidateRect(&rect);
			m_ptActiveCell.x--;    
			rect=CellToRect(m_ptActiveCell.x,m_ptActiveCell.y);
			InvalidateRect(&rect);
		}	  
		break;
	case VK_RIGHT:
		if(m_ptActiveCell.x>=m_nCols-1) return;
		else 
		{                         
			if(m_ptActiveCell.x==GetLastViewableCol())
			{
				rect.left=m_nColWidth[0];
	            if(m_ptFirst.x >= m_szScroll.cx)    return;
    	        i =m_nColWidth[m_nFirstViewableCol] ;
        	    m_nFirstViewableCol++;     
           	    m_ptFirst.x += i;
            	ScrollWindow(-i,0,&rect,&rect);
            	SetScrollPos(SB_HORZ, m_ptFirst.x);
			}
			rect=CellToRect(m_ptActiveCell.x,m_ptActiveCell.y);
			InvalidateRect(&rect);
			m_ptActiveCell.x++;    
			rect=CellToRect(m_ptActiveCell.x,m_ptActiveCell.y);
			InvalidateRect(&rect);
		}	  
		break;
	} 
    CRect cliprect;
	GetParent()->GetUpdateRect(&cliprect);
    GetParent()->InvalidateRect(&cliprect);
    GetParent()->UpdateWindow();    
	CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CYYHGrid::OnSetFocus(CWnd* pOldWnd)
{
	CWnd::OnSetFocus(pOldWnd);
	
	// TODO: Add your message handler code here
	
}

void CYYHGrid::OnKillFocus(CWnd* pNewWnd)
{
	CWnd::OnKillFocus(pNewWnd);
	
	// TODO: Add your message handler code here
	
}                                                    


int CYYHGrid::GetFirstViewableRow()
{
	return m_ptFirst.y/m_nDefRowHeight+1;
}

int CYYHGrid::GetLastViewableRow()
{
//    CRect rectClient;
//    GetClientRect(&rectClient);
    int nRow=(m_rectClient.bottom+m_ptFirst.y)/m_nDefRowHeight+1;
    return nRow-1;
}

int CYYHGrid::GetLastViewableCol()
{
//    CRect rectClient;
//    GetClientRect(&rectClient);
    int t=m_nColWidth[0];
    int nCol=m_nFirstViewableCol;
    while(t<m_rectClient.right&&nCol<m_nCols)
    {
       t+=m_nColWidth[nCol];
       nCol++;
    } 
    return nCol-1;
}
void CYYHGrid::OnRButtonDown(UINT nFlags, CPoint point)
{
	GetParent()->SendMessage(WM_RBUTTONDOWN,nFlags,MAKELONG(point.x,point.y));
	
	CWnd::OnRButtonDown(nFlags, point);
}
