![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вывод текста через Canvas.TextOut
Lines © (2008-07-18 18:11:00)Существует светодиодная панель, имеющая некоторое разрешение, на этой панели соответственно можно зажигать или гасить определенные светодиоды. Например, в транспорте светодиодные бегущие строки с названиями остановок и прочее.
Но в данном случае панель управляется компьютером, есть задача выводить на эту панель текст. Чтобы не придумывать собственные шрифты решено рисовать на TBitmap с помощью Canvas.TextOut текст, а потом попиксельно считывать получившееся изображения для передачи на устройство.
Но есть такое понятие как мигание символов, то есть по таймеру то на панель передается изображение со всеми символами, то передается изображение, где мигающие символы не прорисованы, возникает эффект мигания символов. При этом символы, которые не мигают должны статично оставаться на своих местах.
То есть, сразу вывести весь текст с помощью TextOut нельзя, все символы прорисуются.
Другой вариант - прорисовывать отдельно каждый символ, каждый раз сдвигая позицию вывода вправо на TextWidth от символа. При этом произойдет эффект затирания для некоторых шрифтов (думаю, кто знает - сталкивался с проблемой).
Другой вариант - выводить строчку сразу всю, где символы которые не нужно выводить заменены на пробелы. Тоже не вариант, так как символы имеют не постоянную ширину и в результате все "поедет".
Кто какие знает варианты решения проблемы?
P.S. Переиначив задачу скажу так:
Как вывести некую строку текста, притом чтобы не выводились определенные символы в строке, но оставшиеся видимые символы были на том же месте, на котором они бы были, если эти не отображаемые символы бы выводили. ;)
Тын-Дын (2008-07-20 19:07:00) [1]
> AlexanderMS_ (19.07.08 17:08) [28]
Так и не понял проблемы особо.
По мне, так вот такая простая реализация решает проблемы.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Math, ExtCtrls;
type
TSym=class
public
FCanvas: TCanvas;
FW: array[0..255] of Integer;
constructor Create(Canvas: TCanvas);
procedure Paint(const Str: String;X,Y: Integer);
end;
TForm1 = class(TForm)
Timer1: TTimer;
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const
StrPaint='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var
Form1: TForm1;
SymObj: TSym;
implementation
{$R *.dfm}
procedure TForm1.FormPaint(Sender: TObject);
begin
SymObj.Paint(StrPaint,FOrm1.Tag,0);
end;
{ TSym }
constructor TSym.Create(Canvas: TCanvas);
var
i: Integer;
begin
FCanvas := Canvas;
for i := 0 to 255 do
begin
FW[i] := FCanvas.TextWidth(Chr(i));
end;
end;
procedure TSym.Paint(const Str: String; X, Y: Integer);
var
i: Integer;
XP: Integer;
begin
XP := X;
for i := 1 to Length(Str) do
begin
FCanvas.TextOut(XP,Y,Str[i]);
Inc(XP,FW[Ord(Str[i])]{+1});
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Tag := 1;
Canvas.Font.Size := 10;
Canvas.Font.Name := 'Arial Black';
DoubleBuffered := True;
SymObj := TSym.Create(Form1.Canvas);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SymObj.Free;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
case Timer1.Tag of
1: if Form1.Tag+Form1.Canvas.TextWidth(StrPaint)>Form1.Width then Timer1.Tag := -1;
-1: if Form1.Tag<0 then Timer1.Tag := 1;
end;
Form1.Tag := Form1.Tag+Timer1.Tag;
Form1.Repaint;
end;
end.
User (2008-07-19 22:49:00) [2]>> близко к теме ...
была аналогичная задумка 10 лет тому назад, правда далее тестового варианта не дошло, а реализация на К155ИР13, вывод через LPT - работало ;-) ...
<< по теме:
- непонятно, зачем использовать TextOut, графику и т.д. для вывода текста в строку? Тем более отображать весь символ сразу ... правда, все зависит от способа вывода текста и/или его отображения ...
Судя по постановке задачи (бегущая строка в транспорте), то символы нужно выводить не сразу, а "постолбично", смещая отображаемый текст с сторону (лево или право, в зависимости от движения текста).
Свой шрифт я не придумывал, просто в цикле выводил масштабированый символ в область на экране, по столбцам считывал цвет в определенных координатах, и все по-новому - получалось для каждого символа массив из 8-и байт (символы тогда были 8х8, EGA). Для вывода использовались эти заготовки ... реализация кода - на Turbo Pascal 5.5.
Применительно к теме - можно мрименить тот же принцип для получения "матрицы" символов - их не так уж много (можно норма, I, B, IB )...
antonn (2008-07-19 18:36:00) [3]я про затирание не понял:)
привык, что сначала фон очищается и на него наносятся надписи, там где надо. т.ч. оно все просто "затирается"
{RASkov} (2008-07-19 17:15:00) [4]> [28] AlexanderMS_ (19.07.08 17:08)
Можно сделать:
inc(x, Canvas.TextWidth('W') +1) ;
например.
{RASkov} (2008-07-19 17:12:00) [5]> [26, 27] antonn © (19.07.08 16:55)
Ну вообще-то так и планируется.... т.е. не затирать соседние символы фоном текущего :)
Хотя в моем примере без прозрачного стиля кисти, а если с bsClear то появляется нежелаемый эффект...
По крайней мере у меня при "тестировании" оказалось лучше без bsClear :)
Возможно при наклонном тексте и происходит наложение символов и следственно затирание, но при обычном - "все пучком" ...вроде)
AlexanderMS_ (2008-07-19 17:08:00) [6]
> точнее заставляет рисовать без фона :)
просто если рисовать с фоном, возможен эффект затирания символов.
Пример (сорри, что без with)
procedure TForm1.FormPaint(Sender: TObject);
var
X, Y : Integer;
begin
X := 0;
Y := 0;
Canvas.Font.Size := 10;
Canvas.Font.Name := 'Arial Black';
Canvas.Brush.Style := bsClear;
Canvas.TextOut(x,y, 'W');
inc(x, Canvas.TextWidth('W')) ;
Canvas.TextOut(x,y, 'W');
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := clBtnFace;
Y := Canvas.TextHeight('W');
X := 0;
Canvas.TextOut(x,y, 'W');
inc(x, Canvas.TextWidth('W')) ;
Canvas.TextOut(x,y, 'W');
end;
Разница есть, к сожалению.
antonn (2008-07-19 16:55:00) [7]эта строчка рисует текст без фона :)
antonn (2008-07-19 16:55:00) [8]точнее заставляет рисовать без фона :)
AlexanderMS_ (2008-07-19 15:58:00) [9]
> Проблема в том, что при ВЫВОДЕ на TBitmap не всей строчки
> сразу, а отдельными символами происходит частичное затирание
> иногда предыдущего символа
а эта строчка не спасла отца русской демократии? :)
Canvas.Brush.Style := bsClear;
Её нужно непосредственно перед выводом текста написать, после заливки и прочих операций.
И символ не затирается.
{RASkov} (2008-07-19 15:51:00) [10]
const Txt= 'Текстовая "ВНИМАНИЕ" строка';
var N, J, K: Integer;
begin
Canvas.Font.Name:='Tahoma';
Canvas.Font.Size:=30;
for N:=1 to 6 do begin
K:=0;
for J:= 1 to Length(Txt) do begin
if J>1 then INC(K, Canvas.TextWidth(Txt[J-1]));
if ODD(N) and (J in [12,13,14,15,16,17,18,19]) then Canvas.Font.Color:=Canvas.Brush.Color
else Canvas.Font.Color:=Font.Color;
Canvas.TextOut(50+K, 100, Txt[J]);
end;
Sleep(250);
end;
end;
Нормально вроде мигает :)
Или это не то?
antonn (2008-07-19 15:51:00) [11]
> почему никто полностью посты не читает? Это не мерцание
> как в телевизоре, это именно мигание СИМВОЛОВ. Символы то
> выводятся на экран, то не выводятся СПЕЦИАЛЬНО. Получается,
> они то есть на экране, то их нету - и они визуально как
> бы мигают. Секунду горят, на полсекунды тухнут. Ну как еще
> объяснить?! Специальный эффект который надо делать!!! Чтобы
> символы или целая строчка мигала, привлекая к себе внимание!
>
потому что в куче постов все размыто и общими понятиями написано.
в чем проблема-то? рисуете на битмапе с черным фоном белый текст. в следующую рисуете черый текст - вот и мигание.
Тын-Дын (2008-07-19 15:37:00) [12]
> Тын-Дын © (19.07.08 14:10) [19]
> Я имел ввиду - полностью стирать текст и отрисовывать его
> заново
>
> перечитайте ветку заново. Вы вообще о чем-то совсем другом.
>
Можешь привести кусок кода с отрисовкой на Bimap, где проявляется этот эффект затирания?
Lines (2008-07-19 15:27:00) [13]korneley © (19.07.08 14:00) [18]
Разница в скорости обмена
и что? Причем здесь это?! Это никак не проблема недостаточной пропускной способности. Проблема в том, что при ВЫВОДЕ на TBitmap не всей строчки сразу, а отдельными символами происходит частичное затирание иногда предыдущего символа. Причем тут вообще табло? Надо было наверное вообще про него ничего не говорить, оно тут не причем, косяк уже на TBitmap виден...
Тын-Дын © (19.07.08 14:10) [19]
Я имел ввиду - полностью стирать текст и отрисовывать его заново
перечитайте ветку заново. Вы вообще о чем-то совсем другом.
Каждый раз я забеляю полностью поверхность TBitmap'а...
antonn © (19.07.08 15:09) [20]
если монитор/телефизор, то я начинаю понимать что такое "мигание символов" :)
почему никто полностью посты не читает? Это не мерцание как в телевизоре, это именно мигание СИМВОЛОВ. Символы то выводятся на экран, то не выводятся СПЕЦИАЛЬНО. Получается, они то есть на экране, то их нету - и они визуально как бы мигают. Секунду горят, на полсекунды тухнут. Ну как еще объяснить?! Специальный эффект который надо делать!!! Чтобы символы или целая строчка мигала, привлекая к себе внимание!
antonn (2008-07-19 15:09:00) [14]если монитор/телефизор, то я начинаю понимать что такое "мигание символов" :)
Тын-Дын (2008-07-19 14:10:00) [15]
> э-э-э... Не понял. Зачем их гасить?
Я имел ввиду - полностью стирать текст и отрисовывать его заново.
korneley (2008-07-19 14:00:00) [16]
> Lines (19.07.08 13:28) [17]
> > Неизвестно, табло у Вас "знакоместное" или "поле".
> "поле"
> > Интерфейс связи не озвучен
>какая разница? Я могу зажигать и тушить любой "пиксель".
Разница в скорости обмена. Именно с графикой и возникают траблы т.к. знакогенератор удалён и каждый пиксель нужно отрисовать на табло. А теперь просчитайте темп выдачи "картинки" (кадра) на табло и объём перекачиваемых данных, а затем сравните его с пропускной способность интерфейса комп <-> контроллер. Или у Вас все таки не табло, а телевизор/монитор? Тогда и подходы другие.
Lines (2008-07-19 13:28:00) [17]
> Неизвестно, табло у Вас "знакоместное" или "поле".
"поле"
> Интерфейс связи не озвучен
какая разница? Я могу зажигать и тушить любой "пиксель".
> Но, в любом случае, правильней (имхо) переложить задачу
> мигания на контроллер
может быть. Но я не пишу прошивки контроллера, я пишу программы под windows и задание такое ;)
> Canvas.Brush.Style := bsClear;
> Должно помочь
большое спасибо! Попробую.
AlexanderMS_ (2008-07-19 13:13:00) [18]
> режим прозрачного фона при TextOut?!
Canvas.Brush.Style := bsClear;
Должно помочь.
korneley (2008-07-19 13:13:00) [19]
> Lines (19.07.08 12:44) [14
> ...Но буквы, которые всегда прорисовываются должны оставаться
> на своих местах...
Неизвестно, табло у Вас "знакоместное" или "поле". Интерфейс связи не озвучен. Но, в любом случае, правильней (имхо) переложить задачу мигания на контроллер. Опять же, как в DOS-е: байт атрибута + байт информации = счастье :) "Похожие задачи рождают похожие решения" (с)
Lines (2008-07-19 12:44:00) [20]Интересно, что перенесли в начинающие ;)
На самом деле тонкий момент.
> Есть у меня чувство, что при выводе можно задать режим прозрачного
> фона и все будет ништяк
Очень неплохой вариант... Но я тоже не знаю как задать режим прозрачного фона при TextOut?! Если так можно - проблема бы решилась.
> А гасить все символы перед выводом новых не получится?
э-э-э... Не понял. Зачем их гасить?
Проблема не в том, что какие-то последующие изображения накладываются на предыдущую картинку. Проблема в том, что при выводе очередного знако-места оно для не моноширинных шрифтов может немного затирать предыдущее знако-место.
> не понял проблемы... если вывод будет идти на светодиодную
> панель с совсем конкретными размерами букв в пикселях
в том и дело, что нет. Клиент сам задает какиш шрифтом, размером, стилемшрифта выводить информацию на табло. Делать все вручную - имхо, повторять систему шрифтов в windows. Только работы прибавится по ручному рисованию и созданию шрифтов.
> а что, индент между буквами сделать религия не позволяет?
Что такое индент? В смысле, увеличить расстояние между буквами? Ну тогда мы поимеем косяк в том, что расстояния между буквами будут больше, чем нужно.
> Мигание для табло - вообще вещь непонятная. Это следствие
> или неправильной работы самого табло
ты не понял. Проблема не в том, что табло мигает. Надо СДЕЛАТЬ, чтобы табло мигало. А точнее, отдельные его пиксели.
Если ты говоришь про спортивные табло, то например представь, что на табло пишется список замен игроков. И при замене, идущей прямо сейчас, имена игроков мигают. То есть, мигание определенных элементов, части надписи на табло нужно для привлечения внимания к этому месту. И реализуется это не средствами табло, а путем периодического изменения картинки на табло. То некоторые буквы прорисоваются, то прорисовываются, возникает эффект мигания.
Но буквы, которые всегда прорисовываются должны оставаться на своих местах. Из всего этого и возникла тема.