powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / WinAPI DrawText
12 сообщений из 12, страница 1 из 1
WinAPI DrawText
    #32236294
lnu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот такой вопрос.

Как правильно рассчитать прямоугольник для 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
WinAPI DrawText
    #32237405
lnu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если надо, вот код проги которая печатает текст на екран и на принтер:
Код: 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
WinAPI DrawText
    #32237494
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я могу ошибаться, поскольку в API - не силен, но здесь явная проблема в единицах измерения.

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

Если же это твипы (twip), то проблема где-то в другом месте :) поскольку как раз-таки твипы не зависят от настроек устройства (для чего собственно и были введены)
...
Рейтинг: 0 / 0
WinAPI DrawText
    #32237616
lnu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там используються пикселы.
Если в екрана 96 dpi, а в принтера 300 dpi я пробовал умножать эти координаты на INT(300/96), но прямоугольники всё ровно не идентичны.
...
Рейтинг: 0 / 0
WinAPI DrawText
    #32237626
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет. Перевод не такой простой. Размер пиксела зависит от текущей настройки соответсвующего устройства. Универсальной единицей измерения является твип (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
WinAPI DrawText
    #32237776
lnu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Функция 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
WinAPI DrawText
    #32237826
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, то что я написал раньше в данном случае неуместно. Печать через @Say определяет координаты в так называемых "фокселах". 1 фоксел - это средний размер одного символа в текущем шрифте.

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

X*300/96+k

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

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

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

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

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

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


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