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

📄 crecttracker.cs

📁 采用重心法求坐标
💻 CS
📖 第 1 页 / 共 2 页
字号:
			SelectObject(hdc,hOldPen);
			DeleteObject(hPen);
			SetROP2(hdc,OldMode);
			gs.ReleaseHdc(hdc);
		}

		public virtual void DrawTrackerRect(Rectangle Rect, System.Windows.Forms.Control  ClipToFrm,Graphics gs,System.Windows.Forms.Control  Frm)
		{
			// first, normalize the rectangle for drawing
			Rectangle rect = Rect;
			NormalizeRect(ref rect);
			// convert to client coordinates
			if (ClipToFrm != null)
			{
				rect=Frm.RectangleToScreen(rect);
				rect=ClipToFrm.RectangleToClient(rect);
			}

			Size size=new Size(0, 0);
			if (!m_bFinalErase)
			{
				// otherwise, size depends on the style
				if ((m_nStyle & StyleFlags.hatchedBorder)!=0)
				{
					size.Width = size.Height = Math.Max(1, GetHandleSize(rect)-1);
					rect.Inflate(size);
				}
				else
				{
					size.Width = CX_BORDER;
					size.Height = CY_BORDER;
				}
			}

			if (m_bFinalErase || !m_bErase)
				DrawDragRect(gs,rect,m_rectLast);
			// remember last rectangles
			m_rectLast = rect;
			m_sizeLast = size;
		}

		public virtual void AdjustRect(int nHandle, ref Rectangle Rect)
		{
			if (nHandle ==(int)TrackerHit.hitMiddle)
				return;

			// convert the handle into locations within m_rect
			int px=-1, py=-1;
			int ix=-1,iy=-1;
			GetModifyPointers(nHandle,ref px, ref py,ref ix, ref iy,false);

			// enforce minimum width
			int []refRectAry=new int[4]{m_rect.Left,m_rect.Right,m_rect.Top,m_rect.Bottom};
			int nNewWidth = m_rect.Width;
			int nAbsWidth = m_bAllowInvert ? Math.Abs(nNewWidth) : nNewWidth;
			if (nAbsWidth < m_sizeMin.Width)
			{
				nNewWidth = nAbsWidth != 0 ? nNewWidth / nAbsWidth : 1;
				RECTINFO refrectinfo=RectInfo[px];
				px = refRectAry[(int)refrectinfo.nOffsetAcross] +
					nNewWidth * m_sizeMin.Width * -refrectinfo.nSignAcross;
			}

			// enforce minimum height
			int nNewHeight = m_rect.Height;
			int nAbsHeight = m_bAllowInvert ? Math.Abs(nNewHeight) : nNewHeight;
			if ((py != -1)&&(nAbsHeight < m_sizeMin.Height))
			{
				nNewHeight = nAbsHeight != 0 ? nNewHeight / nAbsHeight : 1;
				Debug.Assert(py<4);
				RECTINFO refrectinfo=RectInfo[py];
				py = refRectAry[(int)refrectinfo.nOffsetAcross] +
					nNewHeight * m_sizeMin.Width * -refrectinfo.nSignAcross;
			}
		}

		public void GetTrueRect(ref Rectangle TrueRect)
		{
			Rectangle rect = m_rect;
			NormalizeRect(ref rect);
			int nInflateBy = 0;
			if ((m_nStyle & (StyleFlags.resizeOutside|StyleFlags.hatchedBorder)) != 0)
				nInflateBy += GetHandleSize(new Rectangle(0,0,0,0)) - 1;
			if ((m_nStyle & (StyleFlags.solidLine|StyleFlags.dottedLine)) != 0)
				++nInflateBy;
			rect.Inflate(new Size(nInflateBy, nInflateBy));
			TrueRect = rect;
		}

		public virtual void OnChangedRect(Rectangle rectOld)
		{
		}

		protected void GetHandleRect(int nHandle, ref Rectangle Changerect)
		{
			System.Diagnostics.Debug.Assert(nHandle < 8);

			// get normalized rectangle of the tracker
			Rectangle rectT = m_rect;
			NormalizeRect(ref rectT);
			if ((m_nStyle & (StyleFlags.solidLine|StyleFlags.dottedLine)) != 0)
				rectT.Inflate(+1, +1);

			// since the rectangle itself was normalized, we also have to invert the
			//  resize handles.
			nHandle = NormalizeHit(nHandle);

			// handle case of resize handles outside the tracker
			int size = GetHandleSize(new Rectangle());
			if ((m_nStyle&StyleFlags.resizeOutside)!=0)
				rectT.Inflate(size-1, size-1);

			// calculate position of the resize handle
			int nWidth = rectT.Width;
			int nHeight = rectT.Height;
			Rectangle rect=new Rectangle();
			HANDLEINFO refHandleInfo = HandleInfo[nHandle];
			int []refRectAry=new int[4]{rectT.Left,rectT.Right,rectT.Top,rectT.Bottom};

			rect.X = refRectAry[(int)refHandleInfo.nOffsetX];
			rect.Y =	refRectAry[(int)refHandleInfo.nOffsetY];
			rect.X += size * refHandleInfo.nHandleX;
			rect.Y += size * refHandleInfo.nHandleY;
			rect.X += refHandleInfo.nCenterX * (nWidth - size) / 2;
			rect.Y += refHandleInfo.nCenterY * (nHeight - size) / 2;
			rect.Width = size;
			rect.Height = size;

			Changerect = rect;
		}

		protected virtual int GetHandleSize(Rectangle rect)
		{
			if (rect.IsEmpty)
				rect = m_rect;

			int size = m_nHandleSize;
			if ((m_nStyle & StyleFlags.resizeOutside)==0)
			{
				// make sure size is small enough for the size of the rect
				int sizeMax = Math.Min(Math.Abs(rect.Right - rect.Left),Math.Abs(rect.Bottom - rect.Top));
				if (size * 2 > sizeMax)
					size = sizeMax / 2;
			}
			return size;
		}

		protected TrackerHit HitTestHandles(Point point)
		{
			Rectangle Truerect=new Rectangle(0,0,0,0);
			uint mask = GetHandleMask();

			// see if hit anywhere inside the tracker
			GetTrueRect(ref Truerect);
			if (!Truerect.Contains(point))
				return TrackerHit.hitNothing;  // totally missed

			// see if we hit a handle
			for (int i = 0; i < 8; ++i)
			{
				if((mask&(1<<i))!=0)
				{
					GetHandleRect(i, ref Truerect);
					if (Truerect.Contains(point))
						return (TrackerHit)i;
				}
			}

			// last of all, check for non-hit outside of object, between resize handles
			if ((m_nStyle & StyleFlags.hatchedBorder) == 0)
			{
				Rectangle rect = m_rect;
				NormalizeRect(ref rect);
				if ((m_nStyle & (StyleFlags.dottedLine|StyleFlags.solidLine)) != 0)
					rect.Inflate(+1, +1);
				if (!rect.Contains(point))
					return TrackerHit.hitNothing;  // must have been between resize handles
			}
			return TrackerHit.hitMiddle;   // no handle hit, but hit object (or object border)
		}
		protected bool TrackHandle(int nHandle,System.Windows.Forms.Control frm,Point point,System.Windows.Forms.Control frmClipTo)
		{
			Debug.Assert(nHandle >= 0);
			Debug.Assert(nHandle <= 8);   // handle 8 is inside the rect

			// don't handle if capture already set
			//if(frm.Capture) return false;

			Debug.Assert(!m_bFinalErase);

			// save original width & height in pixels
			int nWidth = m_rect.Width;
			int nHeight = m_rect.Height;

			// set capture to the window which received this message
			frm.Capture=true;
			Debug.Assert(frm.Capture);
			frm.Update();
			if (frmClipTo!=null)
				frmClipTo.Update();
			Rectangle rectSave = m_rect;

			// find out what x/y coords we are supposed to modify
			int px=0, py=0;
			int xDiff=0, yDiff=0;
			GetModifyPointers(nHandle,ref px,ref py,ref xDiff,ref yDiff,true);
			xDiff = point.X - xDiff;
			yDiff = point.Y - yDiff;

			// get DC for drawing
			Graphics gs;
			if (frmClipTo!=null)
			{
				// clip to arbitrary window by using adjusted Window DC
				gs=frmClipTo.CreateGraphics();
			}
			else
			{
				// otherwise, just use normal DC
				gs=frm.CreateGraphics();
			}

			Rectangle rectOld;
			bool bMoved = false;

			// get messages until capture lost or cancelled/accepted
			for (;;)
			{
				MSG msg=new MSG();
				if(GetMessage(ref msg, 0, 0, 0)!=1) break;
				if(!frm.Capture) break;

				switch (msg.message)
				{
						// handle movement/accept messages
					case WM_LBUTTONUP:
						goto case WM_MOUSEMOVE;
					case WM_MOUSEMOVE:
						rectOld = m_rect;
						// handle resize cases (and part of move)
						if (px != -1)
						{
							int []refRectAry=new int[4]{m_rect.Left,m_rect.Right,m_rect.Top,m_rect.Bottom};
							int x=msg.lParam&0x0000ffff;
							refRectAry[px]=x-xDiff;
							m_rect=new Rectangle(refRectAry[0],refRectAry[2],refRectAry[1]-refRectAry[0],refRectAry[3]-refRectAry[2]);
						}
						if (py != -1)
						{
							int []refRectAry=new int[4]{m_rect.Left,m_rect.Right,m_rect.Top,m_rect.Bottom};
							int y=msg.lParam>>16;
							refRectAry[py]=y-yDiff;
							m_rect=new Rectangle(refRectAry[0],refRectAry[2],refRectAry[1]-refRectAry[0],refRectAry[3]-refRectAry[2]);
						}

						// handle move case
						if (nHandle == (int)TrackerHit.hitMiddle)
						{
							m_rect.Width=nWidth;
							m_rect.Height=nHeight;
						}
						// allow caller to adjust the rectangle if necessary
						AdjustRect(nHandle,ref m_rect);

						// only redraw and callback if the rect actually changed!
						m_bFinalErase = (msg.message == WM_LBUTTONUP);
						if (m_bFinalErase)
							goto ExitLoop;

						if (!rectOld.Equals(m_rect) || m_bFinalErase)
						{
							if (bMoved)
							{
								m_bErase = true;
								DrawTrackerRect(rectOld, frmClipTo, gs, frm);
							}
							OnChangedRect(rectOld);
							if (msg.message != WM_LBUTTONUP)
								bMoved = true;
						}
						if (m_bFinalErase)
							goto ExitLoop;

						if (!rectOld.Equals(m_rect))
						{
							m_bErase = false;
							DrawTrackerRect(m_rect, frmClipTo, gs, frm);
						}
						break;

						// handle cancel messages
					case WM_KEYDOWN:
						if (msg.wParam != 0x1B)//VK_ESCAPE
							break;
						goto default;
					case WM_RBUTTONDOWN:
						if (bMoved)
						{
							m_bErase = m_bFinalErase = true;
							DrawTrackerRect(m_rect, frmClipTo, gs, frm);
						}
						m_rect = rectSave;
						goto ExitLoop;

						// just dispatch rest of the messages
					default:
						DispatchMessage(ref msg);
						break;
				}
			}

			ExitLoop:
				gs.Dispose();
			frm.Capture=false;
			// restore rect in case bMoved is still FALSE
			if (!bMoved)
				m_rect = rectSave;
			m_bFinalErase = false;
			m_bErase = false;

			// return TRUE only if rect has changed
			return !rectSave.Equals(m_rect);
		}

		protected void GetModifyPointers(int nHandle,ref int ppx,ref int ppy,ref int px,ref int py,bool bModify)
		{
			Debug.Assert(nHandle >= 0);
			Debug.Assert(nHandle <= 8);

			if (nHandle ==(int)TrackerHit.hitMiddle)
				nHandle = (int)TrackerHit.hitTopLeft;   // same as hitting top-left

			ppx = -1;
			ppy = -1;

			// fill in the part of the rect that this handle modifies
			//  (Note: handles that map to themselves along a given axis when that
			//   axis is inverted don't modify the value on that axis)

			HANDLEINFO refHandleInfo = HandleInfo[nHandle];
			int []refRectAry=new int[4]{m_rect.Left,m_rect.Right,m_rect.Top,m_rect.Bottom};

			if (refHandleInfo.nInvertX != nHandle)
			{
				ppx=(int)refHandleInfo.nOffsetX;
				if (bModify)
					px = refRectAry[ppx];
			}
			else
			{
				// middle handle on X axis
				if (bModify)
					px = m_rect.Left + Math.Abs(m_rect.Width) / 2;
			}
			if (refHandleInfo.nInvertY != nHandle)
			{
				ppy=(int)refHandleInfo.nOffsetY;
				if (bModify)
					py = refRectAry[ppy];
			}
			else
			{
				// middle handle on Y axis
				if (bModify)
					py = m_rect.Top + Math.Abs(m_rect.Height) / 2;
			}
		}

		protected virtual uint GetHandleMask()
		{
			uint mask = 0x0F;   // always have 4 corner handles
			int size = m_nHandleSize*3;
			if (Math.Abs(m_rect.Width) - size > 4)
				mask |= 0x50;
			if (Math.Abs(m_rect.Height) - size > 4)
				mask |= 0xA0;
			return mask;
		}


		public void NormalizeRect(ref Rectangle rect)
		{
			Rectangle refrect=rect;
			if(rect.Width<0)
			{
				rect.X=refrect.Right;
				rect.Width=-rect.Width;
			}
			if(rect.Height<0)
			{
				rect.Y=rect.Bottom;
				rect.Height=-rect.Height;
			}
		}

	}
}

⌨️ 快捷键说明

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