⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nrdbgrid.cpp

📁 一个英国人写的GIS查看/编辑工具。支持标准的shapefile地图文件格式和coverage地图文件格式。同时可以编辑相应的dbf文件。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////
//
// NRDB Pro - Spatial database and mapping application
//
// Copyright (c) 1989-2004 Richard D. Alexander
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// NRDB Pro is part of the Natural Resources Database Project 
// 
// Homepage: http://www.nrdb.co.uk/
// Users' Forum: http://nrdb.mypalawan.info/
// 

#include "stdafx.h"
#include <math.h>

#include "nrdb.h"
#include "NRDBGrid.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

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

void inline swap(long& a, long& b)
{
   long c = a;
   a = b;
   b = c;
}

COLORREF inline InverseColor(COLORREF cr)
{
   return RGB(255-GetRValue(cr), 255-GetGValue(cr), 255 - GetBValue(cr));
};

/////////////////////////////////////////////////////////////////////////////
// CNRDBGrid

CNRDBGrid::CNRDBGrid()
{
   m_nActiveRow = 1;
   m_nActiveCol = 1;
   m_nFocusRow = 1;
   m_nFocusCol = 1;

   m_nFirstVisibleRow = 1;
   m_nFirstVisibleCol = 1;
   m_nVisibleColumns = 0;
   m_nVisibleRows = 0;

   m_celltopleft.Row = -2;
   m_celltopleft.Col = -2;
   m_cellbottomright.Col = -2;
   m_cellbottomright.Row = -2;

   m_nRows = 0;
   m_nCols = 0;

   m_dColWidth = 1;

   m_hFont = NULL;

   m_bShift = FALSE;
   m_bCtrl = FALSE;   
   m_bLButton = FALSE;
   
   m_nUndoRow = 0;
   m_nUndoCol = 0;

   m_hDragCursor = LoadCursor(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_DRAGHORZ));
   //m_hDefaultCursor = ::GetCursor();

   m_nDragCol = 0;
   m_bDragCursor = FALSE;

   m_bEditMode = FALSE;
   
}

CNRDBGrid::~CNRDBGrid()
{
   if (m_hDragCursor != NULL) DestroyCursor(m_hDragCursor);
}


BEGIN_MESSAGE_MAP(CNRDBGrid, CButton)
	//{{AFX_MSG_MAP(CNRDBGrid)
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_WM_KEYDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_CHAR()
	ON_WM_KILLFOCUS()
	ON_WM_SETFOCUS()
	ON_WM_KEYUP()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()   
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_WM_SETCURSOR()
	//}}AFX_MSG_MAP

   ON_MESSAGE(WM_SETEDITMODE, OnSetEditMode)
   ON_MESSAGE(WM_COPY, OnCopy)
   ON_MESSAGE(WM_CUT, OnCut)
   ON_MESSAGE(WM_PASTE, OnPaste)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNRDBGrid message handlers

CGridRow::CGridRow(CGridRow& rSrc)
{
   *this = rSrc;
}

CGridRow& CGridRow::operator=(CGridRow& rSrc )
{
   RemoveAll();
   Copy(rSrc);
   return *this;
}

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

BOOL CNRDBGrid::ClearDataRange(SS_COORD Col,  SS_COORD Row, 
                      SS_COORD Col2, SS_COORD Row2)
{
   for (int i = Col; i <= Col2; i++)
   {
      for (int j = Row; j <= Row2; j++)
      {
         SetValue(i, j, "");         
         SetInteger(i, j, 0);
         SetIndex(i, j, -1);
      }
   }
   return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//
// Resize the grid to reflect the number of columns
//

void CNRDBGrid::SetMaxCols(SS_COORD MaxCols)
{
   m_nCols = MaxCols+1;
   for (int iRow = 0; iRow < m_nRows; iRow++)
   {
      int nSize = m_aGrid[iRow].GetSize();
      m_aGrid[iRow].SetSize(m_nCols);      
   };

   m_aColumns.SetSize(m_nCols);
}   

///////////////////////////////////////////////////////////////////////////////
//
// Resize the grid to reflect the number of rows
//

void CNRDBGrid::SetMaxRows(SS_COORD MaxRows) 
{   
   m_nRows = MaxRows+1;
   m_aGrid.SetSize(m_nRows);   
   
   // Update the column size for the new columns

   SetMaxCols(m_nCols-1);
};

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

BOOL CNRDBGrid::DelRow(SS_COORD Row) 
{
   if (m_nRows > 2)
   {
      m_aGrid.RemoveAt(Row); 
      SetMaxRows(GetMaxRows()-1);      

      // Create a blank row

      if (m_nRows == 1)
      {
         InsRow(1);
      }
   };
     
   return TRUE;
}

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

BOOL CNRDBGrid::InsRow(SS_COORD nRow) 
{
   CGridRow row; 
   m_aGrid.InsertAt(nRow, row); 
   SetMaxRows(GetMaxRows()+1);
   return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//
// Set value, update number of columns if necessary
//

BOOL CNRDBGrid::SetValue(SS_COORD Col, SS_COORD Row, LPCTSTR lpData)
{
   if (Row >= m_nRows) SetMaxRows(Row);
   if (Col >= m_nCols) SetMaxCols(Col);   

   m_aGrid[Row][Col].m_sText = lpData; 
   m_aGrid[Row][Col].m_sText.TrimRight();
   
   Invalidate(FALSE);
      
   return TRUE;
}

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

BOOL CNRDBGrid::SetColWidth(SS_COORD Col, double Width)
{ 
   if (Col == -1)
   {
      for (int i = 0; i < m_nCols; i++)
      {
         m_aColumns[i].m_dWidth = Width; 
      }

      // Set default column width
      m_dColWidth = Width;
   } else
   {
      m_aColumns[Col].m_dWidth = Width; 
   }
   return TRUE;
}

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

double CNRDBGrid::GetColWidth(SS_COORD Col)
{
   // If no column width set then use default

   double dWidth = m_aColumns[Col].m_dWidth;

   // Comparing with -1 should be ok because no arithmetic performed

   if (Col == 0) return 4;
   else if (dWidth == -1) return m_dColWidth;
   else return dWidth;

   return TRUE;
}

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

BOOL CNRDBGrid::SetColor(SS_COORD Col, SS_COORD Row, COLORREF Background,
                COLORREF Foreground)
{
   // 
   Invalidate(FALSE);

   return TRUE;
}

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

COLORREF CNRDBGrid::GetCellColor(SS_COORD Col,  SS_COORD Row)
{
   if (Col == 0 || Row == 0) return RGB(192, 192, 192);

   long n;
   if (GetInteger(Col,  Row, &n) && n == 0) return RGB(255,255,255);
   else return RGB(0,0,250);
}

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

void CNRDBGrid::PreSubclassWindow() 
{   
	CButton::PreSubclassWindow();
}


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

void CNRDBGrid::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{      
   CString s;

   // Determine characer width

   CDC* pDC = CDC::FromHandle(lpDIS->hDC);
   CSize sz = pDC->GetTextExtent("A");   

   CRect rectC;
   CRect rect;
   GetClientRect(&rectC);

   pDC->SetBkMode(TRANSPARENT);

   // Initialise

   m_aRectCols.RemoveAll();
   m_aRectRows.RemoveAll();

   // Use the font

   CFont* pFont = CFont::FromHandle(m_hFont);

   CFont* pFontOld = pDC->SelectObject(pFont);
   
   // Draw the grid

   int y = 0;
   int x = 0;
   int xMax = 0;

   for (int iRow = 0; iRow < m_nRows; iRow++)
   {
      x = 0;
      double dHeight;
      GetRowHeight(iRow, &dHeight);
      int nHeight  = (int)(sz.cy * dHeight * 1.3);

      // Allow for scolling

      if (iRow != 0 && iRow < m_nFirstVisibleRow) iRow = m_nFirstVisibleRow;
      if (y > rectC.bottom) break;      

      for (int iCol = 0; iCol < m_nCols; iCol++)
      {   
         // Allow for scrolling

          if (iCol != 0 && iCol < m_nFirstVisibleCol) iCol = m_nFirstVisibleCol; 

          // Don't draw if not visible

          if (x > rectC.right) break;          

          if (m_aColumns[iCol].m_bVisible)
		  {

			  // Determine column width

			  int nWidth = (int)(sz.cx * GetColWidth(iCol) * 1.2);
   
			  // Draw rectangle

			  rect.left = x;
			  rect.right = x + nWidth;
			  rect.top = y;
			  rect.bottom = y + nHeight;

			  COLORREF cr = GetCellColor(iCol, iRow);
			  COLORREF crT = RGB(0,0,0);

			   // Check if selected

			  if ((m_celltopleft.Row <= iRow && iRow <= m_cellbottomright.Row ||
				  m_celltopleft.Row == -1) && 
				  (m_celltopleft.Col <= iCol && iCol <= m_cellbottomright.Col ||
				  m_celltopleft.Col == -1) && !(iRow == m_nActiveRow && 
				  iCol == m_nActiveCol))
			  {
				 // Inverse colour
				 cr = InverseColor(cr);
				 crT = InverseColor(crT);
			  }


			  pDC->FillSolidRect(rect.left,rect.top, rect.Width(), rect.Height(), cr);

			  if (iCol == 0 || iRow == 0)
			  {                  
				 pDC->Draw3dRect(rect.left, rect.top, rect.Width()+1, rect.Height()+1, 
					   0,0);             
				 pDC->Draw3dRect(rect.left+1, rect.top+1, rect.Width()-1, rect.Height()-1, 
					   RGB(255,255,255), RGB(128,128,128));
			  } else
			  {
				 pDC->Draw3dRect(rect.left, rect.top, rect.Width()+1, rect.Height()+1, 
					   RGB(192,192,192), RGB(192,192,192));             
			  }

			  // If cell is active then indicate this

			  if (iCol == m_nActiveCol && iRow == m_nActiveRow && iCol > 0 && iRow > 0)
			  {
				 cr = InverseColor(cr);
				 pDC->Draw3dRect(rect.left+1, rect.top+1, rect.Width()-2, rect.Height()-2, 
					   cr, cr);                          
			  }
          
			  // Draw the text - for numbers do not display

			  if (iRow == 0 || m_aColumns[iCol].m_celltype.m_nType == Edit || 
				  m_aColumns[iCol].m_celltype.m_nType == Combo)
			  {
				 s = GetValue(iCol, iRow);

				 int nFlags = DT_LEFT|DT_NOPREFIX;
				 if (iRow == 0 || iCol == 0) 
				 {
					if (pDC->GetTextExtent(s).cx < rect.Width())
					{
						nFlags = DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX|DT_CENTER;
					} else
					{
						nFlags = DT_WORDBREAK|DT_NOPREFIX|DT_CENTER;                
					};
				 };

				 // Display row numbers

				 if (iCol == 0 && iRow != 0) s.Format("%i", iRow);

				 CRect rectT = rect;
				 rectT.left += 2;
				 rectT.top += 2;

				 pDC->SetTextColor(crT);
				 pDC->DrawText(s, &rectT, nFlags);
			  };
                    
			  // Update the position

			  x += nWidth;

			  // Determine approximate number of columns from last drawn

			  m_nVisibleColumns = (long)(ceil(rectC.Width() / nWidth));
		  } else
		  {
			  rect = CRect();
		  }


          // Store the position of the cell

          if (iRow == 0) m_aRectCols.Add(rect);
      };      
      
      y += nHeight;
      xMax = max(x, xMax);

      m_nVisibleRows = (long)ceil(rectC.Height() / nHeight);

      m_aRectRows.Add(rect);
   }  
   
   // Clear space to right (more smooth than repainting)

   pDC->FillSolidRect(xMax, 0, rectC.right, y, RGB(192,192,192));
   pDC->FillSolidRect(0, y, rectC.right, rectC.bottom, RGB(192,192,192));


   // Set scroll position
   
   SetScrollRange(SB_HORZ, 1, m_nCols-1, FALSE);
   SetScrollPos(SB_HORZ, m_nFirstVisibleCol, TRUE); 

   SetScrollRange(SB_VERT, 1, m_nRows-1, FALSE);
   SetScrollPos(SB_VERT, m_nFirstVisibleRow, TRUE); 

   // Tidy up

   pDC->SelectObject(pFontOld);
}

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

void CNRDBGrid::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
   int nCol = 0;

   switch(nSBCode)
   {     
      case SB_LINELEFT:                          
         if (m_nFirstVisibleCol > 1)
         {
            m_nFirstVisibleCol--;                  
            while (m_nFirstVisibleCol > 1 && !m_aColumns[m_nFirstVisibleCol].m_bVisible) m_nFirstVisibleCol--;
         }
         else return;
      break;

      case SB_LINERIGHT:        
         // Skip hidden         
         if (m_nFirstVisibleCol+1 < m_nCols) 
         {
            m_nFirstVisibleCol++;        
            while (m_nFirstVisibleCol+1 < m_nCols && !m_aColumns[m_nFirstVisibleCol].m_bVisible) m_nFirstVisibleCol++;
         }
         else return;
      break;

  // page left
         
      case SB_PAGELEFT:        
         nCol = max(1, m_nFirstVisibleCol - m_nVisibleColumns);
         if (nCol != m_nFirstVisibleCol) m_nFirstVisibleCol = nCol;
         else return;         
      break;            
  
  // page right
      
      case SB_PAGERIGHT:          
         nCol = min(m_nCols-1, m_nFirstVisibleCol + m_nVisibleColumns);
         if (nCol != m_nFirstVisibleCol) m_nFirstVisibleCol = nCol;
         else return;
      break;         
      
      case SB_THUMBPOSITION:         
          m_nFirstVisibleCol = nPos;
      break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -