写个截图程序之 区域绘制
闲的无聊就写了个截图程序。
基本思路
做一个主界面,然后在主界面上绘制一个矩形,把矩形里填上底图,看上去是截了个图出来。最后把矩形位置的图片保存到剪贴板或者是保存到路径。其实这里最主要的地方就是在界面上怎么来绘制一个矩形,然后是截图快捷键的问题(Hook),这里先写个怎么在界面上绘制一个矩形。矩形的构成如下图:
矩形的位置由两个顶点决定,矩形在的方位有10个位置,当在9的位置时,是移动矩形,在10的位置时绘制新的矩形,在其他8个位置时,根据不同点点或边改变矩形的大小。
这里用一个枚举来表示矩形的位置
public enum MouseSize { None=0, UpLeft, UpCentre, UpRight, CentreRight, DownRight, DownCentre, DownLeft, CentreLeft, Centre }
1.重绘矩形
当矩形的形状或位置改变的时候,需要重绘矩形。这里利用OnPaint函数来重绘矩形
protected override void OnPaint(PaintEventArgs e) { try { e.Graphics.DrawRectangle(new Pen(Color.Black, 4), recttangle);//绘制矩形 e.Graphics.DrawImage(CatSize(), recttangle.Location);//给矩形填充图片 CatSize是返回了recttangle区域的图片 } catch { } }当矩形改变的时候,需要通知函数重新绘制界面,这里只需要喲功能到
this.Invalidate();
就能够实现通知界面重绘了
2.改变矩形
在改变矩形的时候,首先固定了一个点,然后另一个点跟着鼠标改变,这里我们可以得到固定点P1(x1,y1),和跟着鼠标改变的点P2(x2,y2),这个时候固定点个鼠标点会有很多中状况。
这里我们不管鼠标和固定点的位置是怎么样的我们都把他们的位置转换成红色区域的位置情况:顶点O的x,y始终是小于点P的x,y
/// <summary> /// 修正两个点的位置转换成左上右下型 /// </summary> /// <param name="a"></param> /// <param name="b"></param> private void SetMousePoint(ref Point a,ref Point b) { int width = a.X - b.X; int height = a.Y - b.Y; Point start = new Point(width <= 0 ? a.X : b.X, height <= 0 ? a.Y : b.Y); Point End = new Point(width >= 0 ? a.X : b.X, height >= 0 ? a.Y : b.Y); a = start; b = End; }
这样我们就不用管鼠标的位置了,不管鼠标在哪里我们都转换成左上右下型。
3鼠标的位置
在绘制的过程中需要考虑鼠标的位置。在这里在这个以顶点为中心 ,长为10个像素的正方形为鼠标变化的位置。这样就可以根据位置来改变鼠标的形状
首先我们需要判断点是否在区域内:
/// <summary> /// 判断点point在a,b构成的区域之内,还是之外 /// </summary> /// <param name="a">顶点</param> /// <param name="b">底点</param> /// <param name="point"></param> /// <returns></returns> private bool GetPintSize(Point a, Point b, Point point) { if (point.X > a.X && point.X < b.X && point.Y > a.Y && point.Y < b.Y) { return true; } else { return false; } }
我们需要一个返回鼠标位置的函数,并且在指定的鼠标位置上,鼠标指针的形状跟着改变
/// <summary> /// 判断鼠标所在的位置 设置鼠标的形状 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="e"></param> /// <returns>鼠标鼠标的位置</returns> private MouseSize GetPosition(Point a, Point b,MouseEventArgs e) { //鼠标所在的位置有10个方位 对应的10个方位 SetMousePoint(ref a, ref b); //左上 if (GetPintSize (new Point (a.X -5,a.Y -5),new Point (a.X +5,a.Y +5),e.Location)) { this.Cursor =Cursors.SizeNWSE; return MouseSize .UpLeft; } //上中 if (GetPintSize(new Point(a.X + 5, a.Y - 5), new Point(b.X -5, a.Y + 5), e.Location)) { this.Cursor =Cursors.SizeNS; return MouseSize.UpCentre ; } //上右 if (GetPintSize(new Point(b.X -5, a.Y - 5), new Point(b.X+ 5, a.Y + 5), e.Location)) { this.Cursor =Cursors.SizeNESW; return MouseSize .UpRight; } //右中 if (GetPintSize(new Point(b.X - 5, a.Y + 5), new Point(b.X + 5, b.Y - 5), e.Location)) { this.Cursor =Cursors.SizeWE; return MouseSize .CentreRight; } //右下 if (GetPintSize(new Point(b.X - 5, b.Y - 5), new Point(b.X + 5, b.Y +5), e.Location)) { this.Cursor =Cursors.SizeNWSE; return MouseSize .DownRight; } //下中 if (GetPintSize(new Point(a.X + 5, b.Y - 5), new Point(b.X - 5, b.Y + 5), e.Location)) { this.Cursor =Cursors.SizeNS ; return MouseSize .DownCentre; } //下左 if (GetPintSize(new Point(a.X - 5, b.Y-5), new Point(a.X + 5, b.Y +5), e.Location)) { this.Cursor =Cursors.SizeNESW; return MouseSize .DownLeft; } //中左 if (GetPintSize(new Point(a.X - 5, a.Y + 5), new Point(a.X + 5, b.Y - 5), e.Location)) { this.Cursor =Cursors.SizeWE; return MouseSize .CentreLeft; } //中心 if (GetPintSize(new Point(a.X + 5, a.Y + 5), new Point(b.X - 5, b.Y - 5), e.Location)) { this.Cursor =Cursors.SizeAll; return MouseSize .Centre; } else { this.Cursor =Cursors.Default ; return MouseSize .None ; } }
4 开始绘制
用两个点表示上面我们所说的固定点和运动的点,用一个变量来表示绘制的状态。
Point MouseLeftDown=new Point (0,0);//固定点 Point MouseLeftUp=new Point (0,0);//移动点 bool mouseClick = false; //当前是否是处于绘制状态
除了在中心区域表示移动意外,其他的区域都只要重绘的,只是绘制的方式不一样。当鼠标在顶点时,固定点为它的对角的那个点。当鼠标在上边或下边的时候,鼠标改变的只有鼠标坐在的Y的值。当在左右边的时候只改变鼠标的X的值。
if (e.Button == MouseButtons.Left && mouseClick)// { GetPosition(recttangle.Location, new Point(recttangle.Location.X + recttangle.Width, recttangle.Location.Y + recttangle.Height), e); switch (mouseSize) { case MouseSize .UpLeft: case MouseSize .UpRight: case MouseSize .DownLeft: case MouseSize .DownRight: MouseLeftUp = e.Location; break; case MouseSize .CentreLeft: MouseLeftUp = new Point(e.Location.X, MouseLeftDown.Y - recttangle.Height); break; case MouseSize .CentreRight: MouseLeftUp =new Point(e.Location.X, MouseLeftDown .Y +recttangle .Height); break; case MouseSize .DownCentre: MouseLeftUp =new Point(MouseLeftDown.X+recttangle .Width, e.Location.Y); break; case MouseSize .UpCentre: MouseLeftUp = new Point(MouseLeftDown .Y+recttangle .Height , e.Location.Y); break; default : MouseLeftUp = e.Location; break; } GetRecttangleSize(MouseLeftUp, MouseLeftDown,e); this.Invalidate();//指定的区域无效重新绘制 return; }
上面是在绘制状态的时候,当鼠标在非绘制状态的时候,只有在中心的时候是移动,而在其他位置的时候都是进入绘制状态,当然在不同的位置进入绘制的时候,固定的那个点就确定了。
if (e.Button == MouseButtons.Left && !mouseClick) { //框架位置 Point start = recttangle.Location; Point end = new Point(recttangle.X + recttangle.Width, recttangle.Y + recttangle.Height); switch (mouseSize) { case MouseSize .Centre : //移动位置 Point p = recttangle.Location; p.Offset(e.X - MouseLeftDown.X, e.Y - MouseLeftDown.Y); recttangle.Location = p; MouseLeftDown = e.Location; FormMove(); break; //四个顶点的变动 设置两个变动 case MouseSize .UpLeft: MouseLeftDown = end; mouseClick = true; break; case MouseSize .UpRight: MouseLeftDown = new Point(start.X, end.Y); mouseClick = true; break; case MouseSize .DownRight: MouseLeftDown = start; mouseClick = true; break; case MouseSize .DownLeft: MouseLeftDown = new Point(end.X, start.Y); mouseClick = true; break; //左右变动 case MouseSize .UpCentre: MouseLeftDown = end; mouseClick = true; break; case MouseSize.DownCentre: MouseLeftDown = start; mouseClick = true; break; case MouseSize .CentreLeft: MouseLeftDown = end; mouseClick = true; break; case MouseSize .CentreRight: MouseLeftDown = start; mouseClick = true; break; } }
到这里截图的绘制程序就完成了。接下来我们只需要把指定区域的图片拷到剪贴板,或者是指定路径就行了。
看一下界面
截个LOGO试试:
最后的话
这个截图程序虽然简单,但是弄了两天,也走了点弯路,最开始用了一个图片控件,来改变它的位置,非常不好控制,而且图片和主界面的位置也不好确定。
第二点就是鼠标绘制的情况,比如把固定点和动点转换成左上右下型了在操作。
第三点,编辑的状态没有确定好,当第一次绘制时,由鼠标确定一个定点,然后移动鼠标作为动点绘制一个矩形。后面在不同的位置改变矩形的大小这里,最开始总是想着在不同的位置怎么改变,总在想当位置边界重合的时候怎么改变,其实也只在重写绘制。只是绘制的方式不同,移动的点位置不同。 归到绘制的情况中就行了。
接下来该设置截图快捷键了…………(未完待续)代码等快捷键弄完了在放出来
下一篇 截图程序之 快捷键