Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2003.08.28;
Скачать: [xml.tar.bz2];

Вниз

Режимы координат для экрана, отличные от MM_TEXT   Найти похожие ветки 

 
KSergey   (2003-06-23 17:17) [0]

Как в режиме координат, отличном от MM_TEXT, для экрана сопоставить логические координаты с физическими точками экрана? Или это невозможно? (например, режим MM_HIMETRIC)

Вообще-то задача вот какая: необходимо задать высоту шрифта текста в каких-либо единицах точнее, чем 1 физический пиксел. Я понимаю, что точнее на экран не выведешь, но при отрисовке если задавать высоту с точностью выше (мельче) чем пиксел - хоть и визуально высота не совсем меняется, но ширина текста (особенно блинного) плывет, что и надо. А надо отобразить идентично на экране и на принтере. При этом на принтере то все отлично - сколько хочешь милиметров (например) - столько и получаешь, а вот совместить это с экраном - не совсем удается. Т.е. различные элементы не адекватно выравниваются там и тут (особенно, если шрифт мелкий и его высота на экране в пикселах невелика (5-7, например) - разница очень разительна).
Понимаю, надо ввести возможность масштабирования на экране - это есть, но хотелось бы, чтобы и при мелком масштабе более-менее походило на правду (а то при различных масштабах элементы смещаются).

И еще. А как всякие фотошопы при отображении текста делают его контур как бы размытым, т.е. этакая иллюзия немного шире/уже пиксела текст? Как такого можно добиться? Просто OutText не хочет такого делать.. Или на то он и фотошоп?


 
DieHard   (2003-06-23 17:48) [1]

procedure HimetricToPixels( const x_hi, y_hi : integer; var x_px, y_px: integer );
const
HIMETRIC_INCH = 2540;
var
dc : HDC;
begin

dc := GetDC( 0 );
if dc <> 0 then
begin

x_px := MulDiv(x_hi, GetDeviceCaps(dc, LOGPIXELSX), HIMETRIC_INCH);
y_px := MulDiv(y_hi, GetDeviceCaps(dc, LOGPIXELSY), HIMETRIC_INCH);

ReleaseDC( 0 , dc );
end;
end;


 
KSergey   (2003-06-24 16:57) [2]

Что-то не выходит...
GetDeviceCaps при любом раскладе всегда возвращает 96... (для экрана)

Вот как я делаю для пробы:

procedure TMyForm.FormPaint(Sender: TObject);
var
Hmm: Integer;
begin
SetMapMode (Canvas.Handle, MM_HIMETRIC); // уст. единицы изменения - 0.01 мм
Hmm := GetDeviceCaps (Canvas.Handle, LOGPIXELSY); { =96 }
SetMapMode (Canvas.Handle, MM_LOMETRIC); // уст. единицы изменения - 0.1 мм
Hmm := GetDeviceCaps (Canvas.Handle, LOGPIXELSY); { =96 }
SetMapMode (Canvas.Handle, MM_TEXT); // уст. единицы - пикселы
Hmm := GetDeviceCaps (Canvas.Handle, LOGPIXELSY); { =96 }
... далее не важно ...
end;


GetDeviceCaps не зависимо от режима всегда возвращает 96! При этом сами различные единицы явно устанавливаются (судя по тем координатам, в которых приходится выводить текст и задавать его высоту - явно не в пикселах; здесь это опущено - не суть). Не пойму никак - как же это все пересчитывать...

Пробовал и с явным получением HDC (для пробы) - нифига. Всегда GetDeviceCaps возвращает 96, хоть и вызываю его после установки режима отображения... Может поделитесь еще секретами?


 
DieHard   (2003-06-25 13:32) [3]

96 - это кол-во пикселей на логический дюйм
Поэтому мы его и делим на HIMETRIC_INCH, чтобы получить коэффициент для пересчета в пиксели.
Тогда, например, если в режиме MM_HIMETRIC у нас высота h_hi = 254, то при переводе в пиксели получаем h_px = h_hi * 96 / HIMETRIC_INCH = 9.6 писелей.
Для режима MM_LOMETRIC получили бы (при h_lo = 254 и LOMETRIC_INCH = 254 ) h_px = h_lo * 96 / LOMETRIC_INCH = 96 пикселей.
Соответственно для MM_HIENGLISH значение логического дюйма равно 1000, а для MM_LOENGLISH - 100;


 
KSergey   (2003-06-26 08:47) [4]

Спасибо за ответы, нто что-то не получается пока.
Посути эта константа (HIMETRIC_INCH) - лишь соотносит дюймы и сотые доли мм. Если попробовать таки приводимые Вами методики (ради любопытства: Вы пробовали?), то не пашет.

Вот пример (вместо HIMETRIC_INCH вписал число):

procedure TTestForm.FormPaint(Sender: TObject);
var
Hlog, Hpx: Integer;
begin
Hpx := 30; // высота, которую хотим получить на экране в пикселах
Hlog := MulDiv (Hpx, 2540, PixelsPerInch); // высота в лог. единицах
Canvas.Brush.Color := clWhite;
Canvas.Font.Name := "Times New Roman"; // здесь какой-нибудь масштабируемый шрифт
Canvas.Font.Height := Hlog;
Canvas.TextOut (500, -50, "ЙЙЙЙуууууу");
Canvas.Brush.Color := clBlack;
Canvas.FillRect (Rect(2000, -20, 3000, -20 - Hlog));
end;


Что получаем: высота квадрата равно высоте текста (это просто для проверки), но их высота ника не равна заданной в Hpx величине...
Что я делаю не так?


 
DieHard   (2003-06-26 11:57) [5]

...
begin
SetMapMode(Canvas.Handle, MM_HIMETRIC);
...


 
KSergey   (2003-06-26 13:35) [6]

Извиняюсь, я не верно скопировал текст (убирал лишнее - ну и выкинул по недогляду).
Текст (сейчас еще раз проверил) буквально такой

procedure TAboutForm.FormPaint(Sender: TObject);
var
Hlog, Hpx: Integer;
begin
SetMapMode (Canvas.Handle, MM_HIMETRIC); // уст. единицы изменения - 0.01 мм
Hpx := 40; // высота, которую хотим получить на экране в пикселах
Hlog := MulDiv (Hpx, 2540, PixelsPerInch); // высота в лог. единицах
Canvas.Brush.Color := clWhite;
Canvas.Font.Name := "Times New Roman"; // здесь какой-нибудь масштабируемый шрифт
Canvas.Font.Height := Hlog;
Canvas.TextOut (500, -50, "ЙЙЙЙуууууу");
Canvas.Brush.Color := clBlack;
Canvas.FillRect (Rect(2000, -20, 3000, -20 - Hlog));
end;


Но я ведь не напрасно спрашивал: Вы пробовали? ;)

Вообще-то что-то я стормозил - есть же готовая ф-ция пересчета из логических координат в физические.

Так, например, вот такой код дает нужный в принципе результат:

procedure TAboutForm.FormPaint(Sender: TObject);
var
Hlog, Hpx: Integer;
pt: TPoint;
begin
Hpx := 35; // высота, которую необходимо получить в пикселах
pt.x := 0;
pt.y := Hpx;
SetMapMode (Canvas.Handle, MM_HIMETRIC); // уст. единицы изменения - 0.01 мм
DPtoLP (Canvas.Handle, pt, 1); ( pt.y)
Извиняюсь, я не верно скопировал текст (убирал лишнее - ну и выкинул по недогляду).
Текст (сейчас еще раз проверил) буквально такой

procedure TAboutForm.FormPaint(Sender: TObject);
var
Hlog, Hpx: Integer;
begin
SetMapMode (Canvas.Handle, MM_HIMETRIC); // уст. единицы изменения - 0.01 мм
Hpx := 40; // высота, которую хотим получить на экране в пикселах
Hlog := MulDiv (Hpx, 2540, PixelsPerInch); // высота в лог. единицах
Canvas.Brush.Color := clWhite;
Canvas.Font.Name := "Times New Roman"; // здесь какой-нибудь масштабируемый шрифт
Canvas.Font.Height := Hlog;
Canvas.TextOut (500, -50, "ЙЙЙЙуууууу");
Canvas.Brush.Color := clBlack;
Canvas.FillRect (Rect(2000, -20, 3000, -20 - Hlog));
end;


Но я ведь не напрасно спрашивал: Вы пробовали? ;)

Вообще-то что-то я стормозил - есть же готовая ф-ция пересчета из логических координат в физические.

Так, например, вот такой код дает нужный в принципе результат:

procedure TAboutForm.FormPaint(Sender: TObject);
var
Hlog, Hpx: Integer;
pt: TPoint;
begin
Hpx := 35; // высота, которую необходимо получить в пикселах
pt.x := 0;
pt.y := Hpx;
SetMapMode (Canvas.Handle, MM_HIMETRIC); // уст. единицы изменения - 0.01 мм
DPtoLP (Canvas.Handle, pt, 1); // а вот он и пересчет!
HLog := -Round(pt.y);
Canvas.Brush.Color := clWhite;
Canvas.Font.Name := "Times New Roman";
Canvas.Font.Height := Hlog;
Canvas.TextOut (500, -50, "ЙЙЙЙуууууу");
Canvas.Brush.Color := clBlack;
Canvas.FillRect (Rect(2000, -20, 3000, -20 - Hlog));
end;


Вот в этом случае получается то, что и ожидалось - высота квадрата и букв ровно 35 пикселей (ну вернее 34, но это стандартная хитрость GDI). С любой другой заданной высотой тоже все отлично.
Но вот общей поставленной цели это не решает.
Опишу на примере. Все цифры с потолка, лишь для иллюстрации.

Например, для физического размера 10 пикселей логическая высота 500, а для 11 пикселей - 600. При этом при высоте в пикселях 10 получаем длину строки 1000 пикселей, при высоте 11 - ширина той же строки 1100.
Затевая все это я надеялся, сто при указании логической высоты между 500 и 600 (например 550, т.е. как бы 10.5 пикселей) ширина строки тоже немного увеличится, и окажется равной, например, 1050 (визуально высота, конечно, не изменится (в пикселах) но при выводе символов они в ширину немного как бы поплывут, т.к. тут есть куда плять - разница-то больше физического пиксела) - но не тут то было... Ширина так же меняется скачком...
А ведь все начиналось именно с того, чтобы получить изменение ширины более чуствительное, чем шаг физической высоты.
Вот в этом плане как быть?
И еще повторю вопрос: а как всякие колелы делают анлиалиасинг при выводе шрифтов? Примеры есть только для всяких заштриховок.


 
KSergey   (2003-06-26 13:37) [7]

Уточню: первый код предыдущего поста не дает нужного результата. Во втором Round конечно же лишнее, по запарке не убрал.


 
DieHard   (2003-06-26 16:44) [8]

Да, я тогда попробовал, но больше обратил внимание на эффект от пропущенной строки, чем на то, что в результате получилось. Странно, что DPtoLP и мой способ отличаются. Но факт :)
Я его использую для несколько иных целей (конкретно - пересчет размеров, полученных из IPicture, в пиксели) и там он работает прекрасно.
А со шрифтами задуманное похоже может не выйти. Скорее всего при выводе на экран по-любому производится пересчет в физические координаты и поэтому сказываются ошибки округления.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2003.08.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.006 c
3-91998
boka
2003-08-06 08:24
2003.08.28
При организации доступа к Ecxel файлу через ODBC возникла проблем


14-92257
dataMaster
2003-08-09 09:53
2003.08.28
Delphi 3 Professional


3-92050
Nikolay M.
2003-08-04 10:48
2003.08.28
MIDAS, ReconcileError и ClientDataSet.Append


6-92147
Sheng
2003-06-19 11:44
2003.08.28
Обмен данными по локальной сети


14-92238
Marser
2003-07-16 19:25
2003.08.28
Абитуриада-2003





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский