Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Trang 1 của 3 123 CuốiCuối
Kết quả 1 đến 10 của 24
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Lập trình đồ họa trên C# | Tìm hiểu về đồ họa và GDI+ (nhiều kỳ)

    KỲ 1
    LỜI MỞ ĐẦU

    • .NET cung cấp một framework mới các lớp cho phép vẽ 2 chiều và tô vẽ. Nhìn chung lại với nhau, các lớp này mà bạn có thể tìm thấy trong 5 namespace System.Drawing (được chứa trong assembly System.Drawing.dll), tượng trưng cho GDI+.Về mặt kỹ thuật, GDI+ vẫn còn dựa trên các hàm cấp thấp Windows API, mà có thể trong quá khứ bạn đã dùng trong lập trình Windows. Các hàm API này thường quen được gọi là GDI (Graphical Device Interface). Ý niệm chủ yếu nằm sau các hàm API là lập trình viên có thể viết văn bản và hình ảnh lên nhiều thiết bị (máy in, màn hình và video card), không cần hiểu sâu phần cứng nằm đằng sau. Đến phiên mình, Windows bảo đảm sự tương thích khá rộng lớn, tận dụng bất cứ tối ưu hóa nào của phần cứng cung cấp được. Rất tiếc là các hàm GDI đòi hỏi phải lập trình khá rắc rối, hiểm hóc.Các kiểu dữ liệu GDI+ trên .NET FRAMEWORK là những lớp vỏ bọc thiên đối tượng bao quanh các hàm API cấp thấp, và thật tình mà nói chúng không thêm chức năng gì mới. Tuy nhiên, các kiểu dữ liệu GDI+. .NET cung cấp 1 mức độ trừu tượng hóa cao cấp hơn với những hỗ trợ khá thuận lợi về biến đổi hình học, kỹ thuật vuốt mịn các đường cong (antialiasing), và pha màu (pallete blending). Trong quá khứ, những kỹ thuật này đòi hỏi lập trình khá công phu và gian nan.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    KỲ 2
    LƯỚT SƠ QUA VỀ CÁC GDI+ NAMESPACE
    .NET FRAMEWORK (.NF) cung cấp 1 số namespace lo việc đồ họa 2 chiều. Ngoài những chức năng cơ bản, còn có một số chức năng hỗ trợ đồ họa (chẳng hạn color, font, pen, brush, và thao tác image). Ngoài ra, bạn còn có thể tìm thấy những lớp cho bạn khả năng thực hiện những biến đổi hình học làm cho mượt mà, pha màu và hỗ trợ in tài liệu. Nhìn chung, những namespace này làm thành tiện nghi .NET mà chúng ta thường gọi là GDI+ (tối tân hơn GDI cổ điển). Sau đây là các namespace cốt lõi của GDI+


  3. #3
    KỲ 3
    CẤU HÌNH MỘT GDI+ PROJECT
    Khi bạn muốn sử dụng đến GDI+, bạn phải thiết lập 1 quy chiếu về assembly System.Drawing.dll (muốn thế, bạn chọn menu Project\Add Reference rồi chọn System.Drawing.dll). Trình này chứa những lớp liên quan đến mỗi namespace cốt lõi của GDI+. Bạn để ý là khi bạn chọn tạo 1 dự án Windows trên VS.NET, thì quy chiếu System.Drawing sẽ tự động được đưa vào giùm bạn ở đầu dự án. Một khi quy chiếu này được thiết lập, bạn chỉ cần sử dụng đến từ chốt using của C# thì lúc ấy bạn đã sẵn sàng có thể tiến hành các công việc đồ họa.

    KỲ 4
    TỔNG QUAN VỀ NAMESPACE System.Drawing
    Bảng dưới đây sẽ liệt kê một số lớp cốt lõi của namespace System.Drawing







  4. #4
    Ngày tham gia
    Sep 2015
    Đang ở
    hà nội
    Bài viết
    0
    Sau đây là các cấu trúc khác nhau sử dụng trong namespace System.Drawing

    Phần lớn những lớp cốt lõi kể trên sử dụng đến khá nhiều những enum liên đới, và những enum này được khai báo trong namespace System.Drawing. Sau đây là các enum của namespace System.Drawing


  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    KỲ 5
    THỬ XEM NHỮNG LỚP TIỆN ÍCH CỦA SYSTEM.DRAWING
    1.Kiểu dữ liệu Point(F):
    Lớp tiện ích đầu tiên mà bạn phải quan tâm là System.Drawing.Point(F). Bảng dưới đây cho thấy các thành viên của lớp cấu trúc Point(F):

    Mặc dù kiểu dữ liệu Point (và PointF) thường xuyên được sử dụng khi làm việc với GDI+ cũng như với các ứng dụng giao diện UI, bạn nên biết là bạn có thể sử dụng bất cứ kiểu dữ liệu tiện ích nào từ bất cứ ứng dụng nào đó. Sau đây là 1 ứng dụng console sử dụng đến lớp System.Drawing.Point

    Mã:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing; // cần namespace này để sử dụng GDI+
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                //tao mot doi tuong Point va cho offset
                Point diem01 = new Point(100, 72);
                Console.WriteLine(diem01);
                diem01.Offset(20, 20);
                Console.WriteLine(diem01);
                /ap chong tac tu Point
                Point diem02 = diem01;
                if (diem01 == diem02)
                    Console.WriteLine("Point giong nhau");
                else
                    Console.WriteLine("Point khac nhau");
                diem02.X = 400;
                //cho biet cac diem
                Console.WriteLine("Diem 1: " + diem01);
                Console.WriteLine("Diem 2: " + diem02);
            }
        }
    }
    2.Kiểu dữ liệu Rectangle(F):
    Rectangle, xem ra hữu ích đối với bất cứ ứng dụng nào. Bảng sau liệt kê các thành phần cốt lõi của lớp cấu trúc Rectangle và RectangleF:

    3.Kiểu dữ liệu Size(F):
    Thao tác kiểu dữ liệu Size và SizeF cũng khá đơn giản, mình không giải thích thêm.

    4.Lớp Region:
    Lớp Region tượng trưng cho "phần ruột" của 1 khuôn hình học. Hàm constructor của lớp này đòi hỏi bạn phải gởi vào 1 thể hiện của 1 vài pattern hình học hiện hữu. Ví dụ, giả sử bạn đã tạo ra một hình chữ nhật 100x100 pixel. Nếu bạn muốn chui vào trong ruột của hình chữ nhật, bạn có thể viết như sau:
    Mã:
    //Chui vao trong ruot hinh chu nhat
    Rectangle hcn = new Rectangle(0,0,100,100): //top, left, bottom, right
    Region ruot = new Region(hcn);

    Một khi bạn đã ở trong ruột của 1 khuôn hình học nào đó, bạn có thể thao tác nó sử dụng đến các thành viên của lớp Region. Bảng sau liệt kê các thành viên của lớp này:

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    KỲ 6
    TÌM HIỂU CÁC CHẦU TÔ VẼ VỚI GDI+
    1.Truy cập đối tượng Graphics:
    Có 2 cách truy cập một thể hiện của các lớp Graphics:
    - Cho phủ quyết phương thức OnPaint() : đây là cách tiếp cận tốt nhất đối với 1 ô control owner-drawn. Như bạn có thể thấy, lớp Control, cho phép tạo các ô control, có định nghĩa một phương thức virtual mang tên OnPaint(). Khi một biểu mẫu (hoặc bất cứ hậu duệ nào của lớp Control) muốn vẽ ra những thông tin kiểu đồ họa, bạn có thể phủ quyết OnPaint() này và trích ra một đối tượng Graphics từ thông số nhập vào PaintEventArgs. Ví dụ:

    Mã:
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                g.DrawLine(Pens.Blue, new Point(15, 15), new Point(100, 100));
            }
        }
    }
    - Trực tiếp thụ lý tình huống Paint . Do đó, ta có thể viết lại đoạn mã ở trên như sau:
    Mã:
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                g.DrawLine(Pens.Blue, new Point(15, 15), new Point(100, 100));
            }
            
        }
    }
    Không cần biết bạn phản ứng thế nào trước tình huống Paint, bạn nên biết cho là bất cứ lúc nào khi một cửa sổ “bị làm ô uế” thì một thông điệp Paint sẽ được gọi tới hàng nối đuôi thông điệp (message queue). Cửa sổ xem ra “bị ô uế” khi nó bị thay đổi kích thước, hoặc khi bị một cửa sổ khác che lấp đi toàn phần hoặc một phần, hoặc bị cho teo lại rồi phình lên,… Trong những trường hợp như thế, .NET FRAMEWORK bảo đảm là khi form của bạn cần phải tô điểm lại thì hàm thụ lý tình huống Paint sẽ tự động được triệu gọi vào.
    Bạn không phải chờ đợi cho 1 tình huống Paint xảy ra. Thay vào đó, bạn có thể nhận trực tiếp đối tượng Graphics GDI+ đối với một ô control hoặc một đối tượng sử dụng hàm hành sự Control.CreateGraphics(). Phương thức này tạo một đối tượng Graphics đối với ô control. Tuy nhiên, một GDI+ device context (GDC) sẽ sử dụng các nguồn lực hệ thống, và bạn phải bảo đảm triệu gọi phương thức Graphics.Dispose() để giải phóng GDC nếu bạn nhận nó trực tiếp.

    Sau đây là ví dụ vẽ 1 đường thẳng như trên, nhưng lần này từ việc một nút bị ấn xuống:

    Mã:
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Graphics g = this.CreateGraphics();
                g.DrawLine(Pens.Blue, new Point(15, 15), new Point(200, 200));
                g.Dispose();
            }
            
        }
    }
    Tuy nhiên, đoạn mã trên không tương đương với đoạn mã trước đó. Khi bạn cho chạy chương trình, rồi sau đó teo nhỏ (minimize) form lại, sau đó phóng to lên (maximize) lần nữa thì đường thẳng bị biến mất. Và nó đoạn thẳng đó chỉ hiện lên khi bạn lại nhấn nút nữa.
    Windows không cho trữ phần biểu diễn đồ họa của 1 cửa sổ lên bộ nhớ. Đây là lí do hồi trước bộ nhớ khan hiếm; việc cho trữ các bitmap của mỗi cửa sổ được mở ra sẽ nhanh chóng ngốn hàng chục MB, làm tê liệt luôn máy tính.
    Thay vào đó, Windows tự động gạt bỏ nội dung của 1 cửa sổ khi nó bị thu nhỏ lại hoặc bị che lấp bởi 1 cửa sổ khác. Khi chương trình cửa sổ bị phục hồi, Windows sẽ tống đạt một thông điệp cho ứng dụng, yêu cầu nó tự tô vẽ lại.Trong .NET, như vậy là một tình huống Paint được khởi sự.
    Nói tóm lại, lập trình viên chịu trách nhiệm tô vẽ lại cửa sổ khi thấy cần thiết. Với các hàm thụ lý tình huống Paint, đoạn mã tô vẽ sẽ tự động được kích hoạt đúng lúc. Tuy nhiên, nếu bạn tô vẽ trong lòng 1 phương thức khác, thì kết quả của bạn sẽ bị đánh mất trừ khi bạn tiến hành những bước cụ thể cho hoàn nguyên cửa sổ sau khi nó bị thu nhỏ hoặc bị che lấp.

    Bạn lưu ý: không có cách gì “xóa sạch” nội dung mà bạn đã vẽ, bạn chỉ có cách vẽ chồng lên, hoặc invalidate cửa sổ và lúc này toàn bộ cửa sổ sẽ được vẽ lại từ đầu.

    2. Tối ưu hóa GDI+ Painting:
    Tô vẽ và chỉnh lại kích thước (resizing):
    Trong việc tự động tô vẽ lại, một điểm thường xuyên ta không để ý đến là việc tô vẽ chỉ ảnh hưởng lên phần cửa sổ bị che lấp. Điều này đặc biệt quan trọng khi cho chỉnh lại kích thước cửa sổ. Ví dụ, ta thử xem một đoạn mã Paint() cho vẽ một Elilipse mang cùng kích thước với cửa sổ chứa Elip này:

    Khi bạn cho chỉnh lại kích thước cửa sổ, bạn thấy là đoạn mã tô vẽ không chạy lại. Những phần cửa sổ được trưng ra mới sẽ được diễn bởi Elip kích thước được chỉnh lại, nhưng phần còn lại của cửa sổ thì không được nhật tu, nên bạn thấy một hình thù cổ quái như sau:


  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    KỲ 7
    TỔNG QUAN LỚP GRAPHICS
    Các thành viên cốt lõi của lớp Graphics



    Các phương thức vẽ của lớp Graphics: gồm các phương thức dạng DrawXXX(..) với XXX là tên của các hình vẽ. Cụ thể ở đây mình liệt kê vài phương thức cơ bản:
    - DrawArc(): vẽ vòng cung
    - DrawBezier/DrawBeziers: vẽ hình Bezier
    - DrawEllipse() : vẽ hình Elip và hình tròn
    - DrawIcon(): vẽ một icon tượng trưng bởi một đối tượng Icon
    - DrawImage(): vẽ một hình ảnh tượng trưng bởi 1 đối tượng Image
    - DrawLine()/DrawLines(): vẽ đường thẳng
    - DrawPolygon(): vẽ đa giác.
    - DrawRectangle()/DrawRectangles() vẽ hình chữ nhật
    - DrawString(): vẽ một chuỗi văn bản.

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    KỲ 8
    HỆ THỐNG TỌA ĐỘ MẶC NHIÊN CỦA GDI+
    Đơn vị đo lường mặc định là pixel, với góc trên tay trái (upper left) làm điểm gốc và với trục x tăng theo chiều qua phải và trục y tăng theo chiều từ trên xuống.
    Ví dụ: nếu bạn muốn vẽ một hình chữ nhật như sau, bạn sẽ thấy một hình vuông cạnh bằng 90 pixel khởi đi từ 10 pixel từ trái qua và từ trên xuống:

    Mã:
            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                g.DrawRectangle(Pens.Blue, 10, 10, 100, 100);
            }
    Tuy nhiên, bạn có thể thay đổi hệ thống tọa độ mặc định của GDI+ bằng cách khai báo một đơn vị đo lường thay thế. Như đã nói, pixel là đơn vị đo lường mặc định, nhưng bạn có thể chọn 1 đơn vị đo lường khác thông qua enum GraphicsUnit như sau:

    Ví dụ, bạn sửa đoạn mã trên lại như sau:

    Mã:
            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                g.PageUnit = GraphicsUnit.Inch;
                g.DrawRectangle(Pens.Blue, 0,0, 100, 100);
            }
    Kết quả sẽ là:

    KHAI BÁO 1 ĐIỂM GỐC THAY THẾ:
    Giả sử ứng dụng cần dành riêng 1 đường viền dày 100 pixel xung quanh vùng client của form. Bạn phải làm sao để bảo đảm tất cả các tác vụ GDI+ sẽ được thực hiện đâu đó trong Region nội tại này?
    Một cách giải quyết là dùng di số (offset) bằng tay tất cả đoạn mã tô vẽ. Tất nhiên, việc này mất nhiều công sức. Tốt hơn là chúng ta có thể thiết đặt một thuộc tính có tác dụng như sau: "Mặc dù ta bảo là vẽ một hình chữ nhật với điểm gốc (0,0), nhưng bản đảm là anh cứ bắt đầu từ điểm gốc (100,100) đi". Như vậy cho nó nhẹ cái đời.
    Trên GDI+, bạn có thể điều chỉnh điểm gốc bằng cách cho thiết đặt để trị biến đổi sử dụng phương thức TranslateTransform() thuộc lớp Graphics. Ví dụ, đoạn mã sau đây cho phép bạn tiếp tục giữ logical mapping ở (0,0) trong khi thay đổi device view cho bắt đầu từ (100,100):

    Mã:
    private void Form1_Paint(object sender, PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                g.PageUnit = GraphicsUnit.Point;
                g.TranslateTransform(100, 100);
                g.DrawRectangle(new Pen(Color.Red, 2), 0, 0, 100, 100);
            }

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Hình die hết rồi, mong các anh cập nhập lại.

  10. #10
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    bác nào đã tải về các bài này gửi lên cho anh em download với, cái này không có hình gì cả.

 

 
Trang 1 của 3 123 CuốiCuối

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •