继承 TPaintBox 实现信息发布滚屏显示控件


//------------------------------------------------------------------------------------------------------------
// unit_ScrollDrawText.cpp
//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "unit_ScrollDrawText.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(TScrollDrawText *)
{
 new TScrollDrawText(NULL);
}
//---------------------------------------------------------------------------
namespace Unit_scrolldrawtext
{
 void __fastcall PACKAGE Register()
 {
  TComponentClass classes[1] = {__classid(TScrollDrawText)};
  RegisterComponents("My Component", classes, 0);
 }
}
//---------------------------------------------------------------------------
__fastcall TScrollDrawText::TScrollDrawText(TComponent* Owner)
 : TPaintBox(Owner)
{
 SourceStringList = new TStringList;  // 初始化来源字符串列表
 ReleaseStringList = new TStringList; // 初始化发布列表

 ShowControl = new TShowControl(true); // 初始化多线程控制

 OutTextWidth = 20; // 设定默认行宽
}
//---------------------------------------------------------------------------
__fastcall TScrollDrawText::~TScrollDrawText()
{
 ShowControl->Done(); // 设置关闭标记

 InitReleaseStringList(); //
 InitSourceStringList(); // 清空 StringList 对象

 delete SourceStringList;
 delete ReleaseStringList;

 delete ShowControl;
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::InitSourceStringList()
{
 for ( int i = 0; i < SourceStringList->Count; i++)
 {
  if ( SourceStringList->Objects[i] != NULL )
  {
   delete (TFont*)SourceStringList->Objects[i]; // 删除表内 TFont 对象
   SourceStringList->Objects[i] = NULL;
  }
 }
 SourceStringList->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::InitReleaseStringList()
{
 // 发布字符串的对象指针全部来自 SourceStringList
 // 清除指针对象只需要由 SourceStringList 完成即可

 ReleaseStringList->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::AddString(const String InsertString, const TColor Color)
{
 // 插入数据,也就是外部接口之一

 TFont* Font = new TFont; // 创建一个对象用于保存字体信息
 Font->Charset = DEFAULT_CHARSET;
 Font->Color = Color;
 Font->Name = "宋体";
 Font->Size = 10;

 SourceStringList->AddObject(InsertString, Font);
 ReBuileReleaseStringList(); // 重新构建布字符串
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::ReBuileReleaseStringList()
{
 // 新字符串进入,先清空发布字符串
 // 重新往原字符串中添加

 InitReleaseStringList();

 for (int i = 0; i < SourceStringList->Count; i++)
 {
  CutInsertString
  (
   SourceStringList->Strings[i],
   ReleaseStringList,
   SourceStringList->Objects[i]
  );

  /*CutInsertString // 每行插入一个回车符
  (
   "/n",
   ReleaseStringList,
   SourceStringList->Objects[i]
  );*/
 }
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::CutInsertString
 (const String InsertString, TStringList* ReleaseStringList, TObject* Object)
{
 // 裁剪来源字符串达到额定宽度,再插入发布字符串

 WideString wdStr = InsertString;

 if ( wdStr.Length() <= 0 )
 {
  return;   
 }

 String NewString = "";

 for ( int Index = 1; ; Index++ ) // 搜索字符串,将每个字符追加到 wdStr
 {
  // 单字符累加,双字节由 WideString 自动处理
  NewString = NewString + wdStr.SubString( Index, 1 );

  if ( NewString == "" || NewString == NULL ) // 字符不存在
  {
   break;
  }

  if ( Index == ( InsertString.Length() ) ) // 循环出口,最后一个字符串
  {
   ReleaseStringList->AddObject(NewString, Object);
   NewString = "";
   break;
  }
  else if ( NewString.Length() <= OutTextWidth ) // 个字节一行,将进来的字符串分行
  {
   continue;
  }
  else
  {
   ReleaseStringList->AddObject ( NewString, Object ); // 向发布字符串输入新的对象
   NewString = "";
  }
 }
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::Suspend()
{
 ShowControl->Suspend(); // 启动多线程
}
//---------------------------------------------------------------------------
bool __fastcall TScrollDrawText::Suspended()
{
 return ShowControl->Suspended; // 察看多线程状态
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::Resume()
{
 /*String temp = "";
 for ( int i = 0; i < ReleaseStringList->Count; i++ ) // 测试代码
 {
  temp = ReleaseStringList->Strings[i];
 }*/
 
 ShowControl->SetScreenText(this, ReleaseStringList); // 设置输出宽度
 ShowControl->Resume(); // 开始滚动运行
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::SetScrollSpeed(const int ScrollSpeed)
{
 ShowControl->SetScrollSpeed(ScrollSpeed); // 设置速度 20~100 为宜
}
//---------------------------------------------------------------------------
void __fastcall TScrollDrawText::SetOutTextWidth(const int OutTextWidth)
{
 this->OutTextWidth = OutTextWidth; // 设置宽度
 
 ShowControl->Suspend();
 ReBuileReleaseStringList();  // 重新根据宽度生成发布字符串
 ShowControl->Resume();
}
//---------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------------------
// unit_ScrollDrawText.h
//---------------------------------------------------------------------------

#ifndef unit_ScrollDrawTextH
#define unit_ScrollDrawTextH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
#include "unit_ShowControl.h"
//---------------------------------------------------------------------------
class PACKAGE TScrollDrawText : public TPaintBox
{
__published:
 void __fastcall AddString(const String InsertString, const TColor Color);
 void __fastcall Resume();
 void __fastcall Suspend();
 bool __fastcall Suspended();
 void __fastcall SetScrollSpeed(const int ScrollSpeed);
 void __fastcall SetOutTextWidth(const int OutTextWidth);
private:
 TStringList* SourceStringList; // 近来的字符串列
 TStringList* ReleaseStringList; // 过滤后的字符串列
 int OutTextWidth; // 输入宽度字节数
 TShowControl* ShowControl; // 多线程控制器
 void __fastcall CutInsertString
  (const String InsertString, TStringList* ReleaseStringList, TObject* Object);
 void __fastcall InitSourceStringList();
 void __fastcall InitReleaseStringList();
 void __fastcall ReBuileReleaseStringList();
protected:
public:
 __fastcall TScrollDrawText(TComponent* Owner);
 __fastcall ~TScrollDrawText();
};
//---------------------------------------------------------------------------
#endif

//------------------------------------------------------------------------------------------------------------
// unit_ShowControl.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "unit_ShowControl.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------

//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(&UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TShowControl::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------
__fastcall TShowControl::TShowControl(bool CreateSuspended)
 : TThread(CreateSuspended)
{
 OnClose = false;
 ScrollSpeed = 20; // 默认微秒每像素滚动
 
 pBitmap = new Graphics::TBitmap(); // 创建缓冲区
}
//---------------------------------------------------------------------------
void __fastcall TShowControl::Execute()
{
 //---- Place thread code here ----
 Go();
}
//---------------------------------------------------------------------------
__fastcall TShowControl::~TShowControl()
{
 delete pBitmap; // 释放缓冲区
}
//---------------------------------------------------------------------------
void __fastcall TShowControl::SetScreenText(TPaintBox* Image, TStringList* StringList)
{
 ScreenImage = Image; // ScreenImage 指针指向窗体上的 Image
 this->StringList = StringList; // 指向处理好可以发布的字符串

 if ( pBitmap->Canvas->LockCount == 0 )
 {
   // 设置缓冲区尺寸
  pBitmap->Canvas->Lock();
  pBitmap->Height = Image->Height;
  pBitmap->Width = Image->Width;
  pBitmap->Canvas->Unlock();
 }
}
//---------------------------------------------------------------------------
void __fastcall TShowControl::Done()
{
 OnClose = true; // 关闭标记
}
//---------------------------------------------------------------------------
inline void __fastcall TShowControl::Drow()
{
 // 对显示区进行 Draw 操作
 if ( ScreenImage->Canvas->LockCount == 0 )
 {
  ScreenImage->Canvas->Lock();
  ScreenImage->Canvas->Draw(0,0,pBitmap);
  ScreenImage->Canvas->Unlock();
 }
}
//---------------------------------------------------------------------------
void __fastcall TShowControl::Go()
{
 const int RowHeight = 20; // 设定行高
 const LeftSpace = 4; // 设定左间距

 for ( int OutLine = pBitmap->Height * (1-0.618) ; OutLine >= - RowHeight ; OutLine -- )
 {
  // 循环条件描述, height*(1-0.618) 为起始位置,-20为回滚位置

  if ( OnClose ) // 判断是否关闭
   break;

  Synchronize(&InitImage); // 初始化 Bitmap
 
  for (int ChildIndex = 0; ChildIndex < StringList->Count; ChildIndex ++ )
  {
   if ( pBitmap->Canvas->LockCount == 0 )
   {
    pBitmap->Canvas->Lock();

    /*if ( StringList->Objects[ChildIndex] != NULL )
    {
     pBitmap->Canvas->Font->Assign((TFont*)StringList->Objects[ChildIndex]);
    }*/

    // 对缓冲区输出内容
        pBitmap->Canvas->Font->Assign((TFont*)StringList->Objects[ChildIndex]);
    pBitmap->Canvas->TextOutA (
     LeftSpace, OutLine + ChildIndex * RowHeight , StringList->Strings[ChildIndex]);
     // 左边距,高度,内容
   
    pBitmap->Canvas->Unlock();
   }
  
   if ( ChildIndex * RowHeight > pBitmap->Height )
   {
       // 发布行数过多不对其进行绘画,只需超过 Height 即可
    break;
   }
  }
  Synchronize(&Drow); // 缓冲区输出到显示区

  //pBitmap->SaveToFile("jjj.bmp"); // 作为测试

  if ( GetSleep() == -1 ) // 设置滚动速度,同时侦测是否需要退出
   break;

  if ( OutLine == - RowHeight ) // 回滚控制,当升至顶端 -20 的位置,把 0 移动到 最后
  {
   StringList->AddObject(StringList->Strings[0],StringList->Objects[0]); // 复制 0 至末尾
   StringList->Delete(0); // 删除 0

   OutLine = 0 ; // 总体位置回移 20 个像素
  }
 }
}
//---------------------------------------------------------------------------
inline int __fastcall TShowControl::GetSleep()
{
 int ScrollSpeedTemp = ScrollSpeed;
 while ( ScrollSpeedTemp > 0 ) // 作为封闭循环的调处条件
 {
  if ( OnClose ) // 但完成标记为真
   return -1;

  Sleep(1); // 延时
  ScrollSpeedTemp --;
 }
 return 0; 
}
//---------------------------------------------------------------------------
inline void __fastcall TShowControl::InitImage()
{
 // 初始化缓冲区
 if ( pBitmap->Canvas->LockCount == 0 )
 {
  pBitmap->Canvas->Lock();
  pBitmap->Canvas->Brush->Style = bsClear;
  pBitmap->Canvas->Brush->Color = clWhite;
  pBitmap->Canvas->FillRect(TRect(0, 0, pBitmap->Width, pBitmap->Height));
  pBitmap->Canvas->Unlock();
 }
}
//---------------------------------------------------------------------------
void __fastcall TShowControl::SetScrollSpeed(int ScrollSpeed)
{
 // 设置滚动速度
 this->ScrollSpeed = ScrollSpeed;
}
//---------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------------
// ShowControl.h
//-------------------------------------------------------------------------------------------------------

#ifndef unit_ShowControlH
#define unit_ShowControlH
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class TShowControl : public TThread
{
private:
 Graphics::TBitmap *pBitmap; // 缓冲
 TPaintBox* ScreenImage; // 来源
 TStringList* StringList;
 bool OnClose;
 int ScrollSpeed; // 默认微秒每像素滚动
 inline int __fastcall GetSleep();
 inline void __fastcall Drow();
 void __fastcall Go();
 inline void __fastcall InitImage();
protected:
 void __fastcall Execute();
public:
 __fastcall TShowControl(bool CreateSuspended);
 __fastcall ~TShowControl();
 void __fastcall SetScreenText(TPaintBox* Image, TStringList* StringList);
 void __fastcall Done();
 void __fastcall SetScrollSpeed(int ScrollSpeed);
};
//---------------------------------------------------------------------------
#endif

//---------------------------------------------------------------------------------------------------------
// 使用示范
//---------------------------------------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)
 : TForm(Owner)
{
 LabeledEdit1->Text = 20;
 LabeledEdit2->Text = 20;

 ScrollDrawText1->AddString("This is new message 1", clGreen);
 ScrollDrawText1->AddString("This is new message 2", clBlue);
 ScrollDrawText1->AddString("This is new message 3", clBlack);
 ScrollDrawText1->AddString("This is new message 4", clSkyBlue);
 ScrollDrawText1->AddString("This is new message 5", clYellow);
 ScrollDrawText1->AddString("This is new message 6", clTeal);
 ScrollDrawText1->AddString("This is new message 7", clPurple);
 ScrollDrawText1->AddString("This is new message 8", clAqua);
 ScrollDrawText1->AddString("This is new message 9", clSkyBlue);
 ScrollDrawText1->AddString("This is new message 0", clHotLight);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 ScrollDrawText1->AddString(LabeledEdit3->Text, clHotLight);
 ScrollDrawText1->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
 ScrollDrawText1->SetScrollSpeed(LabeledEdit1->Text.ToInt());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 ScrollDrawText1->SetOutTextWidth(LabeledEdit2->Text.ToInt());
}
//---------------------------------------------------------------------------
 
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值