• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Các bài viết hướng dẫn về Visual Basic .NET và C#

Moderators: tungcan5diop, QUANITGROBEST

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Thu 23/10/2008 4:25 pm

Tên bài viết: Tập tành vẽ những nét cơ bản
Tác giả: 1045007
Cấp độ bài viết: nâng cao đối với những ai đang cơ bản.
Tóm tắt: các bạn thấy rằng ngày càng có nhiều các phần mềm về đồ họa, chỉnh sửa ảnh cho ra đời, chúng ta dễ dàng nhận ra các điểm chung giữa các sản phẩm đó là đầu vào là một tấm ảnh (hoặc không), đầu ra là một tấm ảnh đã được xử lý. Ở đây tôi không nói về vấn đề xử lý như thế hay các cấu trúc file ảnh ra sao vì khả năng tôi có giới hạn… Nhưng tôi sẽ hướng dẫn các bạn cách kết xuất ra một file ảnh do chính ta vẽ ra và hiểu được cách làm việc của các nét vẽ cơ bản (pixel, hình tròn, hình chữ nhật…).


Project:
UseGraphic.rar
(111.1 KiB) Downloaded 2515 times



Phần I: Vẽ Ảnh



I. CÁC NÉT VẼ CƠ BẢN

Các khai báo cần thiết:

Code: Select all

  1. Dim bm As Bitmap 'biến bitmap lưu những gì ta đã vẽ
  2.     Dim gp As Graphics 'biến chính để vẽ ảnh
  3.     Dim draw As Boolean
  4.     Dim line As String = "pixel" 'kiểu vẽ
  5.     Dim c As Color = Color.Black 'Màu vẽ
Trong Form cho đối tượng PictureBox có Name là pic.
Nếu chỉ để vẽ lên đối tượng ta chỉ cần viết code:

Code: Select all

  1. 'gan giá trị Graphics của đối tượng cho gp
  2. gp = Me.pic.CreateGraphics()

Vấn đề là khi runtime form luôn được vẽ lại khi có sự tác động, hậu quả là nó xóa luôn những gì ta đã vẽ lên.

Để khắc phục hiện tượng trên ta cần lưu những gì đã vẽ được vào một BitMap.

Code: Select all

  1. 'Thủ tục Chính để khởi tạo và thể hiện bm lên pictureBox
  2.     Private Sub NewBitmap(ByVal w As Integer, ByVal h As Integer)
  3.         bm = New Bitmap(w, h)
  4.         Me.pic.Image = bm
  5.         gp = Graphics.FromImage(bm)
  6.     End Sub


1. Nét vẽ điểm (pixel)
Trong lớp Drawing2D không có sẵn hàm vẽ một điểm như là putpixel(x,y) trong ngôn ngữ C,C++…

Để vẽ một điểm ta có thể dùng:

Code: Select all

  1. bm.SetPixel(100, 100, Color.Black)


Mặc khắc có thể dùng hàm FillRectangle tô một hình chữ nhật có chiều dài và rộng = 1.

Code: Select all

  1. Private Sub pixel(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         point = New Point(e.X, e.Y)
  3.         gp.FillRectangle(New Pen(c).Brush, point.X, point.Y, 1, 1)
  4.     End Sub

Bây giờ ta muốn khi rê chuột đến đâu, click chổ nào thì vẽ tại chổ đó, hoặc vừa kéo chuột vừa vẽ.
Vậy ta sẽ bắt 3 sự kiện chính: MouseDown, MouseUp, MouseMove của PictureBox cần vẽ lên.

Code: Select all

  1. Private Sub pic_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseDown
  2.         If e.Button = Windows.Forms.MouseButtons.Left Then
  3.                 draw = True
  4.                 MyDraw(e)
  5.         End If
  6.     End Sub
  7.  
  8.     Private Sub pic_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseMove
  9.         If draw = True Then
  10.             MyDraw(e)
  11.         End If
  12.     End Sub
  13.  
  14.     Private Sub pic_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseUp
  15.         If draw = True Then
  16.             draw = False
  17.         End If
  18.     End Sub

Còn đây là thủ tục MyDraw(e) chính gọi lại thủ tục pixel(e):

Code: Select all

  1. Private Sub MyDraw(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         If line = "pixel" Then
  3.             pixel(e)
  4.         End If
  5.     End Sub


Bây giờ thử được rồi đấy! kết quả mà ta mong đợi chắc là vầy:
1.PNG
1.PNG (12.96 KiB) Viewed 19457 times

Nhưng kết quả thực thì là vầy:
2.PNG
2.PNG (12.39 KiB) Viewed 19461 times

Lý do: tốc độ của vết chuột đi qua là rất cao mà sự kiện MouseMove không thể bắt kịp được tất cả các điểm đó nên kết quả cho ta thấy như hình trên.
Để khắc phục được nhược điểm, ta để ý rằng mỗi lần vết chuột đi qua nó cho ta một điểm, khoảng cách giữa 2 điểm liên tiếp vết chuột đi qua là tương đối gần do sự kiện MouseMove bắt được. Nên việc nối 2 điểm gần này lại với nhau là có thể tạm chấp nhận được.
Vậy việc cần làm là lưu các điểm vết chuột đi qua rồi nối chúng lại với nhau. Rất may lớp Drawing2D cho ta sẵn một kiểu GraphicsPath để lưu lại những gì ta vẽ lên:

Code: Select all

  1. 'Lưu lại đường thẳng được nối từ các điểm
  2. Dim mousepath As New GraphicsPath
  3. Dim point As Point 'Lưu các điểm đi qua

Thủ tục pixel và MyDraw được viết lại như sau:

Code: Select all

  1. Private Sub pixelDrag(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         point = New Point(e.X, e.Y)
  3.         mousepath.AddLine(point, point)
  4.         gp.DrawPath(New Pen(c), mousepath)
  5.     End Sub
  6.     Private Sub MyDraw(ByVal e As System.Windows.Forms.MouseEventArgs)
  7.         If line = "pixel" Then
  8.             pixel(e)
  9.             pixelDrag(e)
  10.         Me.pic.Invalidate()
  11.         End If
  12.     End Sub

Nhớ lưu rồi thì phải xóa để còn sử dụng lại:

Code: Select all

  1. Private Sub pic_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseUp
  2.         If draw = True Then
  3.             draw = False
  4.             mousepath.Reset()
  5.         End If
  6.     End Sub


Và đây khuyến mãi thêm con chuột nhìn trông có vẽ pro hơn:

Code: Select all

  1. Public Function CreateCursor(ByVal bm As Bitmap, ByVal size As Size) As Cursor
  2.         Try
  3.             bm = New Bitmap(bm, size)
  4.             bm.MakeTransparent()
  5.             Return New Cursor(bm.GetHicon)
  6.         Catch ex As Exception
  7.         End Try
  8.         Return Cursors.Default
  9.     End Function


Xong! bây giờ thử nhé:

Code: Select all

  1. Private Sub f_paint_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  2.         NewBitmap(Me.pic.Width, Me.pic.Height)
  3.     End Sub
Last edited by 1045007 on Thu 04/12/2008 4:58 pm, edited 11 times in total.


Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
Dang Minh Du
Thành viên ưu tú
Thành viên ưu tú
Posts: 531
Joined: Wed 02/04/2008 2:08 pm
Location: RGames Team
Has thanked: 3 times
Been thanked: 17 times
Contact:

Re: Sử Dụng Lớp Drawing2D - Vẽ Những Nét Cơ Bản

Postby Dang Minh Du » Thu 23/10/2008 4:29 pm

Đâu rồi, post nhanh đi anh, em muốn tập tành một chút về Graphic đây :)
~°Dòng Sông Mùa Thu°~
Studying...!

User avatar
VBNewbie
Thành viên tích cực
Thành viên tích cực
Posts: 113
Joined: Sat 29/03/2008 7:13 pm
Location: Computer
Been thanked: 3 times
Contact:

Re: Sử Dụng Lớp Drawing2D - Vẽ Những Nét Cơ Bản

Postby VBNewbie » Thu 23/10/2008 4:38 pm

Hay quá ! Very cool ! Đang cần !
Post thêm đi anh !
Còn vẽ trong 3D thì sao !
-------[[[[[[[ VMind - PM trắc nghiệm đa năng ]]]]]]]]------
http://vmind.co.cc/vmind
-------[[[[ Diễn đàn trí tuệ Việt Nam ! ]]]]]]]]-----
http://vmind.co.cc

User avatar
anhtuyenbk
Guru
Guru
Posts: 1311
Joined: Thu 22/09/2005 4:12 pm
Location: Một nơi chừa từng biết, chưa từng nghe, chưa từng thấy
Been thanked: 38 times

Re: Sử Dụng Lớp Drawing2D - Vẽ Những Nét Cơ Bản

Postby anhtuyenbk » Thu 23/10/2008 4:42 pm

Hay lắm, cố lên post tiếp nữa đi.
Dang Minh Du wrote:Đâu rồi, post nhanh đi anh, em muốn tập tành một chút về Graphic đây :)

Muốn nghiên cứu nhanh thì tải cuốn Pro Control Net của Hai PT hay mấy cuốn VB Pro kìa, có nhiều đọc lắm --> chỉ có điều phải chịu khó đọc English >:) >:)
Kiếm cơm cho qua ngày tháng
https://www.facebook.com/pinduphongpisenchinhhang

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Thu 23/10/2008 9:14 pm

VBNewbie wrote:Hay quá ! Very cool ! Đang cần !
Post thêm đi anh !
Còn vẽ trong 3D thì sao !

Hiện tại thấy trong đây chưa có cái nào nên post lên cho anh em xem. Rất tiếc 3D thì .Net không có sẵn, sử dụng DirectX thì đã có hdn rồi:
Xem link: http://www.caulacbovb.com/forum/viewtopic.php?f=23&t=26
Last edited by 1045007 on Sat 29/11/2008 7:43 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Fri 24/10/2008 3:21 pm

2. Nét lớn có thể thay đổi kích thước

Khai báo thêm biến pensize kích thước của nét cần vẽ:

Code: Select all

  1. Dim pensize As Single = 2

Lưu ý: có 2 trạng thái vẽ là click là vẽ và vừa kéo chuột vừa vẽ. Nên ta phải bắt 2 trường hợp này một cách riêng biệt để nét vẽ không đè lên nhau.
Nét chấm:

Code: Select all

  1.    Private Sub pixelchangesize(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         point = New Point(e.X, e.Y)
  3.         gp.FillRectangle(New Pen(c).Brush, (point.X - pensize / 2), (point.Y - pensize / 2), pensize, pensize)
  4.     End Sub

Nét vừa kéo vừa vẽ:

Code: Select all

  1.    Private Sub PixelChangeSizeDrag(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         point = New Point(e.X, e.Y)
  3.         mousepath.AddLine(point, point)
  4.         gp.DrawPath(New Pen(c, pensize), mousepath)
  5.     End Sub

Giải thích về 2 thủ tục trên (Xem hình)
3.PNG
3.PNG (4.24 KiB) Viewed 19355 times

Với 1: điểm nhấn vẽ là chấm đỏ trên hình 1, trông có vẽ bất tiện vì điểm nhấn vẽ và nét vẽ hiển thị không cân đối.
Với 2: dời nét vẽ hiển thị sao cho điểm nhấn vẽ nằm tại giao điểm của như hình 2.
Thủ tục MyDraw(e) được viết lại như sau:

Code: Select all

  1.    Private Sub MyDraw(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         If line = "pixel" Then
  3.             pixelDrag(e)
  4.         ElseIf line = "pixelchangesize" Then
  5.             PixelChangeSizeDrag(e)
  6.         End If
  7.         Me.pic.Invalidate()
  8.     End Sub

Sự kiện MouseDown được viết lại như sau:

Code: Select all

  1.    Private Sub pic_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseDown
  2.         If e.Button = Windows.Forms.MouseButtons.Left Then
  3.             draw = True
  4.             If line = "pixel" Then
  5.                 pixel(e)
  6.                 pixelDrag(e)
  7.             ElseIf line = "pixelchangesize" Then
  8.                 pixelchangesize(e)
  9.                 PixelChangeSizeDrag(e)
  10.             End If
  11.             Me.pic.Invalidate()
  12.         End If
  13.     End Sub


Để kiểm tra những gì ta đã làm, cho thêm vào Form một ComboBox có Name là cb_size, Viết code:

Code: Select all

  1.    Private Sub cb_size_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cb_size.SelectedIndexChanged
  2.         pensize = Me.cb_size.SelectedItem
  3.     End Sub


Kết Quả:
4.PNG
4.PNG (21.49 KiB) Viewed 19356 times
Last edited by 1045007 on Sat 29/11/2008 7:44 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
Kasper
Guru
Guru
Posts: 1063
Joined: Fri 16/05/2008 10:54 am
Has thanked: 2 times
Been thanked: 76 times
Contact:

Re: Sử Dụng Lớp Drawing2D - Vẽ Những Nét Cơ Bản

Postby Kasper » Fri 24/10/2008 4:54 pm

Tiếp đi bạn, làm thành một cái Paint = .net luôn đi :D :D
Lành tợ tòng, ác tợ hoa,
Nhà hòa muôn việc đều nên.

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Sat 25/10/2008 4:16 pm

3. Nét tròn


Cũng với ý tưởng mousepath, mà làm sao mà pixel lại tròn ? Ta chỉ tưởng tượng ra thôi. Là vầy, chấm đại 1 điểm sau đó lấy tiếp 4 điểm xung quanh, nhìn giống dấu + hơn!
5.PNG
5.PNG (2.37 KiB) Viewed 19299 times

Nhìn kỹ hình trên nhé! Chính xác là có 5 pixel: vàng, đỏ, xanh, xanh lá và 1 cái pixel lộn xộn. Do tôi tăng kích thước của mỗi ô lên 1 đơn vị nên nhìn thấy cái pixel lộn xộn hầu như bị đè lên bởi 4 pixel lân cận.
Việc tăng khích lên là có cơ sở nó làm giảm lượng pixel ta cần vẽ nhưng mật độ thì không thay đổi. Như hình trên cái pixel lộn xộn là không cần thiết nửa vậy ta xóa nó đi và nó cũng chính là điểm nhấn của chuột.

Vậy cần khai thêm 4 đối tượng sau:

Code: Select all

  1. Dim path1 As New GraphicsPath
  2. Dim path2 As New GraphicsPath
  3. Dim path3 As New GraphicsPath
  4. Dim path4 As New GraphicsPath


Thủ tục PixelFullDrag(e) được viết như sau:

Code: Select all

  1. Private Sub PixelFullDrag(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         point = New Point(e.X, e.Y)
  3.         path1.AddLine(New Point(point.X, point.Y - 1), New Point(point.X, point.Y - 1))
  4.         path2.AddLine(New Point(point.X + 1, point.Y), New Point(point.X + 1, point.Y))
  5.         path3.AddLine(New Point(point.X, point.Y + 1), New Point(point.X, point.Y + 1))
  6.         path4.AddLine(New Point(point.X - 1, point.Y), New Point(point.X - 1, point.Y))
  7.  
  8.         gp.DrawPath(New Pen(c, 2), path1)
  9.         gp.DrawPath(New Pen(c, 2), path2)
  10.         gp.DrawPath(New Pen(c, 2), path3)
  11.         gp.DrawPath(New Pen(c, 2), path4)
  12.     End Sub


Và PixelFull(e):

Code: Select all

  1.    Private Sub PixelFull(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         point = New Point(e.X, e.Y)
  3.         gp.FillRectangle(New Pen(c).Brush, point.X - 1, point.Y - 1 - 1, 2, 2)
  4.         gp.FillRectangle(New Pen(c).Brush, point.X + 1 - 1, point.Y - 1, 2, 2)
  5.         gp.FillRectangle(New Pen(c).Brush, point.X - 1, point.Y + 1 - 1, 2, 2)
  6.         gp.FillRectangle(New Pen(c).Brush, point.X - 1 - 1, point.Y - 1, 2, 2)
  7.     End Sub


Thủ tục MyDraw(e) được viết lại như sau:

Code: Select all

  1.    Private Sub MyDraw(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         If line = "pixel" Then
  3.             pixelDrag(e)
  4.         ElseIf line = "pixelchangesize" Then
  5.             PixelChangeSizeDrag(e)
  6.         ElseIf line = "pixelfull" Then
  7.             PixelFullDrag(e)
  8.         End If
  9.         Me.pic.Invalidate()
  10.     End Sub


Trong sự kiện MouseDown viết tiếp dòng này:

Code: Select all

  1. ...............
  2. ElseIf line = "pixelfull" Then
  3.                 PixelFull(e)
  4.                 PixelFullDrag(e)
  5.             End If


Sau khi vẽ xong 1 nét ta Reset path lại:

Code: Select all

  1.    Sub ResetPath()
  2.         mousepath.Reset()
  3.         path1.Reset()
  4.         path2.Reset()
  5.         path3.Reset()
  6.         path4.Reset()
  7.     End Sub
  8.  
  9. Private Sub pic_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseUp
  10.         If draw = True Then
  11.             draw = False
  12.             ResetPath()
  13.         End If
  14.         End Sub



TẠM DỪNG Ở ĐÂY! BÀI SAU NÓI VỀ CÁC NÉT....?
Last edited by 1045007 on Sat 29/11/2008 7:45 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Tue 28/10/2008 6:42 pm

HỆ SỐ ZOOM


Độ phóng đại là tỷ lệ kích thước của ảnh phóng đại so với ảnh gốc (ảnh ban đầu), được tính bằng kích thước của ảnh gốc (rộng, cao) nhân cho hệ số zoom n.
Từ bài này trở về sau mặc định trong các hàm tôi luôn tính sẵn hệ số zoom trong đó và chỉ nêu các hàm chính còn thao tác để vẽ thì các bạn đã hiểu, các bài viết trước các bạn sửa lại cho phù hợp.

Để khảo sát, ta thêm vào 2 biến:

Code: Select all

  1. Public zoom As Single = 1 ‘hệ số ban đầu bằng 1
  2. Dim bmsize As Size ‘lưu kích thước ảnh thật


Ta thêm vào Form đối tượng ComboBox có Name là cb_zoom gồm các giá trị (1,2,4,8)

Code: Select all

  1.    Private Sub cb_zoom_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cb_zoom.SelectedIndexChanged
  2.         If Me.cb_zoom.SelectedIndex = 0 Then
  3.             zoom = 1
  4.         ElseIf Me.cb_zoom.SelectedIndex = 1 Then
  5.             zoom = 2
  6.         ElseIf Me.cb_zoom.SelectedIndex = 2 Then
  7.             zoom = 4
  8.         Else
  9.             zoom = 8
  10.         End If
  11.         Me.pic.Size = New Size(bmsize.Width * zoom, bmsize.Height * zoom)
  12.     End Sub

Để dịch ngược lại giá trị thật:

Code: Select all

  1.           Private Sub pic_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic_center.MouseMove
  2.             Me.lb_pixel.Text = "Điểm ảnh: ( " & (e.X \ zoom).ToString & " , " & (e.Y \ zoom).ToString & " )"
  3.            End Sub
Last edited by 1045007 on Sat 29/11/2008 7:45 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Tue 28/10/2008 7:00 pm

II. Các Nét: Đường Thẳng, Hình Tròn, Hình Chữ Nhật…


1. Vẽ Đường Thẳng
Khái quát: đường thẳng, hình tròn, hình chữ nhật,… là những hình tương đối đặc biệt, đặc biệt ở đây không phải là ghê gốm gì mà ở chổ các nét này từ lúc đặt điểm chuột rồi kéo, đến lúc thôi nhấn chuột mới tạo nên một hình (cần vẽ) thật sự, và trong giữa 2 thời điểm đó có vô số các hình (không cần thiết) tạo ra. Vấn đề là chổ này, làm sao để chỉ lấy được những nét cần vẽ là thực sự cần thết.
- Có nhiều cánh khắc phục, mà cách này là một trong những cánh tôi thích nhất khi trình bày vì (ngoài cách này ra tôi chưa biết cách nào khác…ac ac).
Thế này: tạo 1 Picture khác tạm gọi là picture mặt nạ (pic_Mask), khi ấy ta vẽ vô tư lên pic_Mask này đến lúc xong rồi vẽ lại hình này vào pic thật của ta.
- Đại khái là vậy, để đơn giản tôi sử dụng nốt thuộc tính BackGoundImage của pic để làm điều này.
Cần khai báo:

Code: Select all

  1. Dim bmdown As Bitmap 'lưu ảnh khi chuột vừa nhấn xuống

Thủ tục MouseDown viết lại tiếp…

Code: Select all

  1.             .....
  2.              ElseIf line = "line" Then
  3.                 point = New Point(e.X / zoom, e.Y / zoom)
  4.                 bmdown = New Bitmap(bm)
  5.                 Me.pic.BackgroundImage = bmdown
  6.             End If


Và Mouseup…

Code: Select all

  1.            If line = "line" Then
  2.                 Me.pic.BackgroundImage = Nothing
  3.                 gp.DrawImage(bmdown, 0, 0)
  4.                 gp.DrawLine(New Pen(c), New Point(point.X / zoom, point.Y / zoom),  New Point(e.X / zoom, e.Y / zoom))
  5.             End If

Thủ tục chính MyLine(e)

Code: Select all

  1.    Private Sub MyLine(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         gp.Clear(Color.Empty)
  3.   gp.DrawLine(New Pen(c), New Point(point.X / zoom, point.Y / zoom),  New Point(e.X / zoom, e.Y / zoom))    
  4.     End Sub
Last edited by 1045007 on Sat 29/11/2008 7:46 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Thu 30/10/2008 5:45 pm

2. Hình Chữ Nhật


- Cũng giống với cách vẽ đường thẳng, xuất phát từ điểm bắt đầu và điểm kết thúc, nhưng lúc này không phải nối 2 điểm lại mà ta đi xác định điểm kết thúc nằm ở vị trí nào so với điểm bắt đầu: bên trái, bên phải, phía trên, phía dưới, bên phải phía dưới, bên phải phía trên…
- Mục đích của việc xác định vị trí đó nhằm tính khoảng cách giữa 2 điểm và thể hiện hình chữ nhật một cách phù hợp
- Tiến hành khai báo:

Code: Select all

  1.    'Lấy hình chữ nhật hiện tại
  2.     Dim rec As Rectangle


Khoản cách 2 điểm A & B

Code: Select all

  1.    Private Function Distance(ByVal A As Point, ByVal B As Point) As Integer
  2.         Return CType(Math.Sqrt((B.X - A.X) ^ 2 + (B.Y - A.Y) ^ 2), Integer)
  3.     End Function


Thủ tục vẽ hình chữ nhật

Code: Select all

  1.    Private Sub Rectangle(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         Dim npoint As New Point(e.X / zoom, e.Y / zoom)
  3.         gp.Clear(Color.Empty)
  4.         Dim teampoint As Point
  5.         If npoint.X > point.X And npoint.Y > point.Y Then
  6.             teampoint = New Point(point.X, point.Y)
  7.         ElseIf npoint.X < point.X And npoint.Y < point.Y Then
  8.             teampoint = New Point(npoint.X, npoint.Y)
  9.         ElseIf npoint.X > point.X And npoint.Y < point.Y Then
  10.             teampoint = New Point(point.X, npoint.Y)
  11.         ElseIf npoint.X < point.X And npoint.Y > point.Y Then
  12.             teampoint = New Point(npoint.X, point.Y)
  13.         End If
  14.         rec = New Rectangle(teampoint, New Size(Distance(point, New Point(npoint.X, point.Y)), Distance(point, New Point(point.X, npoint.Y))))
  15.         gp.DrawRectangle(New Pen(c, pensize), rec)
  16.  
  17.     End Sub

Sự kiện MouseUp sửa:

Code: Select all

  1.            .............
  2.             If line = "rectangle" Then
  3.                 Me.pic.BackgroundImage = Nothing
  4.                 gp.DrawImage(bmdown, 0, 0)
  5.                 gp.DrawRectangle(New Pen(c, pensize), rec) ' rec: HCN được lấy trong lúc vẽ
  6.             End If



3. Hình tròn
- Tương tự hình chữ nhật, sửa lại là DrawElip
Last edited by 1045007 on Sat 29/11/2008 7:47 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Mon 10/11/2008 5:37 pm

III. Lấy Màu và Tô Màu


1. Lấy Màu

- Đối tượng bm cho ta phương thức GetPixel(x,y) kiểu trả về là một màu tại điểm được chỉ định
- Lấy màu không giống với các nét vẽ mà ta đã trình bày ở trên, chỉ cần click chuột là lấy không cần phải Drag chuột, đồng thời kiểm tra xem màu vừa lấy có trùng với màu trong suốt hay không nếu có thì bỏ qua.
Thủ Tục GetColor(e) được viết như sau:

Code: Select all

  1. 'Lay mau____________
  2.     Private Sub GetColor(ByVal e As System.Windows.Forms.MouseEventArgs)
  3.         Try
  4.             point = New Point(e.X / zoom, e.Y / zoom)
  5.             If bm.GetPixel(point.X, point.Y) <> Color.FromArgb(0, 0, 0, 0) Then
  6.                 c = bm.GetPixel(point.X, point.Y)
  7.                 Me.lb_color.BackColor = c
  8.                 Me.bt_Color.ForeColor = c
  9.             End If
  10.         Catch ex As Exception
  11.         End Try
  12.     End Sub


Bạn đưa thủ tục này vào sự kiện Pic_MouseDown(..) của Picturebox không cần phải đưa vào thủ tục MyDraw(e)
Last edited by 1045007 on Sat 29/11/2008 7:47 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Tue 11/11/2008 5:57 pm

2. Tô màu vùng khép kín

- Lớp Graphics cung cấp cho ta khá đầy đủ các phương thức tô màu, cũng như các phương thức vẽ, các phương thức này luôn đứng đầu bởi tiếp đầu ngữ Fill…
- Để tô màu 1 hình chữ nhật ta dùng: FillRectangle(…), hình tròn FillElip(…) ...
- Nhìn chung, các phương thức tô màu trên chỉ tô những vùng chưa xác định hoặc các vùng ta đã biết trước Region của nó. Vậy để tô một vùng khép kín ngẫu nhiên hay chưa xác định được Region các bạn tham khảo 1 Class trích xuất từ thư viện gdi32.

Code: Select all

  1. ' Tham khao ham API cua thu vien gdi32
  2. Public Class FillColor
  3.  
  4. #Region " FloodFill"
  5.  
  6.     Private Structure BITMAPINFOHEADER
  7.         Dim biSize As Integer
  8.         Dim biWidth As Integer
  9.         Dim biHeight As Integer
  10.         Dim biPlanes As Short
  11.         Dim biBitCount As Short
  12.         Dim biCompression As Integer
  13.         Dim biSizeImage As Integer
  14.         Dim biXPelsPerMeter As Integer
  15.         Dim biYPelsPerMeter As Integer
  16.         Dim biClrUsed As Integer
  17.         Dim biClrImportant As Integer
  18.     End Structure
  19.  
  20.     ' Truy cap thu vien
  21.     Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As IntPtr) As IntPtr
  22.     Private Declare Function CreateDIBSection Lib "gdi32" (ByVal hdc As IntPtr, ByRef pBitmapInfo As BITMAPINFOHEADER, ByVal un As Integer, ByRef lplpVoid As IntPtr, ByVal handle As Integer, ByVal dw As Integer) As IntPtr
  23.     Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal dwRop As Integer) As Integer
  24.     Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal crColor As Integer, ByVal wFillType As Integer) As Integer
  25.     Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Integer) As IntPtr
  26.     Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As IntPtr, ByVal X As Integer, ByVal Y As Integer) As Integer
  27.     Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As IntPtr, ByVal hObject As IntPtr) As IntPtr
  28.     Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As IntPtr) As Integer
  29.     Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As IntPtr) As Integer
  30.     Private Declare Function GdiFlush Lib "gdi32" Alias "GdiFlush" () As Integer
  31.     Private Const SRCCOPY As Integer = &HCC0020
  32.  
  33.  
  34.     Public Sub FloodFill(ByRef bm As Bitmap, ByVal col As Color, ByVal Pt As Point)
  35.         If bm Is Nothing Then Exit Sub
  36.         Dim srcDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)
  37.         Dim dstDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)
  38.         Dim dstBMI As BITMAPINFOHEADER
  39.         With dstBMI
  40.             .biBitCount = 24
  41.             .biHeight = bm.Height
  42.             .biSize = System.Runtime.InteropServices.Marshal.SizeOf(dstBMI)
  43.             .biWidth = bm.Width
  44.             .biPlanes = 1
  45.         End With
  46.         Dim dstBits As IntPtr
  47.         Dim mbmpGetHbitmap As IntPtr = bm.GetHbitmap
  48.         'Select the bitmap into an HDC
  49.         Dim Obmp As IntPtr = SelectObject(srcDC, mbmpGetHbitmap)
  50.         'Create a DIB
  51.         Dim dstBMP As IntPtr = CreateDIBSection(dstDC, dstBMI, 0, dstBits, 0, 0)
  52.         Dim Obmp2 As IntPtr = SelectObject(dstDC, dstBMP)
  53.         'Place our bitmap in the DIB
  54.         BitBlt(dstDC, 0, 0, bm.Width, bm.Height, srcDC, 0, 0, SRCCOPY)
  55.         GdiFlush()
  56.         'Create a brush to use to FloodFill
  57.         Dim mBrush As IntPtr = CreateSolidBrush(System.Drawing.ColorTranslator.ToOle(col))
  58.         Dim hmm As IntPtr = SelectObject(dstDC, mBrush)
  59.         'Fill with color
  60.         ExtFloodFill(dstDC, Pt.X, Pt.Y, GetPixel(dstDC, Pt.X, Pt.Y), 1)
  61.         'Get the bitmap back with the Filled Color
  62.         bm = Bitmap.FromHbitmap(dstBMP)
  63.         'Go berserk clearing memory
  64.         'ExtFloodFill has a bad reputation for gobbling up memory
  65.         'if you dont clean up properly
  66.         DeleteObject(mBrush)
  67.         DeleteObject(SelectObject(dstDC, mBrush))
  68.         DeleteObject(SelectObject(dstDC, dstBMP))
  69.         DeleteObject(SelectObject(srcDC, mbmpGetHbitmap))
  70.         DeleteObject(hmm)
  71.         DeleteObject(dstBits)
  72.         DeleteObject(Obmp2)
  73.         DeleteObject(Obmp)
  74.         DeleteObject(dstBMP)
  75.         DeleteDC(dstDC)
  76.         DeleteDC(srcDC)
  77.         mbmpGetHbitmap = Nothing
  78.         hmm = Nothing
  79.         dstBits = Nothing
  80.         Obmp2 = Nothing
  81.         Obmp = Nothing
  82.         dstBMP = Nothing
  83.         dstDC = Nothing
  84.         srcDC = Nothing
  85.         dstBMI = Nothing
  86.     End Sub
  87.  
  88. #End Region
  89. End Class


- Sử Dụng: Do tham số bm của phương thức FloodFill được chuyền theo kiểu tham chiếu làm thay đổi tham số đầu vào nên khi sử dụng phương thức này nó sẽ tạo ra một bitmap làm che lắp bm đang vẽ và chúng ta không thể tiếp tục...

- Thủ tục FillColor(e) được viết như sau:

Code: Select all

  1. Private Sub FillColor(ByVal e As System.Windows.Forms.MouseEventArgs)
  2.         Try
  3.             Dim f_fill As New FillColor
  4.             f_fill.FloodFill(Me.pic.Image, c, New Point(e.X / zoom, e.Y / zoom))
  5.             ' Xoa bitmap cua ham FloodFill
  6.             bm = New Bitmap(Me.pic.Image)
  7.             Me.pic.Image = bm
  8.             gp = Graphics.FromImage(bm)
  9.         Catch ex As Exception
  10.         End Try
  11.     End Sub
Last edited by 1045007 on Sat 29/11/2008 7:48 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
vo_minhdat2007
Quản trị
Quản trị
Posts: 2227
Joined: Sun 17/07/2005 1:40 am
Has thanked: 13 times
Been thanked: 87 times
Contact:

Re: Sử Dụng Lớp Drawing2D - Vẽ Những Nét Cơ Bản

Postby vo_minhdat2007 » Thu 13/11/2008 5:41 pm

Xin giúp em chút nhé : Em tạo 1 mạng lưới khoảng 100 ô. Tuy nhiên em tạo label Loading ở trên che hết hoạt động và hiện %, tuy nhiên khi unload cái Label thì toàn bộ các đường vẽ... tiêu hết :( . Trường hợp ko có cái Label thì OK. Có cách nào không hay đành làm cái Label ở form khác?

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Thu 13/11/2008 5:51 pm

Vẽ trong sự kiện paint thì không có việc bị mất.
Nếu vẽ trên Bitmap thì dùng Invalidate() cập nhật lại.
Last edited by 1045007 on Sat 29/11/2008 7:50 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
vo_minhdat2007
Quản trị
Quản trị
Posts: 2227
Joined: Sun 17/07/2005 1:40 am
Has thanked: 13 times
Been thanked: 87 times
Contact:

Re: Sử Dụng Lớp Drawing2D - Vẽ Những Nét Cơ Bản

Postby vo_minhdat2007 » Thu 13/11/2008 7:15 pm

Code đây :

Code: Select all

  1. For i As Integer = 0 To 9
  2.             For j As Integer = 0 To 9
  3.                 PGr.DrawImage(My.Resources.Square, New RectangleF(10 + 30 * i, 10 + 30 * j, 30, 30))
  4.                 CGr.DrawImage(My.Resources.Square, New RectangleF(10 + 30 * i, 10 + 30 * j, 30, 30))
  5.             Next
  6.         Next

Dù đặt sự kiện nào (trừ Paint) đều bị mất sau khi load, còn đặt trong sự kiện Paint thì nó lại vẽ nhiều lần (trong form còn vài picturebox khác)!

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Thu 13/11/2008 10:33 pm

Vẽ lại nhiều lần là đúng rồi! vì mỗi lần active form thì form dc vẽ lại lúc này nó không nhận dc đối tượng đồ họa đã vẽ! nên ta đặc trong Paint(e), Lấy cái e này vẽ!

Trong Form còn vài PictureBox khác là sao nhỉ? nói rõ xem sao?
Xem thử cái này:
Attachments
Project.rar
(256.79 KiB) Downloaded 688 times
Last edited by 1045007 on Sat 29/11/2008 7:50 am, edited 1 time in total.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Sat 22/11/2008 4:10 pm

IV. Lưu Ảnh


- Cho vào Form 1 saveFileDialog và 1 MainMenuTrip.
- Để lưu ảnh ta dùng phương thức save của đối tượng bm: bm.Save(FileName,ImageFormat).
- Lưu ảnh là phần quan trọng trong quá trình vẽ ảnh, đôi khi đang vẽ vô tình nhấn vào nút close của Form thì mọi thứ ta đã làm cũng vô tình biến mất. Vậy hãy xác định rõ trạng thái lưu hay chưa lưu để phản hồi lại sự kiện Closing của Form.
- Các biến cần khai báo:

Code: Select all

  1. Dim saved As Boolean = True ‘Giữ trạng thái đã save
  2. Me.SaveFileDialog1.Filter = "Bitmap file|*.bmp|jpg file|*.jpg|png file|*.png" ‘Khai bộ lọc gồm 3 loại định dạng


Thủ tục SaveBitmap():

Code: Select all

  1. private Sub SaveBitmap()
  2.         If SaveFileDialog1.FilterIndex = 1 Then
  3.             bm.Save(SaveFileDialog1.FileName, ImageFormat.Bmp)
  4.         ElseIf SaveFileDialog1.FilterIndex = 2 Then
  5.             bm.Save(SaveFileDialog1.FileName, ImageFormat.Jpeg)
  6.         Else
  7.             bm.Save(SaveFileDialog1.FileName, ImageFormat.Png)
  8.         End If
  9.         saved = Trueset giá trị đã save là True
  10. End Sub


Munu file/save as được chọn:

Code: Select all

  1. Private Sub mn_saveas_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mn_saveas.Click
  2.         Try
  3.             If Me.SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
  4.                 SaveBitmap()
  5.             End If
  6.         Catch ex As Exception
  7.             MsgBox(ex.Message)
  8.         End Try
  9. End Sub


Phản hồi sự kiện Closing của Form:

Code: Select all

  1. Private Sub f_paint_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
  2.         If saved = False Then
  3.             Dim re As DialogResult
  4.             re = MessageBox.Show("Bạn có muốn lưu lại không ?", "Thong Bao", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning)
  5.             If re = Windows.Forms.DialogResult.Yes Then
  6.                 If Me.SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
  7.                     SaveBitmap()
  8.                 Else
  9.                     e.Cancel = True
  10.                 End If
  11.             ElseIf re = Windows.Forms.DialogResult.No Then
  12.                 e.Cancel = False
  13.             Else
  14.                 e.Cancel = True
  15.             End If
  16.         End If
  17. End Sub


Tuần tự của sự kiện Closing như sau:
Đóng Form:
- Kiểm tra đã save chưa?
+ đã save --> không làm gì, thoát.
+ chưa save: hỏi có muốn save hay không hay hủy bỏ thao tác đóng form
# Nếu yes:
@ Nếu save: thoát
@ Nếu cancel: không thoát, không save
# Nếu No: thoát.
# Nếu Cancel: hủy bỏ thao tác đóng Form
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

User avatar
1045007
Thành viên danh dự
Thành viên danh dự
Posts: 551
Joined: Mon 09/06/2008 3:35 pm
Location: TP Cần Thơ
Has thanked: 2 times
Been thanked: 64 times
Contact:

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby 1045007 » Thu 04/12/2008 5:04 pm

V. UnDo - Redo


- Trong quá trình vẽ, việc lùi lại (undo) bước vừa vẽ hay hủy thao tác lùi lại (redo) là một phần quan trọng giúp ta đỡ phải tốn thời gian khi phải ngồi vẽ lại từ đầu. Đương nhiên việc undo hay redo không tự nhiên sẵn có. Để làm được công việc này bạn cần phải lưu vào đâu đó để khi cần chúng ta đem sử dụng lại chúng.
- Đối với hình ảnh hay các kiểu dữ liệu khác cần khai báo mảng đối tượng phù hợp với kiểu dữ liệu cần lưu. Để undo hay redo lại được nhiều lần tùy thuộc vào cách lập trình của chúng ta, lưu nhiều tốn tài nguyên hệ thống nhiều, lưu ít tốn tài nguyên ít và ở đây không bàn về vấn đề tài nguyên hệ thống.
- Để tiến hành cần khai báo các biến sau:

Code: Select all

  1.    ' Cac bien Undo
  2.     Dim bmUndo As Bitmap ‘biến lưu ảnh cần undo
  3.     Dim listBMUndo(127) As Bitmap ‘danh sách ảnh undo
  4.     Dim nUndo As Short = -1 ‘vị trí undo


Thủ tục lưu ảnh Undo nếu số lượng ảnh cần lưu là < 128 ảnh:

Code: Select all

  1. Private Sub SaveUndo()
  2.             If nUndo <= 127 Then
  3.                 bmUndo = New Bitmap(bm)
  4.                 nUndo += 1
  5.                 listBMUndo(nUndo) = bmUndo
  6.                 saved = False
  7.             End If
  8.  End Sub


- Ví trí để đặt thủ tục này là khi kết thúc một nét vẽ để cho ta một hình ảnh xác định hay chính là sự kiện MouseUp của pictureBox

Code: Select all

  1. Private Sub pic_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles pic.MouseUp
  2.         If draw = True Then
  3.             draw = False
  4.             ResetPath()
  5.            ……………………………………
  6.                   ……………………………………
  7.             SaveUndo()
  8.         End If
  9.     End Sub


- Thao tác Undo – Redo

Code: Select all

  1. Private Sub mn_undo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mn_undo.Click
  2.         Try
  3.             nUndo -= 1
  4.             bm = New Bitmap(CType(listBMUndo(nUndo), Bitmap))
  5.             Me.pic.Image = bm
  6.             gp = Graphics.FromImage(bm)
  7.         Catch ex As Exception
  8.             nUndo += 1
  9.         End Try
  10.     End Sub
  11.  
  12.     Private Sub mn_redo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mn_redo.Click
  13.         Try
  14.             nUndo += 1
  15.             bm = New Bitmap(CType(listBMUndo(nUndo), Bitmap))
  16.             Me.pic.Image = bm
  17.             gp = Graphics.FromImage(bm)
  18.         Catch ex As Exception
  19.             nUndo -= 1
  20.         End Try
  21.  
  22.     End Sub


- Đây là cách làm đơn giản nhất, vì sao chúng ta nói thế? Khẳng định một điều rằng: làm như vầy CT chúng ta chiếm rất nhiều tài nguyên nếu CT sử dụng lâu vì quá nhiều ảnh được lưu và điều đó là dư thừa bởi trong quá trình vẽ ảnh cần kết xuất chỉ có 1, phần còn lại để làm gì?
- Thay vào đó các bạn có thể cải tiến bằng cách xây dựng một mảng vòng, những ảnh không còn sử dụng sẽ được chồng lên bởi ảnh mới -> số lượng ảnh lưu là ít -> tốc độ CT nhanh hơn.

Bài viết sẽ còn tiếp tục với phần 2: Edit
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

tungtot_vl
Thành viên chính thức
Thành viên chính thức
Posts: 11
Joined: Thu 02/04/2009 10:03 am

Re: Sử Dụng Lớp Graphics - Vẽ Những Nét Cơ Bản

Postby tungtot_vl » Tue 07/04/2009 4:40 pm

mình mới vào nghề chưa rành vb lắm. bạn chỉ giúp mình cái này nhé.
có cách nào để chia Picture box này thành n hàng và n cột không anh
vi dụ tạo 1 Picture box và chia nó thành 10 hàng, 10 cột (100cell). giống như tạo các ô lưới trong MSHFlexGrid. khi ta click chuột vào ô nào thì sẽ tạo màu cho ô đó. các ảnh load vào cũng được phân mảnh dưới dạng cell như trên. độ rộng các cell có thể thay đổi được.
bạn biết thì giúp mình nhé!


Return to “[.NET] Bài viết hướng dẫn”

Who is online

Users browsing this forum: No registered users and 1 guest