using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace System.Windows.Forms
{
	/// <summary>
	/// 对DataGrid进行操作方法的方法和属性
	/// </summary>
	public class DataGridAccess
	{
		public DataGridAccess()
		{
			//
			// TODO: 在此处添加构造函数逻辑
			//
		}

		#region 网格行列数、列标题、起始可见行列、在RowHeader/ColumnHeader上画行/列序列号、行序号所需宽
		/// <summary>
		/// 返回DataGrid行数
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <returns></returns>
		public int GetRowCount(DataGrid p_dataGrid)
		{
			#region 实现...
			
			int intReturn = 0;

			if (p_dataGrid.DataSource != null)
			{
				try
				{
					CurrencyManager cm;
					cm = (CurrencyManager)p_dataGrid.BindingContext[p_dataGrid.DataSource, p_dataGrid.DataMember]; 
					intReturn = cm.Count;
				}	
				catch{}
			}

			return intReturn;

			#endregion
		}

		/// <summary>
		/// 返回DataGrid列数
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <returns></returns>
		/// 基本与GetRowCount的方法类似，只是加了一求文本的
		public int GetColCount(DataGrid p_dataGrid)
		{
			#region 实现...
			
			int intReturn = 0;

			if (p_dataGrid.DataSource != null)
			{
				try
				{
					CurrencyManager cm;
					cm = (CurrencyManager)p_dataGrid.BindingContext[p_dataGrid.DataSource, p_dataGrid.DataMember]; 
					
					intReturn = cm.GetItemProperties().Count;
				}	
				catch{}
			}

			return intReturn;

			#endregion
		}

		/// <summary>
		/// 返回DataGrid的列标题
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <returns></returns>
		public string[] GetColumnHeadersText(DataGrid p_dataGrid)
		{ 
			#region 实现...
			
			string[] arrReturn = null;

			int intCols = 0;

			if (p_dataGrid.DataSource != null)
			{
				try
				{
					CurrencyManager cm;
					cm = (CurrencyManager)p_dataGrid.BindingContext[p_dataGrid.DataSource, p_dataGrid.DataMember]; 
					
					//PropertyCollection  描述DataColumn DataSet DataTable的属性
					PropertyDescriptorCollection pdc = cm.GetItemProperties();
					intCols = pdc.Count;

					arrReturn = new string[intCols];
					for(int i=0 ; i<intCols ; i++)
					{
						arrReturn[i] = pdc[i].Name;
					}
				}	
				catch{}
			}

			return arrReturn;

			#endregion
		}

		/// <summary>
		/// 返回DataGrid第一个可视行索引
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <returns></returns>
		public int GetFirstVisibleRow(DataGrid p_dataGrid)
		{
			#region 实现...

			int intReturn = -1;
		
			int intRowCount	= 0;		//总行数
			int intFirstVisibleRow = -1;		//

			if (p_dataGrid.DataSource != null && p_dataGrid.VisibleRowCount > 0)
			{
				
				try
				{
					//提供给计算第一可视行，要重绘的话也只从第一可视行开始画起，提高效率。用户可能用鼠标调整某些行高，因些不能平均。
					
					int y = 0;
					int x = 0;

					x = 2;
					
					while(intFirstVisibleRow < 0)
					{
						intFirstVisibleRow = p_dataGrid.HitTest(x,y).Row;
						y++;
					}

				}
				catch
				{}

			}
		
			intReturn = intFirstVisibleRow;
			return intReturn;

			#endregion
		}

		/// <summary>
		/// 返回DataGrid第一个可视列索引（直接引用dataGrid.FirstVisibleColumn）
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <returns></returns>
		public int GetFirstVisibleCol(DataGrid p_dataGrid)
		{
			#region 实现...

			int intReturn = -1;

			intReturn = p_dataGrid.FirstVisibleColumn;
		
			return intReturn;

			#endregion
		}

		/// <summary>
		/// 获取DataGrid中RowHeader上设置行序列号所需的宽度。
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_font"></param>
		/// <returns></returns>
		public int GetRowHeaderSerialNoWidth(DataGrid p_dataGrid,Font p_font)
		{
			#region 实现...

			int intFixedSelectFlagsWidth = 15;			//要与SetRowHeaderSerialNo中的一至
			int intRowCount = GetRowCount(p_dataGrid);
			Graphics g = p_dataGrid.CreateGraphics();
			
			int intRowHeaderWidth = (int)g.MeasureString(intRowCount.ToString(),p_font).Width + intFixedSelectFlagsWidth + 1;

			g.Dispose();
			g = null;
			return intRowHeaderWidth;

			#endregion
		}

		/// <summary>
		/// 为DataGrid在RowHeader上设置行序列号，如果设置，则使RowHeadersVisible为可见，默认字体为网格Font，并会重新设置RowHeaderWidth。，需要在OnPaint中调用重绘。
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_font"></param>
		public void SetRowHeaderSerialNo(DataGrid p_dataGrid,Font p_font)
		{
			//为里不要改变Caption Header的字体等，因为这样会再次引发重绘
			#region 实现...	
			int intFixedSelectFlagsWidth = 15;			//要与GetRowHeaderSerialNoWidth中的一至

			//Graphics g = e.Graphics;
			Graphics g = p_dataGrid.CreateGraphics();

			int intRowCount = GetRowCount(p_dataGrid);			
			int intFirstVisibleRow= GetFirstVisibleRow(p_dataGrid);
			
			if (p_dataGrid.VisibleRowCount > 0)
			{	
				System.Drawing.Font font;
				System.Drawing.Brush brush = Brushes.Red;				

				if (p_font == null)
				{
					font = (System.Drawing.Font)p_dataGrid.Font.Clone();
				}
				else
				{
					font = (System.Drawing.Font)p_font.Clone();
				}

				p_dataGrid.RowHeadersVisible = true;	//使RowHeadersVisible为可见，并会重新设置RowHeaderWidth 

				int intRowHeaderWidth = p_dataGrid.RowHeaderWidth;	
		
				intRowHeaderWidth = (int)g.MeasureString(intRowCount.ToString(),font).Width + intFixedSelectFlagsWidth + 1;
				
				p_dataGrid.RowHeaderWidth = intRowHeaderWidth;

				int intTop = 0;
				int intLeft = 0;
				int intWidth = 0;
				int intHeight = 0;

				Rectangle recRowHeader;

				//设置有效裁剪区
				g.SetClip(p_dataGrid.DisplayRectangle);

				int intVisibleRowCount = p_dataGrid.VisibleRowCount;

				int i = intFirstVisibleRow;

				StringFormat format = new StringFormat();
				format.Alignment = StringAlignment.Center;

				for(int visibleRow = 0 ; visibleRow < intVisibleRowCount ;visibleRow++)
				{
					intTop = p_dataGrid.GetCellBounds(i, 0).Top + 1;
					intLeft = p_dataGrid.GetCellBounds(i, 0).Left -  (int)intRowHeaderWidth + intFixedSelectFlagsWidth ;
					intWidth = p_dataGrid.GetCellBounds(i,0).Width;
					intHeight = p_dataGrid.GetCellBounds(i,0).Height;
					recRowHeader = new Rectangle(intLeft,intTop,intRowHeaderWidth - intFixedSelectFlagsWidth,intHeight);
					
					//只有相交才重绘，提高效率
					g.DrawString((i+1).ToString(), font,brush,recRowHeader,format);		
					i++;
				}
				
				format.Dispose();
				font.Dispose();
				g.Dispose();
				font = null;
				g = null;
				format = null;

			}				

			#endregion
		}


		/// <summary>
		/// 为DataGrid在ColumnHeaders上设置列序列号，如果设置，则使ColumnHeadersVisible为可见，默认字体为HeaderFont。需要在OnPaint中调用重绘。
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_font"></param>
		public void SetColHeaderSerialNo(DataGrid p_dataGrid,Font p_font)
		{
			//为里不要改变Caption Header的字体等，因为这样会再次引发重绘
			#region 实现...	

			//Graphics g = e.Graphics;
			Graphics g = p_dataGrid.CreateGraphics();

			int intColCount = GetColCount(p_dataGrid);			
			int intFirstVisibleCol = p_dataGrid.FirstVisibleColumn;
			
			if (p_dataGrid.VisibleColumnCount > 0)
			{	
				System.Drawing.Font font;
				System.Drawing.Brush brush = Brushes.Red;				

				if (p_font == null)
				{
					font = (System.Drawing.Font)p_dataGrid.HeaderFont.Clone();
				}
				else
				{
					font = (System.Drawing.Font)p_font.Clone();
				}

				p_dataGrid.ColumnHeadersVisible = true;	//使ColumnHeadersVisible为可见 

				int intFixedColFlagsHeight = (int)g.MeasureString("1",font).Height + 1;	 //数字需要的高

				int intTop = 0;
				int intLeft = 0;
				int intWidth = 0;
				int intHeight = 0;

				Rectangle recColHeader;

				//设置有效裁剪区
				g.SetClip(p_dataGrid.DisplayRectangle);

				int intVisibleColCount = p_dataGrid.VisibleColumnCount;
				int intFirstVisibleRow = GetFirstVisibleRow(p_dataGrid);

				int i = intFirstVisibleCol;

				StringFormat format = new StringFormat();
				format.Alignment = StringAlignment.Center;

				for(int visibleCol = 0 ; visibleCol < intVisibleColCount ;visibleCol++)
				{
					intTop = p_dataGrid.GetCellBounds(intFirstVisibleRow, i).Top - intFixedColFlagsHeight;
					intLeft = p_dataGrid.GetCellBounds(0, i).Left;
					intWidth = p_dataGrid.GetCellBounds(0,i).Width;
					intHeight = intFixedColFlagsHeight;
					recColHeader = new Rectangle(intLeft,intTop,intWidth,intHeight);
					
					//只有相交才重绘，提高效率
					g.DrawString((i+1).ToString(), font,brush,recColHeader,format);		
					i++;
				}

				format.Dispose();
				font.Dispose();
				g.Dispose();
				font = null;
				g = null;
				format = null;
			}
				
			#endregion
		}
		#endregion

		#region 在网格指定行/列或区域上写相同文本

		/// <summary>
		/// 在网格指定列上写相同文本
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_Col"></param>
		/// <param name="p_Text"></param>
		public void SetColText(DataGrid p_dataGrid,int p_Col,string p_Text)
		{
			int intRows = GetRowCount(p_dataGrid);

			for (int i = 0 ; i < intRows ; i++)
			{
				p_dataGrid[i,p_Col] = p_Text;
			}		
		}

		/// <summary>
		/// 在网格指定行上写相同文本
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_Row"></param>
		/// <param name="p_Text"></param>
		public void SetRowText(DataGrid p_dataGrid,int p_Row,string p_Text)
		{
			int intCols = GetColCount(p_dataGrid);

			for (int i = 0 ; i < intCols ; i++)
			{
				p_dataGrid[p_Row,i] = p_Text;
			}		
		}

		/// <summary>
		/// 在网格指定区域上写相同文本
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_Row"></param>
		/// <param name="p_Text"></param>
		public void SetRangeText(DataGrid p_dataGrid,int p_startRow,int p_startCol,int p_endRow,int p_endCol,string p_Text)
		{
			int intRows = GetRowCount(p_dataGrid);
			int intCols = GetColCount(p_dataGrid);

			if(p_startRow < 0)
			{
				p_startRow = 0;
			}

			if(p_endRow > intRows)
			{
				p_endRow = intRows;
			}

			if(p_endCol > intCols)
			{
				p_endCol = intCols;
			}

			if(p_startCol < 0)
			{
				p_startCol = 0;
			}

			for (int i = p_startRow ; i < p_endRow ; i++)
			{
				for (int j = p_startCol ; j < p_endCol ; j++)
				{
					p_dataGrid[i,j] = p_Text;
				}
			}		
		}

		#endregion
		
		#region 在网格数据行上写行/列号，而非RowHeader/ColumnHeader上绘制
		/// <summary>
		/// 从网格的第一个数据行开始写行序列，从1开始，注意是写在数据行上，而SetRowHeaderSerialNo()是画在RowHeader上
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_col"></param>
		public void SetRowSerialNo(DataGrid p_dataGrid,int p_col)
		{
			int intRows = GetRowCount(p_dataGrid);

			for (int i = 0 ; i < intRows ; i++)
			{
				p_dataGrid[i,p_col] = (i + 1).ToString();
			}		
		}

		/// <summary>
		/// 从网格的第一个数据列开始写列序列，从1开始，注意是写在数据列上，而SetColHeaderSerialNo()是画在ColumnHeader上
		/// </summary>
		/// <param name="p_dataGrid"></param>
		/// <param name="p_row"></param>
		public void SetColSerialNo(DataGrid p_dataGrid,int p_row)
		{
			int intCols = GetColCount(p_dataGrid);

			for (int i = 0 ; i < intCols ; i++)
			{
				p_dataGrid[p_row,i] = (i + 1).ToString();
			}		
		}

		#endregion

		public string GetCenterCaptionText(DataGrid p_dataGrid)
		{
			#region 实现...
			string strReturn = p_dataGrid.CaptionText;

			if (strReturn != "")
			{
				int perWidth;		//一个英文字符占据的宽度
				int count;			//标题栏所能容纳的字符数
				int len;			//已有标题的字符数

				perWidth = (int)(Graphics.FromHwnd(p_dataGrid.Handle).MeasureString("ABCDEFGHIJKLMNOPQRSTUVWXYZ", p_dataGrid.CaptionFont).Width / 26.0F);
				count = (int)(p_dataGrid.Width / perWidth);
				len = System.Text.Encoding.Default.GetByteCount(p_dataGrid.CaptionText);	//英文占一个字节，中文是占两个字节，用此解决

				int c = (int)((count - len) / 2);
				for(int i = 0 ; i < c ;i++ )
				{
					strReturn = " " + strReturn;			
				}
			}

			return strReturn;
			#endregion			
		
		}			

	}//End Class
}//End NameSpace