>  기사  >  백엔드 개발  >  C# GDI+ 간단한 그리기 (3)

C# GDI+ 간단한 그리기 (3)

高洛峰
高洛峰원래의
2016-12-17 09:45:171720검색

처음 두 기사에서는 기본적으로 그림의 기본 지식을 소개했습니다. 따라서 이전 두 기사에서 배운 내용을 활용하여 몇 가지 예를 만들어 보겠습니다.
먼저 간단한 것부터 해보겠습니다. QQ 스크린샷을 모방하는 것입니다. 사실 이미 인터넷에 이에 대한 정보가 있지만, 기사의 완성도를 위해 여전히 설명이 필요하다고 생각합니다.
먼저 효과를 살펴보겠습니다.

C# GDI+ 간단한 그리기 (3)


C# GDI+ 간단한 그리기 (3)

다음으로 이것이 어떻게 이루어지는지 살펴보겠습니다.
아이디어: 채팅 양식에 스크린샷 버튼이 있습니다. 버튼을 클릭하면 프로그램이 전체 화면을 새로운 전체 화면 양식으로 표시한 다음 이 양식을 표시합니다. -화면 형태, 그리고 메뉴바, 툴바 등이 숨겨져 있어서 우리에게는 데스크탑의 스크린샷처럼 보이지만 이 새로운 형태에 직사각형이 그려지고 마지막으로 직사각형 안의 내용이 저장되어 표시됩니다. 원래 채팅 양식에 있습니다.
단계:
A. 새 양식을 만듭니다. 이름을 Catch로 지정하고 이 양식의 FormBorderStyle을 None으로 설정하고 WindowState를 Maximized로 설정합니다.
 B. 코드를 편집합니다:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Client
{
    public partial class Catch : Form
    {
        public Catch()
        {
            InitializeComponent();
        }

        用户变量

        //窗体初始化操作
        private void Catch_Load(object sender, EventArgs e)
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
            this.UpdateStyles();
            //以上两句是为了设置控件样式为双缓冲,这可以有效减少图片闪烁的问题,关于这个大家可以自己去搜索下
            originBmp = new Bitmap(this.BackgroundImage);//BackgroundImage为全屏图片,我们另用变量来保存全屏图片
        }

        //鼠标右键点击结束截图
        private void Catch_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        //鼠标左键按下时动作
        private void Catch_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (!CatchStart)
                {//如果捕捉没有开始
                    CatchStart = true;
                    DownPoint = new Point(e.X, e.Y);//保存鼠标按下坐标
                }
            }
        }

        private void Catch_MouseMove(object sender, MouseEventArgs e)
        {
            if (CatchStart)
            {//如果捕捉开始
                Bitmap destBmp = (Bitmap)originBmp.Clone();//新建一个图片对象,并让它与原始图片相同
                Point newPoint = new Point(DownPoint.X, DownPoint.Y);//获取鼠标的坐标
                Graphics g = Graphics.FromImage(destBmp);//在刚才新建的图片上新建一个画板
                Pen p = new Pen(Color.Blue,1);
                int width = Math.Abs(e.X - DownPoint.X), height = Math.Abs(e.Y - DownPoint.Y);//获取矩形的长和宽
                if (e.X < DownPoint.X)
                {
                    newPoint.X = e.X;
                }
                if (e.Y < DownPoint.Y)
                {
                    newPoint.Y = e.Y;
                }
                CatchRect = new Rectangle(newPoint,new Size(width,height));//保存矩形
                g.DrawRectangle(p,CatchRect);//将矩形画在这个画板上
                g.Dispose();//释放目前的这个画板
                p.Dispose();
                Graphics g1 = this.CreateGraphics();//重新新建一个Graphics类
                //如果之前那个画板不释放,而直接g=this.CreateGraphics()这样的话无法释放掉第一次创建的g,因为只是把地址转到新的g了.如同string一样
                g1 = this.CreateGraphics();//在整个全屏窗体上新建画板
                g1.DrawImage(destBmp,new Point(0,0));//将刚才所画的图片画到这个窗体上
                //这个也可以属于二次缓冲技术,如果直接将矩形画在窗体上,会造成图片抖动并且会有无数个矩形.
                g1.Dispose();
                destBmp.Dispose();//要及时释放,不然内存将会被大量消耗
                
            }
        }

        private void Catch_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (CatchStart)
                {
                    CatchStart = false;
                    CatchFinished = true;
                  
                }
            }
        }

        //鼠标双击事件,如果鼠标位于矩形内,则将矩形内的图片保存到剪贴板中
        private void Catch_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left&&CatchFinished)
            {
                if (CatchRect.Contains(new Point(e.X, e.Y)))
                {
                    Bitmap CatchedBmp = new Bitmap(CatchRect.Width, CatchRect.Height);//新建一个于矩形等大的空白图片
                    Graphics g = Graphics.FromImage(CatchedBmp);
                    g.DrawImage(originBmp, new Rectangle(0, 0, CatchRect.Width, CatchRect.Height), CatchRect, GraphicsUnit.Pixel);
                    //把orginBmp中的指定部分按照指定大小画在画板上
                    Clipboard.SetImage(CatchedBmp);//将图片保存到剪贴板
                    g.Dispose();
                    CatchFinished = false;
                    this.BackgroundImage = originBmp;
                    CatchedBmp.Dispose();
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }
            }
        }
    }
}

C. Catch 양식을 만든 후 스크린샷 버튼(채팅 양식에 있음)에 다음 이벤트를 추가합니다.

 private void bCatch_Click(object sender, EventArgs e)
        {

            if (bCatch_HideCurrent.Checked)
            {
                this.Hide();//隐藏当前窗体
                Thread.Sleep(50);//让线程睡眠一段时间,窗体消失需要一点时间
                Catch CatchForm = new Catch();
                Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);//新建一个和屏幕大小相同的图片         
                Graphics g = Graphics.FromImage(CatchBmp);
                g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height));//保存全屏图片
                CatchForm.BackgroundImage = CatchBmp;//将Catch窗体的背景设为全屏时的图片
                if (CatchForm.ShowDialog() == DialogResult.OK)
                {//如果Catch窗体结束,就将剪贴板中的图片放到信息发送框中
                    IDataObject iData = Clipboard.GetDataObject();
                    DataFormats.Format myFormat = DataFormats.GetFormat(DataFormats.Bitmap);
                    if (iData.GetDataPresent(DataFormats.Bitmap))
                    {
                        richtextbox1.Paste(myFormat);
                        Clipboard.Clear();//清除剪贴板中的对象
                    }
                    this.Show();//重新显示窗体
                }
            }

        }

이로써 스크린샷 기능이 완성되었습니다.
처음 그린 그림을 지우는 것은 초보자에게는 어려운 문제인 것 같아요. 아무 조치도 취하지 않으면 마우스를 움직이는 동안 직사각형이 그려져 N개의 직사각형이 더 생기고 마지막 직사각형만 필요하다는 것을 알게 될 것입니다.
이 문제를 해결하는 방법은 일반적으로 두 가지가 있습니다.
1. 두 번째 그림을 그릴 때 먼저 마지막으로 그린 ​​그림을 배경색과 같은 색으로 다시 그립니다. 하지만 배경색이 단색인 경우에는 이 방법을 사용해야 하는 경우가 많습니다.
2. 그림판에 직접 그래픽을 그리지는 않습니다. 원본 그림판에 그림을 저장하기 위해 그림A를 사용합니다. 그런 다음 그림 A와 동일한 새로운 그림 B를 만들고 그림 B에 우리가 그리고 싶은 그래픽을 그린 다음 그림 B를 작업판에 그립니다. 이런 식으로 그림 A는 변경되지 않았습니다. 그래서 두 번째 그림을 그릴 때도 그림 A와 똑같은 그림을 새로 만들어서 그렸습니다. 그러면 마지막 그래픽이 유지되지 않습니다. 문제가 해결되었습니다.

다음번에는 윈도우 스케치패드를 흉내내는 프로그램 만드는 방법을 소개하겠습니다.


C# GDI+ 간단한 그리기 더보기 (3) 관련 글은 PHP 중국어 홈페이지를 주목해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.