как мне выполнить предварительный просмотр в win32 c ++?

StackOverflow https://stackoverflow.com/questions/2240243

Вопрос

У меня есть функция рисования, которая просто использует HDC.Но мне нужно показать ТОЧНУЮ масштабированную версию того, что будет напечатано.

Итак, в настоящее время я использую CreateCompatibleDC() с HDC принтера и CreateCompatibleBitmap() с HDC принтера.

Я полагаю, что таким образом DC будет иметь точную ширину и высоту принтера.И когда я выбираю шрифты в этом HDC, текст будет масштабироваться точно так же, как это делал бы принтер.

К сожалению, я не могу с помощью StretchBlt () скопировать пиксели этого HDC в HDC элемента управления, поскольку, я думаю, они относятся к разным типам HDC.

Если я создам "memory canvas" из window HDC с теми же размерами, что и на странице принтера, шрифты получатся крошечными, поскольку они масштабируются для экрана, а не для страницы...

Должен ли я создать compatibledc() из DC окна и CreateCompatibleBitmap() из DC принтера или что-то в этом роде??

Если бы кто-нибудь мог объяснить, как ПРАВИЛЬНО это сделать.(И все еще есть что-то, что выглядит ТОЧНО так же, как это было бы на принтере)...

Что ж, я был бы вам очень признателен!!

...Стив

Это было полезно?

Решение

В зависимости от того, насколько точным вы хотите быть, это может стать затруднительным.

Существует много подходов.Звучит так, как будто вы пытаетесь нарисовать растровое изображение размером с принтер, а затем уменьшить его.Шаги для этого следующие:

  1. Создайте DC (или, что еще лучше, IC-Информационный контекст) для принтера.
  2. Запросите DC принтера, чтобы узнать разрешение, размер страницы, физические смещения и т.д.
  3. Создайте DC для окна / экрана.
  4. Создайте совместимый постоянный ток (постоянный ток памяти).
  5. Создайте совместимое растровое изображение для окна / экрана, но размер должен соответствовать размеру страницы принтера в пикселях.(Проблема с таким подходом заключается в том, что это ОГРОМНОЕ растровое изображение, и оно может выйти из строя.)
  6. Выберите совместимое растровое изображение в памяти DC.
  7. Рисуйте в постоянном токе памяти, используя те же координаты, которые вы использовали бы при рисовании на самом принтере.(При выборе шрифтов убедитесь, что вы масштабируете их до логического дюйма принтера, а не до логического дюйма экрана.)
  8. StretchBlt память подключается к окну, которое уменьшит масштаб всего изображения.Возможно, вы захотите поэкспериментировать с режимом растягивания, чтобы увидеть, что лучше всего подходит для того типа изображения, которое вы собираетесь отображать.
  9. Высвободите все ресурсы.

Но прежде чем вы двинетесь в этом направлении, рассмотрите альтернативные варианты.Этот подход предполагает выделение ОГРОМНОГО растрового изображения за пределами экрана.Это может привести к сбою на компьютерах с ограниченными ресурсами.Даже если этого не произойдет, возможно, вам не понравятся другие приложения.

Метафайловый подход, приведенный в другом ответе, является хорошим выбором для многих приложений.Я бы начал с этого.

Другой подход заключается в том, чтобы вычислить все размеры в каком-нибудь вымышленном устройстве с высоким разрешением.Например, предположим, что все находится в 1000-й доле дюйма.Затем ваши процедуры рисования будут масштабировать эту воображаемую единицу измерения до фактического значения dpi, используемого целевым устройством.

Проблема с этим последним подходом (и, возможно, с метафайловым подходом) заключается в том, что шрифты GDI не масштабируются идеально линейно.Ширина отдельных символов изменяется в зависимости от целевого разрешения.На устройстве с высоким разрешением (например, лазерном принтере с разрешением более 300 точек на дюйм) эта настройка минимальна.Но на экране с разрешением 96 точек на дюйм эти настройки могут привести к значительной ошибке по длине строки.Таким образом, текст в окне предварительного просмотра может казаться непропорциональным (обычно шире), чем на печатной странице.

Таким образом, жесткий подход заключается в измерении текста в контексте принтера, повторном измерении в контексте экрана и корректировке с учетом несоответствия.Например (используя вымышленные числа), вы можете измерить ширину некоторого текста в контексте принтера, и она составит 900 пикселей принтера.Предположим, что отношение пикселей принтера к пикселям экрана равно 3:1.Можно было бы ожидать, что один и тот же текст на экране будет иметь ширину 300 пикселей.Но вы измеряете в контексте экрана и получаете значение, равное 325 пикселям экрана.Когда вы рисуете на экране, вам нужно каким-то образом сделать текст на 25 пикселей уже.Вы можете расположить символы ближе друг к другу или выбрать шрифт чуть меньшего размера, а затем растянуть их.

Хардкорный подход предполагает большую сложность.Вы могли бы, например, попытаться обнаружить замены шрифтов, сделанные драйвером принтера, и как можно точнее сопоставить их с доступными экранными шрифтами.

Мне повезло с гибридом подхода big bitmap и hardcore.Вместо того чтобы создавать гигантское растровое изображение для всей страницы, я делаю его достаточно большим для строки текста.Затем я рисую в формате принтера закадровое растровое изображение и StretchBlt это зависит от размера экрана.Это избавляет от необходимости иметь дело с несоответствием размера при незначительном ухудшении качества шрифта.Он подходит для реального предварительного просмотра, но вы бы не захотели создавать подобный редактор WYSIWYG.Однострочное растровое изображение достаточно маленькое, чтобы сделать это практичным.

Хорошая новость в том, что труден только текст.Все остальное рисование представляет собой простое масштабирование координат и размеров.

Я не часто использовал GDI +, но я думаю, что он покончил с нелинейным масштабированием шрифта.Так что, если вы используете GDI +, вам нужно просто масштабировать свои координаты.Недостатком является то, что я не думаю, что качество шрифта на GDI + такое же хорошее.

И, наконец, если вы используете собственное приложение в Vista или более поздней версии, убедитесь, что вы пометили свой процесс как "Поддержка DPI" .В противном случае, если пользователь находится на экране с высоким разрешением, Windows солгет вам и заявит, что разрешение составляет всего 96 точек на дюйм, а затем нечетко увеличит масштаб того, что вы рисуете.Это ухудшает визуальное качество и может еще больше усложнить отладку предварительного просмотра.Поскольку многие программы плохо адаптируются к экранам с более высоким разрешением, Microsoft добавила "масштабирование с высоким разрешением" по умолчанию, начиная с Vista.

Отредактировано для добавления

Еще одно предостережение:Если вы выберете HFONT в памяти DC с растровым изображением размером с принтер, это возможный что вы получите шрифт, отличный от того, который был бы получен при выборе того же HFONT в реальном принтере DC.Это связано с тем, что некоторые драйверы принтеров заменяют обычные шрифты шрифтами в памяти.Например, некоторые принтеры PostScript заменяют некоторые распространенные шрифты TrueType внутренним шрифтом PostScript.

Вы можете сначала выбрать HFONT в микросхеме принтера, а затем использовать функции GDI, такие как GetTextFace, GetTextMetrics, и , возможно , GetOutlineTextMetrics чтобы узнать о фактически выбранном шрифте.Затем вы можете создать новый ЛОГ-шрифт, чтобы попытаться более точно соответствовать тому, что будет использовать принтер, превратить его в HFONT и выбрать его в своем контроллере памяти DC.Это признак действительно хорошей реализации.

Другие советы

Одна вещь, которую, возможно, стоит попробовать, - это создать расширенный метафайл DC, отрисовывать его как обычно, а затем масштабировать этот метафайл, используя показатели принтера.Именно такой подход используется WTL Пример BmpView - я не знаю, насколько это будет точно, но, возможно, на это стоит посмотреть (должно быть легко перенести соответствующие классы в Win32, но WTL - отличная замена программированию на Win32, поэтому, возможно, стоит использовать.)

Ну, это не будет выглядеть так же, потому что у вас более высокое разрешение в DC принтера, поэтому вам придется написать своего рода функцию преобразования.Я бы выбрал метод, с которым вы работали, но текст был слишком маленьким, и просто умножил каждую позицию / размер шрифта на ширину окна принтера и разделил на ширину окна источника.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top