Vẽ một pixel duy nhất trên Windows Forms


92

Tôi gặp khó khăn khi cố bật một pixel duy nhất trên Biểu mẫu Windows.

graphics.DrawLine(Pens.Black, 50, 50, 51, 50); // draws two pixels

graphics.DrawLine(Pens.Black, 50, 50, 50, 50); // draws no pixels

API thực sự nên có một phương pháp để đặt màu của một pixel, nhưng tôi không thấy một phương pháp nào.

Tôi đang sử dụng C #.


Tôi đã thực hiện một điều khiển trong đó vẽ một số đồ thị khoa học rất đẹp (với các tính năng bổ sung mà tôi không cần có trong bất kỳ điều khiển thương mại nào). Tôi có thể vẽ một điểm dữ liệu với và X hoặc + hoặc một hộp nhỏ. Nhưng đối với dữ liệu không quan trọng, tôi chỉ muốn một pixel duy nhất.
Đánh dấu T

Tất cả các câu trả lời tôi thấy có vẻ như chúng thực sự quá mức cần thiết cho một pixel? Tại sao chỉ làm một bộ đệm [y * width + x] = color có vẻ dễ dàng hơn;
NoMoreZealots 14/02/19

Câu trả lời:


113

Điều này sẽ đặt một pixel duy nhất:

e.Graphics.FillRectangle(aBrush, x, y, 1, 1);

18
Ai có thể đoán được rằng DrawRectangle vẽ 2x2 nhưng FillRectange lại vẽ 1x1 với các đối số tương tự? Cảm ơn.
Đánh dấu T

9
@Mark: Nó thực sự có ý nghĩa ... DrawRectangle nói "vẽ một đường viền bắt đầu từ x và y với chiều rộng và chiều cao này", vì vậy nó vẽ cả điểm đầu và điểm cuối (x, y; x + 1, y ; x, y + 1; x + 1, y + 1) và các đường thẳng giữa chúng. FillRectangle nói "vẽ một bề mặt rắn bắt đầu từ x, y của chiều rộng và chiều cao này." Ngẫu nhiên, FillRectangle sử dụng Brush, không phải Pen.
Powerlord

5
@R. Bemrose: Thực ra, nó phụ thuộc vào đối tượng Pen mà bạn chuyển đến DrawRectangle(). Nếu có, Pen.Alignment = PenAlignment.Outsetnó sẽ vẽ Pen.Widthđường viền dày pixel quanh hình chữ nhật nhất định. Nhưng nếu bạn chỉ định, Pen.Alignment = PenAlignment.Insetnó sẽ vẽ "đường viền" dày pixel Pen.Width bên trong hình chữ nhật nhất định.
Cipi

2
Đây là một câu trả lời không thỏa đáng. Mặc dù điều này đặt một pixel duy nhất, nhưng yêu cầu không phải lúc nào cũng đặt pixel theo nghĩa đen. Tất cả những lần tôi cần điều này, thường là, tôi cần dấu chấm được vẽ bằng cùng một cây bút vẽ các đường nét chứ không phải bút lông. Nói cách khác, chúng ta cần một dòng ngắn hơn 2 pixel. Tôi nghi ngờ đó là những gì OP cần.
RobertT

6
Tôi không thích câu trả lời này. Cách này không hiệu quả cao.
user626528 22/02

18

Đối Graphicstượng không có điều này, vì nó là một sự trừu tượng và có thể được sử dụng để bao gồm một định dạng đồ họa vector. Trong bối cảnh đó, việc đặt một pixel đơn lẻ sẽ không có ý nghĩa. Các Bitmapđịnh dạng hình ảnh không có GetPixel()SetPixel(), nhưng một đồ họa không đối tượng được xây dựng trên một. Đối với kịch bản của bạn, tùy chọn của bạn thực sự có vẻ như là lựa chọn duy nhất vì không có cách nào phù hợp nhất để đặt một pixel duy nhất cho một đối tượng đồ họa chung (và bạn không biết CHÍNH XÁC nó là gì, như điều khiển / biểu mẫu của bạn có thể được đệm kép, v.v.)

Tại sao bạn cần đặt một pixel duy nhất?


18

Chỉ để hiển thị mã hoàn chỉnh cho câu trả lời Henk Holterman:

Brush aBrush = (Brush)Brushes.Black;
Graphics g = this.CreateGraphics();

g.FillRectangle(aBrush, x, y, 1, 1);

9

Khi tôi đang vẽ rất nhiều pixel đơn lẻ (cho nhiều màn hình dữ liệu tùy chỉnh khác nhau), tôi có xu hướng vẽ chúng thành một bitmap và sau đó đưa chúng lên màn hình.

Các hoạt động Bitmap GetPixel và SetPixel không đặc biệt nhanh vì chúng thực hiện rất nhiều lần kiểm tra giới hạn, nhưng khá dễ dàng để tạo một lớp 'bitmap nhanh' có quyền truy cập nhanh vào một bitmap.


2

Trang MSDN trên GetHdc

Tôi nghĩ rằng đây là những gì bạn đang tìm kiếm. Bạn sẽ cần lấy HDC và sau đó sử dụng lệnh gọi GDI để sử dụng SetPixel. Lưu ý rằng COLORREF trong GDI là DWORD lưu trữ màu BGR. Không có kênh alpha và nó không phải là RGB như cấu trúc Màu của GDI +.

Đây là một đoạn mã nhỏ mà tôi đã viết để hoàn thành nhiệm vụ tương tự:

public class GDI
{
    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    internal static extern bool SetPixel(IntPtr hdc, int X, int Y, uint crColor);
}

{
    ...
    private void OnPanel_Paint(object sender, PaintEventArgs e)
    {
        int renderWidth = GetRenderWidth();
        int renderHeight = GetRenderHeight();
        IntPtr hdc = e.Graphics.GetHdc();

        for (int y = 0; y < renderHeight; y++)
        {
            for (int x = 0; x < renderWidth; x++)
            {
                Color pixelColor = GetPixelColor(x, y);

                // NOTE: GDI colors are BGR, not ARGB.
                uint colorRef = (uint)((pixelColor.B << 16) | (pixelColor.G << 8) | (pixelColor.R));
                GDI.SetPixel(hdc, x, y, colorRef);
            }
        }

        e.Graphics.ReleaseHdc(hdc);
    }
    ...
}

1

Rõ ràng DrawLine vẽ một đường ngắn hơn một pixel so với chiều dài được chỉ định thực tế. Dường như không có DrawPoint / DrawPixel / whatnot, nhưng thay vào đó bạn có thể sử dụng DrawRectangle với chiều rộng và chiều cao được đặt thành 1 để vẽ một pixel duy nhất.


2
Rất vui, nhưng với kích thước 1, nó vẽ 2x2 pixel. (Vẽ nó bên cạnh một đường thẳng, và bạn có thể thấy nó rộng gấp đôi.) Và với kích thước 0, tất nhiên, nó không vẽ gì cả.
Đánh dấu T

Đúng, sai lầm của tôi. :) Điều tốt FillRectangle thực hiện thủ thuật.
Rytmis

0

Vẽ Đường 2px bằng Bút với DashStyle.DashStyle.Dot vẽ một Pixel duy nhất.

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        using (Pen p = new Pen(Brushes.Black))
        {
            p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
            e.Graphics.DrawLine(p, 10, 10, 11, 10);
        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.