В зависимости от того, насколько точным вы хотите быть, это может быть сложно.
Есть много подходов. Звучит так, будто вы пытаетесь нарисовать растровое изображение размером с принтер, а затем уменьшить его. Шаги для этого:
- Создайте DC (или, еще лучше, IC - информационный контекст) для принтера.
- Запросите DC принтера, чтобы узнать разрешение, размер страницы, физические смещения и т. Д.
- Создание DC для окна / экрана.
- Создание совместимого DC (памяти DC).
- Создайте совместимое растровое изображение для окна / экрана, но размер должен соответствовать размеру пикселя страницы принтера. (Проблема этого подхода в том, что это ОГРОМНОЕ растровое изображение, и оно может дать сбой.)
- Выберите совместимое растровое изображение в памяти DC.
- Рисовать в памяти DC, используя те же координаты, которые вы использовали бы при рисовании на реальном принтере. (При выборе шрифтов убедитесь, что вы масштабируете их до логического дюйма принтера, а не логического дюйма экрана.)
StretchBlt
память DC до окна, которое будет уменьшать все изображение. Возможно, вы захотите поэкспериментировать с режимом растяжения, чтобы увидеть, что лучше всего подходит для изображения, которое вы собираетесь отображать.
- Освободить все ресурсы.
Но прежде чем идти в этом направлении, рассмотрите альтернативы. Этот подход включает в себя выделение ОГРОМНОГО закадрового изображения. Это может произойти сбой на компьютерах с ограниченными ресурсами. Даже если это не так, вы можете голодать другие приложения.
Подход метафайла, приведенный в другом ответе, является хорошим выбором для многих приложений. Я бы начал с этого.
Другой подход - выяснить все размеры в некоторой вымышленной единице с высоким разрешением. Например, предположим, что все в тысячных дюйма. Тогда ваши процедуры рисования будут масштабировать эту воображаемую единицу к фактическому dpi, используемому целевым устройством.
Проблема этого последнего подхода (и, возможно, метафайла) заключается в том, что шрифты GDI не линейно масштабируются. Ширина отдельных символов настраивается в зависимости от целевого разрешения. На устройстве с высоким разрешением (например, лазерный принтер с разрешением 300+ точек на дюйм) эта настройка минимальна. Но на экране с разрешением 96 точек на дюйм твики могут привести к значительной ошибке по всей длине линии. Поэтому текст в окне предварительного просмотра может отображаться непропорционально (как правило, шире), чем на печатной странице.
Таким образом, хардкорный подход заключается в измерении текста в контексте принтера, повторном измерении в контексте экрана и корректировке на несоответствие. Например, (используя выдуманные числа), вы можете измерить ширину некоторого текста в контексте принтера, и она составит 900 пикселей принтера. Предположим, что отношение пикселей принтера к пикселям экрана составляет 3: 1. Вы ожидаете, что один и тот же текст на экране будет иметь ширину 300 пикселей. Но вы измеряете в контексте экрана, и вы получаете значение, как 325 пикселей экрана. Когда вы рисуете на экране, вам нужно как-то сузить текст на 25 пикселей. Вы можете объединить символы ближе друг к другу или выбрать немного меньший шрифт и затем растянуть их.
Хардкорный подход подразумевает большую сложность. Например, вы можете попытаться обнаружить замены шрифтов, сделанные драйвером принтера, и сопоставить их как можно точнее с доступными экранными шрифтами.
Мне повезло с гибридом большого битмапа и хардкорного подхода. Вместо создания гигантского растрового изображения для всей страницы, я создаю одно достаточно большое для строки текста. Затем я рисую на принтере до размера закадрового изображения и StretchBlt
до размера экрана. Это устраняет проблему с несоответствием размера при небольшом ухудшении качества шрифта. Он подходит для предварительного просмотра, но вы не захотите создавать такой редактор WYSIWYG. Однострочное растровое изображение достаточно мало, чтобы сделать это практичным.
Хорошая новость в том, что только текст сложен. Все остальные рисунки представляют собой простое масштабирование координат и размеров.
Я не слишком много использовал GDI +, но я думаю, что он покончил с нелинейным масштабированием шрифтов. Поэтому, если вы используете GDI +, вам просто нужно масштабировать свои координаты. Недостатком является то, что я не думаю, что качество шрифта в GDI + так хорошо.
И, наконец, если вы являетесь родным приложением в Vista или более поздней версии, убедитесь, что вы пометили свой процесс как " DPI-based ". В противном случае, если пользователь находится на экране с высоким разрешением, Windows будет вам лгать и утверждать, что разрешение составляет всего 96 dpi, а затем делать нечеткое масштабирование того, что вы рисуете. Это ухудшает визуальное качество и может усложнить отладку предварительного просмотра. Поскольку многие программы плохо адаптируются к экранам с более высоким DPI, Microsoft по умолчанию добавила «масштабирование с высоким DPI», начиная с Vista.
Отредактировано для добавления
Еще одно предупреждение: если вы выберете HFONT в DC памяти с помощью растрового изображения размером с принтер, то возможно , что вы получите другой шрифт, чем тот, который был бы при выборе того же HFONT в реальном DC принтера , Это связано с тем, что некоторые драйверы принтеров заменяют обычные шрифты в памяти. Например, некоторые принтеры PostScript заменяют внутренний шрифт PostScript на некоторые распространенные шрифты TrueType.
Вы можете сначала выбрать HFONT в ИС принтера, затем использовать функции GDI, такие как GetTextFace
, GetTextMetrics
и, возможно, GetOutlineTextMetrics
, чтобы узнать о фактическом выбранном шрифте. Затем вы можете создать новый LOGFONT, чтобы попытаться более точно соответствовать тому, что будет использовать принтер, превратить его в HFONT и выбрать его в свой DC памяти. Это знак действительно хорошей реализации.