Форум: "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