运行效果:
BulletScreenMain.h
/***************************************************************
* Name: BulletScreenMain.h
* Purpose: Defines Application Frame
* Author: Leslie (nowreadygo@163.com)
* Created: 2025-03-09
* Copyright: Leslie ()
* License:
**************************************************************/
#ifndef BULLETSCREENMAIN_H
#define BULLETSCREENMAIN_H
#include "BulletScreenApp.h"
#include "GUIFrame.h"
class BulletScreenFrame: public BulletScreenMainFrame
{
public:
BulletScreenFrame(wxFrame *frame);
~BulletScreenFrame();
//void OnApplyText( wxCommandEvent& event ) { event.Skip(); }
};
#endif // BULLETSCREENMAIN_H
BulletScreenApp.h
/***************************************************************
* Name: BulletScreenApp.h
* Purpose: Defines Application Class
* Author: Leslie (nowreadygo@163.com)
* Created: 2025-03-09
* Copyright: Leslie ()
* License:
**************************************************************/
#ifndef BULLETSCREENAPP_H
#define BULLETSCREENAPP_H
#include <wx/app.h>
class BulletScreenApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif // BULLETSCREENAPP_H
GUIFrame.h
#pragma once
#include <wx/wx.h>
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/sizer.h>
#include <wx/frame.h>
#include <cstdlib>
#include <vector>
#include <random>
#include <wx/dcbuffer.h>
using namespace std;
///
struct ScrollingText{
wxString content;
int x;
int y;
int speed = 4;
wxColour color;
};
///
/// Class BulletScreenMainFrame
///
class BulletScreenMainFrame : public wxFrame
{
private:
void OnPaint(wxPaintEvent& event);
void OnTimer(wxTimerEvent& event);
void OnSize(wxSizeEvent& event);
int m_FrameWidth;
int m_FrameHeight;
wxString m_displayString = "";
//int m_offset = 0;
wxTimer* m_timer;
mt19937 rng;
vector<ScrollingText> m_texts;
protected:
wxTextCtrl* m_TextInput;
void OnApplyText( wxCommandEvent& event );
void AddNewTextLine(const wxString& text);
void OnEraseBackground(wxEraseEvent& event);
public:
int randHeight = 0;
BulletScreenMainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("弹幕-----Leslie"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 700,570 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
~BulletScreenMainFrame();
};
BulletScreenMain.cpp
/***************************************************************
* Name: BulletScreenMain.cpp
* Purpose: Code for Application Frame
* Author: Leslie (nowreadygo@163.com)
* Created: 2025-03-09
* Copyright: Leslie ()
* License:
**************************************************************/
#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif
#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__
#include "BulletScreenMain.h"
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__WXMAC__)
wxbuild << _T("-Mac");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
BulletScreenFrame::BulletScreenFrame(wxFrame *frame)
: BulletScreenMainFrame(frame)
{
}
BulletScreenFrame::~BulletScreenFrame()
{
}
BulletScreenApp.cpp
/***************************************************************
* Name: BulletScreenApp.cpp
* Purpose: Code for Application Class
* Author: Leslie (nowreadygo@163.com)
* Created: 2025-03-09
* Copyright: Leslie ()
* License:
**************************************************************/
#ifdef WX_PRECOMP
#include "wx_pch.h"
#endif
#ifdef __BORLANDC__
#pragma hdrstop
#endif //__BORLANDC__
#include "BulletScreenApp.h"
#include "BulletScreenMain.h"
IMPLEMENT_APP(BulletScreenApp);
bool BulletScreenApp::OnInit()
{
BulletScreenFrame* frame = new BulletScreenFrame(0L);
frame->SetIcon(wxICON(aaaa)); // To Set App Icon
frame->Show();
return true;
}
GUIFrame.cpp
///
// C++ code generated with wxFormBuilder (version 4.2.1-52-g73f12a06)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///
#include "GUIFrame.h"
///
BulletScreenMainFrame::BulletScreenMainFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
rng.seed(random_device()());
//srand(static_cast<unsigned int>(time(0)));
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVECAPTIONTEXT ) );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
m_TextInput = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), wxBORDER_SIMPLE | wxTE_PROCESS_ENTER);
m_TextInput->SetBackgroundStyle(wxBG_STYLE_PAINT);//防止输入文字时文字闪烁
this->SetBackgroundStyle(wxBG_STYLE_PAINT); //防止文字闪烁
m_TextInput->SetBackgroundColour(wxColour(0,255,64));
bSizer1->Add( m_TextInput, 0, wxEXPAND, 5 );
this->SetSizer( bSizer1 );
this->Layout();
this->Centre( wxBOTH );
// Connect Events
//m_TextInput->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( BulletScreenMainFrame::OnApplyText ), NULL, this );
m_TextInput->Bind(wxEVT_TEXT_ENTER, &BulletScreenMainFrame::OnApplyText, this);
Bind(wxEVT_PAINT, &BulletScreenMainFrame::OnPaint, this);
m_timer = new wxTimer(this, wxID_ANY);
Bind(wxEVT_TIMER, &BulletScreenMainFrame::OnTimer, this);
m_timer->Start(20);
Bind(wxEVT_SIZE, &BulletScreenMainFrame::OnSize, this);
GetClientSize(&m_FrameWidth, &m_FrameHeight);
SetBackgroundStyle(wxBG_STYLE_PAINT);
}
BulletScreenMainFrame::~BulletScreenMainFrame()
{
}
void BulletScreenMainFrame::OnTimer(wxTimerEvent& event)
{
/*
m_offset += 2;
int textWidth;
GetTextExtent(m_displayString, & textWidth, nullptr);
if( m_offset > GetSize().GetWidth() + textWidth)
{
m_offset = -textWidth;
}
Refresh();
*/
//更新所有文字位置
int textWidth;
GetTextExtent(m_displayString, & textWidth, nullptr);
for(auto& text : m_texts)
{
if(text.x > m_FrameWidth + textWidth)
{
text.x = -textWidth;
}
text.x += text.speed;
}
Refresh();
}
void BulletScreenMainFrame::AddNewTextLine(const wxString& text)
{
if(text.empty()) return;
uniform_int_distribution<int> distY(20, m_FrameHeight - 40);
uniform_int_distribution<int> distColor(50,255);
int y = distY(rng);
int textWidth;
GetTextExtent(m_displayString, & textWidth, nullptr);
m_texts.push_back({
text, //内容
-textWidth, //初始X位置(左侧外)
y, //随机Y位置
4,
wxColor(distColor(rng),distColor(rng),distColor(rng))});
Refresh();
}
void BulletScreenMainFrame::OnApplyText( wxCommandEvent& event )
{
/*
m_displayString = m_TextInput->GetValue();
m_TextInput->Clear();
Refresh();
randHeight = rand() % GetSize().GetHeight();
//event.Skip();
*/
m_displayString = m_TextInput->GetValue();
AddNewTextLine(m_displayString);
m_TextInput->Clear();
}
void BulletScreenMainFrame::OnEraseBackground(wxEraseEvent& event)
{
// 空实现,禁止自动擦除
}
void BulletScreenMainFrame::OnPaint(wxPaintEvent& event)
{
//SetDoubleBuffered(true);
//wxPaintDC dc(this);
wxAutoBufferedPaintDC dc(this);
//wxBufferedPaintDC dc(this);
//dc.SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
//dc.SetTextForeground(*wxRED);
//dc.DrawText(m_displayString, creaseX, randHeight);
dc.SetBackground(wxBrush(GetBackgroundColour()));
dc.Clear();
dc.SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD));
dc.SetTextForeground(*wxRED);
//dc.DrawText(m_displayString, m_offset, randHeight);
for(const auto& text : m_texts)
{
dc.SetTextForeground(text.color);
dc.DrawText(text.content, text.x, text.y);
}
}
void BulletScreenMainFrame::OnSize(wxSizeEvent& event)
{
GetClientSize(&m_FrameWidth, &m_FrameHeight);
event.Skip();
};