context: #region Copyright (c)2003 Juanjo < http://lphant.sourceforge.net >
  /*
  * This file is part of eLePhant
  * Copyright (C)2003 Juanjo < j_u_a_n_j_o@users.sourceforge.net / http://lphant.sourceforge.net >
  * 
  * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
  #endregion
  
  using System;
  using System.ComponentModel;
  using System.Collections;
  using System.Diagnostics;
  using System.Windows.Forms;
  using System.Drawing;
  using System.Runtime.InteropServices;
  using System.Text;
  
  namespace eLePhant.Client
  {
  	//The delegate for the HeaderEventArgs class
  	public delegate void HeaderEventHandler(object sender, HeaderEventArgs e);
  	//The delegate for drawing the entire header
  	public delegate void DrawHeaderEventHandler(DrawHeaderEventArgs e);
  	//The delegate for click the header
  	public delegate void ClickHeaderEventHandler(ColumnClickEventHandler e);
  
  	public class eLePhantListView : ListView
  	{
  		public int SortColumnIndex;
  		//The event for drawing columns
  		public event DrawItemEventHandler DrawColumn;
  		//The event for handling the entire border drawing of the header
  		public event DrawHeaderEventHandler DrawHeader;
  
  		//Event handlers associated with the header control
  		public event HeaderEventHandler BeginDragHeaderDivider;
  		public event HeaderEventHandler DragHeaderDivider;
  		public event HeaderEventHandler EndDragHeaderDivider;
  		public event HeaderEventHandler ClickHeader;
  
  		private System.ComponentModel.Container components = null;
  		//private StringBuilder strB;
  		private Pen borderPen;
  		public int ScrollBarBKColor;
  		ListColumnArray myColumns;		
  		public ImageList headerImages;
  		HeaderControl header;
  		bool ownerDrawHeader;
  		int increaseHeaderHeight;
  		public Color headerBackColor;
  		public Color headerForeColor;
  		int headerHeight;
  		bool defaultCustomDraw;
  		bool m_Loaded;
  		private int m_sortColumn;
  
  		protected int[] m_DefaultWidths;
  		public int sortOrder;
  		
  		private int[] m_headerleft=new int[20];
  		private int[] m_headerright=new int[20];
  		private Pen m_ArrowPen;
  		public Color HeaderBorderColor
  		{
  			set 
  			{
  				borderPen=new Pen(value);
  			}
  		}
  
  		public int sortColumn
  		{
  			get
  			{
  				return m_sortColumn;
  			}
  			set
  			{
  				m_sortColumn=value;
  				this.Refresh();
  			}
  		}
  
  		public eLePhantListView()
  		{
  			InitializeComponent();
  			
  			//strB=new StringBuilder();
  			myColumns = new ListColumnArray(); 
  			ownerDrawHeader = false;			
  			headerBackColor = Color.FromArgb(222,231,247);//SystemColors.Control;
  			headerForeColor= Color.Black;
  			ScrollBarBKColor = 0x00F7E7DE;
  			//m_ArrowPen=new Pen(headerForeColor);
  			m_ArrowPen=new Pen(Color.FromArgb(0x80,0,0,0));
  			borderPen=new Pen(Color.FromArgb(68,69,151));
  			increaseHeaderHeight = 0;
  			defaultCustomDraw = false;
  			this.CheckBoxes = false;
  			this.FullRowSelect=true;
  			this.AllowColumnReorder=true;
  			this.AutoArrange=false;
  			this.HideSelection=false;
  			ownerDrawHeader = true;
  			this.defaultCustomDraw=false;
  			headerImages=new ImageList();
  			sortColumn=-1;
  			sortOrder=1;
  			m_Loaded=false;
  			InsertColumns();
  		}
  
  		public int GetColumnPosition(int column)
  		{
  			Win32.LV_COLUMN pcol = new Win32.LV_COLUMN();
  			pcol.mask = Win32.LVCF_ORDER;
  			Win32.SendMessage(Handle, Win32.LVM_GETCOLUMN, column, ref pcol);
  			return (int)pcol.iOrder;
  		}
  		public void SetColumnPosition(int column, int position)
  		{
  			Win32.LV_COLUMN pcol = new Win32.LV_COLUMN();
  			pcol.mask = Win32.LVCF_ORDER;
  			pcol.iOrder = position;
  			Win32.SendMessage(Handle, Win32.LVM_SETCOLUMN, column, ref pcol);
  		}
  		public int GetColumnsWidth(int column)
  		{
  			return Win32.SendMessage(Handle,Win32.LVM_GETCOLUMNWIDTH,column,0);
  		}
  		public void SetColumnWidth(int column, int width)
  		{
  			IntPtr lPram=Win32.MakeLParam(width,0);
  			Win32.SendMessage(Handle,Win32.LVM_SETCOLUMNWIDTH,column,lPram);
  		}
  		public void SetFlatScrollBar()
  		{
  			IntPtr stylePtr;
  			int style;
  			stylePtr=Win32.SendMessage(this.Handle, 4151, IntPtr.Zero , IntPtr.Zero);
  			style=stylePtr.ToInt32();
  			style+=256;
  			stylePtr=(IntPtr)style;
  			Win32.SendMessage(this.Handle, 4150, IntPtr.Zero , stylePtr);	
  			Win32.FlatSB_SetScrollProp(this.Handle,0x80,(IntPtr)ScrollBarBKColor,true);
  			Win32.FlatSB_SetScrollProp(this.Handle,0x40,(IntPtr)ScrollBarBKColor,true);
  		}
  		public void SavePreferences()
  		{
  			for (int i=0;i<Columns.Count;i++)
  			{
  				eLePhantForm.preferences.SetProperty(Name+"ColumnWidth-"+i.ToString(),GetColumnsWidth(i));
  				eLePhantForm.preferences.SetProperty(Name+"ColumnPosition-"+i.ToString(),this.GetColumnPosition(i));
  			}
  		}
  		protected override void OnVisibleChanged(EventArgs e)
  		{
  			if (this.Visible) m_LoadPreferences();
  			base.OnVisibleChanged(e);
  		}
  		protected void m_LoadWidths()
  		{
  			int def;
  			for (int i=0;i<Columns.Count;i++)
  			{
  				if ((m_DefaultWidths==null)||(i>m_DefaultWidths.Length))
  					def=60;
  				else 
  					def=m_DefaultWidths[i];
  				Columns[i].Width=eLePhantForm.preferences.GetInt(Name+"ColumnWidth-"+i.ToString(),def);
  			}
  		}
  		private void m_LoadPreferences()
  		{
  			if (m_Loaded) return;
  			m_Loaded=true;
  			int newPosition;
  			for (int i=0;i<Columns.Count;i++)
  			{
  				newPosition=eLePhantForm.preferences.GetInt(Name+"ColumnPosition-"+i.ToString(),i);
  				this.SetColumnPosition(i,newPosition);
  			}
  		}
  		/// <summary>
  		/// Clean up any resources being used.
  		/// </summary>
  		protected override void Dispose( bool disposing )
  		{
  			if( disposing )
  			{
  				if(components != null)
  				{
  					components.Dispose();
  				}
  			}
  			base.Dispose( disposing );
  		}
  	    protected virtual void OnDrawItem(int item,int column,Graphics g,Rectangle rec)
  		{
  
  		}
  		#region Overriden methods
  		
  		protected override void OnResize(EventArgs e)
  		{
  			this.Invalidate();
  			base.OnResize (e);
  		}
  
  		protected override void OnHandleCreated(EventArgs e)
  		{
  			//Create a new HeaderControl object
  			header = new HeaderControl(this);
  			if(header.Handle != IntPtr.Zero)
  			{
  				if(headerImages != null)//If we have a valid header handle and a valid ImageList for it
  					//send a message HDM_SETIMAGELIST
  					Win32.SendMessage(header.Handle,0x1200+8,IntPtr.Zero,headerImages.Handle);
  				//Insert all the columns in Columns collection
  				if(this.Columns.Count > 0)
  					InsertColumns();				
  			}
  			base.OnHandleCreated(e);
  			SetFlatScrollBar();
  		}
  
  		protected override void WndProc(ref Message m)
  		{
  			Win32.NMHEADER nm;
  
  			switch(m.Msg)
  			{
  				
  				case 0x004E://WM_NOTIFY
  					base.WndProc(ref m);
  					Win32.NMHDR nmhdr = (Win32.NMHDR)m.GetLParam(typeof(Win32.NMHDR));
  					switch(nmhdr.code)
  					{
  						case (int)Win32.NM.NM_CLICK-320:
  							nm=(Win32.NMHEADER)m.GetLParam(typeof(Win32.NMHEADER));
  							if (ClickHeader!=null)
  							{
  								sortColumn=nm.iItem;
  								if (sortOrder==1) sortOrder=-1;
  											else sortOrder=1;
  								ClickHeader(this.Columns[nm.iItem], 
  									new HeaderEventArgs(nm.iItem, nm.iButton));
  								
  							}
  							break;
  						case (0-300-26)://HDN_BEGINTRACK
  							nm=(Win32.NMHEADER)m.GetLParam(typeof(Win32.NMHEADER));
  							if(BeginDragHeaderDivider != null)
  								BeginDragHeaderDivider(this.Columns[nm.iItem], 
  									new HeaderEventArgs(nm.iItem, nm.iButton));
  							break;
  						case (0-300-20)://HDN_ITEMCHANGING
  							nm=(Win32.NMHEADER)m.GetLParam(typeof(Win32.NMHEADER));
  							//Adjust the column width
  
gt: 							Win32.RECT rect = new Win32.RECT();