none
[VB2005] 兩個PICTUREBOX 相疊的問題 RRS feed

  • 問題

  • 我想做出一個類似AUTOCAD 在底圖上 根據滑鼠的位置顯示目前座標的功能。

    我設了兩個大小位置一樣的picturebox, PictureBox1是底圖, CrossPicture 是上面的圖 預設是透明,

    我的想法是  我把 座標值寫在CrossPicture 這樣應該就可以做到這個效果。

    我現在遇到一個很怪的狀況,為了避免 滑鼠在移動時 座標值 會有殘影,我試著每次把CrossPicture 重繪,但總是有問題,不是看不到底圖 ,不然就是有殘影。

    請問我是哪裡寫錯了?

     

      Dim myCrossGraphics As Graphics
      Dim myGraphics As Graphics
      Dim DrawingBoard As MyPaint
        Dim CrossBoard As MyPaint

     

    Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            '
    初始化

            init()

         CrossPicture.Parent = Me.PictureBox1
            CrossPicture.Dock = DockStyle.Fill

      End Sub

     

     Private Sub init()

         
            myCrossGraphics = Me.CrossPicture.CreateGraphics

            Me.PictureBox1.BackColor = Color.White
            myGraphics = Me.PictureBox1.CreateGraphics
            '
    初始畫另一塊畫版

            DrawingBoard = New MyPaint(Me.PictureBox1.Width, Me.PictureBox1.Height, Me.PictureBox1.BackColor)
            CrossBoard = New MyPaint(Me.PictureBox1.Width, Me.PictureBox1.Height,
    , Me.CrossPicture.BackColor)


            TextBox1.Text = 0
            TextBox2.Text = 0
        End Sub

     

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
            '
    按滑鼠左鍵拖曳


            If e.Button = Windows.Forms.MouseButtons.Left Then
                 myGraphics.DrawImage(DrawingBoard.GetBitmap, 0, 0)

                                    crossIcon(e.X, e.Y)

            End If
        End Sub

     

        Sub crossIcon(ByVal ex As Integer, ByVal ey As Integer)

            Dim s As String

    '清除 舊的座標直

            CrossBoard.CleanAllImage(0, 0, Me.CrossPicture.Width, Me.CrossPicture.Height)

    '寫入新的座標直
            s = "(" & ex.ToString & "," & ey.ToString & ")"
            CrossBoard.myDrawLine(0, ey, Me.PictureBox1.Width, ey, Color.Black)

        CrossBoard.myDrawLine(ex, 0, ex, Me.PictureBox1.Height, Color.Black)

            Dim myfont As Font
            myfont = New System.Drawing.Font("
    新細明體
    ", 16.0, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point)
            CrossBoard.myDrawString(s, myfont, ex - 10, ey - 10)

    '畫出來
            CrossPicture.Image = CrossBoard.GetBitmap

        End Sub

     

    Public Class MyPaint

        Public Sub CleanAllImage(ByVal x As Integer, ByVal y As Integer, ByVal w As Integer, ByVal h As Integer)
            Dim clean As New Bitmap(w, h)
            Dim clean_g As Graphics = Graphics.FromImage(clean)
            clean_g.Clear(Color.Transparent)     '
    若是用透明填滿 底圖看得到 但是有殘影

         '   clean_g.Clear(Color.White)    '
    若是用白色填滿 底圖看不到 畫面變成白色 沒有殘影

            g.DrawImage(clean, x, y)

        End Sub
    End Class

     

    2008年3月14日 下午 02:29

解答

所有回覆

  • 你可以先搜尋 PictureBox 透明

    http://forums.microsoft.com/MSDN-CHT/Search/Search.aspx?words=PictureBox+%u900f%u660e&localechoice=31748&SiteID=14&searchscope=forumscope&ForumID=232

     

    裡面有一堆既有討論,.Net 的 PictureBox 的透明並非你想像的做法,實際上會有很多問題。

    我自己是畫在一張圖上,透過圖層控制來決定哪些要畫,例如:

     

    2008年3月14日 下午 04:33
    版主
  •  

    我有做過類似圖片合成的Work你試試看這個方法

     

    將底圖放在PictureBox.BackImage

    將要繪製的座標放在PictureBox.Image

     

    只使用一個PictureBox應該就可以解決你的問題了.....

    2008年3月18日 上午 02:12
  • 謝謝 璉璉大大跟Louis 的協助,

    後來 我改用一個 picturebox , 另外 使用一個畫板, 平常的繪圖工作都先畫在畫板上。

    myGraphics = Me.PictureBox1.CreateGraphics

    DrawingBoard = New MyPaint(Me.PictureBox1.Width, Me.PictureBox1.Height, Me.PictureBox1.BackColor)

     

    myGraphics.DrawImage(DrawingBoard.GetBitmap, 0, 0)

    '需要顯示座標時(按滑鼠右鍵拖曳時),先把 DrawingBoard(原圖) 畫到PictureBox1 裡,然後把座標值 直接畫在 picturebox

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove

            '按滑鼠左鍵拖曳

    Dim s As String

            If e.Button = Windows.Forms.MouseButtons.Left Then

                '讀取原圖畫板,不讓圖有殘影

               

                myGraphics.DrawImage(DrawingBoard.GetBitmap, 0, 0)

    Select Case DrawingBoard.StyleFlag

               Case "Cross"

                        crossIcon(e.X, e.Y)

     

                End Select

            End If

        End Sub

     

        Sub crossIcon(ByVal ex As Integer, ByVal ey As Integer)

      

              s = "(" & ex.ToString & "," & ey.ToString & ")"

            Me.myGraphics.DrawLine(Pens.Black, 0, ey, Me.PictureBox1.Width, ey)

            Me.myGraphics.DrawLine(Pens.Black, ex, 0, ex, Me.PictureBox1.Height)

     

            Dim myfont As Font

            myfont = New System.Drawing.Font("新細明體", 16.0, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point)

            Me.myGraphics.DrawString(s, myfont, Brushes.Black, ex + 10, ey - 20)

     

        End Sub

    '最後 mouse 放開時,再把畫板的原圖再放回 picturebox1 , 把有座標的圖蓋掉,就大概得到我要的結果了

    Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp

      Select Case DrawingBoard.StyleFlag

    Case "Cross"

                    myGraphics.DrawImage(DrawingBoard.GetBitmap, 0, 0)

            End Select

        End Sub

     

    不過 璉璉大大 說的圖層控制 是怎麼做的?

    能否提供範例給我參考一下呢?

     

    2008年3月18日 上午 07:42
  • 基本觀念是參考左邊工具列是否為 Checked ,由下往上畫。

     

    我自己在做是弄一個資料表,叫做 MapList ,裡面決定圖層的順序、是否顯示與相關資訊。

     

    當工具列的圖層被點選時,依照圖層順序呼叫 DrawImage 畫到一個記憶體中的圖檔,最後再畫出來,而圖層裡若是直接是圖檔的,就直接疊,若是資料檔的,依據圖層屬性呼叫對應的繪圖函式輸出圖檔,在套疊在一起。

     

    你的說明看起來是要做選取框?先前我有貼個範例在版上,後來有看到 MSDN 上也有個範例,有把 MSDN 上的那個範例網址放到板上的公告裡面。

     

    我的做法跟 MSDN 差不多,都是弄成一個 ShapeControl 來畫。

    2008年3月18日 上午 07:56
    版主