C#编写图像裁剪控件

话不多说 先看看效果吧


好吧 你想说这是截图?好吧其实就是、、- -!我本来就打算做重写我的截图程序只是还在做控件期间 就顺带的把 这个控件发上来了

这里 就当截图程序来说吧 反正把控件放大全屏化也就是截图了、、看到很多人问 截图的时候 怎么让周围暗下来、、

protected override void OnPaint(PaintEventArgs e) {
    Graphics g = e.Graphics;
    if (this._Image != null) {
        g.DrawImage(this._Image, Point.Empty);//原图
        using (SolidBrush sb = new SolidBrush(this._MaskColor)) {
            g.FillRectangle(sb, this.ClientRectangle);//遮罩
        }
        if (!this._SelectedRectangle.IsEmpty)
            this.DrawSelectedRectangle(g);//选框
        if (this._IsDrawMagnifier && m_bMouseHover && !_IsDrawed && !m_bMoving)
            this.DrawMagnifier(g, m_ptCurrent);//放大镜
    }
    base.OnPaint(e);
}
上面是我OnPaint里面的代码 一个四个大的阶段 首先低下绘制原图 然后绘制一层遮罩(其实原图和遮罩何以混合成一张图这样就只绘制一次了) 如果有选择区域那么绘制选框(- -!在绘制选框的代码里有再次绘制一份选区大小的原图 这样就能看到明暗变化了) 然后就是放大镜的问题

接下来问题是 如何制作这个裁剪控件 首先不说业务问题 就绘制做一个样子而言 你得有八个顶点

private Rectangle[] m_rectDots = new Rectangle[8];  //八个控制点
//初始化顶点
for (int i = 0; i < 8; i++) {
    m_rectDots[i].Size = new Size(5, 5);
}
//绘制选框
protected virtual void DrawSelectedRectangle(Graphics g) {
    m_rectDots[0].Y = m_rectDots[1].Y = m_rectDots[2].Y 
        = this._SelectedRectangle.Y - 2;
    m_rectDots[5].Y = m_rectDots[6].Y = m_rectDots[7].Y 
        = this._SelectedRectangle.Bottom - 2;
    m_rectDots[0].X = m_rectDots[3].X = m_rectDots[5].X 
        = this._SelectedRectangle.X - 2;
    m_rectDots[2].X = m_rectDots[4].X = m_rectDots[7].X 
        = this._SelectedRectangle.Right - 2;
    m_rectDots[3].Y = m_rectDots[4].Y 
        = this._SelectedRectangle.Y + this._SelectedRectangle.Height / 2 - 2;
    m_rectDots[1].X  = m_rectDots[6].X 
        = this._SelectedRectangle.X + this._SelectedRectangle.Width / 2 - 2;

    g.DrawImage(this._Image, this._SelectedRectangle, 
        this._SelectedRectangle, GraphicsUnit.Pixel);
    g.DrawRectangle(Pens.Cyan, 
        this._SelectedRectangle.Left, this._SelectedRectangle.Top,
        this._SelectedRectangle.Width - 1, this._SelectedRectangle.Height - 1);
    foreach (Rectangle rect in m_rectDots)
        g.FillRectangle(Brushes.Yellow, rect);
}
这里 八个顶点就有了 而且可以看到 这个方法在我的OnPaint里面有调用 然后要操作这些点 来拖动区域或者改变大小什么的 就需要控件的一些鼠标事件了 比如MouseDown事件 如果初次点下 那么你需要记录下这个点ptStart然后在MouseMove中就可以进行绘制了 因为有ptStart所以Move中就可以确定矩形框的大小 然后当鼠标抬起的时候确定这个大小 当然中间需要一些变量来标记一些东西 比如是否已经绘制了一个矩形框了什么的

其实 直接绘制矩形框什么的没有啥难度 因为确定两个点 就能确定大小了 重点在于 绘制了矩形框之后 如何改变他的大小 如果已经绘制好了一个矩形框 那么在MouseMove中 你就需要判断当前鼠标是不是在顶点上或者 区域里面 为什么?因为你需要判断 来设置鼠标应该显示箭头还是什么的啊、、、然后你需要在MouseDown里面判断 是不是是在某个点上点击的

//设置鼠标样式
protected virtual void SetCursorStyle(Point pt) {
    if (m_rectDots[0].Contains(pt) || m_rectDots[7].Contains(pt))
        this.Cursor = Cursors.SizeNWSE;
    else if (m_rectDots[1].Contains(pt) || m_rectDots[6].Contains(pt))
        this.Cursor = Cursors.SizeNS;
    else if (m_rectDots[2].Contains(pt) || m_rectDots[5].Contains(pt))
        this.Cursor = Cursors.SizeNESW;
    else if (m_rectDots[3].Contains(pt) || m_rectDots[4].Contains(pt))
        this.Cursor = Cursors.SizeWE;
    else if (this._SelectedRectangle.Contains(pt))
        this.Cursor = Cursors.SizeAll;
    else
        this.Cursor = Cursors.Default;
}
//MouseDown中
if (this._IsDrawed) {
    this._IsDrawed = false;
    if (m_rectDots[0].Contains(e.Location)) {
        m_ptStart.X = this._SelectedRectangle.Right;
        m_ptStart.Y = this._SelectedRectangle.Bottom;
    } else if (m_rectDots[1].Contains(e.Location)) {
        m_ptStart.Y = this._SelectedRectangle.Bottom;
        m_bChangeWidth = false;
    } else if (m_rectDots[2].Contains(e.Location)) {
        m_ptStart.X = this._SelectedRectangle.X;
        m_ptStart.Y = this._SelectedRectangle.Bottom;
    } else if (m_rectDots[3].Contains(e.Location)) {
        m_ptStart.X = this._SelectedRectangle.Right;
        m_bChangeHeight = false;
    } else if (m_rectDots[4].Contains(e.Location)) {
        m_ptStart.X = this._SelectedRectangle.X;
        m_bChangeHeight = false;
    } else if (m_rectDots[5].Contains(e.Location)) {
        m_ptStart.X = this._SelectedRectangle.Right;
        m_ptStart.Y = this._SelectedRectangle.Y;
    } else if (m_rectDots[6].Contains(e.Location)) {
        m_ptStart.Y = this._SelectedRectangle.Y;
        m_bChangeWidth = false;
    } else if (m_rectDots[7].Contains(e.Location)) {
        m_ptStart = this._SelectedRectangle.Location;
    } else if (this._SelectedRectangle.Contains(e.Location)) {
        m_bMoving = true;
        m_bChangeWidth = false;
        m_bChangeHeight = false;
    } else { this._IsDrawed = true; }
}
如果用户是在四个角上面点击的 其实很好处理 比如用户点击的是右下角的顶点来改变大小 那么请问 这个和刚才上面提到的初次绘制矩形框有什么区别?把ptStart重置为原本左上角的坐标 就相当于在左上角点下了 然后鼠标已经拖动到右下角的位置了而已、、当然 如果是点击的中间的点 就需要一些标志变量了

由于全部代码还是有点分量 加上注释 神马的还是有三百多接近四百行、、这里就单开页面上传全部代码

这里代码传送门

代码注释也很详细了 具体详情还是看代码吧、、


添加时间:2014-08-04 01:27:33 编辑时间:2016-11-09 22:39:54 阅读:5810 
C#自定义控件开发 C#GDI
小草 - 2019-04-22 14:42:00
您好!请教您一个问题,直接使用这个控件设置image属性,完整的图片显示不了,只能显示选框部分,这个要怎么处理,谢谢
码农一个 - 2019-09-06 23:34:16
谢谢,我可以直接拿来用吗
 - 2021-03-12 11:02:55
不错
  • 编写评论

      我觉得区分大小写是一个码农的基本素质
[访问统计] 今天:18 总数:262829 提示:未成年人 请在大人陪同下浏览本站内容 还有:世界上最帅的码农 -> 石头 RSS:http://st233.com/rss Powered by -> Crystal_lz