Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / WinAPI DrawText / 12 сообщений из 12, страница 1 из 1
14.08.2003, 11:34
    #32236294
lnu
lnu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Вот такой вопрос.

Как правильно рассчитать прямоугольник для DrawText?

= DrawText (PrinterHDC, lcText, Len(lcText), @lcRect, DT_WORDBREAK)
= DrawText ( 0 , lcText, Len(lcText), @lcRect, DT_WORDBREAK)

На екране получается одно, а на принтере совсем другое. Т.е. в одном случае в строку попадает например 5 слов, а в другом 4.
Пробовал искать какие-то коефициенты с GetDeviceCaps, но ничего хорошего не получилось.

На одном из форумов по API мне ответили:

Используя флаг DT_CALCRECT сделать сначала DrawText в DC своего окна, потом в DC принтера. Имея два RECT можно посчитать пропорции.

Но как, я так и не понял :(
...
Рейтинг: 0 / 0
15.08.2003, 11:33
    #32237405
lnu
lnu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Если надо, вот код проги которая печатает текст на екран и на принтер:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
DO decl 
#DEFINE TRANSPARENT   1  
#DEFINE OPAQUE        2  

#DEFINE DT_LEFT       0  
#DEFINE DT_CENTER     1  
#DEFINE DT_TOP        0  
#DEFINE DT_RIGHT      2  
#DEFINE DT_WORDBREAK  16  

    LOCAL hWindow, hDC, lcRect, lcText 
    hWindow = GetActiveWindow() 
    hDC = GetWindowDC(hWindow)   
    lcText =  "The DrawText function draws formatted text "  +; 
         "in the specified rectangle. It formats the text "  +; 
         "according to the specified method (expanding tabs, "  +; 
         "justifying characters, breaking lines, and so forth)."  

    lcRect = n2dw( 100 ) + n2dw( 300 ) + n2dw( 400 ) + n2dw( 600 ) 
    = Rectangle(hdc, 100 - 1 , 300 - 1 , 400 + 1 , 600 + 1 )
    = DrawText (hDC, lcText, Len(lcText), @lcRect, DT_WORDBREAK) 
    = ReleaseDC(hWindow, hDC) 

a=GETPRINTER( )
IF !EMPTY(a)
  printerHDC=createdc('',a, 0 , 0 )
  lcDocInfo = Chr( 20 ) + Repli(Chr( 0 ),  19 ) 
  IF StartDoc(printerhDC, @lcDocInfo) >  0 
        = StartPage(printerhDC)
        = Rectangle(printerhdc, 100 - 1 , 300 - 1 , 400 + 1 , 600 + 1 )
        = DrawText (printerHDC, lcText, Len(lcText), @lcRect, DT_WORDBREAK) 
        = EndPage(printerhDC)
        = EndDoc(printerhDC)
  ENDIF 
 ENDIF 

PROCEDURE decl 
    DECLARE INTEGER GetActiveWindow IN user32 
    DECLARE INTEGER GetWindowDC IN user32 INTEGER hWnd 
    DECLARE INTEGER ReleaseDC IN user32 INTEGER hWnd, INTEGER hDC 
    DECLARE INTEGER DrawText IN user32; 
        INTEGER hDC, STRING lpString, INTEGER nCount,; 
        STRING @lpRect, INTEGER uFormat 
   DECLARE INTEGER CreateDC IN gdi32 STRING lpszDriver, STRING lpszDevice,INTEGER lpszOutput,   INTEGER lpInitData 
   DECLARE INTEGER StartDoc IN gdi32 INTEGER hdc, STRING @ lpdi  
   DECLARE INTEGER EndDoc IN gdi32 INTEGER hdc 
   DECLARE INTEGER StartPage IN gdi32 INTEGER hdc 
   DECLARE INTEGER EndPage IN gdi32   INTEGER hdc
   DECLARE INTEGER Rectangle IN gdi32   INTEGER hdc,INTEGER x1,INTEGER y1,INTEGER x2,INTEGER y2


FUNCTION n2dw (lnValue) 
#DEFINE m0        256  
#DEFINE m1      65536  
#DEFINE m2   16777216  
    LOCAL b0, b1, b2, b3 
    b3 = Int(lnValue/m2) 
    b2 = Int((lnValue - b3*m2)/m1) 
    b1 = Int((lnValue - b3*m2 - b2*m1)/m0) 
    b0 = Mod(lnValue, m0) 
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3) 



но результат на екране и на бумаге почемуто не совпадает :(
...
Рейтинг: 0 / 0
15.08.2003, 12:26
    #32237494
ВладимирМ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Я могу ошибаться, поскольку в API - не силен, но здесь явная проблема в единицах измерения.

В каких единицах измерения задаются координаты в lcRect ? Если это пикселы или логические дюймы (логические санитиметры), то требуются специальные переводные коэффициенты, чтобы привести в соответсвие координаты экрана и координаты принтера. Это можно сделать через функцию GetDeviceCaps() для экрана и принтера соответственно.

Если же это твипы (twip), то проблема где-то в другом месте :) поскольку как раз-таки твипы не зависят от настроек устройства (для чего собственно и были введены)
...
Рейтинг: 0 / 0
15.08.2003, 13:40
    #32237616
lnu
lnu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Там используються пикселы.
Если в екрана 96 dpi, а в принтера 300 dpi я пробовал умножать эти координаты на INT(300/96), но прямоугольники всё ровно не идентичны.
...
Рейтинг: 0 / 0
15.08.2003, 13:49
    #32237626
ВладимирМ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Нет. Перевод не такой простой. Размер пиксела зависит от текущей настройки соответсвующего устройства. Универсальной единицей измерения является твип (twip). Т.е. тебе надо перевести экранные пискелы в твипы, а потом из твипов в принтерные пикселы.

Перевод экранных пикселов в твипы делается так:

DECLARE INTEGER GetActiveWindow IN WIN32API
DECLARE INTEGER GetDC IN WIN32API INTEGER iHDC
DECLARE INTEGER GetDeviceCaps IN WIN32API INTEGER iHDC, INTEGER iIndex

LOCAL liHDC
liHDC = GetDC(GetActiveWindow())
LOCAL lnTwipX, lnTwipY
lnTwipX = 1440/GetDeviceCaps(m.liHDC,88)
lnTwipY = 1440/GetDeviceCaps(m.liHDC,90)

* Освобождение контекста устройства, для освобождения памяти
DECLARE INTEGER ReleaseDC IN WIN32API INTEGER, INTEGER
=ReleaseDC(GetActiveWindow(),m.liHDC)

Т.е. размер в твипах на экране это

(размер в пикселах по Х) * m.lnTwipX
(размер в пикселах по Y) * m.lnTwipY

Аналогичный перерасчет необходимо сделать для принтера. Правда как взять контекст принтера я не знаю :(

Чтобы относительные размеры были равны соответсвующие координаты в твипах должны быть равны как у экрана так и у принтера. Думаю, тут уже легко получишь переводной коэффициент.
...
Рейтинг: 0 / 0
15.08.2003, 15:34
    #32237776
lnu
lnu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Функция GetDeviceCaps(HDC,88) для екрана взвращает 96, а для принтера 300. Так что переводным коефициентом для екрана может быть 96, а для принтера 300; тогда еденица измерения будет дюйм. Но все равно, даже с теми коефициентами есть неточности :(\r
\r
2ВладимирМ \r
...как взять контекст принтера... \r
\r
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
a=GETPRINTER( )\r
IF !EMPTY(a)\r
  printerHDC=createdc(\'\',a, 0 , 0 ) && тут и берём контекст\r
  kX=GetDeviceCaps(printerHDC, 88 ) && у меня получилось  300 \r
  xY=GetDeviceCaps(printerHDC, 90 )\r
  lcDocInfo = Chr( 20 ) + Repli(Chr( 0 ),  19 ) \r
  IF StartDoc(printerhDC, @lcDocInfo) >  0 \r
        = StartPage(printerHDC)\r
        = Rectangle(printerHDC*kX,y1*kY,x2*kX,y2*kY)\r
        = DrawText (printerHDC, lcText, Len(lcText), @lcRect, DT_WORDBREAK) \r
        = EndPage(printerhDC)\r
        = EndDoc(printerhDC)\r
  ENDIF \r
 ENDIF \r
\r
\r
P.S. Посмотрите, Владимир, сюда :)\r
Ведь все же можно, осталось добится, чтоб работало корректно...
...
Рейтинг: 0 / 0
15.08.2003, 15:57
    #32237826
ВладимирМ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Ну, то что я написал раньше в данном случае неуместно. Печать через @Say определяет координаты в так называемых "фокселах". 1 фоксел - это средний размер одного символа в текущем шрифте.

В принципе, я уже сталкивался с тем, что разные драйверы принтера под один символ отводят разный размер (при печати через REPORT FORM). Разница заключалась буквально в одной...двух точках, но этого хватало, чтобы отчет "поплыл". С чем это связано я не стал выяснять, просто делал размер по ширине несколько избыточным (буквально на пол-символа). Может и тебе имеет смысл делать перевод по типу:

X*300/96+k

Где k - это и есть небольшая поправка

А кстати, почему не использовать стандартный генератор отчетов? Не обязательно FoxPro, мало ли других генераторов. Там эта проблема должна быть решена.
...
Рейтинг: 0 / 0
15.08.2003, 16:26
    #32237863
lnu
lnu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Ну генератор отчётов я уже сделал свой.
Задача моя заключалася в том, чтоб заполнять готовые бланки документов.
Текст я вводил (или читал с dbf) в Edit'ы, которыt потом переганял в мой репорт.
И тут таже проблемма (kX+k). Для некоторых шрифтов как нибуть подбирал k,
а для не которых.... Вобщем желательно было перед печатью нажать кнопочку "Предварительный просмотр", чтобы убидится всё ли совпалает.
А с DrawText то, что в Edit'е и что вывел этой функцией совпадает.
Т.е. экран -> экран - всё нормально, экран -> принтер - не очень.
Поэтому и хочу переделать эту программку через DrawText, чтоб не использовать репортов (остаеться же это k), а на прямую печатать на принтер.

И что означает
Используя флаг DT_CALCRECT сделать сначала DrawText в DC своего окна, потом в DC принтера. Имея два RECT можно посчитать пропорции.

Как его использовать? Может так удастся найти это k...
...
Рейтинг: 0 / 0
15.08.2003, 16:36
    #32237876
ВладимирМ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Как предположение. Не знаю, насколько правильное.

Вероятно, при использовании DT_CALCRECT происходит расчет размеров прямоугольника с поправкой значений в lcRect . Вот на это и намекали - делаешь 2 расчета и смотришь какие стали значение в lcRect .
...
Рейтинг: 0 / 0
15.08.2003, 16:44
    #32237893
lnu
lnu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Да, пробовал посмотреть, что сидит в lcRect но в VFP это не так уж легко сделать. Не получилось :(
...
Рейтинг: 0 / 0
15.08.2003, 16:53
    #32237911
ВладимирМ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
А в чем проблема-то. У тебя же есть функция формирования lcRect. Сделать все то же самое в обратном порядке лично мне не представляется особо сложным. У тебя же стоит символ @. Т.е. значение lcRect передается по ссылке, значит после выполнения она уже содержит измененное значение надо его только "развернуть".

На сегодня все, сейчас у нас сеть отрубят. Опасаются субботних вирусов :)
...
Рейтинг: 0 / 0
15.08.2003, 17:16
    #32237937
Догма
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
WinAPI DrawText
Эх, Вовка. Твоими бы устами да мед хлебать.
...
Рейтинг: 0 / 0
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / WinAPI DrawText / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]