![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TLabel; Не рисуется T Canvas при запуске формы.
JetAPI © (2007-08-17 21:48:00)Здравствуйте всем.
Помогите пожалуйста понять: почему, при запуске программы, в TLabel, не работает TCanvas? Что нужно сделать?.. Никак не могу понять?
Если сделать в обработчичике OnClick (кнопки), то все рисуется. А вот при запуске, этого не происходит.
Вот код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Width:=150;
Label1.AutoSize:=False;
Label1.Canvas.Brush.Color:=clWindow;
Label1.Canvas.FillRect(clientrect);
Label1.Canvas.Font.Color:=clLime;
Label1.Canvas.TextOut(6,0,'01');
Label1.Canvas.Font.Color:=clBlue;
Label1.Canvas.TextOut(26,0,'02');
end;
end.
Спасибо за любой ответ.
JetAPI (2007-08-18 15:41:00) [21]to RaskovДа... Да... Прочитал.
Просто разбираюсь и с одним и другим....
{RASkov} (2007-08-18 15:24:00) [22]Все что в [8] и у тебя в [19] - это и есть метод OnPaint у формы :)
Можно было и проще:
procedure TForm1.Paint();
begin
Label1.Width:=150;
Label1.AutoSize:=False;
Label1.Canvas.Brush.Color:=clWindow;
Label1.Canvas.FillRect(clientrect);
Label1.Canvas.Font.Color:=clLime;
Label1.Canvas.TextOut(6,0,'01');
Label1.Canvas.Font.Color:=clBlue;
Label1.Canvas.TextOut(26,0,'02');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Invalidate;
end;
:o)
{RASkov} (2007-08-18 15:21:00) [23]> [19] JetAPI © (18.08.07 15:08)
> Identifier redeclared
И зачем два раза реализовал WMPaint????
А [17,18] прочитал?
JetAPI (2007-08-18 15:16:00) [24]Ко всем...
Я только учусь... Только постигаю... Поэтому для меня важна каждая мелочь.
Каждое ваше слово ловлю и мотаю на "ус".
Если очень дотошен и назойлив... прошу прощения!
Постарайтесь понять ламмера.
Все равно спасибо всем.
ЗЫ.
Все ваши примеры и коментарии сохраняю в отдельной папке. Это для меня, как учебник.
Спасибо огромное всем.
JetAPI (2007-08-18 15:08:00) [25]tmp
Нет... именно все так и поняли... По нажатию кнопки выполнить прорисовку в Лайбл2. Это делает... Но как только добавляю...
procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
begin
inherited;
Button1Click(self);
end;
Не могу откомпилировать... выдает 2 ошибки...
[Pascal Error] TLabel02_Unit1.pas(47): E2004 Identifier redeclared: 'TForm1.WMPaint'
[Pascal Fatal Error] TLabel02_Project.dpr(5): F2063 Could not compile used unit 'TLabel02_Unit1.pas'
Вот весь код целиком...
unit TLabel02_Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure WMPaint(var MsgPaint: TWMPaint); message WM_PAINT;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
begin
inherited;
Button1Click(self);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Label2.Width:=150;
Label2.AutoSize:=False;
Label2.Canvas.Brush.Color:=clWindow;
Label2.Canvas.FillRect(clientrect);
Label2.Canvas.Font.Color:=clLime;
Label2.Canvas.TextOut(6,0,'01');
Label2.Canvas.Font.Color:=clBlue;
Label2.Canvas.TextOut(26,0,'02');
end;
procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
begin
inherited;
Label1.Width:=150;
Label1.AutoSize:=False;
Label1.Canvas.Brush.Color:=clWindow;
Label1.Canvas.FillRect(clientrect);
Label1.Canvas.Font.Color:=clLime;
Label1.Canvas.TextOut(6,0,'01');
Label1.Canvas.Font.Color:=clBlue;
Label1.Canvas.TextOut(26,0,'02');
end;
end.
В чем же ошибка?.. Вроде же все правильно написал...
{RASkov} (2007-08-18 15:03:00) [26]> > procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
> > begin
> > inherited; - // первый раз
> > Label1.Width:=150;
> > Label1.AutoSize:=False;
Да еще и размеры менять в этом методе..... не серьезно....
Я понимаю, что это было для примера, но..... нужно и это учесть. В методе прорисовки, лучше не менять ничего не касающего TPen, TBrush, TFont....
И вот еще.... я все прорисовка да прорисовка... объясняю:
есть у меня понятие рисование и прорисовка
первое - это как бы разовое. Нарисовали и забыли...
а второе - то самое первое, но рисуется(прорисовывается) тогда когда необходимо....например по сообщению WM_PAINT...
И поэтому мы контролы видим такими какими мы их видим, потому что они прорисовываются при необходимости....
{RASkov} (2007-08-18 14:54:00) [27]> [9] JetAPI © (18.08.07 13:49)
> Сейчас стараюсь понять, что же предпочтительней и практичней.
Да ты не "заморачивайся" на этом вопросе.... главное пойми как в Windows происходит прорисовка....
и здесь ты выйдешь наprocedure WMPaint(var MsgPaint: TWMPaint); message WM_PAINT;
Которое в TGraphicControl'ах реализовано процедурой Paint, и если ты перекроешь ее у себя, то можешь рисовать все, что захочешь и где захочешь(TgraphicControl, например TLabel, TPaintBox)...
Inherited; - это, как уже обяснили, вызов того же самого метода у предка.... поэтому если эту строку убрать, то можно полностью заменить "рисунок" в контроле..... и еще отсюда же - нет смысла вызывать inherited в последнюю очередь.... так как все старания затрутся методом предка.
Я бы так [8], в конкретном случае, не делал.... зачем рисовать два раза на одном и том же месте?
> procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
> begin
> inherited; - // первый раз
> Label1.Width:=150;
> Label1.AutoSize:=False;
> Label1.Canvas.Brush.Color:=clWindow;
> Label1.Canvas.FillRect(clientrect); //все стерли и ниже второй раз
Имхо.... я уже упомянул, об..... зачем извращатся над не преднозначенными для этого контролами (TLabel)..... почему-бы не использовать Паинт?
А уж стандартную метку в нем(в его методе Paint) изобразить раз плюнуть....
tmp (2007-08-18 14:24:00) [28]Практичней - не всегда предпочтительней. Если воспользоваться примером, который привёл для тебя Leonid Troynovsky, т.е. создать своего наследника и переопределить процедуру Paint - не будут происходить лишние манипуляции с канвой для вывода текста Caption'а. Если же воспользоваться перехватом WM_PAINT, то сначала отрисуется всё стандартное, а потом - что хочешь ты, но в этом случае меньше стучать по клавишам:)
Leonid Troyanovsky (2007-08-18 14:24:00) [29]
> JetAPI © (18.08.07 14:06) [10]
> в Label2 тоже происходила прорисовка чего-нибудь (не важно
> чего)?
Прорисовка не важно чего происходит в TImage.
--
Regards, LVT.
Leonid Troyanovsky (2007-08-18 14:17:00) [30]
> JetAPI © (18.08.07 13:49) [9]
> Сейчас стараюсь понять, что же предпочтительней и практичней.
Вот и изучай [1].
OnPaint - это значит этот обработчик надо назначить OnPaint формы.
--
Regards, LVT.
tmp (2007-08-18 14:16:00) [31]
> JetAPI © (18.08.07 14:06) [10]
Не совсем понял, что ты хочешь. Может так?
procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
begin
inherited;
Button1Click(self);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Label2.Width:=150;
Label2.AutoSize:=False;
Label2.Canvas.Brush.Color:=clWindow;
Label2.Canvas.FillRect(clientrect);
Label2.Canvas.Font.Color:=clLime;
Label2.Canvas.TextOut(6,0,'01');
Label2.Canvas.Font.Color:=clBlue;
Label2.Canvas.TextOut(26,0,'02');
end;
Leonid Troyanovsky (2007-08-18 14:15:00) [32]
> JetAPI © (18.08.07 13:07) [6]
> Caption := 'MyLabel';, и каким образом влияет на прорисовку?
А ширину будет задавать Пушкин? Width := 50;
> Захотел вывести , точно таким же образом, второй лейбл -
> т.е., чтобы было, например: MyLabel1, MyLabel2, и никак
> не могу.
Меняй второй метке координаты.
--
Regards, LVT.
tmp (2007-08-18 14:11:00) [33]
> JetAPI © (18.08.07 13:49) [9]
Здесь ничего особенного не происходит: просто перехватывется сообщение Windows на отрисовку WM_PAINT, где инструкцией inheritedвызываются стандартные процедуры отрисовки, в том числе и метод Paint Label'а, который выводит на канву содержание Caption, а уже потом затираем выведенное ранее и помещаем на канву нечто своё.
А вот, если сначала попытаться манипулировать канвой Label'а, а уже потом вызвать inherited, стандартная процедура отрисовки Label'а Paintвыведет на канву содержание Caption.
JetAPI (2007-08-18 14:06:00) [34]to tmp
А как сделать теперь, если, скажем, мы на форму положили 2-ой Label2 и еще кнопку (Button1), по нажатию которой, в Label2 тоже происходила прорисовка чего-нибудь (не важно чего)?
Как Label2 привязать к procedure WMPaint(var MsgPaint: TWMPaint); message WM_PAINT; ?
Можете еще один пример показать?.. (если не трудно).
JetAPI (2007-08-18 13:49:00) [35]to mp
Да... Это тоже работает... И работает без создание какого-либо класса. После сворачивания в панель, данные тоже не затираются... Вот это!..
Ламмеру есть чему удивиться.!
Сейчас стараюсь понять, что же предпочтительней и практичней.
tmp (2007-08-18 13:22:00) [36]
type
TForm1 = class(TForm)
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
procedure WMPaint(var MsgPaint: TWMPaint); message WM_PAINT;
public
end;
var
Form1: TForm1;
implementation
procedure TForm1.WMPaint(var MsgPaint: TWMPaint);
begin
inherited;
Label1.Width:=150;
Label1.AutoSize:=False;
Label1.Canvas.Brush.Color:=clWindow;
Label1.Canvas.FillRect(clientrect);
Label1.Canvas.Font.Color:=clLime;
Label1.Canvas.TextOut(6,0,'01');
Label1.Canvas.Font.Color:=clBlue;
Label1.Canvas.TextOut(26,0,'02');
end;
JetAPI (2007-08-18 13:10:00) [37]to Leonid Troyanovsky
Ой!.. код забыл...
procedure TMyLabel.Paint;
begin
inherited;
{Canvas.Brush.Style := bsClear;}
Canvas.Brush.Color:=clWindow;
Canvas.FillRect(clientrect);
Canvas.Font.Color:=clLime;
Canvas.TextOut(6,0,'01');
Canvas.Font.Color:=clBlue;
Canvas.TextOut(26,0,'02');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
with Tmylabel.Create(Self) do begin
Parent := Self;
Left:=20;
Top:=20;
Caption := 'MyLabel';
{ SetBounds(0, 0, 50, 20);}
end;
end;
JetAPI (2007-08-18 13:07:00) [38]Ой!.. сейчас... всё попорядочку...
to Raskovво-первых, самое искреннее спасибо за ответ и на достаточно понятное объяснение! Теперь...
> А у тебя хватает размеров Лэйблы для вывода функцией TextOut?
Да. К тому же тексАут в 30 пикселей шириной сделал... хватает
> В общем ты наверное не понимаешь, что такое канва и как
> происходит на нее вывод...
!00% понял, что прорисовка в Делфи это не такое уж простое дело. Шагу ступить не возможно, чтоб не споткнуться... Впрочем, это может только у меня так.
> Окно получило сообщение на перерисовку... оно перерисовалось
> и нарисовало на канве метки - '02', (пусть будет так - Label1.
> Canvas.TextOut(0, 0, '02'); - это все в твоем примере из
> [2]), но следом перерисовалась сама метка(У нее тоже есть
> Paint) вот оно и затерло "твое художество"...
Теперь я это понимаю... Но до этого-то, я это не знал.... Голову всем морочу, зато узнал. Там даже сложнее все... Виндос компоненту посылает сообщение WM_PAINT, чтобы сам себя перересовал. Я до такого уровня еще не дошел... Вот поэтому и поселился на форуме...
> Так вот там ты нарисовал "это дело" на канве, пусть даже
> на форме... да на любой, а что происходит потом.... потом
> идет вызов еще кучи методов, такие как например OnResize,
> OnActivate, OnShow.... и последним OnPaint... т.е. хоть
> у тебя в [1] и не было ничего в этом(OnPaint) обработчике,
> но окно получило команду перерисоваться и ему(окну) пофик
> что ты рисовал на его создании.... ведь рисунок на канве
> нигде не храниться.... все что мы видим все перерисовывается.
> ...
Блин... Как все сложно... Как все сложно... Но хотя бы, хоть чуть стало кое-что развеиваться...
> И в заключении..... зачем использовать TLabel если нам нужна
> канва на которой мы хотим что-то рисовать??? А TPaintBox
> чем не устроил?
100% Вы правы... Вначале, я думал, что TLabel TPaintBox разница мизер... В общем найвный. А теперь вот столкнулся, и вижу: что нет... TPaintBox это TPaintBolx, а TLabel это TLabel, и каждый предназначен для своего.
Для рисования, TPaintBox, это действитель, оптимальный вариант.
> Нужен пример?
Да... Примеры, это лучше все... Но вы уже и Leonid Troyanovsky ©, привели... Сейчас в редактор "забью", и буду смотреть... Спасибо.
Leonid Troyanovsky, спасибо большое ответ!
Это то!!!!!!!
Все получается и работает... Я только код чуть подправил под себя - чтобы проще понимать было.
В общем понятно: чтобы перерисовать, мы создали свой класс - TMyLabel/
Теперь, как я понял, Виндоус нам никаких команд не посылает.
Но тут, у меня сразу другой вопрос возник, который, мне кажется, еще сложней.
Разбейся на осколки, но понять не могу: причем здесь свойствой Caption?
Вот причем?!.. Если мы уберем эту строку:
Caption := 'MyLabel';
,..нам ничего не нарисуется. Я просто не понимаю: как Caption := 'MyLabel';, и каким образом влияет на прорисовку?
Прошу, пожалуйста, объясните... Иначе, все впустую будет, если не понимать, что и как.
И вот сразу еще одна непонятность возникла...
Захотел вывести , точно таким же образом, второй лейбл - т.е., чтобы было, например: MyLabel1, MyLabel2, и никак не могу.
Попробовал так... Попробовал по другому,.. Ничего не получается.
Подскажите, если не затруднит, как это правильно делается.
Спасибо.
Leonid Troyanovsky (2007-08-18 11:26:00) [39]
> JetAPI © (17.08.07 23:08) [2]
> Но так не получается... Голова кругом идет, а я даже близко
> подойти не могу, чтобы научиться рисовать на лейбле.
type
TMyLabel = class(TLabel)
procedure Paint; override;
end;
procedure TMyLabel.Paint;
begin
inherited;
Canvas.Font.Color := clBlue;
Canvas.Brush.Style := bsClear;
Canvas.TextOut(0, 0,'---');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
with Tmylabel.Create(Self) do
begin
Parent := Self;
Caption := 'mylabel';
SetBounds(0, 0, 50, 20);
end;
end;
--
Regards, LVT.
{RASkov} (2007-08-18 03:33:00) [40]> А у тебя хватает размеров Лэйблы для вывода функцией TextOut?
Сорри... не особо обратил внимание на размеры метки и автосайз, так как смысла всего в [1] в FormCreate - нет.
Ладно вот попробуй, чисто для примера, но не прямой ответ на твой вопрос.
Брось на форму TPaintBox и TCheckBox и вот ихи обработчики:
procedure TForm1.PaintBox1Paint(Sender: TObject);
var R: Trect; // Это нужно Var-параметром для DrawText.....
begin
R:=PaintBox1.ClientRect; // ..... но можно и не использовать DrawText, и соответственно R будет не нужна.
DrawText(PaintBox1.Canvas.Handle, 'Текст метки', -1, R, DT_RIGHT); //Выводим текст "якобы" метки
if CheckBox1.Checked then begin // Если какие-то дополнительные параметры рисования
PaintBox1.Canvas.Font.Color:=clBlue; // то выстовляем параметры...
PaintBox1.Canvas.TextOut(0, 0, '02'); // ...и собственно рисуем
end;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
PaintBox1.Invalidate; //Просто застовляем обновится(перерисоваться) ПаинтБокс
end;
Кстати... еслиб мы делали так
PaintBox1.Font.Color:=clBlue;ВместоPaintBox1. Canvas.Font.Color:=clBlue;
то нам пришлось бы восстанавливать каждый раз фонт перед прорисовкой...