• 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#

Điều hành viên: tungcan5diop, QUANITGROBEST

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Năm 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) Đã tải 2420 lần



Phần I: Vẽ Ảnh



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

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

Mã: Chọn hết

  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:

Mã: Chọn hết

  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.

Mã: Chọn hết

  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:

Mã: Chọn hết

  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.

Mã: Chọn hết

  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.

Mã: Chọn hết

  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):

Mã: Chọn hết

  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) Đã xem 14367 lần

Nhưng kết quả thực thì là vầy:
2.PNG
2.PNG (12.39 KiB) Đã xem 14371 lần

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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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é:

Mã: Chọn hết

  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
Sửa lần cuối bởi 1045007 vào ngày T.Năm 04/12/2008 4:58 pm với 11 lần sửa.


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

Hình đại diện của người dùng
Dang Minh Du
Thành viên ưu tú
Thành viên ưu tú
Bài viết: 531
Ngày tham gia: T.Tư 02/04/2008 2:08 pm
Đến từ: RGames Team
Has thanked: 3 time
Been thanked: 17 time
Liên hệ:

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

Gửi bàigửi bởi Dang Minh Du » T.Năm 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...!

Hình đại diện của người dùng
VBNewbie
Thành viên tích cực
Thành viên tích cực
Bài viết: 113
Ngày tham gia: T.Bảy 29/03/2008 7:13 pm
Đến từ: Computer
Been thanked: 3 time
Liên hệ:

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

Gửi bàigửi bởi VBNewbie » T.Năm 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

Hình đại diện của người dùng
anhtuyenbk
Guru
Guru
Bài viết: 1311
Ngày tham gia: T.Năm 22/09/2005 4:12 pm
Đến từ: Một nơi chừa từng biết, chưa từng nghe, chưa từng thấy
Been thanked: 38 time

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

Gửi bàigửi bởi anhtuyenbk » T.Năm 23/10/2008 4:42 pm

Hay lắm, cố lên post tiếp nữa đi.
Dang Minh Du đã viết:Đâ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

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Năm 23/10/2008 9:14 pm

VBNewbie đã viết: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
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:43 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Sáu 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ẽ:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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ẽ:

Mã: Chọn hết

  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) Đã xem 14265 lần

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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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) Đã xem 14266 lần
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:44 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
Kasper
Guru
Guru
Bài viết: 1061
Ngày tham gia: T.Sáu 16/05/2008 10:54 am
Has thanked: 2 time
Been thanked: 76 time
Liên hệ:

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

Gửi bàigửi bởi Kasper » T.Sáu 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.

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Bảy 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) Đã xem 14209 lần

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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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):

Mã: Chọn hết

  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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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....?
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:45 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Ba 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:

Mã: Chọn hết

  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)

Mã: Chọn hết

  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:

Mã: Chọn hết

  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
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:45 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Ba 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:

Mã: Chọn hết

  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…

Mã: Chọn hết

  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…

Mã: Chọn hết

  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)

Mã: Chọn hết

  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
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:46 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Năm 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:

Mã: Chọn hết

  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

Mã: Chọn hết

  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

Mã: Chọn hết

  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:

Mã: Chọn hết

  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
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:47 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Hai 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:

Mã: Chọn hết

  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)
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:47 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Ba 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.

Mã: Chọn hết

  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:

Mã: Chọn hết

  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
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:48 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 87 time
Liên hệ:

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

Gửi bàigửi bởi vo_minhdat2007 » T.Năm 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?

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Năm 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.
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:50 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 87 time
Liên hệ:

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

Gửi bàigửi bởi vo_minhdat2007 » T.Năm 13/11/2008 7:15 pm

Code đây :

Mã: Chọn hết

  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)!

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Năm 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:
Tập tin đính kèm
Project.rar
(256.79 KiB) Đã tải 649 lần
Sửa lần cuối bởi 1045007 vào ngày T.Bảy 29/11/2008 7:50 am với 1 lần sửa.
Xếp hình cổ điển for Android-https://play.google.com
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Bảy 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:

Mã: Chọn hết

  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():

Mã: Chọn hết

  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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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
♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀♂♀

Hình đại diện của người dùng
1045007
Thành viên danh dự
Thành viên danh dự
Bài viết: 551
Ngày tham gia: T.Hai 09/06/2008 3:35 pm
Đến từ: TP Cần Thơ
Has thanked: 2 time
Been thanked: 64 time
Liên hệ:

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

Gửi bàigửi bởi 1045007 » T.Năm 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:

Mã: Chọn hết

  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:

Mã: Chọn hết

  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

Mã: Chọn hết

  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

Mã: Chọn hết

  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
Bài viết: 11
Ngày tham gia: T.Năm 02/04/2009 10:03 am

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

Gửi bàigửi bởi tungtot_vl » T.Ba 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é!


Quay về “[.NET] Bài viết hướng dẫn”

Đang trực tuyến

Đang xem chuyên mục này: Không có thành viên nào trực tuyến.1 khách