В зависимости от того, насколько вы точны быть точным, это может стать затруднительным.
Существует много подходов. Похоже, вы пытаетесь рисовать растровое изображение с размером принтера, а затем сжимаете его. Шаги для этого:
- Создайте DC (или, еще лучше, информационный контекст IC) для принтера.
- Запросить принтер DC, чтобы узнать разрешение, размер страницы, физические смещения и т. Д.
- Создайте DC для окна/экрана.
- Создайте совместимый DC (DC).
- Создайте совместимое растровое изображение для окна/экрана, но размер должен быть размером пикселя на странице принтера. (Проблема с этим подходом заключается в том, что это ОГРОМНОЕ растровое изображение, и он может выйти из строя.)
- Выберите совместимое растровое изображение в память DC.
- Нарисуйте память DC, используя те же координаты, которые вы использовали бы при рисовании на самом принтере.(Когда вы выбираете шрифты, убедитесь, что вы масштабируете их на логический дюйм принтера, а не на логический дюйм экрана.)
StretchBlt
Память DC к окну, которая уменьшит изображение целиком. Возможно, вам захочется поэкспериментировать с режимом растяжения, чтобы увидеть, что лучше всего подходит для изображения, которое вы собираетесь отображать.
- Освободить все ресурсы.
Но прежде чем вы направляетесь в этом направлении, рассмотрите альтернативы. Этот подход предполагает выделение ОГРОМНОГО экранного растрового изображения. Это может привести к сбою на компьютерах с ограниченными ресурсами. Даже если это не так, вы можете голодать на другие приложения.
Подход метафайлов, приведенный в другом ответе, является хорошим выбором для многих приложений. Я бы начал с этого.
Другой подход - выяснить все размеры в каком-то вымышленном устройстве с высоким разрешением. Например, предположим, что все находится в 1000-х дюймах. Затем ваши процедуры рисования масштабируют эту воображаемую единицу до фактических dpi, используемых целевым устройством.
Проблема с этим последним подходом (и, возможно, метафайлом) заключается в том, что шрифты GDI не масштабируются совершенно линейно. Ширины отдельных символов изменяются в зависимости от целевого разрешения. На устройстве с высоким разрешением (например, с лазерным принтером на 300 точек на дюйм) эта настройка минимальна. Но на экране с разрешением 96 точек на дюйм настройки могут содержать значительную ошибку по длине строки. Таким образом, текст в окне предварительного просмотра может оказаться несогласованным (обычно шире), чем на печатной странице.
Таким образом, хардкорный подход состоит в том, чтобы измерять текст в контексте принтера и снова измерять контекст экрана и корректировать несоответствие. Например, с использованием сделанных цифр вы можете измерить ширину текста в контексте принтера, и он будет отображаться до 900 пикселей принтера. Предположим, что отношение пикселей принтера к пикселям экрана равно 3: 1. Вы ожидали, что тот же текст на экране будет иметь ширину экрана 300 пикселей. Но вы измеряете в контексте экрана, и получаете значение, равное 325 пикселям экрана. Когда вы рисуете на экране, вам придется как-то сделать текст на 25 пикселей более узким. Вы можете спрятать символы ближе друг к другу или выбрать немного меньший шрифт, а затем растянуть их.
Хардкорный подход предполагает большую сложность. Например, вы можете попытаться обнаружить замены шрифтов, сделанные драйвером принтера, и сопоставить их так близко, как вы можете, с доступными экранными шрифтами.
Мне повезло с гибридом большого растрового изображения и хардкорными подходами. Вместо того, чтобы создавать гигантские растровые изображения для всей страницы, я делаю один достаточно большой для текста. Затем я рисую на размер принтера на заставку растрового изображения и StretchBlt
до размера экрана. Это устраняет проблему несоответствия размера при небольшом ухудшении качества шрифта. Он подходит для фактического предварительного просмотра, но вы не хотите создавать такой редактор WYSIWYG. Однострочный растровый рисунок достаточно мал, чтобы сделать это практичным.
Хорошей новостью является только текст. Все остальные чертежи - это простое масштабирование координат и размеров.
Я не использовал GDI + много, но я думаю, что он покончил с нелинейным масштабированием шрифтов. Поэтому, если вы используете GDI +, вам просто нужно масштабировать координаты. Недостатком является то, что я не думаю, что качество шрифта на GDI + так же хорошо.
И, наконец, если вы являетесь родным приложением в Vista или более поздней версии, убедитесь, что вы отметили свой процесс как «DPI-aware». В противном случае, если пользователь находится на экране с высоким разрешением DPI, Windows будет лгать вам и утверждать, что разрешение составляет всего 96 точек на дюйм, а затем делает нечеткое масштабирование того, что вы рисуете.Это ухудшает качество изображения и может еще более усложнить отладку вашего предварительного просмотра. Так как многие программы плохо адаптируются к более высоким экранам DPI, Microsoft добавила «высокое масштабирование DPI» по умолчанию, начиная с Vista.
Edited добавить
Еще один нюанс: если вы выбираете HFONT в память с помощью принтера размера растрового изображения, это возможный, что вы получите другой шрифт, чем то, что бы получить при выборе тот же HFONT в фактический принтер DC. Это связано с тем, что некоторые драйверы принтеров заменят обычные шрифты в памяти. Например, некоторые PostScript-принтеры заменят внутренний шрифт PostScript для некоторых распространенных шрифтов TrueType.
Вы можете сначала выбрать HFONT в принтер IC, а затем использовать функции GDI, как GetTextFace
, GetTextMetrics
, и, возможно, GetOutlineTextMetrics
, чтобы узнать о действительном выбранном шрифте. Затем вы можете создать новый LOGFONT, чтобы попытаться более точно сопоставить то, что будет использовать принтер, превратить его в HFONT и выбрать его в память DC. Это признак действительно хорошей реализации.
Я не слишком горжусь тем маршрутом, который я решил ...:/Получить информацию о DC принтера - ширину, высоту и логпиксели. CreateCompatibleDC, Bitmap из DC окна предварительного просмотра печати, но с шириной и высотой принтера (растровое изображение с размером памяти размером с mondo). Когда я создаю CreateFont, я использую - :: MulDiv (point, logPxlY, 72) для высоты (используя logPxlY из dc принтера). Soooooo, я надеюсь вернуться к этому не очень оптимальному решению, но у меня есть другая функциональность, чтобы добавить сначала ...:/http://pianocheater.com fyi :) –
Argh !! Это нехорошее решение (тот, которым я не горжусь). На моей машине Vista с RAM 4 Gigs я не могу создать CreateCompatibleBitmap совместимого с экраном растрового изображения с w, h принтера - вне памяти - возможно, количество памяти графической карты, поскольку я уверен, что это поместилось бы в 4 гигабайта регулярная память. Вернуться к чертежной доске ... –
Я знаю, что это было давно, но пытались ли вы создать растровое изображение из совместимого с принтером DC, а затем отменив его выбор и выбрав его в новый совместимый с DC DC для StretchBlt? Также вы можете просто разделить размеры и координаты растрового изображения на 2, чтобы он соответствовал, не рискуя слишком большим искажением. –