Heim  >  Artikel  >  Backend-Entwicklung  >  C# GDI+ einfaches Zeichnen (3)

C# GDI+ einfaches Zeichnen (3)

高洛峰
高洛峰Original
2016-12-17 09:45:171766Durchsuche

Die ersten beiden Artikel haben Ihnen im Wesentlichen die Grundkenntnisse des Zeichnens vermittelt. Daher werde ich das, was wir in den beiden vorherigen Artikeln gelernt haben, nutzen, um ein paar Beispiele zu erstellen.
Machen wir zunächst eine einfache Sache: Nachahmen von QQ-Screenshots. Es gibt tatsächlich Informationen dazu im Internet, aber der Vollständigkeit halber halte ich es dennoch für notwendig, sie zu erklären.
Schauen wir uns zunächst die Wirkung an:

C# GDI+ einfaches Zeichnen (3)


C# GDI+ einfaches Zeichnen (3)

Als nächstes schauen wir uns an, wie das aussieht Funktioniert. Es ist fertig.
Idee: Es gibt eine Screenshot-Schaltfläche auf dem Chat-Formular. Nach dem Klicken auf die Schaltfläche zeichnet das Programm den gesamten Bildschirm auf einem neuen Vollbild-Formular und zeigt dieses Formular dann an -Bildschirmformular und Die Menüleiste, Symbolleiste usw. sind ausgeblendet, sodass es für uns wie ein Screenshot des Desktops aussieht. Anschließend wird auf diesem neuen Formular ein Rechteck gezeichnet und schließlich der Inhalt im Rechteck gespeichert und angezeigt im ursprünglichen Chat-Formular.
Schritte:
A. Erstellen Sie ein neues Formular. Nennen Sie es Catch. Setzen Sie dann den FormBorderStyle dieses Formulars auf None und WindowState auf Maximized.
 B. Wir bearbeiten den Code:

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. Nach dem Erstellen des Catch-Formulars fügen wir die folgenden Ereignisse zur Screenshot-Schaltfläche (im Chat-Formular) hinzu:

 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();//重新显示窗体
                }
            }

        }

Damit ist unsere Screenshot-Funktion abgeschlossen.
Ich denke, dass es für Anfänger ein schwieriges Problem ist, das erste Bild, das sie zeichnen, zu löschen. Wenn keine Maßnahmen ergriffen werden, werden Sie feststellen, dass solange Sie die Maus bewegen, ein Rechteck gezeichnet wird, sodass es N weitere Rechtecke gibt und wir nur das letzte wollen.
Generell gibt es zwei Möglichkeiten, dieses Problem zu lösen:
1. Beim Zeichnen der zweiten Figur zeichnen wir zunächst die zuletzt gezeichnete Figur mit derselben Farbe wie die Hintergrundfarbe neu. Dies muss jedoch häufig verwendet werden, wenn die Hintergrundfarbe einfarbig ist.
2. Wir zeichnen die Grafiken nicht direkt auf dem Zeichenbrett. Wir verwenden ein Bild A, um das Bild auf dem Original-Zeichenbrett zu speichern. Erstellen Sie dann ein neues Bild B, das mit Bild A identisch ist, zeichnen Sie die Grafiken, die wir zeichnen möchten, auf Bild B und zeichnen Sie dann Bild B auf dem Zeichenbrett. Auf diese Weise wurde Bild A nicht verändert. Als wir also das zweite Mal zeichneten, erstellten wir immer noch ein neues Bild, das dem Bild A entsprach, und zeichneten es. Dann bleiben die letzten Grafiken nicht erhalten. Das Problem ist gelöst.

Das nächste Mal werde ich Ihnen vorstellen, wie Sie ein Programm erstellen, das Windows Sketchpad imitiert.


Mehr C# GDI+ einfaches Zeichnen (3) Für verwandte Artikel achten Sie bitte auf die chinesische PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:c# GDI+ einfaches Zeichnen (2)Nächster Artikel:c# GDI+ einfaches Zeichnen (2)