Аннотация:
Печать в WTL не так хорошо развита и проработана, как в других библиотеках. Статья рассказывает, как преодолеть недостатки этой библиотеки, используя ее гибкость и открытую структуру.
Здравствуйте, Шевченко Александр, Вы писали:
ША>В тексте есть фраза "в нем еще допущены грубые ошибки, выделенные в коде красным.". ША>Так вот ничего красного там нет .
Здравствуйте, Шевченко Александр, Вы писали:
ША>В тексте есть фраза "в нем еще допущены грубые ошибки, выделенные в коде красным.". ША>Так вот ничего красного там нет .
При вызове функции StartDoc спулер печати создает расширенный метафайл (enhanced metafile). В него записываются функции GDI, вызванные для данного контекста принтера. Только после закрытия документа вызовом EndDoc расширенный метафайл выводится на принтер.
Это неверно в общем случае...
Документация гласит:
The EndPage function notifies the device that the application has finished writing to a page. This function is typically used to direct the device driver to advance to a new page.
Достаточно поставить галку в поле "start printing immediately" вместо "last page spooled" и Ваше выражение становится false.
2)
...Здесь сначала вычисляется ширина и высота бумаги в логических единицах, затем вычисляется размер бумаги в дюймах и только потом, с помощью функции MulDiv – размер бумаги в миллиметрах. Стоит ли говорить, что это все это приводит к некоторой потери точности. Стандартный код можно заменить следующим:
RECT rcMM = {0, 0,
dcPrinter.GetDeviceCaps(HORZSIZE)*100,
dcPrinter.GetDeviceCaps(VERTSIZE)*100};
Нельзя! GetDeviceCaps обращается к драйверу принтера.
И не все проиводители драйверов считают что им нужно отрабатывать
HORZSIZE — Width, in millimeters, of the physical screen.
в дополнение к обязательному:
PHYSICALWIDTH — For printing devices: the width of the physical page, in device units.
"Пойдите и спытайте у пани Зборовьской — чи е у нея принтеров Lexmark" — особенно "засадные" драйверы у оных...
( из горького опыта )
А вообще статья полезная. Спасибо от лица читателей.
Андрей.
ПыСы
а красное выделение я бы убрал с
if (*lpsz == ',')
это не бага, а знание того что нулевой codeset (C0) в UNICODE есть ASCII (http://www.unicode.org/charts/PDF/U0000.pdf)
Здравствуйте, c-smile, Вы писали:
CS>... если позволите...
CS>1)
CS>При вызове функции StartDoc спулер печати создает расширенный метафайл (enhanced metafile). В него записываются функции GDI, вызванные для данного контекста принтера. Только после закрытия документа вызовом EndDoc расширенный метафайл выводится на принтер.
CS>Это неверно в общем случае...
CS>Документация гласит: CS>The EndPage function notifies the device that the application has finished writing to a page. This function is typically used to direct the device driver to advance to a new page.
CS>Достаточно поставить галку в поле "start printing immediately" вместо "last page spooled" и Ваше выражение становится false.
Непонятно. Можно поподробней.. Какое выражение? В чем собственно ошибка?
CS>2)
CS>...Здесь сначала вычисляется ширина и высота бумаги в логических единицах, затем вычисляется размер бумаги в дюймах и только потом, с помощью функции MulDiv – размер бумаги в миллиметрах. Стоит ли говорить, что это все это приводит к некоторой потери точности. Стандартный код можно заменить следующим:
CS>RECT rcMM = {0, 0, CS>dcPrinter.GetDeviceCaps(HORZSIZE)*100, CS>dcPrinter.GetDeviceCaps(VERTSIZE)*100};
CS>Нельзя! GetDeviceCaps обращается к драйверу принтера. CS>И не все проиводители драйверов считают что им нужно отрабатывать CS>HORZSIZE — Width, in millimeters, of the physical screen. CS>в дополнение к обязательному: CS>PHYSICALWIDTH — For printing devices: the width of the physical page, in device units.
От себя добавлю, что
MulDiv(GetDeviceCaps(hDC, PHYSICALWIDTH), 2540, GetDeviceCaps(hDC, LOGPIXELSX))
НЕ РАВНО !!!!
GetDeviceCaps(HORZSIZE)*100
..по крайней мере на двух принтерах (Lexmark Z11, Color Laserjet 5M). Из-за этого размер листа подсчитывается неправильно и в целом картинка вылазит за пределы.
CS>А вообще статья полезная. Спасибо от лица читателей.
Здравствуйте, kliff, Вы писали:
K>Здравствуйте, c-smile, Вы писали:
CS>>При вызове функции StartDoc спулер печати создает расширенный метафайл (enhanced metafile). В него записываются функции GDI, вызванные для данного контекста принтера. Только после закрытия документа вызовом EndDoc расширенный метафайл выводится на принтер.
CS>>Это неверно в общем случае...
CS>>Документация гласит: CS>>The EndPage function notifies the device that the application has finished writing to a page. This function is typically used to direct the device driver to advance to a new page.
CS>>Достаточно поставить галку в поле "start printing immediately" вместо "last page spooled" и Ваше выражение становится false.
K>Непонятно. Можно поподробней.. Какое выражение? В чем собственно ошибка?
Выделено bold.
"start printing immediately" означает что metafile создается по StartPage и выводится по EndPage. Т.е. постранично.
А не по EndDoc.
CS>>2)
CS>>...Здесь сначала вычисляется ширина и высота бумаги в логических единицах, затем вычисляется размер бумаги в дюймах и только потом, с помощью функции MulDiv – размер бумаги в миллиметрах. Стоит ли говорить, что это все это приводит к некоторой потери точности. Стандартный код можно заменить следующим:
CS>>RECT rcMM = {0, 0, CS>>dcPrinter.GetDeviceCaps(HORZSIZE)*100, CS>>dcPrinter.GetDeviceCaps(VERTSIZE)*100};
CS>>Нельзя! GetDeviceCaps обращается к драйверу принтера. CS>>И не все проиводители драйверов считают что им нужно отрабатывать CS>>HORZSIZE — Width, in millimeters, of the physical screen. CS>>в дополнение к обязательному: CS>>PHYSICALWIDTH — For printing devices: the width of the physical page, in device units.
K>От себя добавлю, что K> MulDiv(GetDeviceCaps(hDC, PHYSICALWIDTH), 2540, GetDeviceCaps(hDC, LOGPIXELSX)) K>НЕ РАВНО !!!! K> GetDeviceCaps(HORZSIZE)*100
В чем измеряется разрешение принтеров?
В DPI — dots ("pixels") per inch. Правильно?
Т.е. физические характеристики шаговых двигателей, сопел и пр.подогнаны под дюймы.
Естественно что GetDeviceCaps(HORZSIZE) будет возвращать некие округленные значения...
K>..по крайней мере на двух принтерах (Lexmark Z11, Color Laserjet 5M). Из-за этого размер листа подсчитывается неправильно и в целом картинка вылазит за пределы.
Кем или чем просчитывается неправильно?
Re[4]: Замечания...
От:
Аноним
Дата:
29.11.03 12:17
Оценка:
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, kliff, Вы писали:
K>>Здравствуйте, c-smile, Вы писали:
CS>>>...Здесь сначала вычисляется ширина и высота бумаги в логических единицах, затем вычисляется размер бумаги в дюймах и только потом, с помощью функции MulDiv – размер бумаги в миллиметрах. Стоит ли говорить, что это все это приводит к некоторой потери точности. Стандартный код можно заменить следующим:
CS>>>RECT rcMM = {0, 0, CS>>>dcPrinter.GetDeviceCaps(HORZSIZE)*100, CS>>>dcPrinter.GetDeviceCaps(VERTSIZE)*100};
CS>>>Нельзя! GetDeviceCaps обращается к драйверу принтера. CS>>>И не все проиводители драйверов считают что им нужно отрабатывать CS>>>HORZSIZE — Width, in millimeters, of the physical screen. CS>>>в дополнение к обязательному: CS>>>PHYSICALWIDTH — For printing devices: the width of the physical page, in device units.
K>>От себя добавлю, что K>> MulDiv(GetDeviceCaps(hDC, PHYSICALWIDTH), 2540, GetDeviceCaps(hDC, LOGPIXELSX)) K>>НЕ РАВНО !!!! K>> GetDeviceCaps(HORZSIZE)*100
CS>В чем измеряется разрешение принтеров? CS>В DPI — dots ("pixels") per inch. Правильно? CS>Т.е. физические характеристики шаговых двигателей, сопел и пр.подогнаны под дюймы.
CS>Естественно что GetDeviceCaps(HORZSIZE) будет возвращать некие округленные значения...
Я наверное чего-то не понимаю.. Зачем подсчитывать приближенно, если известны все переменные — разрешение (DPI), размер листа в точках и мера перевода из дюймов в миллиметры.. Тут по идее не должно быть никаких приближений, кроме ситуаций когда DPI возвращается неправильный (т.е. принтер говорит 1440, а на самом деле 1410). Такое разве возможно?
K>>..по крайней мере на двух принтерах (Lexmark Z11, Color Laserjet 5M). Из-за этого размер листа подсчитывается неправильно и в целом картинка вылазит за пределы.
CS>Кем или чем просчитывается неправильно?
Сорри, это все комментарий к решению Алексея подсчитывать размеры листа в миллиметрах. Когда я стал подсчитывать таким образом моя картинка стала немного вылазить за пределы листа. Поэтому сейчас подсичтывается стандартным WTL-ым способом.
Уважаемые, никто не сталкивался с проблемой preview альбомной ориентации в Win9x?
Как известно, preview страницы создается в CPrintPreview::SetPage(), код такой:
// создаем dc принтера...
CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
m_pInfo->PrePrintPage(nPage, dcMeta); // здесь ::SaveDC()
m_pInfo->PrintPage(nPage, dcMeta); // здесь печать наших данных в HDC meta
m_pInfo->PostPrintPage(nPage, dcMeta); // здесь ::RestoreDC()
m_meta.Attach(dcMeta.Close()); // m_meta проигрывается в DoPaint()
} // end func()
так вот оказывается, что ::CreateEnhMetaFile() из конструктора CEnhMetaFileDC
в ОС Win9x для страниц альбомной ориентаци (dcPrinter — альбомное) создает портретный
dc метафайла (смотрим по ::GetDeviceCaps(dc, HORZRES)). То есть на вход даем rcMM
альбомный — получаем портретный dcMeta. Если сделать swap сторон rcMM, получаем
альбомный dcMeta. Но это же не метод ?!
А на платформе NT — все хорошо, создается альбомное dcMeta во всех случаях и красиво
рисуется.
Есть идеи по этому поводу? MSDN про различия платформ для ::CreateEnhMetafile()
скромно молчит.
Здравствуйте, alexvrsdn, Вы писали:
A>Уважаемые, никто не сталкивался с проблемой preview альбомной ориентации в Win9x?
A>Как известно, preview страницы создается в CPrintPreview::SetPage(), код такой:
A>
A> // создаем dc принтера...
A> CEnhMetaFileDC dcMeta(dcPrinter, &rcMM);
A> m_pInfo->PrePrintPage(nPage, dcMeta); // здесь ::SaveDC()
A> m_pInfo->PrintPage(nPage, dcMeta); // здесь печать наших данных в HDC meta
A> m_pInfo->PostPrintPage(nPage, dcMeta); // здесь ::RestoreDC()
A> m_meta.Attach(dcMeta.Close()); // m_meta проигрывается в DoPaint()
A>} // end func()
A>
A>так вот оказывается, что ::CreateEnhMetaFile() из конструктора CEnhMetaFileDC A>в ОС Win9x для страниц альбомной ориентаци (dcPrinter — альбомное) создает портретный A>dc метафайла (смотрим по ::GetDeviceCaps(dc, HORZRES)). То есть на вход даем rcMM A>альбомный — получаем портретный dcMeta. Если сделать swap сторон rcMM, получаем A>альбомный dcMeta. Но это же не метод ?!
A>А на платформе NT — все хорошо, создается альбомное dcMeta во всех случаях и красиво A>рисуется.
A>Есть идеи по этому поводу? MSDN про различия платформ для ::CreateEnhMetafile() A>скромно молчит.
У себя такого не замечал. Что точно — так это без доработок CPrintPreview под 9х не работает.