![]() |
|
|
![]()
|
|
| Dreamer_0x01 |
|
|||
![]() Терминатор ![]() ![]() Профиль Группа: Участник Сообщений: 780 Регистрация: 14.4.2005 Где: Санкт-Петербург Репутация: 9 Всего: 12 |
Здравствуйте.
Есть объект CDC, созданный при рисовании содержимого CWnd. В обработчике WM_PAINT содержимое контекста выводится в окно с помощью BitBlt(). Хочу теперь вывести это же содержимое контекста на принтер, причем так, чтобы выводилось на весь лист бумаги. Скопировал такой пример из инета:
dcMem - мой контекст, объевлен глобально, заполняется содержимом в процессе работы программы. Инициализируется так : CDC * pDCDest=GetDC(); dcMem.CreateCompatibleDC(pDCDest); BmpNewMem.CreateCompatibleBitmap(pDCDest, rCl.Width(), rCl.Height());//BmpNewMem - объект CBitmap dcMem.SelectObject(&BmpNewMem); Данный код выводит содержимое окна на печать, но напечатанное изображение получается очень мелким. Как мне сделать так, чтобы изображение масштабировалось на весь лист? Либо подскажите дргой метод, как сделать распечатку содержимого окна CWnd. Спасибо. -------------------- Нет ничего невозможного. Есть цели, и есть время и силы на их достижение. |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Если у тебя обычное рисование происходит в режиме MM_TEXT (по-умолчанию), то так и будет. Пикселы у принтера очень маленькие.
Придется самому пересчитывать координаты. И выполнять не BitBlt, а StrechBlt. Но тогда сам понимаешь, тонкие линии превратятся в бревна, причем ступенчатые. Первое, возможно, и неплохо, а вот второе... Более правильно всю графику выводить векторно в контекст принтера, но с пересчетом координат. Или изначально работать в каком-то размерном пространстве типа MM_LOMETRIC. Тогда логические координаты при выводе на принтер пересчитает сам контекст. -------------------- ... |
|||
|
||||
| Dreamer_0x01 |
|
|||
![]() Терминатор ![]() ![]() Профиль Группа: Участник Сообщений: 780 Регистрация: 14.4.2005 Где: Санкт-Петербург Репутация: 9 Всего: 12 |
Earnest,
Я не могу понять следующее - для корректного масштабирования мне нужно сделать разные функции прорисовки для контекста принтера и контекста окна?
У меня по техзаданию важна пиксельная точность прорисовки именно на экране - внешнее устройство за одну итерацию выдает информацию ровно о 512 измерениях, которые должны соответствовать определенным 512 пикселам на мониторе, поэтому размерность обязательно должна быть в пикселах. Вот на принтер большой точности вывода не требуется - по принципу "лишь бы можно было прочитать ранее сохраненный результат". Но надо печатать на весь лист. -------------------- Нет ничего невозможного. Есть цели, и есть время и силы на их достижение. |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Можно, конечно, и так, но криво. Лучше сделать разные функции установки системы координат. Но для этого функции рисования должны рисовать не в пикселах, а логических координатах. И вовсе не обязательно использовать логические координаты устройства (т.е. ф-и CDC). Например, я делаю так: вся графика у меня в действительных координатах (субпиксельная), а при выводе в зависимости от масштаба и позиции экрана трансформируется в экранные пикселы. На печати, соответственно, в твипсы. Если у тебя нет задачи масштабировать-панорамировать вывод, то можно для экрана сделать пустое (единичное) преобразование. -------------------- ... |
|||
|
||||
| Dreamer_0x01 |
|
||||
![]() Терминатор ![]() ![]() Профиль Группа: Участник Сообщений: 780 Регистрация: 14.4.2005 Где: Санкт-Петербург Репутация: 9 Всего: 12 |
У меня функция рисования - достаточно большой код, все сделано функциями CDC и более того, привязана к абсолютным значениям в пикселах. Переделывать ее будет трудно, писать вторую, делающую то же самое - тоже не выход. Разьъясни, пожалуйста, по шагам, что мне нужно сделать, чтбы получить печать с минимальными потерями. Примем это во внимание:
Ничего масштабировать не надо - вывод на экран всегда в область определенного размера, все размерности меряются в пикселах. Опять же, если печать будет не точь в точь на полный лист, а плюс-минус пару сантиметров - тоже не страшно. -------------------- Нет ничего невозможного. Есть цели, и есть время и силы на их достижение. |
||||
|
|||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Разъясняю.
Все координаты перед выводом на экран пропускаешь через некоторую функцию (объект) преобразователь. Что-то типа TransformPoints (CPoint* pp, size_t np); Для вывода на экран используешь пустую функцию (которая не меняет координаты). Для вывод на принтер устанавливаешь такие параметры, чтобы все растянуть на лист. Преобразование линейное (масштаб + возможно, сдвиг). Параметры уж сам как-нибудь вычисли, не маленький. Например из расчета отобразить прямоугольник экрана в прямоугольник на листе. Не хочешь в даблах - делай в интах, только поаккуратнее с вычислениями. Другой способ (вернее тот же самый, но с подходом сбоку). Делаем обертку вокруг CDC, которая сама будет вычислить (преобразовывать) координаты при всех нужных функциях рисования.
Все что надо - заменить CDC на MYSuperDC. Естественно, реализовать все нужные функции по мере воплей компилятора. Это лучше в смысле инкапсуляции - код рисования не загромождается, а все преобразования координат запихиваются в контекст. Собственно, примерно то же самое делает и Windows, если режим не MM_TEXT. Если решишь делать так, совет: не наследуй CDC, а сделай именно обертку - так более управляемо в смысле сопровождения и вообще более гибко. В конце концов, если где-то нужен "чистый" контекст (и не важны координаты), можно сделать get-метод (всякие SelectObject). Но можно и дальше пойти - скажем, у меня на таком супер-контексте висит слежение за устанавливаемыми в контекст перьями и прочей фигней, чтобы, во-первых, ресурсы не уплывали, а во-вторых, оптимизация (если просят то же самое перо, что уже стоит, ничего не делаем). В общем, есть простор для выдумывания лучшего, которое враг хорошего... -------------------- ... |
|||
|
||||
| Dreamer_0x01 |
|
|||
![]() Терминатор ![]() ![]() Профиль Группа: Участник Сообщений: 780 Регистрация: 14.4.2005 Где: Санкт-Петербург Репутация: 9 Всего: 12 |
Хорошо, допустим, делаю обертку, в которой поределяю все, что использую - рисование линий, дуг, текста. Все функции преобразовывают координаты в зависимости от настроек принтер-экран.
Но как быть с вывода текста? У меня в CreateFont передается высота символов в пикселах. Получается, для шрифтов надо тоже обертки сделать? -------------------- Нет ничего невозможного. Есть цели, и есть время и силы на их достижение. |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Я бы сделала не для самих шрифтов, а для функции SelectObject, которая шрифт устанавливает (в смысле отдельную функцию SelectObject (CFont*).
Она должна, если это контекст печати, создавать новый фонт, пересчитывая размеры переданного. Только эти созданные шрифты где-то хранить надо, т.е. придется завести у себя в обертке CFont. Как-то так. -------------------- ... |
|||
|
||||
| Dreamer_0x01 |
|
|||
![]() Терминатор ![]() ![]() Профиль Группа: Участник Сообщений: 780 Регистрация: 14.4.2005 Где: Санкт-Петербург Репутация: 9 Всего: 12 |
Ага, идея ясна. И последний, самый дурацкий вопрос - а как узнать, какому количеству пикселей соответствует размер печатного листа?
Не могу найти нужные функции. -------------------- Нет ничего невозможного. Есть цели, и есть время и силы на их достижение. |
|||
|
||||
| Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
А фиг его знает, если честно. Сто лет этим не занималась. Вот смотри, выдрала из приложения кусок кода, который вроде параметры бумаги устанавливает. Код древний и кривой, но вроде работает, так что разбирайся.
Там вроде все выковыривается то ли в мм, то ли в долях мм, а твипсы (пикселы принтера) получаются согласно определению:
И обрати внимание, по отношению к MM_TEXT это "перевернутая" CК (т.е. у растет вверх); это нужно учесть при преобразовании координат.
-------------------- ... |
||||
|
|||||
| Dreamer_0x01 |
|
|||
![]() Терминатор ![]() ![]() Профиль Группа: Участник Сообщений: 780 Регистрация: 14.4.2005 Где: Санкт-Петербург Репутация: 9 Всего: 12 |
В общем, мучался я очень долго. Не знаю почему, но мне так и не удалось заставить принтер хоть что-либо печатать в том случае, если делал SetMapMode с любым параметром, у которого координата у направлена снизу вверх.
Однако, использование StretchBlt вместо BitBlt уже само по себе позволило растянуть изображение почти на весь лист, но с прикидкой "на глаз". Код Earnest рабочий, но он видимо дает размеры печатной области соответствующие режима MM_LOMETRIC, с которым как я говорил у меня ни печатать не получилось, ни даже рисовать напрямую тестовые линии/кружочки. Для листа А4 эти параметры как раз равны 2969 и 2101. На вид требовалось явно в двое большая размерность. Выход нашел такой - не менял никакие режимы вывода, то есть оставил MM_TEXT по умолчанию. Размеры печатной области в логических координатах получил через функцию контекста GetClipBox. Теперь печатный рисунок вписывается точь в точь в размеры листа бумаги, что мне и требовалось сделать. Что касается этого эффекта: Показал заказчику - его такое качество изображения удовлетворило вполне, так как ему совершенно не важна "красивость" линий и шрифтов, а важно только, чтобы расстояние на картинке между контрольными точками было пропорционально экранным расстояниям. Спасибо Earnest за то, что цепочкой рассуждений привела к хорошему решению ;) -------------------- Нет ничего невозможного. Есть цели, и есть время и силы на их достижение. |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |