• ByakaBuka (20.04.07 15:32) [0]
    Делаю наследника лейбла. Приходится временами отрисовывать на его канве что-нибудь. Как сделать это, чтобы изображение не терялось (как TImage)
  • Юрий Зотов © (20.04.07 16:06) [1]
    Заместить метод Paint и рисовать в нем.
  • DimaBr © (20.04.07 16:14) [2]

    > Приходится временами отрисовывать на его канве что-нибудь

    Покажите где и как отрисоываете.
  • ByakaBuka (20.04.07 17:15) [3]
    2 DimaBar
    QQQ=class(TLabel)

    x:=QQQ.create(form1)
    x.Left:=...
    ....
    ....
    ....
    ....
    ....
    x.Canvas.MoveTo(...
    x.Canvas.LineTo(...

    form1.show;

    Разумеется ничего так не видно :)

    2 Юрий Зотов

    На скока я понял приблизительно так

    1. Создать свойство вроде TBitMap, в котором хранить картинку
    2. Переписать метод Paint в котором отрисовывать BitMap на конву
    или ошибаюсь?
  • {RASkov} (20.04.07 17:30) [4]
    > или ошибаюсь?

    Ошибаешься.

    TMyLabel = class (TCustomLabel)
    ...
    procedure Paint; override;
    end;

    procedure TMyLabel.Paint;
    begin
     inherited; //или без него но все сам...
     Canvas.MoveTo();
    ....
    end;
    Хотя... если тебе нужен сложный рисунок на канве твоей метки, то нужен будет и ТBitMap...
  • ByakaBuka (20.04.07 17:46) [5]
    Так он будет отрисовывать постоянный некий Label (например в какой-то цветной рамке)

    Создается куча TMyLabel-ов. В зависимости от того что за его свойства, иногда надо что-бы он отображал не Caption а эту картинку, и чтоб она не исчезала.

    procedure TMyLabel.Paint;
    begin
    if условие(отображать как картинку)
    then
    inherited;
    Canvas.MoveTo();
    ....
    end;
  • ByakaBuka (20.04.07 17:55) [6]
    begin...end; забыл
  • icWasya © (20.04.07 18:41) [7]
    и не забыть при смене картинки вызывать invalidate
  • ByakaBuka (21.04.07 14:04) [8]
    1. Как при не выполнении условия "отображать как картинку" вызвать метод Paint предка
    2. При попатке BitMap.LoadFromFile вылетает AV. Подозреваю что накасячил в Get/SetBitmap

    Вот код:

    unit flabel;

    interface

    uses
     StdCtrls, Controls, Graphics, Classes;

    type
     TViewStyle = (vsText, vsImage);
     TFLabel=class(TLabel)
     private
       FNumber: Integer;
       FMaxLength: Integer;
       FTextColor: TColor;
       FViewStyle: TViewStyle;
       FBitMap: Pointer;
     protected
       procedure Paint; override;
       function GetNumber: Integer;
       procedure SetNumber(Value: Integer);
       function GetMaxLength: Integer;
       procedure SetMaxLength(Value: Integer);
       function GetTextColor: TColor;
       procedure SetTextColor(Value: TColor);
       function GetViewStyle: TViewStyle;
       procedure SetViewStyle(Value: TViewStyle);
       function GetBitMap: TBitMap;
       procedure SetBitMap(Value: TBitMap);

     published
       property Number: Integer read GetNumber write SetNumber;
       property MaxLength: Integer read GetMaxLength write SetMaxLength;
       property TextColor: TColor read GetTextColor write SetTextColor;
       property ViewStyle: TViewStyle read GetViewStyle write SetViewStyle default vsText;
       property BitMap: TBitmap read GetBitMap write SetBitMap;
     end;

    implementation

    uses main;

    procedure TFLabel.Paint;
    begin
     if Viewstyle = vsImage then
       with inherited Canvas do
         Draw(0,0, BitMap);
    end;

    function TFLabel.GetNumber;
    begin
     Result:=FNumber;
    end;

    procedure TFLabel.SetNumber(Value: Integer);
    begin
     FNumber:=Value;
    end;

    function TFLabel.GetMaxLength;
    begin
     Result:=FMaxLength;
    end;

    procedure TFLabel.SetMaxLength(Value: Integer);
    begin
     FMaxLength:=Value;
    end;

    function TFLabel.GetTextColor: TColor;
    begin
     Result:=FTextColor;
    end;

    procedure TFLabel.SetTextColor(Value: TColor);
    begin
     FTextColor:=Value;
    end;

    function TFLabel.GetViewStyle: TViewStyle;
    begin
     Result:=FViewStyle;
    end;

    procedure TFLabel.SetViewStyle(Value: TViewStyle);
    begin
     FViewStyle:=Value;
    end;

    function TFLabel.GetBitMap: TBitMap;
    begin
     Result:=TBitMap(FBitMap);
    end;

    procedure TFLabel.SetBitMap(Value: TBitMap);
    begin
     FBitMap:=Value;
     invalidate;
    end;

    end.

  • iXT © (21.04.07 14:22) [9]
    1. Снимается - туплю :)
  • ByakaBuka (21.04.07 14:24) [10]
    [9] Мой, Sorry.
  • ByakaBuka (21.04.07 14:31) [11]
    procedure TFLabel.Paint;
    begin
    if not(Viewstyle = vsImage)
     then
       inherited
     else
       Canvas.Draw(0,0, BitMap);
    end;
  • {RASkov} (21.04.07 15:35) [12]
    > procedure TFLabel.SetBitMap(Value: TBitMap);
    > begin
    > FBitMap:=Value;
    > invalidate;
    > end;

    FBitMap: TBitMap;

    function TFLabel.GetBitMap: TBitMap;
    begin
    Result:=FBitMap;
    end;

    procedure TFLabel.SetBitMap(Value: TBitMap);
    begin
    FBitMap.Assign(Value);
    invalidate;
    end;
  • ByakaBuka (21.04.07 16:07) [13]
    А TBitMap.Create в конструкторе нужен? Думаю что да. Да и деструктором чистить надо.
  • {RASkov} (21.04.07 16:23) [14]
    > [13] ByakaBuka   (21.04.07 16:07)

    Правильно думаешь...

    И Paint ченить вот так:

    procedure TFLabel.Paint;
    begin
     if (Viewstyle<>vsImage) or FBitMap.Empty then inherited
     else with Canvas do StretchDraw(ClipRect, FBitMap);
    end;
  • ByakaBuka (21.04.07 16:35) [15]
    Вот последней релиз:

    unit flabel;

    interface

    uses
     StdCtrls, Controls, Graphics, Classes;

    type
     TViewStyle = (vsText, vsImage);
     TFLabel=class(TLabel)
     private
       FNumber: Integer;
       FMaxLength: Integer;
       FTextColor: TColor;
       FViewStyle: TViewStyle;
       FBitMap: TBitMap;
     protected
       procedure Paint; override;
       function GetNumber: Integer;
       procedure SetNumber(Value: Integer);
       function GetMaxLength: Integer;
       procedure SetMaxLength(Value: Integer);
       function GetTextColor: TColor;
       procedure SetTextColor(Value: TColor);
       function GetViewStyle: TViewStyle;
       procedure SetViewStyle(Value: TViewStyle);
       function GetBitMap: TBitMap;
       procedure SetBitMap(Value: TBitMap);
     public
       constructor Create(AOwner: TComponent); override;
       destructor Destroy; override;
       
     published
       property Number: Integer read GetNumber write SetNumber;
       property MaxLength: Integer read GetMaxLength write SetMaxLength;
       property TextColor: TColor read GetTextColor write SetTextColor;
       property ViewStyle: TViewStyle read GetViewStyle write SetViewStyle default vsText;
       property BitMap: TBitmap read GetBitMap write SetBitMap;
     end;

    implementation

    uses main;

    procedure TFLabel.Paint;
    begin
     if Viewstyle = vsText then inherited;
     if (Viewstyle <> vsImage) or FBitMap.Empty
       then inherited
       else
         with Canvas do
           StretchDraw(ClipRect, BitMap);
    end;

    function TFLabel.GetNumber;
    begin
     Result:=FNumber;
    end;

    procedure TFLabel.SetNumber(Value: Integer);
    begin
     FNumber:=Value;
    end;

    function TFLabel.GetMaxLength;
    begin
     Result:=FMaxLength;
    end;

    procedure TFLabel.SetMaxLength(Value: Integer);
    begin
     FMaxLength:=Value;
    end;

    function TFLabel.GetTextColor: TColor;
    begin
     Result:=FTextColor;
    end;

    procedure TFLabel.SetTextColor(Value: TColor);
    begin
     FTextColor:=Value;
    end;

    function TFLabel.GetViewStyle: TViewStyle;
    begin
     Result:=FViewStyle;
    end;

    procedure TFLabel.SetViewStyle(Value: TViewStyle);
    begin
     FViewStyle:=Value;
    end;

    function TFLabel.GetBitMap: TBitMap;
    begin
     Result:=FBitMap;
    end;

    procedure TFLabel.SetBitMap(Value: TBitMap);
    begin
     FBitMap.Assign(Value);
     invalidate;
    end;

    constructor TFlabel.Create(AOwner: TComponent);
    begin
     BitMap:=TBitmap.Create;
     inherited Create(AOwner);
    end;

    destructor TFlabel.Destroy;
    begin
     BitMap.Free;
     invalidate;
     inherited Destroy;
    end;

    end.


    AV вылетает на
    FBitMap.Assign(Value);
    при создании
  • {RASkov} (21.04.07 17:03) [16]
    > constructor TFlabel.Create(AOwner: TComponent);
    > begin
    > BitMap:=TBitmap.Create;
    > inherited Create(AOwner);
    > end;

    Inherited; сначала, а потом создание FBitMap'а
    constructor TFLabel.Create;
    begin
     inherited;
     FBitMap:=TBitMap.Create;
    end;


    и Paint переделай(См[14]) :) два раза рисует текст - не серьезно :(
    Так-же используются не все свойства, типа TextColor, MaxLength, Number - может и нафик не нужны?
    TextColor - заменятся Font.Color. В принципе можно так:

    function TFLabel.GetTextColor: TColor;
    begin
    Result:=Canvas.Font.Color;
    end;

    procedure TFLabel.SetTextColor(Value: TColor);
    begin
    Canvas.Font.Color:=Value;
    Invalidate;
    end;


    FTextColor - не нужна.
  • ByakaBuka (21.04.07 22:26) [17]

    > Inherited; сначала, а потом создание FBitMap'а

    Да, спасибо. FBitMap


    > и Paint переделай

    Косяк. :) Осталась строчка. Забыл убрать. Но не смертельно!
    Думаю вот так:

    procedure TFLabel.Paint;
    begin
     if (Viewstyle <> vsImage)// or FBitMap.Empty
       then inherited
       else
         if not(FBitMap.Empty) then
           with Canvas do
             StretchDraw(ClipRect, BitMap);
    end;


    Кстати, почему Stretch?


    > Так-же используются не все свойства, типа TextColor, MaxLength,
    >  Number - может и нафик не нужны?
    > TextColor - заменятся Font.Color. В принципе можно так:
    >
    > function TFLabel.GetTextColor: TColor;
    > begin
    > Result:=Canvas.Font.Color;
    > end;
    >
    > procedure TFLabel.SetTextColor(Value: TColor);
    > begin
    > Canvas.Font.Color:=Value;
    > Invalidate;
    > end;
    > FTextColor - не нужна.


    TextColor <> Font.Color

    Font.Color может менятся (например при наведении крыски) TextColor это изначальный цвет который должен быть (например мышь ушла). Можно конечно использывать tag, но не красиво это, если можно сво-во свое прикрутить в данный момент.
    Но это уже в другую тему.

    Еще раз спасибо!
  • {RASkov} (21.04.07 23:59) [18]
    > Кстати, почему Stretch?

    Это на твое усмотрение, можно и Draw'ом выводить... но учитывай, что рисунок может быть не равным клиентской области твоей метки...
    Так-же еще есть и CopyRect....тоже может пригодится при "наведении мышки" на метку

    > Косяк. :) Осталась строчка. Забыл убрать. Но не смертельно!
    > Думаю вот так:
    >
    > procedure TFLabel.Paint;
    > begin
    > if (Viewstyle <> vsImage)// or FBitMap.Empty
    >   then inherited
    >   else
    >     if not(FBitMap.Empty) then
    >       with Canvas do
    >         StretchDraw(ClipRect, BitMap);
    > end;

    Ну опять... вот смотри: если стоит стиль vsImage, а FBitMap=nil(Empty), то что - твоя метка ничего не покажет?(т.е будет пустой). Ну если ты так задумал, то ладно.


    > TextColor <> Font.Color
    >
    > Font.Color может менятся (например при наведении крыски) TextColor это изначальный цвет который должен быть (например мышь ушла).

    Ну здесь однозначно напрашиваются тройка свойств, типа: HotTrack: Boolean и TextColor1, TextColor2: TColor(названия только поэлегантней придумай).
    И также добавить OnMouseEnter(Leave) события.:
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;

    ЗЫ ByakaBuka - А почему не iXT? :)
  • DimaBr © (23.04.07 08:38) [19]
    Добавлю свои пять копеек. Не плохо было бы перерисовать при изменении картинки. Я возьму и не буду добавлять через LadFromFile, а просто нарисую что-нибудь на ней. Или изменю размеры.

    constructor TFlabel.Create(AOwner: TComponent);
    begin  
     inherited Create(AOwner);
     BitMap:=TBitmap.Create;
     BitMap.OnChange := ChangeBitMap;
    end;

    procedure TFlabel.ChangeBitMap;
    begin
     Invaidate;
    end;

  • ByakaBuka (23.04.07 10:34) [20]

    > Ну опять... вот смотри: если стоит стиль vsImage, а FBitMap=nil(Empty),
    >  то что - твоя метка ничего не покажет?(т.е будет пустой).
    >  Ну если ты так задумал, то ладно.

    Имменно, если vsImage, то caption не должен отображаться. Отображам BitMap, ну а если он пустой.....


    > Ну здесь однозначно напрашиваются тройка свойств, типа:
    > HotTrack: Boolean и TextColor1, TextColor2: TColor(названия
    > только поэлегантней придумай).
    > И также добавить OnMouseEnter(Leave) события.:
    > procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    >
    > procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    >

    Это уже после :)


    > ЗЫ ByakaBuka - А почему не iXT? :)


    Одна машина в нете (на работе) много людей, желающих написать сюда :)


    > DimaBr ©   (23.04.07 08:38) [19]


    В данном случае не рационально. Не должны меняться ни размеря (с момента создания), ни рисовать на нем никто не собирается, хотя если рисовать на Bitmap, а не на Canvas объекта, то вроде все и так хорошо :)

    Вот не понял одну фишку:

    system.pas

    TObject.Destroy;
    begin
    end;



    Это как понимать?

    и должен ли после Free => TFLabel = nil
  • DimaBr © (23.04.07 11:34) [21]

    >  Не должны меняться ни размеря (с момента создания), ни рисовать на нем никто не собирается

    Если бы все так думали VCL была бы в 1000 раз меньше.
  • ByakaBuka (23.04.07 12:40) [22]
    Ну это только в данном случае, т.к. потомка пишу не для всех :) А так ничего против пяти копеек не имею.
  • DimaBr © (23.04.07 13:26) [23]
    Хорошо, тогда могу высказаться подробнее.
    Замечания:
    1. Нет необходимости писать методы доступа если ничего кроме чтения/присвоениея они не делают.
    2. Если вы описали свойство с default, то как минимум его нужно задать в конструкторе.
    3. При уничтожении компонента нет смысла его перерисовывать.
    4. При изменении свойств от которых зависит изображение нужно бы перерисоватся
    5. Вообще, весь ваш компонент на данном этапе больше похож на TImage.
  • ByakaBuka (23.04.07 14:41) [24]
    5. В принципе это и хотелось TLabel + TImage
    4. Согласен, просто в данном контексте он не должен изменяться с момента его создания, до сомой смерти
    3. Да, косяк :)
    2. ?
    1. ?

    и самое главное (сейчас)

    system.pas

    TObject.Destroy;
    begin
    end;


    Это как понимать?

    и должен ли после Free => TFLabel = nil
  • DimaBr © (23.04.07 15:12) [25]

    > и должен ли после Free => TFLabel = nil

    Нет не должен, если вы самостоятельно не установите или не воспользуетесь  процеруриной FreeAndNill().


    > Это как понимать?

    Всё правильно, а что вы желали увидеть ???

    2.

    property ViewStyle: TViewStyle read GetViewStyle write SetViewStyle default vsText;

    constructor TFlabel.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    BitMap:=TBitmap.Create;
    fViewStyle := vsText;
    end;



    1.

    property Number: Integer read GetNumber write SetNumber;
    property Number: Integer read fNumber write fNumber;



    На мой взгляд проще унаследоваться от TImage, открыть свойство Caption и отрисовать его в зависимости от ViewStyle.
  • ByakaBuka (23.04.07 15:45) [26]
    Thenks!


    > На мой взгляд проще унаследоваться от TImage, открыть свойство
    > Caption и отрисовать его в зависимости от ViewStyle.


    У ТLabel есть еще много свойств. И в основном используется он, ни иногда, надо еще и картиночку отрисовывать :)
    Вот с WorldWrap отрисовывать гараздо сложнее придется, хотя тут уже кому как и что вкуснее :)

    Еще раз Спасибо!
  • DimaBr © (23.04.07 16:15) [27]

    > Вот с WorldWrap отрисовывать гараздо сложнее придется

    Это вам только кажется, если внимательно присмотрется к DrawText то всё окажется намного проще.
Есть новые Нет новых   [134427   +35][b:0][p:0.004]