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

📄 crecttracker.cs

📁 采用重心法求坐标
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Runtime.InteropServices; 
using System.Drawing.Drawing2D;

namespace zuobiao
{
	/// <summary>
	/// CRectTracker 的摘要说明。
	/// </summary>
	/// <summary>
	/// CRectTracker主要是绘制橡皮线的一个类
	/// </summary>
	public class CRectTracker : System.Object
	{
		private static Cursor []Cursors =new Cursor[10];
		private static HatchBrush HatchBrush = null;
		private static Pen BlackDottedPen = null;
		private static int HandleSize = 4;
		private static Pen DotedPen=null;

		#region "API Calls"
		struct POINTAPI
		{
			public Int32 x;
			public Int32 y;
		};
		struct MSG
		{
			public Int32 hwnd;
			public Int32 message;
			public Int32 wParam;
			public Int32 lParam;
			public Int32 time;
			public POINTAPI pt;
		};
		[DllImport("user32.dll", SetLastError=true )]
		private static extern Int32 GetMessage (ref MSG lpMsg,Int32 hwnd,Int32 wMsgFilterMin,Int32 wMsgFilterMax);

		[DllImport("user32.dll", SetLastError=true )]
		private static extern Int32 DispatchMessage (ref MSG lpMsg);

		[DllImport("user32.dll", SetLastError=true )]
		private static extern Int32 TranslateMessage (ref MSG lpMsg);

		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern drawingMode SetROP2(IntPtr hdc,drawingMode fnDrawMode); 

		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern backMode SetBkMode(IntPtr hdc,backMode fnBKMode); 
		public enum drawingMode
		{
			R2_BLACK=            1  ,
			R2_NOTMERGEPEN=      2  , 
			R2_MASKNOTPEN=       3  , 
			R2_NOTCOPYPEN=       4  , 
			R2_MASKPENNOT=       5  , 
			R2_NOT=              6  , 
			R2_XORPEN=           7  , 
			R2_NOTMASKPEN=       8  , 
			R2_MASKPEN=          9  , 
			R2_NOTXORPEN=        10 , 
			R2_NOP=              11 , 
			R2_MERGENOTPEN=      12 , 
			R2_COPYPEN=          13 , 
			R2_MERGEPENNOT=      14 , 
			R2_MERGEPEN=         15 , 
			R2_WHITE=            16 , 
			R2_LAST=             16
		}; 
		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern bool MoveToEx(IntPtr hDC,int x,int y,POINTAPI lpPoint);

		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern bool LineTo(IntPtr hDC,int x,int y); 

		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern IntPtr CreatePen(int nPenStyle,int nWidth,int crColor);

		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern IntPtr SelectObject(IntPtr hDC,IntPtr hObject);

		[DllImport("gdi32.dll", SetLastError=true )]
		private static extern bool DeleteObject(IntPtr hObject);

		private const int CX_BORDER=1;
		private const int CY_BORDER=1;
		private const int WM_MOUSEFIRST    = 0x0200;
		private const int WM_MOUSEMOVE     = 0x0200;
		private const int WM_LBUTTONDOWN   = 0x0201;
		private const int WM_LBUTTONUP     = 0x0202;
		private const int WM_LBUTTONDBLCLK = 0x0203;
		private const int WM_RBUTTONDOWN   = 0x0204;
		private const int WM_RBUTTONUP     = 0x0205;
		private const int WM_RBUTTONDBLCLK = 0x0206;
		private const int WM_MBUTTONDOWN   = 0x0207;
		private const int WM_MBUTTONUP     = 0x0208;
		private const int WM_MBUTTONDBLCLK = 0x0209;
		private const int WM_KEYDOWN = 0x100; 
		private const int WM_KEYUP = 0x101; 

		#endregion


		// Style Flags
		public enum StyleFlags
		{
			solidLine = 1, dottedLine = 2, hatchedBorder = 4,
			resizeInside = 8, resizeOutside = 16, hatchInside = 32,
		};

		// Hit-Test codes
		public enum TrackerHit
		{
			hitNothing = -1,
			hitTopLeft = 0, hitTopRight = 1, hitBottomRight = 2, hitBottomLeft = 3,
			hitTop = 4, hitRight = 5, hitBottom = 6, hitLeft = 7, hitMiddle = 8
		};
		public enum backMode
		{
			TRANSPARENT=		 1,
			OPAQUE=				 2
		};
		public	enum rectPos
		{
			Left	=0,
			Right,
			Top,
			Bottom
		};
		struct HANDLEINFO
		{
			public HANDLEINFO(rectPos X,rectPos Y,int CX,int CY,int HX,int HY,int IX,int IY)
			{
				nOffsetX=X;
				nOffsetY=Y;
				nCenterX=CX;
				nCenterY=CY;
				nHandleX=HX;
				nHandleY=HY;
				nInvertX=IX;
				nInvertY=IY;
			}
			public rectPos nOffsetX;	    // offset within RECT for X coordinate
			public rectPos nOffsetY;		// offset within RECT for Y coordinate
			public int nCenterX;       // adjust X by Width()/2 * this number
			public int nCenterY;       // adjust Y by Height()/2 * this number
			public int nHandleX;       // adjust X by handle size * this number
			public int nHandleY;       // adjust Y by handle size * this number
			public int nInvertX;       // handle converts to this when X inverted
			public int nInvertY;       // handle converts to this when Y inverted
		};
		struct RECTINFO
		{
			public RECTINFO(rectPos offset,int nsign)
			{
				nOffsetAcross=offset;
				nSignAcross=nsign;
			}
			public rectPos nOffsetAcross; // offset of opposite point (ie. left->right)
			public int nSignAcross;        // sign relative to that point (ie. add/subtract)
		}

		static HANDLEINFO [] HandleInfo=new HANDLEINFO[]{
															// corner handles (top-left, top-right, bottom-right, bottom-left
															new HANDLEINFO(rectPos.Left, rectPos.Top,0, 0,  0,  0, 1, 3 ),
															new HANDLEINFO(rectPos.Right,rectPos.Top,0, 0, -1,  0, 0, 2),
															new HANDLEINFO(rectPos.Right,rectPos.Bottom,0, 0, -1, -1, 3, 1),
															new HANDLEINFO(rectPos.Left, rectPos.Bottom, 0, 0,  0, -1, 2, 0 ),
															// side handles (top, right, bottom, left)
															new HANDLEINFO(rectPos.Left, rectPos.Top,1, 0,  0,  0, 4, 6),
															new HANDLEINFO(rectPos.Right,rectPos.Top,0, 1, -1,  0, 7, 5),
															new HANDLEINFO(rectPos.Left, rectPos.Bottom, 1, 0,  0, -1, 6, 4 ),
															new HANDLEINFO(rectPos.Left, rectPos.Top,0, 1,  0,  0, 5, 7)
														};
		static RECTINFO [] RectInfo=new RECTINFO[]{
													  new RECTINFO(rectPos.Right, +1),
													  new RECTINFO(rectPos.Bottom, +1),
													  new RECTINFO(rectPos.Left,-1),
													  new RECTINFO(rectPos.Top, -1 )
												  };
		// Attributes
		public StyleFlags m_nStyle;      // current state
		public Rectangle m_rect;       // current position (always in pixels)
		public Size m_sizeMin;    // minimum X and Y size during track operation
		public int m_nHandleSize=0;  // size of resize handles (default from WIN.INI)
		protected bool m_bAllowInvert=false;    // flag passed to Track or TrackRubberBand
		protected Rectangle m_rectLast;
		protected Size m_sizeLast;
		protected bool m_bErase=false;          // TRUE if DrawTrackerRect is called for erasing
		protected bool m_bFinalErase=false;     // TRUE if DragTrackerRect called for final erase
		protected static bool bInitialized=false;

		public CRectTracker()
		{
			Construct();
		}
		public CRectTracker(Rectangle rect, StyleFlags nStyle)
		{
			Construct();
			m_rect=rect;
			m_nStyle = nStyle;
		}
		protected void Construct()
		{	
			if(false==bInitialized)
			{
				// initialize the cursor array
				Cursors[0] = System.Windows.Forms.Cursors.SizeNWSE;
				Cursors[1] = System.Windows.Forms.Cursors.SizeNESW;
				Cursors[2] = Cursors[0];
				Cursors[3] = Cursors[1];
				Cursors[4] = System.Windows.Forms.Cursors.SizeNS;
				Cursors[5] = System.Windows.Forms.Cursors.SizeWE;
				Cursors[6] = Cursors[4];
				Cursors[7] = Cursors[5];
				Cursors[8] = System.Windows.Forms.Cursors.SizeAll;
				Cursors[9] = System.Windows.Forms.Cursors.PanSW;
				bInitialized = true;
				BlackDottedPen=new Pen(System.Drawing.Color.Red,1);
				HatchBrush=new HatchBrush(HatchStyle.BackwardDiagonal,Color.Red,Color.FromArgb(0));
				DotedPen=new Pen(Color.Red ,1);
				DotedPen.DashStyle=DashStyle.Dot;
			}
			m_nStyle = 0;
			m_nHandleSize = HandleSize;
			m_sizeMin.Height = m_sizeMin.Width = m_nHandleSize*2;

			m_rectLast=new Rectangle(0,0,0,0);
			m_sizeLast.Width = m_sizeLast.Height = 0;
			m_bErase = false;
			m_bFinalErase =  false;
		}

		// Operations
		public void OnDraw(Graphics gs)
		{
			System.Drawing.Drawing2D.GraphicsState OldState=gs.Save();
			
			IntPtr hdc = new IntPtr();
			// get normalized rectangle
			Rectangle rect = m_rect;
			NormalizeRect(ref rect);
			// draw lines
			if ((m_nStyle & (StyleFlags.dottedLine|StyleFlags.solidLine)) != 0)
			{
				if((m_nStyle&StyleFlags.dottedLine)!=0)
					BlackDottedPen.DashStyle=DashStyle.Dot;
				else
					BlackDottedPen.DashStyle=DashStyle.Solid;
				rect.Inflate(new Size(+1, +1));   // borders are one pixel outside
				gs.DrawRectangle(BlackDottedPen,rect);
			}

			
			// hatch inside
			if ((m_nStyle & StyleFlags.hatchInside) != 0)
			{
				gs.FillRectangle(HatchBrush,rect.Left+1, rect.Top+1, rect.Width-1, rect.Height-1);
			}

			// draw hatched border
			if ((m_nStyle & StyleFlags.hatchedBorder) != 0)
			{
				Rectangle rectTrue=new Rectangle(0,0,0,0);
				GetTrueRect(ref rectTrue);
				gs.FillRectangle(HatchBrush,rectTrue.Left, rectTrue.Top, rectTrue.Width,rect.Top-rectTrue.Top);
				gs.FillRectangle(HatchBrush,rectTrue.Left, rect.Bottom,rectTrue.Width,rectTrue.Bottom-rect.Bottom);
				gs.FillRectangle(HatchBrush,rectTrue.Left, rect.Top, rect.Left-rectTrue.Left,rect.Height);
				gs.FillRectangle(HatchBrush,rect.Right, rect.Top, rectTrue.Right-rect.Right,rect.Height);
			}

			// draw resize handles
			if ((m_nStyle & (StyleFlags.resizeInside|StyleFlags.resizeOutside)) != 0)
			{
				uint mask = GetHandleMask();
				for (int i = 0; i < 8; ++i)
				{
					if ((mask&(1<<i))!=0)
					{
						GetHandleRect(i, ref rect);
						SolidBrush bursh=new SolidBrush(Color.YellowGreen);
						gs.FillRectangle(bursh,rect);
					}
				}
			}
			gs.Restore(OldState);
		}
		public bool SetCursor(System.Windows.Forms.Control  frm, uint nHitTest,Point MousePoint) 
		{
			// trackers should only be in client area
			frm.PointToClient(MousePoint);
			if (!frm.ClientRectangle.Contains(MousePoint))
				return false;

			// convert cursor position to client co-ordinates
			// do hittest and normalize hit
			int nHandle = (int)HitTestHandles(MousePoint);
			if (nHandle < 0)
				return false;

			// need to normalize the hittest such that we get proper cursors
			nHandle = NormalizeHit(nHandle);

			// handle special case of hitting area between handles
			//  (logically the same -- handled as a move -- but different cursor)
			if (nHandle == (int)TrackerHit.hitMiddle && !m_rect.Contains(MousePoint))
			{
				// only for trackers with hatchedBorder (ie. in-place resizing)
				if ((m_nStyle & StyleFlags.hatchedBorder)!=0)
					nHandle = 9;
			}

			Debug.Assert(nHandle < 10);
			frm.Cursor=Cursors[nHandle];
			return true;
		}
		public TrackerHit HitTest(Point point) 
		{
			TrackerHit hitResult = TrackerHit.hitNothing;

			Rectangle rectTrue=new Rectangle();
			GetTrueRect(ref rectTrue);
			Debug.Assert(rectTrue.Left <= rectTrue.Right);
			Debug.Assert(rectTrue.Top <= rectTrue.Bottom);
			if (rectTrue.Contains(point))
			{
				if ((m_nStyle & (StyleFlags.resizeInside|StyleFlags.resizeOutside)) != 0)
					hitResult = HitTestHandles(point);
				else
					hitResult = TrackerHit.hitMiddle;
			}
			return hitResult;
		}
		protected int NormalizeHit(int nHandle) 
		{
			Debug.Assert(nHandle <= 8 && nHandle >= -1);
			if (nHandle == (int)TrackerHit.hitMiddle || nHandle ==(int)TrackerHit.hitNothing)
				return nHandle;

			HANDLEINFO refHandleInfo = HandleInfo[nHandle];
			if (m_rect.Width< 0)
			{
				nHandle = refHandleInfo.nInvertX;
				refHandleInfo = HandleInfo[nHandle];
			}
			if (m_rect.Height< 0)
				nHandle = refHandleInfo.nInvertY;
			return nHandle;
		}
		public bool Track(System.Windows.Forms.Control  frm, Point point, bool bAllowInvert,Form frmClipTo)
		{
			// perform hit testing on the handles
			int nHandle = (int)HitTestHandles(point);
			if (nHandle < 0)
			{
				// didn't hit a handle, so just return FALSE
				return false;
			}

			// otherwise, call helper function to do the tracking
			m_bAllowInvert = bAllowInvert;
			return TrackHandle(nHandle, frm, point, frmClipTo);
		}
		public bool TrackRubberBand(System.Windows.Forms.Control  frm, Point point, bool bAllowInvert)
		{
			// simply call helper function to track from bottom right handle
			m_bAllowInvert = bAllowInvert;
			m_rect=new Rectangle(point.X, point.Y,0, 0);
			return TrackHandle((int)TrackerHit.hitBottomRight, frm, point, null);
		}
		// Overridables
		private void DrawDragRect(Graphics gs,Rectangle rect,Rectangle rectLast)
		{
			IntPtr hdc=new IntPtr();
			IntPtr hPen=new IntPtr();
			IntPtr hOldPen=new IntPtr();
			POINTAPI ptsOld = new POINTAPI();
			hdc=gs.GetHdc();
			drawingMode OldMode=SetROP2(hdc,drawingMode.R2_NOTXORPEN);
			hPen=CreatePen(2,1,0x0);
			hOldPen=SelectObject(hdc,hPen);
			if(!rectLast.IsEmpty)
			{
				MoveToEx(hdc, rectLast.Left, rectLast.Top, ptsOld);
				LineTo(hdc,	  rectLast.Right,rectLast.Top);
				LineTo(hdc,	  rectLast.Right,rectLast.Bottom);
				LineTo(hdc,	  rectLast.Left,rectLast.Bottom);
				LineTo(hdc,	  rectLast.Left,rectLast.Top);
			}
			MoveToEx(hdc, rect.Left, rect.Top, ptsOld);
			LineTo(hdc,	  rect.Right,rect.Top);
			LineTo(hdc,	  rect.Right,rect.Bottom);
			LineTo(hdc,	  rect.Left,rect.Bottom);
			LineTo(hdc,	  rect.Left,rect.Top);

⌨️ 快捷键说明

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