C# GDI+ 簡単な描画 (4)
以前の記事で GDI+ を使用して描画する方法を紹介し、スクリーンショットの例を作成しました。この記事では、Windows の描画に似たツールを作成する方法を紹介します。強力なツールを作成する 描画ツールを作成するには、GDI を習得するだけでは不十分です。現時点では、比較的単純な描画ツールしか作成できません。欠陥がある場合はご相談ください。
まずは最終的な効果を見てみましょう:
プラットフォーム:VS2005 WINFORM
1.インターフェース全体をレイアウトします。
2. 描画ツールの機能を実装します
3. カラーピッキングの機能を実装します ここでは前回書いたカスタムコントロールを直接使用します。
4. メニュー機能を実装します
5. キャンバスサイズを手動で調整する機能を実装します
6. テスト
描画ツールの機能を実装します
コードをより一貫性のあるものにするために、いくつかのデザインパターンを使用しました。あまり上手ではないので、コードはまだちょっと汚いですが、ふふ!描画ツールに関するこれらすべての機能ブロックは、DrawTools クラスに記述されます。次に、メイン フォームでは、特定の描画コードをあまり必要とせずに、このクラスを呼び出すだけで描画が完了します。このクラスの描画ツールで提供される主なツールは、鉛筆、消しゴム、直線、長方形、円、塗りつぶし長方形、塗りつぶし円です。これらの関数ブロックのコードは、これまでの記事をよく読んでいれば理解できるはずです。
ここで注意すべき点は次のとおりです:
1. 描画プロセスの不要な痕跡が記録されないようにするにはどうすればよいですか?
この問題については 3 番目の記事で言及されていますので、まずその記事を読んでください。コードを読みやすくするために、2 つの Image 変数を設定しました。finishImg は描画プロセスのトレースを保存するために使用され、originalImg は完了した描画プロセスと初期の背景画像を保存するために使用されます。
2. このクラスはメインフォームとどのように通信しますか?
もちろん、これらのファンクションブロックをメインフォームに直接記述すれば、そのような問題は発生しません。ただし、ツール コードのみに問題がある場合は、コードが非常にわかりにくくなり、プロジェクト全体を変更する必要があります。ここでは、メイン フォームがプロパティに値を割り当てることでアートボード、キャンバス、カラーに関する情報をツール クラスに渡し、対応するツール メソッドを呼び出すことでこれらのツールを使用できるようにメソッドとプロパティを定義します。
3. 主要な属性
これらのツールが適切に動作するためには、ターゲットのアートボード (つまり、ピクチャーボックス)、描画カラー、および元のキャンバスを彼に渡す必要があります。
メニュー機能を実装するには
主な困難は、「開く」メニュー項目の実装です
変更後に開いた画像を再保存したい場合は、開いた後にファイルを閉じる必要があります。そうしないと、ファイルが開いているため、元のファイルが上書きされません。これにより、コンパイル中に「GDI General Error」がポップアップ表示されます。したがって、インターネット上の他の友人のやり方によれば、まず開いている画像を GDI+ 経由で別のキャンバスに描画し、その後、開いている画像と画像の描画に使用した描画ボードをすぐに閉じます。
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(); } }
その他は比較的簡単なので、ここでは詳しく説明しません。
キャンバスサイズの手動調整を実現
ネット上ではAPIを使えという人もいますが、個人的には他のコントロールを使ったほうが簡単だと思います、少なくとも理解はできます。
アイデア:picturebox1(サイズ5*5)を配置し、メイン描画ボードの右下隅に固定し、マウスが入ったときのカーソルを矢印の形に変更し、マウスを押して移動したときのイベントを設定し、そして、picturebox1 をマウスの動きに追従させます。マウスを離したら、メイン描画ボードの右下隅の座標をpicturebox1の座標に合わせます。
コードを見てみましょう:
reSize は、ヘルプに使用するピクチャーボックス コントロールです
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(); }
この時点で、小さな四角をドラッグして画像サイズを調整できます。
このようにして、主な問題はほぼ解決されましたが、まだ不十分な点もいくつかありますので、皆様、貴重なご意見をお待ちしております。
その他の c# GDI+ 簡単な描画 (4) 関連記事については、PHP 中国語 Web サイトに注目してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Cでは、文字列でCharタイプが使用されます。1。単一の文字を保存します。 2。配列を使用して文字列を表し、ヌルターミネーターで終了します。 3。文字列操作関数を介して動作します。 4.キーボードから文字列を読み取りまたは出力します。

c言語のシンボルの使用方法は、算術、割り当て、条件、ロジック、ビット演算子などをカバーします。算術演算子は基本的な数学的操作に使用されます。割り当てと追加、下位、乗算、除算の割り当てには、条件操作に使用されます。ポインター、ファイル終了マーカー、および非数値値。

C言語では、以下などのエスケープシーケンスを通じて特殊文字が処理されます。\ nはラインブレークを表します。 \ tはタブ文字を意味します。 ESACEシーケンスまたは文字定数を使用して、Char C = '\ n'などの特殊文字を表します。バックスラッシュは2回逃げる必要があることに注意してください。さまざまなプラットフォームとコンパイラが異なるエスケープシーケンスを持っている場合があります。ドキュメントを参照してください。

C言語では、charとwchar_tの主な違いは文字エンコードです。CharはASCIIを使用するか、ASCIIを拡張し、WCHAR_TはUnicodeを使用します。 Charは1〜2バイトを占め、WCHAR_Tは2〜4バイトを占有します。 charは英語のテキストに適しており、wchar_tは多言語テキストに適しています。 CHARは広くサポートされており、WCHAR_TはコンパイラとオペレーティングシステムがUnicodeをサポートするかどうかに依存します。 CHARの文字範囲は限られており、WCHAR_Tの文字範囲が大きく、特別な機能が算術演算に使用されます。

マルチスレッドと非同期の違いは、マルチスレッドが複数のスレッドを同時に実行し、現在のスレッドをブロックせずに非同期に操作を実行することです。マルチスレッドは計算集約型タスクに使用されますが、非同期はユーザーインタラクションに使用されます。マルチスレッドの利点は、コンピューティングのパフォーマンスを改善することですが、非同期の利点はUIスレッドをブロックしないことです。マルチスレッドまたは非同期を選択することは、タスクの性質に依存します。計算集約型タスクマルチスレッド、外部リソースと相互作用し、UIの応答性を非同期に使用する必要があるタスクを使用します。

C言語では、charタイプの変換は、キャスト:キャスト文字を使用することにより、別のタイプに直接変換できます。自動タイプ変換:あるタイプのデータが別のタイプの値に対応できる場合、コンパイラは自動的に変換します。

C言語に組み込みの合計機能はないため、自分で書く必要があります。合計は、配列を通過して要素を蓄積することで達成できます。ループバージョン:合計は、ループとアレイの長さを使用して計算されます。ポインターバージョン:ポインターを使用してアレイ要素を指し示し、効率的な合計が自己概要ポインターを通じて達成されます。アレイバージョンを動的に割り当てます:[アレイ]を動的に割り当ててメモリを自分で管理し、メモリの漏れを防ぐために割り当てられたメモリが解放されます。

Char Arrayは文字シーケンスをC言語で保存し、char array_name [size]として宣言されます。アクセス要素はサブスクリプト演算子に渡され、要素は文字列のエンドポイントを表すnullターミネーター「\ 0」で終了します。 C言語は、strlen()、strcpy()、strcat()、strcmp()など、さまざまな文字列操作関数を提供します。
