Ответ 1
К сожалению, GDI + - это насколько я могу сказать один из самых плохо документированных API в Windows. В некоторых браузерах в Интернете появляется очень мало людей, которые очень сильно его используют и не понимают ваш вопрос.
Еще более, к сожалению, API GDI + был в основном скопирован прямо к объекту .NET Graphics
. Даже документация по большей части была просто скопирована дословно. Обратите внимание на сходство между .NET Graphics.BeginContainer Method (RectangleF, RectangleF, GraphicsUnit) и Windows Graphics.BeginContainer(const RectF, const RectF, Unit) страницы.
Чтобы еще больше усложнить ситуацию, эта запись в блоге, которая мучительно читает:
Другим примером являются методы Save и BeginContainer в классе Graphics, которые выполняют совсем по-другому, но имеют одну и ту же документацию MSDN, которая не позволяет различать два вызова
& hellip, но не вдаваясь в подробности о том, как эти два метода действительно отличаются друг от друга.
Теперь, все сказанное, с некоторыми экспериментами, я думаю, что я расшифровал параметры и поведение:
- Параметр
unit
используется для указания единиц, используемых для параметраsrcrect
- Параметры
dstrect
указаны в единицах, используемых в настоящее время для объектаGraphics
- Новый контейнер завершает работу с
Graphics.PageUnit
до значения по умолчаниюGraphicsUnit.Display
Я не мог найти намека на первые два пункта выше в документации. Только благодаря экспериментам и внимательному наблюдению я узнал об этом, и, честно говоря, без фактической документации, чтобы поддержать мой вывод, я все еще не уверен на 100%.
В документации по методу BeginContainer()
есть ссылка на третий пункт:
Состояние графики, установленное методом BeginContainer, включает в себя свойства рендеринга состояния графики по умолчанию; любые изменения состояния качества отображения, существующие при вызове метода, равны reset значениям по умолчанию.
На первый взгляд, это предложение, кажется, говорит о том, что только "изменение состояния качества рендеринга" reset. Но, читая более внимательно, вы видите, что часть государства просто вызвана, в частности, поскольку она включена во все состояние, которое reset. Разумеется, более тщательное чтение не получает никакого дополнительного понимания:(, но, по крайней мере, можно видеть, что предложение не должно восприниматься как последнее слово во всем, что reset.
Таким образом, ключом к правильному функционированию вещей было бы указать единицы, которые вы хотите работать (например, GraphicsUnit.Inch
) на каждом шагу: в начальных настройках перед созданием контейнера в вызове BeginContainer()
(но здесь только для контроля способа srcrect
интерпретируется), а затем, наконец, сразу после BeginContainer()
, снова устанавливая свойство Graphics.PageUnit
.
Когда я это делал, я смог использовать любые единицы, которые я хотел бы рисовать. Я мог даже смешивать и сопоставлять, хотя, конечно, это привело к тому, что некоторые неинтуитивные значения передавались для прямоугольников контейнера по сравнению с прямоугольниками, которые я рисовал.
В качестве примера, здесь фрагмент, в котором я использую дюймы для начального состояния Graphics
и миллиметров для контейнера:
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);
}
Это создает это изображение:
Итак, я могу нарисовать прямоугольник размером 2x2 дюйма за пределами контейнера, а затем внутри контейнера я рисую прямоугольник размером 1.5x1.5 дюймов, но делаю это с помощью миллиметров (прямое преобразование в параметры, чтобы сделать его более четким для себя, что я делаю).