C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

■103794 / 5階層)  Visual Basicで簡易CADを作成
□投稿者/ 魔界の仮面弁士 (3873回)-(2025/07/30(Wed) 15:46:27)
No103792 (shiro さん) に返信
> 回答有難うございます。VBでの壁画は始めたばかりで分からない点が多く参考になります。
壁画というか、描画かな?

掲示板にコードを投稿する時は、
 投稿モード:通常モード / 図表モード
の選択肢を、「通常モード」から「図表モード」に変更しておいてください。
そうしないと、空白やタブでのインデントが潰れてしまいますので。

もし、「通常モード」のままでインデントを維持したいのであれば、
連続する半角スペース を 全角スペース に置き換えておくことでも代用できます。
全角空白を混入させられない言語の時は都合が悪いですけれどね。


インデントが崩れていないかを確認したい場合は、右下の送信ボタンの近くにある
「プレビュー」にチェックをいれて、投稿前に事前確認することもできます。


> 画像削除方法を勉強してみます。
たとえば、先のサンプルの最後にある
「マウスをなぞった位置にリアルタイムに四角形を描画し、マウスを離すとその位置に四角形を追加し、後で追加された四角形をクリックすると色が変わる」
について。
https://www.umayadia.com/vbsample/VBdotNet-Samples201/Sample275WinFormMouseToDraw.htm#A5

ここに下記のコードを加えると、選択状態の黄色い矩形が取り除かれます。

Private Sub PictureBox1_DoubleClick(sender As Object, e As EventArgs) Handles PictureBox1.DoubleClick
  Dim selectedPolygon As Polygon = polygons.FirstOrDefault(Function(p) p.IsSelected)
  If selectedPolygon IsNot Nothing Then
    '選択済みの矩形があれば削除
    polygons.Remove(selectedPolygon)
    PictureBox1.Invalidate() 'PictureBoxを強制的に再描画する
  End If
End Sub


もしも元のサンプルを拡張して、複数選択できるようにしていた場合はこのようにします。

Private Sub PictureBox1_DoubleClick(sender As Object, e As EventArgs) Handles PictureBox1.DoubleClick
  For n = polygons.Count - 1 To 0 Step -1
    '削除するとインデックス番号がズレるので、後ろの番号から探していく
    If polygons(n).IsSelected Then
      polygons.RemoveAt(n)
    End If
  Next
  PictureBox1.Invalidate() 'PictureBoxを強制的に再描画する
End Sub


上記ではダブルクリックで制御しています。
ダブルクリックで削除する方式では操作しにくいという場合は、別途、削除ボタンを用意し、
それを押したときに IsSelected = True なものを取り除く方式にしても良いでしょう。
あるいは、右クリックやコンテキストメニューなどで指示する手法を採用することもできますね。



> そこで、さらに柱を選択し柱を配置すると、全ての壁が消えてしまいます。
たとえば…

最初は、柱が 0 本、壁が 0 枚の状態です。
この場合、Paint イベントでは「方眼グリッドと、0 本の柱と、0 枚の壁」を描画するようにします。

柱を選択して、マウス操作で柱を建てる場所を決めました(MouseUp/MouseDown で座標を決めていきます)。
これにより、柱が 1 本、壁が 0 枚の状態になりました、
この場合、Paint イベントでは「方眼グリッドと、1 本の柱と、0 枚の壁」を描画するようにします。

同様にして、柱を 4 本建てました;左上、右上、左下、右下と正方形の頂点位置にくるように。
この場合、Paint イベントでは「方眼グリッドと、4 本の柱と、0 枚の壁」を描画します。

さらに、壁を 3 枚描きました。上壁、右壁、下壁を作るイメージです。
この場合、Paint イベントでは「方眼グリッドと、4 本の柱と、3 枚の壁」を描画します。壁が【コ】の字に描かれます。

右クリック等で右側の壁を一枚選択して、その壁だけを削除し、再描画を依頼します。
この場合、Paint イベントでは「方眼グリッドと、4 本の柱と、2 枚の壁」を描画します。壁が【=】の字に描かれます。


すなわち、それぞれのオブジェクト(壁や柱)が、どの座標に描かれているのかを
List(Of ) 等で保持しておく必要があるということです。これは、Visual Basic 中学校サンプルでいう
 Private polygons As New List(Of Polygon)
のことです。現状はそれが無いため、再描画に耐えられるコードになっていません。


> それをToolStripMenuItemで「柱・壁」をselect文で場合分けをしようとしました。
変数 element の宣言が無いようですが、Form1 上に
 Private element As String
があるのでしょうか?


> g = PictureBox1.CreateGraphics()
これは使わないでください。

CreateGraphics は一時的な描画であり、恒久的に描画結果を残すものではありません。
ウィンドウのリサイズなどで容易に失われてしまうものです。
また、Invalidate が呼び出された時点で、CreateGraphics による描画結果は失われることになります。

CreateGraphics の呼び出しは行わないようにして、描画処理を
PictureBox1_Paint イベントの引数 e.Graphics に集約させるべきです。

KOZ さんが紹介してくださった Visual Basic 中学校 のサンプルにおいても、
MouseMove/MouseDown 中に Graphics を操作したりはせず、
Graphics での描画処理は、すべて Paint イベント内だけで行っていましたよね。


とはいえ、ラバーバンドのように一時的な描画に対しては、CreateGrapchis でも
用を足せるのですが、その場合も、Dispose の呼び出しは忘れないようにしてください。

Graphics は、Pen や Brush と同様に「破棄が必要なオブジェクト(IDisposable)」です。

CreateGraphics や Graphics.FromImage によって生成した Graphics オブジェクトは、
使用後に処分せねばならない、ということです。Graphics を自分で生成して使うケースでは
保持させる Graphics 変数を Using ブロックで囲んでおくことが望ましいです。

※ただし、Paint イベントの e.Graphics プロパティで得られる Graphics オブジェクトについては
 自分で生成したインスタンスではないため、処分してはいけません。


もしも描画する内容が多く、すべてを Paint イベント毎回再描画するとコストが高すぎる場合には、
永続的に表示し続けたい画像を Bitmap として用意する方法を併用できます。


たとえば、描画先のキャンバス(たとえば PictureBox1)と同サイズの Bitmap を
Dim bmp As New Bitmap(幅, 高さ) などで作成して
 Using g = Graphics.FromImage(bmp)
  …
 End Using
を使って描画した後、PictureBox1.Image = bmp で割り当てるという手法です。

この時、背景画像(PictureBox1.BackgroundImage)と前景画像(PictureBox1.Image)を併用しても構いません。
割り当てた Bitmap の背景部が、完全透過あるいは半透明だった場合、その下の画像や背景色が
透けて描画されますので、これを CAD のレイヤーのように使うことができます。

レイヤー数を増やしたい場合には、透過背景の Bitmap を複数枚用意しておき、
それが g.DrawImage メソッドで重ね合わせて描画することで対応できます。

なお、Bitmap も破棄が必要なオブジェクト(IDisposable)なため、
使わなくなった時点で bmp.Dispose() を呼ぶ必要があります。
編集キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[4]: Visual Basicで簡易CADを作成 /shiro →Re[6]: Visual Basicで簡易CADを作成 /shiro
 
上記関連ツリー

Visual Basicで簡易CADを作成 / shiro (25/07/25(Fri) 20:50) #103783
Re[1]: Visual Basicで簡易CADを作成 / KOZ (25/07/27(Sun) 14:35) #103784
  └ Re[2]: Visual Basicで簡易CADを作成 / shiro (25/07/28(Mon) 20:17) #103785
    ├ Re[3]: Visual Basicで簡易CADを作成 / kiku (25/07/29(Tue) 08:49) #103786
    └ Re[3]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/07/29(Tue) 14:06) #103791
      └ Re[4]: Visual Basicで簡易CADを作成 / shiro (25/07/30(Wed) 12:22) #103792
        └ Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/07/30(Wed) 15:46) #103794 ←Now
          └ Re[6]: Visual Basicで簡易CADを作成 / shiro (25/07/31(Thu) 07:34) #103795
            └ Re[7]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/07/31(Thu) 10:48) #103796
              └ Re[8]: Visual Basicで簡易CADを作成 / shiro (25/08/01(Fri) 06:15) #103797
                ├ Re[9]: Visual Basicで簡易CADを作成 / kiku (25/08/01(Fri) 08:47) #103798
                │└ Re[10]: Visual Basicで簡易CADを作成 / shiro (25/08/02(Sat) 03:40) #103803
                └ Re[9]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/01(Fri) 10:46) #103800
                  ├ Re[10]: Visual Basicで簡易CADを作成 / kiku (25/08/01(Fri) 10:50) #103801
                  └ Re[10]: Visual Basicで簡易CADを作成 / shiro (25/08/02(Sat) 03:38) #103802
                    └ Re[11]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/03(Sun) 11:50) #103805
                      └ Re[12]: Visual Basicで簡易CADを作成 / shiro (25/08/04(Mon) 05:10) #103806
                        └ Re[13]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/04(Mon) 11:36) #103808
                          └ Re[14]: Visual Basicで簡易CADを作成 / shiro (25/08/04(Mon) 18:59) #103811
                            └ Re[15]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/04(Mon) 19:43) #103812
                              └ Re[16]: Visual Basicで簡易CADを作成 / shiro (25/08/05(Tue) 12:42) #103814
                                └ Re[17]: Visual Basicで簡易CADを作成 / shiro (25/08/05(Tue) 12:44) #103815
                                  └ Re[18]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/05(Tue) 18:02) #103817
                                    └ Re[19]: Visual Basicで簡易CADを作成 / shiro (25/08/05(Tue) 19:28) #103819
                                      └ Re[20]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/05(Tue) 20:39) #103821
                                        └ Re[21]: Visual Basicで簡易CADを作成 / shiro (25/08/06(Wed) 12:22) #103822
                                          └ Re[22]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 14:42) #103825
                                            ├ Re[23]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 17:53) #103828
                                            │└ Re[24]: Visual Basicで簡易CADを作成 / shiro (25/08/06(Wed) 19:13) #103830
                                            │  ├ Re[25]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 19:44) #103832
                                            │  │└ Re[26]: Visual Basicで簡易CADを作成 / shiro (25/08/07(Thu) 07:06) #103834
                                            │  │  └ Re[27]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/07(Thu) 12:18) #103835
                                            │  │    └ Re[28]: Visual Basicで簡易CADを作成 / shiro (25/08/07(Thu) 19:14) #103836
                                            │  │      └ Re[29]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/07(Thu) 20:25) #103837
                                            │  │        ├ Re[30]: Visual Basicで簡易CADを作成 / shiro (25/08/08(Fri) 03:34) #103838
                                            │  │        └ Re[30]: Visual Basicで簡易CADを作成 / shiro (25/08/08(Fri) 07:29) #103839
                                            │  │          └ Re[31]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/08(Fri) 09:40) #103841
                                            │  │            └ Re[32]: Visual Basicで簡易CADを作成 / shiro (25/08/09(Sat) 05:05) #103842
                                            │  │              └ Re[33]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/09(Sat) 14:24) #103843
                                            │  │                └ Re[34]: Visual Basicで簡易CADを作成 / shiro (25/08/09(Sat) 19:18) #103844
                                            │  └ Re[25]: Visual Basicで簡易CADを作成 / 魔界の仮面弁士 (25/08/06(Wed) 19:53) #103833
                                            └ Re[23]: Visual Basicで簡易CADを作成 / shiro (25/08/18(Mon) 12:41) #103847
                                              └ Re[24]: Visual Basicで簡易CADを作成 / kiku (25/08/20(Wed) 15:09) #103848
                                                └ Re[25]: Visual Basicで簡易CADを作成 / shiro (25/08/20(Wed) 18:35) #103849
                                                  └ Re[26]: Visual Basicで簡易CADを作成 / kiku (25/08/21(Thu) 09:03) #103850
                                                    └ Re[27]: Visual Basicで簡易CADを作成 / shiro (25/08/21(Thu) 22:01) #103851
                                                      └ Re[28]: Visual Basicで簡易CADを作成 / kiku (25/08/22(Fri) 08:45) #103852
                                                        └ Re[29]: Visual Basicで簡易CADを作成 / shiro (25/08/22(Fri) 13:20) #103853
                                                          └ Re[30]: Visual Basicで簡易CADを作成 / kiku (25/08/22(Fri) 16:45) #103854
                                                            └ Re[31]: Visual Basicで簡易CADを作成 / shiro (25/08/22(Fri) 20:33) #103855
                                                              └ Re[32]: Visual Basicで簡易CADを作成 / kiku (25/08/25(Mon) 08:42) #103857

上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信