2015-03-20 28 views
12

Tôi đang cố gắng tìm ra cách chính xác các thùng chứa đồ họa gdi + hoạt động với các đơn vị đồ họa khác nhau. Hãy xem mã dưới đây. Nó biên dịch, bạn có thể dán nó vào một mẫu mới.Vùng chứa đồ họa hoạt động như thế nào?

void Form2_Paint(object sender, PaintEventArgs e) 
{ 
    var gfx = e.Graphics; 

    System.Diagnostics.Debug.WriteLine("DpiX={0}, DpiY={1}", gfx.DpiX, gfx.DpiY); 

    gfx.PageUnit = GraphicsUnit.Inch; 

    var pen = new Pen(Color.Black, 0.01f); 

    // Create outer container, 2 inches in size with X and Y set to 0.1 inches 
    var outerContainer = gfx.BeginContainer(
     new RectangleF(0.1f, 0.1f, 2, 2), 
     new RectangleF(0, 0, 2, 2), 
     GraphicsUnit.Pixel); 

    // Draw the outer rectangle 
    gfx.DrawRectangle(pen, new Rectangle(0, 0, 2, 2)); 

    // Create inner container, 1 inch in size with X and Y set to 0.1 inches 
    var innerContainer = gfx.BeginContainer(
     new RectangleF(0.1f, 0.1f, 1, 1), 
     new RectangleF(0, 0, 1, 1), 
     GraphicsUnit.Pixel); 

    // Draw the inner rectangle 
    gfx.DrawRectangle(pen, new Rectangle(0, 0, 1, 1)); 

    gfx.EndContainer(innerContainer); 

    gfx.EndContainer(outerContainer); 
} 

Trên mã là một ví dụ khá đơn giản của container đồ họa lồng nhau, tôi đã sử dụng không chuyển đổi rộng. Đây là cách thức trông giống như khi ở trên handler sơn được sử dụng:

graphics container illustration

Nó khá đơn giản. Bây giờ, tôi sẽ cố gắng mô tả vấn đề là gì.

Đây là một chữ ký của phương pháp BeginContainer:

public GraphicsContainer BeginContainer(
    RectangleF dstrect, 
    RectangleF srcrect, 
    GraphicsUnit unit 
) 

Những gì tôi đang thất bại trong việc hiểuGraphicsUnit unit đối số là.

Từ MSDN:

thành viên thuộc kiểu liệt kê GraphicsUnit chỉ định đơn vị đo lường cho container.

Điều này xuất hiện không là đúng!

Như bạn thấy trong mã của tôi, tôi đang sử dụng đơn vị Inch như vậy: gfx.PageUnit = GraphicsUnit.Inch.

Tuy nhiên, khi tôi tạo vùng chứa, đây là những gì tôi chuyển qua dưới dạng đối số đơn vị cho phương thức BeginContainer: GraphicsUnit.Pixel. Điều gì xảy ra sau khi vùng chứa được tạo? Inch đang được sử dụng (những gì tôi thực sự muốn). Nhưng nếu tôi vượt qua GraphicsUnit.Inch (hoặc mm hoặc bất kỳ điều gì khác) với đối số, pixel được sử dụng. Vì vậy, có vẻ như để hoàn thành những gì tôi muốn (sử dụng inch), tôi phải xác định điểm ảnh?

Điều này không có ý nghĩa với tôi. Bạn có thể thử thay đổi các đơn vị trong các phương thức BeginContainer ở mã trên và quan sát kết quả lạ. Tôi đã đọc MSDN và tất cả mọi thứ tôi có thể thu thập về điều này nhưng tôi vẫn không biết gì.

Tôi đang viết phần mềm vẽ nhiều thứ bằng gdi + và sử dụng đơn vị milimet cho mục đích in - khi tôi bắt đầu sử dụng vùng chứa, tôi khá ngạc nhiên khi tôi chỉ định pixel là đơn vị. Tôi thực sự nghi ngờ về bất kỳ mã in nào trong đó pixel được đề cập. Nó phải là tôi có một sự hiểu lầm lớn về vấn đề này.

Vì vậy, tất cả ở trên được xem xét, câu hỏi của tôi là: mục đích của đối số unit là gì trong phương pháp này?

+0

Kết quả sẽ là gì? Hình chữ nhật có kích thước 1 pixel? Tôi nghĩ * các hình chữ nhật bạn đang sử dụng trong hàm tạo có liên quan đến điều đó. Nó trở nên khó hiểu. – LarsTech

+0

@Lars hình chữ nhật được tính bằng đơn vị inch. Ban đầu tôi đã có nhiều con số "bình thường tìm kiếm" tính bằng milimét nhưng tôi nghĩ rằng có thể dễ dàng hơn để gỡ lỗi các inch do DPI là các chấm trên mỗi inch. Cả hai hình chữ nhật bạn nhìn thấy trên biểu mẫu chính xác là kích thước của các vùng chứa. – bokibeg

Trả lời

8

Thật không may, GDI + là như xa như tôi có thể nói với một trong những API kém tài liệu nhất trong Windows. Một số trình duyệt trên web có rất ít người thực sự sử dụng nó nhiều và không có thông tin chi tiết về câu hỏi của bạn.

Thật không may, API GDI + đã được sao chép trực tiếp về đối tượng .NET Graphics. Ngay cả các tài liệu được cho hầu hết các phần chỉ cần sao chép đúng nguyên văn. Lưu ý sự tương đồng giữa.NET Graphics.BeginContainer Method (RectangleF, RectangleF, GraphicsUnit) và Windows Graphics.BeginContainer(const RectF, const RectF, Unit) method trang.

Để làm phức tạp thêm vấn đề, có this blog entry mà mâu thuẫn nực cười đọc:

Một ví dụ khác là phương pháp Lưu và BeginContainer trong lớp Graphics, mà thực hiện rất khác nhau, chưa có tài liệu MSDN giống như thất bại trong việc phân biệt giữa hai cuộc gọi

& hellip; nhưng không đi sâu vào chi tiết về cách hai phương pháp này thực tế khác nhau.

Bây giờ, tất cả những gì đã nói, với một số thử nghiệm, tôi nghĩ rằng tôi đã giải mã các thông số và hành vi:

  • Tham số unit dường như được sử dụng để chỉ định các đơn vị sử dụng cho srcrect tham số
  • Các thông số dstrect được chỉ định trong các đơn vị hiện đang được sử dụng cho đối tượng Graphics
  • Vùng chứa mới sẽ bật lên với giá trị mặc định là GraphicsUnit.Display

Tôi không thể tìm thấy bất kỳ gợi ý nào về hai điểm đầu tiên ở trên trong tài liệu. Chỉ qua thử nghiệm và quan sát cẩn thận rằng tôi đã học được điều đó, và thẳng thắn mà không có tài liệu thực tế để kết luận của tôi, tôi vẫn chưa chắc chắn 100% về nó.

một gợi ý của điểm thứ ba trong tài liệu của BeginContainer() phương pháp:

Các trạng thái đồ họa thành lập theo phương pháp BeginContainer bao gồm những phẩm chất render của trạng thái đồ họa mặc định; bất kỳ trạng thái chất lượng kết xuất nào hiện có khi phương thức được gọi được đặt lại về giá trị mặc định.

Thoạt nhìn, câu này dường như chỉ nói rằng "thay đổi trạng thái chất lượng hiển thị" được đặt lại. Nhưng đọc kỹ hơn, người ta thấy rằng một phần của nhà nước chỉ đơn giản là được gọi ra đặc biệt, vì nó là bao gồm trong tất cả trạng thái được đặt lại. Cấp, đọc cẩn thận hơn không đạt được bất kỳ bản thân thêm hiểu :(, nhưng ít nhất người ta có thể thấy các câu không nên được thực hiện như lời cuối cùng về tất cả mọi thứ đó là reset.


Vì vậy, các chìa khóa để mọi thứ hoạt động chính xác sẽ là chỉ định các đơn vị bạn muốn làm việc (ví dụ: GraphicsUnit.Inch) ở mọi bước của cách: trong cài đặt ban đầu trước khi bạn tạo vùng chứa, trong cuộc gọi tới BeginContainer() (nhưng ở đây, chỉ kiểm soát cách srcrect đang được giải thích) và cuối cùng chỉ sau BeginContainer(), hãy đặt lại thuộc tính Graphics.PageUnit

Khi tôi làm theo cách đó, tôi có thể sử dụng bất kỳ đơn vị nào tôi muốn vẽ. Tôi thậm chí có thể trộn và kết hợp, mặc dù tất nhiên dẫn đến một số giá trị không trực quan được chuyển cho hình chữ nhật container so với hình chữ nhật tôi vẽ.

Như một ví dụ, đây là một đoạn mà tôi sử dụng inch cho tình trạng ban đầu Graphics, và milimét cho container:

gfx.PageUnit = GraphicsUnit.Inch; 

using (Pen blackPen = new Pen(Color.Black, 0.01f)) 
using (Pen redPen = new Pen(Color.Red, 0.01f)) 
{ 
    gfx.DrawRectangle(blackPen, .25f, .25f, 2, 2); 

    var outerContainer = gfx.BeginContainer(
     new RectangleF(.25f, .25f, 2, 2), 
     new RectangleF(0, 0, 2 * 25.4f, 2 * 25.4f), 
     GraphicsUnit.Millimeter); 

    gfx.PageUnit = GraphicsUnit.Millimeter; 
    gfx.DrawRectangle(redPen, .25f * 25.4f, .25f * 25.4f, 1.5f * 25.4f, 1.5f * 25.4f); 

    gfx.EndContainer(outerContainer); 
} 

Đó tạo ra hình ảnh này:

nested rectangles

Vì vậy, tôi có thể vẽ một hình chữ nhật 2x2 inch bên ngoài vùng chứa, và sau đó bên trong vùng chứa, tôi vẽ hình chữ nhật 1,5x1,5 inch, nhưng làm như vậy bằng cách sử dụng milimét (chuyển đổi một cách rõ ràng trong các tham số, chỉ để làm cho nó rõ ràng hơn để bản thân tôi đang làm gì).

+1

Câu trả lời hay! Chuyển đổi của bạn giữa mm và inch chứng minh gợi ý rằng 'đơn vị' thực sự chỉ áp dụng cho' srcrect'. Kết hợp với các thiết lập lại để hiển thị các đơn vị này giải thích các hành vi kỳ lạ. Tôi sẽ thử nghiệm nhiều hơn một chút nhưng ** ít nhất ** tôi sẽ sử dụng đúng chức năng và không mạo hiểm một mớ hỗn độn lớn được gửi tới máy in vào những thời điểm kỳ lạ. Hy vọng rằng những câu hỏi này sẽ được googleable để cứu người khác từ những đau đầu của giải mã gdi + apis. – bokibeg

0

Có lẽ, bạn không cần phải quan tâm chút nào.

Tôi cũng không thể chuyển đối số thích hợp sang Graphics.BeginContainer. Tuy nhiên, bằng cách sử dụng các phương pháp Transform (ResetTransform cuối cùng) đã làm việc hoàn hảo cho vấn đề tôi phải giải quyết.

Vì vậy, trước hết hãy xem xét các phương pháp Transform trước khi cố gắng hiểu các vùng chứa.

Các vấn đề liên quan