Heim  >  Artikel  >  Backend-Entwicklung  >  c# GDI+ einfaches Zeichnen (4)

c# GDI+ einfaches Zeichnen (4)

高洛峰
高洛峰Original
2016-12-17 09:49:461310Durchsuche

Ich habe Ihnen in den vorherigen Artikeln die Verwendung von GDI+ zum Zeichnen vorgestellt und ein Screenshot-Beispiel erstellt. In diesem Artikel werde ich Ihnen vorstellen, wie Sie ein dem Windows-Zeichnen ähnliches Tool erstellen Um ein leistungsstarkes Zeichenwerkzeug zu erstellen, reicht es nicht aus, GDI zu beherrschen. Derzeit kann ich nur ein relativ einfaches Zeichenwerkzeug erstellen. Eventuelle Mängel können gerne besprochen werden!

Schauen wir uns zunächst den endgültigen Effekt an:

c# GDI+简单绘图

Hauptfunktionen: gerade Linien, Rechtecke, Radiergummis, Kreise zeichnen, Farben wechseln, Bilder öffnen, Speichern Sie das Bild, löschen Sie das Bild und passen Sie die Leinwandgröße manuell an. Wenn die Software zum ersten Mal gestartet wird, ist es eine leere Leinwand. Wir können direkt auf der Leinwand zeichnen oder ein Bild über „Öffnen“ im Menü importieren Wir können auf dem Bild zeichnen.

Plattform: VS2005 WINFORM

Aufgrund von zu viel Code werde ich hier nur kurz die Produktionsschritte vorstellen und Ihnen den Projekt-Download zur Verfügung stellen.

1. Entwerfen Sie die gesamte Benutzeroberfläche.
2. Implementieren Sie die Funktion des Zeichentools
3. Implementieren Sie die Farbaufnahmefunktion. Hier verwenden wir direkt das benutzerdefinierte Steuerelement, das wir letztes Mal geschrieben haben.
4. Implementieren Sie die Menüfunktion
5. Implementieren Sie die Funktion zum manuellen Anpassen der Leinwandgröße
6. Testen Sie

Implementieren Sie die Funktion des Zeichenwerkzeugs
Um das zu erstellen Code-Kopplungsgrad kleiner, ein wenig verwenden Ich habe einige Entwurfsmuster gelernt, aber weil ich nicht sehr gut darin bin, ist der Code immer noch etwas chaotisch, hehe! Alle diese Funktionsblöcke zu Zeichenwerkzeugen sind in der DrawTools-Klasse geschrieben. Dann müssen Sie im Hauptformular nur diese Klasse aufrufen, um die Zeichnung fertigzustellen, ohne dass zu viel spezifischer Zeichnungscode erforderlich ist. Die wichtigsten von dieser Klasse von Zeichenwerkzeugen bereitgestellten Werkzeuge sind: Bleistift, Radiergummi, gerade Linie, Rechteck, Kreis, ausgefülltes Rechteck und ausgefüllter Kreis. Der Code für diese Funktionsblöcke ist nicht schwierig. Solange Sie die vorherigen Artikel sorgfältig gelesen haben, sollten Sie ihn verstehen können.
Folgende Punkte sind hierbei zu beachten:
1. Wie kann verhindert werden, dass unnötige Spuren des Zeichenprozesses aufgezeichnet werden?
Dieses Problem wurde im dritten Artikel erwähnt. Möglicherweise möchten Sie diesen Artikel zuerst lesen. Um den Code besser lesbar zu machen, habe ich zwei Bildvariablen eingerichtet: „finishingImg“ dient zum Speichern von Spuren des Zeichenvorgangs und „orginalImg“ zum Speichern des abgeschlossenen Zeichenvorgangs und des anfänglichen Hintergrundbilds.
2. Wie kommuniziert diese Klasse mit dem Hauptformular?
Wenn Sie diese Funktionsblöcke direkt im Hauptformular schreiben, tritt dieses Problem natürlich nicht auf. Der Code erscheint jedoch sehr verwirrend. Wenn nur ein Problem mit dem Toolcode besteht, muss das gesamte Projekt geändert werden. Hier definiere ich Methoden und Eigenschaften, damit das Hauptformular Informationen über Zeichenfläche, Leinwand und Farbe an die Werkzeugklasse übergeben kann, indem es den Eigenschaften Werte zuweist, und diese Werkzeuge dann durch Aufrufen der entsprechenden Werkzeugmethoden verwenden kann.
3. Schlüsselattribute
Damit diese Werkzeuge ordnungsgemäß funktionieren, müssen ihm die folgenden Dinge übergeben werden: Zielzeichenfläche (d. h. Bildfeld), Zeichenfarbe und Originalleinwand.

Implementierung der Menüfunktion

c# GDI+简单绘图

Hier müssen wir ein wenig Verständnis für die Funktionsweise von Dateien haben. Sie können die relevanten Informationen überprüfen.

Die Hauptschwierigkeit ist die Implementierung des Menüpunktes „Öffnen“
Wenn wir das geöffnete Bild nach der Änderung erneut speichern möchten, müssen wir die Datei nach dem Öffnen schließen, sonst wird sie nicht überschrieben, da die Datei geöffnet ist . Originaldokument. Dies führt dazu, dass während der Kompilierung „GDI General Error“ angezeigt wird. Daher zeichnen Sie, wie andere Freunde im Internet es tun, zunächst das geöffnete Bild über GDI+ auf eine andere Leinwand und schließen dann sofort das geöffnete Bild und das Zeichenbrett, mit dem das Bild gezeichnet wurde.

 private void openPic_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();//实例化文件打开对话框
            ofd.Filter = "JPG|*.jpg|Bmp|*.bmp|所有文件|*.*";//设置对话框打开文件的括展名
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                Bitmap bmpformfile = new Bitmap(ofd.FileName);//获取打开的文件
                panel2.AutoScrollPosition = new Point(0,0);//将滚动条复位
                pbImg.Size = bmpformfile.Size;//调整绘图区大小为图片大小

                reSize.Location = new Point(bmpformfile.Width, bmpformfile.Height);//reSize为我用来实现手动调节画布大小用的
                //因为我们初始时的空白画布大小有限,"打开"操作可能引起画板大小改变,所以要将画板重新传入工具类
                dt.DrawTools_Graphics = pbImg.CreateGraphics();

                Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
                Graphics g = Graphics.FromImage(bmp);
                g.FillRectangle(new SolidBrush(pbImg.BackColor), new Rectangle(0, 0, pbImg.Width, pbImg.Height));//不使用这句话,那么这个bmp的背景就是透明的
                g.DrawImage(bmpformfile, 0, 0,bmpformfile.Width,bmpformfile.Height);//将图片画到画板上
                g.Dispose();//释放画板所占资源
                //不直接使用pbImg.Image = Image.FormFile(ofd.FileName)是因为这样会让图片一直处于打开状态,也就无法保存修改后的图片
                bmpformfile.Dispose();//释放图片所占资源
                g = pbImg.CreateGraphics();
                g.DrawImage(bmp, 0, 0);
                g.Dispose();
                dt.OrginalImg = bmp;
                bmp.Dispose();
                sFileName = ofd.FileName;//储存打开的图片文件的详细路径,用来稍后能覆盖这个文件
                ofd.Dispose();

            }
        }
Durch das Löschen des Bildes wird tatsächlich die gesamte Leinwand mit Weiß gefüllt.

Andere sind relativ einfach, daher werde ich hier nicht ins Detail gehen.

Manuelle Anpassung der Leinwandgröße realisieren
Einige Leute im Internet empfehlen die Verwendung einer API, aber ich persönlich denke, dass es einfacher ist, andere Steuerelemente als Hilfe zu verwenden, zumindest können wir es verstehen.
Idee: Platzieren Sie eine Bildbox1 (Größe 5*5), fixieren Sie sie in der unteren rechten Ecke des Hauptzeichenbretts, ändern Sie dann den Cursor beim Betreten der Maus in eine Pfeilform, legen Sie das Ereignis fest, wenn die Maus gedrückt wird, und verschoben, und lassen Sie die Picturebox1 der Mausbewegung folgen. Wenn Sie die Maus loslassen, passen Sie die Koordinaten der unteren rechten Ecke des Hauptzeichenbretts an die Koordinaten von Bildbox1 an.
Schauen wir uns den Code an:
Die reSize ist das Picturebox-Steuerelement, das wir zur Unterstützung verwenden

private bool bReSize = false;//是否改变画布大小
        private void reSize_MouseDown(object sender, MouseEventArgs e)
        {
            bReSize = true;//当鼠标按下时,说明要开始调节大小
        }

        private void reSize_MouseMove(object sender, MouseEventArgs e)
        {
            if (bReSize)
            {
                reSize.Location = new Point(reSize.Location.X + e.X, reSize.Location.Y + e.Y);

            }
        }

        private void reSize_MouseUp(object sender, MouseEventArgs e)
        {
            bReSize = false;//大小改变结束
            //调节大小可能造成画板大小超过屏幕区域,所以事先要设置autoScroll为true.
            //但是滚动条的出现反而增加了我们的难度,因为滚动条上下移动并不会自动帮我们调整图片的坐标。
            //这是因为GDI绘图的坐标系不只一个,好像有三个,没有仔细了解,一个是屏幕坐标,一个是客户区坐标,还个是文档坐标。
            //滚动条的上下移动改变的是文档的坐标,但是客户区坐标不变,而location属性就属于客户区坐标,所以我们直接计算会出现错误
            //这时我们就需要知道文档坐标与客户区坐标的偏移量,这就是AutoScrollPostion可以提供的

            pbImg.Size = new Size(reSize.Location.X - (this.panel2.AutoScrollPosition.X), reSize.Location.Y - (this.panel2.AutoScrollPosition.Y));
            dt.DrawTools_Graphics = pbImg.CreateGraphics();//因为画板的大小被改变所以必须重新赋值

            //另外画布也被改变所以也要重新赋值
            Bitmap bmp = new Bitmap(pbImg.Width, pbImg.Height);
            Graphics g = Graphics.FromImage(bmp);
            g.FillRectangle(new SolidBrush(Color.White), 0, 0, pbImg.Width, pbImg.Height);
            g.DrawImage(dt.OrginalImg, 0, 0);
            g.Dispose();
            g = pbImg.CreateGraphics();
            g.DrawImage(bmp, 0, 0);
            g.Dispose();
            dt.OrginalImg = bmp;

            bmp.Dispose();
        }
Der Effekt ist wie unten gezeigt (schauen Sie sich die untere rechte Ecke des Weiß genau an Bereich):

c# GDI+简单绘图

An dieser Stelle können Sie die Bildgröße anpassen, indem Sie das kleine Quadrat ziehen.
 
Auf diese Weise ist das Hauptproblem fast gelöst, aber es gibt immer noch einige Mängel. Jeder ist willkommen, wertvolle Meinungen abzugeben.


Weitere Artikel zum einfachen Zeichnen von C# GDI+ (4) finden Sie auf der chinesischen 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 (3)Nächster Artikel:C# GDI+ einfaches Zeichnen (3)