Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Бегущая строка


Автор: Демидрол 15.7.2008, 14:20
Доброго времени суток Вам.
Помогите,пожалуйста соорудить компонент бегущей строки на основе класса TLabel.
Не понимаю я как сделать так,чтобы у компонента было свойство "скорость прокрутки",
как сделатьтак,чтобы текст двигался,как проверить,что если длина текста меньше длины Labelа,то он из бегущей строки превращается в обычный Label.
Вот.
Помогите,пожалуйста,а то чего-то никак ничего никуда..... smile 

Автор: Great Cornholio 15.7.2008, 23:04
Сам я в этом не разбираюсь, но данная статья описывает как раз этот пример. В этом пособии в коде символы вполне могут быть изменены(хз, каким образом), на подобные. И вообще я за эту статью не отвечаю.

Автор: Palladin 16.7.2008, 00:53
Label использу лишь для вывода бегущей строки!  Отрисовывай в капшене лейбла. К примеру твой лейбл вмещает 200 символов, тогда вначале запускай цикл и записывай в лейбл 200 пробелов, потом 199 и первую букву твоего предложения, и т.д.
P.S. кустарный метод...

Автор: Демидрол 16.7.2008, 13:10
ммм....чего? smile
Palladin, т.е  в компоненте просто создать функцию,нп, ScrollName,  и в ней получить длину текста в Caption и сделать цикл на столько пробелов???
эээээ......
Тупой тупак давит на мозг....
А как сделать,чтобы скорость прокрутки текста компонента можно было менять?
Сделать отдельное свойство-это понятно.Но как,зная нужную скорость,менять скорость прокрутки?

Автор: Rrader 16.7.2008, 15:35
Демидрол, кидаешь на форму TLabel и TTimer. Ставишь у таймера нужный тебе интервал - это и будет скорость. В OnTimer пишешь:
Код

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    const int Len = 10;
    const char Str[] = "Я знаю, что ничего не знаю Я знаю, чт";

    static int I = 1;
    AnsiString S(Str);
    Label1->Caption = S.SubString(I, Len);
    I++;
    if (S.Length() - Len < I) I = 1;
}

Автор: Демидрол 16.7.2008, 15:46
да-да-да,это все понятно....В сети много про это нашел.
Тока мне надо создать именно КОМПОНЕНТ БЕГУЩАЯ СТРОКА!!!!
чтобы потом его много раз юзать в разных прога.
Вот.
И как это соорудить мозг не сооброжает.
Помогите....................SOS!!!!!  smile 

Автор: Palladin 16.7.2008, 17:44
что тебе мешает юзать в каждой проге это? 

Код

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    const int Len = 10;
    const char Str[] = "Я знаю, что ничего не знаю Я знаю, чт";

    static int I = 1;
    AnsiString S(Str);
    Label1->Caption = S.SubString(I, Len);
    I++;
    if (S.Length() - Len < I) I = 1;
}

Автор: Демидрол 17.7.2008, 11:51
Цитата(Palladin @ 16.7.2008,  17:44)
что тебе мешает юзать в каждой проге это? 

Начальство  smile 

Сижу,пыхчу как паровоз,че-то рожаю...
Никто не знает,в чем косяк:
Код

HANDLE hThread=::CreateThread(0,0,ThreadDraw,0,0,&ThreadID);


выдает ошибки:
E2034 Cannot convert 'unsigned long (__stdcall * (_closure )(void *))(void *)' to 'unsigned long (__stdcall *)(void *)'
и
E2342 Type mismatch in parameter 'lpStartAddress' (wanted 'unsigned long (__stdcall *)(void *)', got 'void')

В чем тут проблема? smile 

Автор: livo 17.7.2008, 14:50
Цитата

Тока мне надо создать именно КОМПОНЕНТ БЕГУЩАЯ СТРОКА!!!!

Попробуй не тред, а апишную SetTimer, KillTimer.
В нее передаеш как один из параметров колбэк функцию с твоим содержанием (будет вызываться с заданным тобой периодом).

Автор: Rrader 17.7.2008, 14:51
Вот, накидал:

*.h
Код

#ifndef ULabelH
#define ULabelH

#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>

//------------------
class PACKAGE TSpecialLabel: public TLabel
{

private:
    int FCounter;
    TTimer* FTimer;
    AnsiString FOrigCaption;
    __fastcall int GetVelocity() {return FTimer->Interval;}
    __fastcall void SetVelocity(int Value) {FTimer->Interval = Value;}

public:
    __fastcall TSpecialLabel(TComponent* Owner);
    __fastcall ~TSpecialLabel() {delete FTimer;}

    void __fastcall TimerFired(System::TObject* Sender)
    {
        const int Len = 10;
        AnsiString S(FOrigCaption);
        S = S + ' ' + S.SubString(1, Len);
        Caption = S.SubString(FCounter, Len);
        FCounter++;
        if (S.Length() - Len < FCounter) FCounter = 1;
    }
    // Запуск бегущей строки
    void StartCreep() {
        FOrigCaption = Caption;
        if (Caption != NULL) {
            FTimer->Enabled = true;
            TimerFired(this);
        }
    }
    // Остановка
    void StopCreep() {
        FTimer->Enabled = false;
        Caption = FOrigCaption;
    }

__published:
    __property int Velocity = {read=GetVelocity, write=SetVelocity };
};

//------
#endif


*.cpp
Код

#include <vcl.h>
#pragma hdrstop
#pragma package(smart_init)
#include "ULabel.h"
//-------
static inline void ValidCtrCheck(TSpecialLabel *)
{
    new TSpecialLabel(NULL);
}
//--------
__fastcall TSpecialLabel::TSpecialLabel(TComponent* Owner)
        : TLabel(Owner)
{
    FTimer = new TTimer(this);
    FTimer->OnTimer = TimerFired;
    FTimer->Enabled = false;
    FCounter = 1;
}
//-------
namespace SpecialLabel
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass Classes[1] = {__classid(TSpecialLabel)};
                 RegisterComponents("Standard", Classes, 0);
        }
}

Пример использования:
Код

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TSpecialLabel *SP = new TSpecialLabel(this);
    SP->Parent = this;
    SP->Caption = "Я знаю, что ничего не знаю";
    SP->Velocity = 50;
    SP->StartCreep();
    // Перед сменой Caption обязательно вызвать StopCreep!
    SP->StopCreep();
    SP->Caption = "Я гуляю по дорожке!";
    SP->StartCreep();
}

Автор: LastAngel 18.7.2008, 08:16
http://ftf.grsu.by/UchProc/konspekt/cbuilder/ch03/ch07/ch01

может кому пригодится ...

Автор: Демидрол 22.7.2008, 10:09
Rrader,спасибо огромное за код.С небольшими исправлениями все зашуршало так,что не остановить. smile
Меня интересует еще какой момент:как сделать,чтобы текст бежал через весь лабл,вне зависимости от размеров текста?Чето сидел,искал,пытался,но не понял.Заранее спасибо. smile 

Автор: LastAngel 22.7.2008, 13:17
Ну смотри если длина фразы меньше ширины лейбла, то дополняй оставшиеся места пробелами и усё ...

Автор: Демидрол 22.7.2008, 13:23
LastAngel,это понятно.Только длина текста в символах,а длина области хз в чем,и как их приравнять для меня загадка. smile 
И поэтому при растягивании лабла и при изменении размера шрифта(и просто при изменении шрифта) возникают траблы с отображением.

Автор: LastAngel 22.7.2008, 13:52
Ну ширина в пикселях мериется ... у лейбла есть свойство AutoSize если померить им реальную ширину лейбла поделить на количество буковок во фразе грубо получишь сколько пикселей одна буковка,потом узнаёшь заданную ширину ну и можно оценить сколько надо пробелов докинуть 

1 пробел вроде 3 пикселя ... так что даже количество пикселей на буковку не надо считать, а только количество пиксов на свободное пространство

Автор: Демидрол 22.7.2008, 14:55
А ничего,если я AutoSize отключу?Оно мне просто мешает сильно,когда строка "бегает".
А померить нужно ширину Caption в пикселях?И,насколько мне известно,каждая буква отображается разным количеством пикслей.Тем более,что при разных шрифтах размер разный...Буду пытаться. smile 

Автор: fish9370 23.7.2008, 15:20
используй для измерения длины текста в пикселах функцию:

Код

int TextWidth (AnsiString Text);


пример:
Код

 int nWidth = Label1->Canvas->TextWidth("Я знаю, что ничего не знаю");


функция учитывает свойства текущего шрифта..

Автор: LastAngel 24.7.2008, 10:55
Цитата(Демидрол @ 22.7.2008,  14:55)
А ничего,если я AutoSize отключу?Оно мне просто мешает сильно,когда строка "бегает".
А померить нужно ширину Caption в пикселях?И,насколько мне известно,каждая буква отображается разным количеством пикслей.Тем более,что при разных шрифтах размер разный...Буду пытаться. smile

Вообще классная функция ...с помощью неё можешь теперь для любых размеров и для любых кодировок сделать ...
Ширина лейбла известна, ширину текста узнать можно ... размер пробела в данной кодировке с помощью int TextWidth (AnsiString Text);
Код

    m_strFullWidth = Caption + strSpace;  // strSpace строка пробелов
    AnsiString strBuf = m_strFullWidth; // m_strFullWidth - строка во всю ширину лейбла
    if(m_unCounter >= 2)
    {
      strCaption = strBuf.SubString(m_unCounter, nLength - m_unCounter - 1)
                  + strBuf.SubString(1, m_unCounter - 1);
    }
    else
    {
      strCaption = strBuf.SubString(m_unCounter, nLength);
    }
    Caption = strCaption;
    m_unCounter++;
    if((UINT)nLength < m_unCounter)
    {
      m_unCounter = 2;
    }    

  Возвращает строку пробелов
Код

int __fastcall TRunString::SpaceString(AnsiString& astrSpace)
{
  unsigned int unWidthBuf = Width;
  this->AutoSize = true;
  unsigned int unLength = unWidthBuf - Width;
  Width = unWidthBuf;
  astrSpace = "";
  int nWidthSpace = Canvas->TextWidth(" ");
  for(UINT i = nWidthSpace; i < unLength; i += nWidthSpace)
  {
    astrSpace += " ";
  }
  this->AutoSize = false;
  return 0;
}

Автор: Демидрол 24.7.2008, 14:21
Всем ОГРОМНОЕ СПАСИБО!!!!!!!!!
С Вашей помощью соорудил сей компонент.
Ниже выкладываю код готового продукта:

файл .h

Код

//---------------------------------------------------------------------------

#ifndef ScrollingLabelH
#define ScrollingLabelH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
//---------------------------------------------------------------------------
class PACKAGE TScrollingLabel : public TLabel
{
     int FCounter;
     TTimer* FTimer;
     AnsiString FOrigCaption;

     int        __fastcall GetScrollingSpeed();
     void       __fastcall SetScrollingSpeed( int Value );
     AnsiString __fastcall GetCaption();
     void       __fastcall SetCaption( AnsiString ACaption );

public:
     __fastcall TScrollingLabel( TComponent* Owner );
     __fastcall ~TScrollingLabel() { delete FTimer; StopCreep(); }
     void __fastcall TimerFired( System::TObject* Sender );
     void StartCreep();
     void StopCreep();

__published:
     __property int        ScrollingSpeed = { read = GetScrollingSpeed, write = SetScrollingSpeed };
     __property AnsiString Caption = { read = GetCaption, write = SetCaption };
};
//---------------------------------------------------------------------------
#endif



файл .cpp

Код

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "ScrollingLabel.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(TScrollingLabel *)
{
    new TScrollingLabel(NULL);
}

//---------------------------------------------------------------------------
__fastcall TScrollingLabel::TScrollingLabel(TComponent* Owner)
        : TLabel(Owner)
{
     FTimer = new TTimer( this );
     FTimer->OnTimer = TimerFired;
     FTimer->Enabled = false;
     FTimer->Interval = 300;
     FCounter = 1;
     AutoSize = false;
}

//------------------------------------------------------------------------------
void __fastcall TScrollingLabel::TimerFired( System::TObject* Sender )
{
     AnsiString Text( FOrigCaption );
     AnsiString Space = ' ';
     int LabelWidth = TLabel::Width;
     int TextLen = Canvas->TextWidth( Text );
     int SpaceLen = Canvas->TextWidth(Space);
     int NumSpace = ( LabelWidth - TextLen ) / SpaceLen;
     for (int i=0; i <= NumSpace; i++) { Text+=Space; }
     int Len =Text.Length();
     Text = Text + Space + Text.SubString( 1, Len );
     TLabel::Caption = Text.SubString( FCounter, Len );
     FCounter++;
     if ( Text.Length() - Len < FCounter ) FCounter = 1;
}

//------------------------------------------------------------------------------
void TScrollingLabel::StartCreep()
{
     FOrigCaption = Caption;
     if ( Caption != NULL ) {
        FTimer->Enabled = true;
        TimerFired( this );
     }
}

//------------------------------------------------------------------------------
void TScrollingLabel::StopCreep()
{
     FTimer->Enabled = false;
     TLabel::Caption = FOrigCaption;
}

//------------------------------------------------------------------------------
int __fastcall  TScrollingLabel::GetScrollingSpeed()
{
     return FTimer->Interval;
}

//------------------------------------------------------------------------------
void __fastcall  TScrollingLabel::SetScrollingSpeed( int Value )
{
     FTimer->Interval = Value;
}

//------------------------------------------------------------------------------
AnsiString __fastcall TScrollingLabel::GetCaption()
{
     return TLabel::Caption;
}

//------------------------------------------------------------------------------
void __fastcall TScrollingLabel::SetCaption( AnsiString ACaption )
{
     StopCreep();
     TLabel::Caption = ACaption;
     StartCreep();
}

//------------------------------------------------------------------------------
namespace Scrollinglabel
{
     void __fastcall PACKAGE Register()
     {
        TComponentClass classes[1] = {__classid(TScrollingLabel)};
        RegisterComponents("MyComponents", classes, 0);
     }
}
//---------------------------------------------------------------------------



Еще раз всем спасибо большое за помощь.

P.S.
Это вариант для посимвольного сдвига,может, кто подскажет,как сдвигать строку попиксельно,чтобы она не так дергалась? Буду очень признателен.  smile 

Автор: Демидрол 28.7.2008, 15:11
После небольших заморок сей компонент сооружен  на основе попиксельного сдвига текста.
Кому нужно - юзайте наздоровье.

файл .h :
Код

//---------------------------------------------------------------------------

#ifndef TRunningLabelH
#define TRunningLabelH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
//---------------------------------------------------------------------------
class PACKAGE TRunningLabel : public TLabel
{
private:
     TTimer* FTimer;
     TRect  FillRect;
     AnsiString FOrigCaption;

protected:     
     int        __fastcall GetScrollingSpeed();
     void       __fastcall SetScrollingSpeed( int Value );
     AnsiString __fastcall GetCaption();
     void       __fastcall SetCaption( AnsiString ACaption );
     int        __fastcall GetTextWidth (System::TObject* Sender, AnsiString Text);

public:
     __fastcall TRunningLabel(TComponent* Owner);
     __fastcall ~TRunningLabel() { delete FTimer; StopCreep(); }
     void __fastcall TimerFired( System::TObject* Sender );
     void __fastcall StartCreep();
     void __fastcall StopCreep();
     void __fastcall ClearCanvas(System::TObject* Sender);

__published:
     __property int        ScrollingSpeed = { read = GetScrollingSpeed, write = SetScrollingSpeed };
     __property AnsiString Caption = { read = GetCaption, write = SetCaption };

};
//---------------------------------------------------------------------------
#endif


файл .cpp :
Код

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "TRunningLabel.h"
#pragma package(smart_init)
//------------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(TRunningLabel *)
{
        new TRunningLabel(NULL);
}
//------------------------------------------------------------------------------
__fastcall TRunningLabel::TRunningLabel(TComponent* Owner)
        : TLabel(Owner)
{
     FTimer = new TTimer( this );
     FTimer->OnTimer = TimerFired;
     FTimer->Enabled = false;
     FTimer->Interval = 35;
     AutoSize = false;
}

//------------------------------------------------------------------------------
namespace Trunninglabel
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TRunningLabel)};
                 RegisterComponents("MyComponents", classes, 0);
        }
}

//------------------------------------------------------------------------------
void __fastcall TRunningLabel::StartCreep()
{
     FOrigCaption = Caption;
     if ( Caption != NULL ) {
        FTimer->Enabled = true;
        TimerFired( this );
     }
}
//------------------------------------------------------------------------------
void __fastcall TRunningLabel::ClearCanvas (System::TObject* Sender)
{
     TRect  FillRect;

     Canvas->Brush->Color = Color;

     FillRect.Left   = 0;
     FillRect.Top    = 0;
     FillRect.Right  = Width;
     FillRect.Bottom = Canvas->TextHeight(FOrigCaption);
     Canvas->FillRect( FillRect );
}

//------------------------------------------------------------------------------
void __fastcall TRunningLabel::StopCreep()
{
     FTimer->Enabled = false;
}

//------------------------------------------------------------------------------
void __fastcall TRunningLabel::TimerFired (System::TObject* Sender)
{
     static int Xcoord = 0;

     ClearCanvas( Sender );
     Canvas->TextOutA( Xcoord, 0, FOrigCaption  );

     Xcoord -= 2;

     if ( -Xcoord >= GetTextWidth( Sender, FOrigCaption ) ) {
          Xcoord = Width;
       }

}

//------------------------------------------------------------------------------
int __fastcall TRunningLabel::GetTextWidth (System::TObject* Sender, AnsiString Text)
{
     return ( Canvas->TextExtent( Text ).cx );
}

//------------------------------------------------------------------------------
int __fastcall  TRunningLabel::GetScrollingSpeed()
{
     return FTimer->Interval;
}

//------------------------------------------------------------------------------
void __fastcall  TRunningLabel::SetScrollingSpeed( int Value )
{
     FTimer->Interval = Value;
}

//------------------------------------------------------------------------------
AnsiString __fastcall TRunningLabel::GetCaption()
{
     StopCreep();
     return TLabel::Caption;
}

//------------------------------------------------------------------------------
void __fastcall TRunningLabel::SetCaption( AnsiString ACaption )
{
     StopCreep();
     TLabel::Caption = ACaption;
     StartCreep();
}

//------------------------------------------------------------------------------


Удачного использования!!!  smile 

Автор: Ildarinho 23.12.2008, 12:36
Демидрол можешь выложить срр и h файлы тестовой проги? 


Автор: Ildarinho 26.12.2008, 20:08
если поместить на форму 2-3 визуальных компонент бегущая строка, то они будут вместе бегать, незнаете в чем глюк???

Автор: Демидрол 28.12.2008, 13:46
в строке 
Код

static int Xcoord = 0;

убери static и всё будет ок!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)