Печать в WTL
От: Алексей Ширшов Россия http://wise-orm.com
Дата: 24.08.03 12:06
Оценка: 190 (8)
Статья:
Печать в WTL
Автор(ы): Алексей Ширшов
Дата: 09.11.2003
Печать в WTL не так хорошо развита и проработана, как в других библиотеках. Статья рассказывает, как преодолеть недостатки этой библиотеки, используя ее гибкость и открытую структуру.


Авторы:
Алексей Ширшов

Аннотация:
Печать в WTL не так хорошо развита и проработана, как в других библиотеках. Статья рассказывает, как преодолеть недостатки этой библиотеки, используя ее гибкость и открытую структуру.
Re: Печать в WTL
От: Шевченко Александр http://alexsoft.home.nov.ru
Дата: 15.11.03 12:46
Оценка: :)
В тексте есть фраза "в нем еще допущены грубые ошибки, выделенные в коде красным.".
Так вот ничего красного там нет .
Мелочь конечно.
Re[2]: Печать в WTL
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 15.11.03 13:54
Оценка:
Здравствуйте, Шевченко Александр, Вы писали:

ША>В тексте есть фраза "в нем еще допущены грубые ошибки, выделенные в коде красным.".

ША>Так вот ничего красного там нет .

Бага. Поправим.
... << RSDN@Home 1.1.0 stable >>
Re[2]: Печать в WTL
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 16.11.03 10:07
Оценка:
Здравствуйте, Шевченко Александр, Вы писали:

ША>В тексте есть фраза "в нем еще допущены грубые ошибки, выделенные в коде красным.".

ША>Так вот ничего красного там нет .

fixed
Re: Замечания...
От: c-smile Канада http://terrainformatica.com
Дата: 18.11.03 07:29
Оценка: 13 (2)
... если позволите...

1)

При вызове функции 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)
Re[2]: Замечания...
От: kliff Россия http://www.esignal.ru
Дата: 28.11.03 15:53
Оценка:
Здравствуйте, 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>А вообще статья полезная. Спасибо от лица читателей.


весьма полезная, присоединяюсь...
Re[3]: Замечания...
От: c-smile Канада http://terrainformatica.com
Дата: 28.11.03 22:20
Оценка:
Здравствуйте, 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-ым способом.
Re: Печать в WTL - проблемы preview в Win9x
От: alexvrsdn Россия  
Дата: 23.08.04 17:07
Оценка:
Уважаемые, никто не сталкивался с проблемой 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()
скромно молчит.
Re[2]: Печать в WTL - проблемы preview в Win9x
От: kliff Россия http://www.esignal.ru
Дата: 23.08.04 17:28
Оценка:
Здравствуйте, 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х не работает.
Re[3]: Печать в WTL - проблемы preview в Win9x
От: alexvrsdn Россия  
Дата: 23.08.04 18:25
Оценка:
Здравствуйте, kliff, Вы писали:

K>У себя такого не замечал. Что точно — так это без доработок CPrintPreview под 9х не работает.


А каких именно, не скажете, если не трудно? Полезна любая информация. А то уже почти решили на API переписать эту часть.
Re[2]: Печать в WTL - проблемы preview в Win9x
От: Блудов Павел Россия  
Дата: 24.08.04 04:14
Оценка:
Здравствуйте, alexvrsdn, Вы писали:

A>Уважаемые, никто не сталкивался с проблемой preview альбомной ориентации в Win9x?


У меня наоборот, в XP идиотский зеракс P8ex упорно печатает портреты. В 2k все в порядке.
Думаю, это из-за драйверов.

(в порядке рекламы) Люди! Покупайте принтеры HP! С ними у меня никогда проблем не было.
... << RSDN@Home 1.1.4 @@subversion >>
Re: Печать в WTL
От: Mr.  
Дата: 22.04.08 09:56
Оценка:
Здравствуйте, Алексей Ширшов, Вы писали:

тут опечатка небольшая:
    CSize phys_offset(
      dc.GetDeviceCaps(PHYSICALOFFSETX)+100,
      dc.GetDeviceCaps(PHYSICALOFFSETY)+100
    );
    
    //Размер листа в пикселах
    CSize physical_size(
      dc.GetDeviceCaps(PHYSICALWIDTH) - 2 * phys_offset.cx,
      dc.GetDeviceCaps(PHYSICALHEIGHT) - 2 * phys_offset.cy
    );

    //Стандартный шрифт с нестандартным размером :) 
    [skip]
    CRect r(0,0,physical_size.cx,physical_size.cy);

Выделенную строчку надо заменить на:
    CRect r(phys_offset.cx,phys_offset.cy,physical_size.cx,physical_size.cy);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.