Использование цифрового дифференциального анализатора (DDA) или алгоритма Брезенхэма даст те же результаты, что и для GDI +, но если вы посмотрите на стандартную реализацию рисования линий GDI, вы заметите, что стандарт GDI LineTo Реализация на самом деле рисует линию на один пиксель короче, чем вы указываете, чтобы процитировать MSDN
' Функция LineTo рисует линию от текущей позиции до указанной точки, но не включая ее. '
Из-за этого, используя GDI, ваша линия рисуется из (1,3) - (4,1), если вы используете те же самые координаты в GDI +, вы увидите, что пиксельная структура линии соответствует тому, что вы видите в более старом версии Paint, за исключением, конечно, что последний пиксель в (5,1) не рисуется. Такая программа, как Paint, просто добавит дополнительный пиксель для завершения линии.
Использование прямого GDI потребовало бы, чтобы вы обрабатывали взаимодействие для создания ручек, выбора объекта в DC, удаления объектов и т. Д. Все это очень возможно, но в конечном итоге неудобно. Скорее вы можете смоделировать это в GDI +, нарисовав линию длиной в один пиксель, а затем проведите линию от этой конечной точки до конечной конечной точки, это заполнит последний пиксель.
Примечание: Я говорю о более старых версиях Paint, потому что, например, если вы используете Paint в Windows 7, вы увидите, что линия нарисована правильно.
Ради забавы я подумал, что быстро покажу, как вы можете использовать классический GDI из .NET, вот код взаимодействия.
[DllImport("gdi32")]
static extern bool MoveToEx(IntPtr hdc, int x, int y, out Point point);
[DllImport("gdi32")]
static extern bool LineTo(IntPtr hdc, int x, int y);
[DllImport("gdi32")]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32")]
static extern IntPtr CreatePen(int penStyle, int width, int color);
[DllImport("gdi32")]
static extern bool DeleteObject(IntPtr hgiobj);
private void Form1_Paint(object sender, PaintEventArgs e)
{
Point ignore;
IntPtr hdc = e.Graphics.GetHdc();
IntPtr pen = CreatePen(1, 1, ColorTranslator.ToWin32(Color.Red));
IntPtr oldPen = SelectObject(hdc, pen);
MoveToEx(hdc, 1, 3, out ignore);
LineTo(hdc, 5, 1);
SelectObject(hdc, oldPen);
DeleteObject(pen);
}
Обратите внимание, что на самом деле линия имеет длину в один пиксель. Лично я хотел бы использовать нативное решение .NET с использованием графического устройства и просто определить правильную координату линии, чтобы повторить классическую функциональность GDI.
Я подумал, что вам может быть интересно узнать, почему GDI пропускает последний пиксель, было обычным делом использовать XOR для рисования линии на экране, что сделало бы удаление той же самой линии очень простым, просто перерисовали линию с помощью XOR и это удаляется с сохранением исходного фона Конечно, вы должны быть осторожны, чтобы не рисовать пиксель дважды, иначе вы бы оставили на экране артефакты.
Поскольку обычно используется рисование фигуры с использованием нескольких вызовов LineTo
, теперь вы можете вызвать LineTo 3, например, чтобы нарисовать треугольник, и не беспокоиться о том, что первая точка каждой линии будет перекрывать последнюю точку предыдущего линии и вызывают указанные артефакты при использовании XOR, например, последующие вызовы LineTo могут безопасно начинаться в том месте, где заканчивалась предыдущая строка, поскольку последний пиксель предыдущей строки не был нарисован.