学习了几天的wx了,作为练习,做了一个程序:随机生成多个小球在窗口内随机方向运动,并且小球碰到屏幕可以反弹。
代码如下,为了方便所有的代码都写在了一个文件中了
main.cpp:
#include
#include
#include
//弹球
typedef struct
{
wxCoord x, y; //位置
wxCoord r; //半径
wxCoord dx, dy; //运动增量
wxColour colour;
}Pinball;
//随机产生一个(minN, maxN]范围的整数
int RandNumber(int minN, int maxN)
{
return minN + rand() % (maxN - minN);
}
//主窗口类
class MyFrame: public wxFrame
{
public:
MyFrame();
~MyFrame();
protected:
//事件处理函数
void OnPaint(wxPaintEvent &event);
void OnTimer(wxTimerEvent &event);
void OnPause(wxCommandEvent &event);
void OnResume(wxCommandEvent &event);
void OnRestart(wxCommandEvent &event);
void OnAbout(wxCommandEvent &event);
//普通函数
void PaintBalls();
//声明事件处理表
wxDECLARE_EVENT_TABLE();
private:
//控件ID定义
enum{
wxIDT_TIEMER = 1000,
wxIDM_PAUSE,
wxIDM_RESUME,
wxIDM_RESTART,
};
//成员变量
int ballCnt;
Pinball *pballs;
wxTimer *timer;
wxBitmap bitmap;
wxMemoryDC memDC;
};
//定义事件处理表
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_PAINT(OnPaint)
EVT_TIMER(wxIDT_TIEMER, MyFrame::OnTimer)
EVT_MENU(wxIDM_PAUSE, MyFrame::OnPause)
EVT_MENU(wxIDM_RESUME, MyFrame::OnResume)
EVT_MENU(wxIDM_RESTART, MyFrame::OnRestart)
EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
MyFrame::MyFrame()
:wxFrame(NULL, wxID_ANY, wxT("弹球"), wxDefaultPosition, wxDefaultSize,
wxDEFAULT_FRAME_STYLE | wxMAXIMIZE)
{
//设置窗口UI
SetBackgroundColour(wxColour(0xf9f9f9));
wxMenu *menuCtrl = new wxMenu;
menuCtrl->Append(wxIDM_PAUSE, wxT("&暂停\tCtrl-P"));
menuCtrl->Append(wxIDM_RESUME, wxT("&继续\tCtrl-R"));
menuCtrl->Append(wxIDM_RESTART, wxT("&重新开始\tCtrl-T"));
menuCtrl->Append(wxID_EXIT);
wxMenu *menuHelp = new wxMenu;
menuHelp->Append(wxID_ABOUT);
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuCtrl, wxT("&控制"));
menuBar->Append(menuHelp, wxT("&帮助"));
SetMenuBar(menuBar);
//初始化成员变量
ballCnt = RandNumber(10, 30);
pballs = new Pinball[ballCnt];
wxRect rect = GetRect();
bitmap.Create(rect.GetWidth(), rect.GetHeight());
memDC.SelectObject(bitmap);
memDC.SetBackground(wxBrush(wxColour(0xf9f9f9)));
wxPen pen(wxColour(128, 128, 128, 32));
memDC.SetPen(pen);
timer = new wxTimer(this, wxIDT_TIEMER);
wxCommandEvent e;
OnRestart(e);
}
MyFrame::~MyFrame()
{
delete[] pballs;
delete timer;
}
//画出所有弹球(双缓冲避免闪烁问题)
void MyFrame::PaintBalls()
{
wxRect rect = GetRect();
//在内存DC画图
memDC.Clear();
for (int i = 0; i < ballCnt; ++ i) {
Pinball *ball = &pballs[i];
wxBrush brush(ball->colour);
memDC.SetBrush(brush);
memDC.DrawCircle(ball->x, ball->y, ball->r);
}
//复制到客户区DC
wxClientDC dc(this);
dc.Blit(0, 0, rect.GetWidth(), rect.GetHeight(), &memDC, 0, 0);
}
//重绘事件处理
void MyFrame::OnPaint(wxPaintEvent &event)
{
PaintBalls();
}
//定时器事件处理
void MyFrame::OnTimer(wxTimerEvent &event)
{
wxRect rect = GetRect();
Pinball *ball;
for (int i = 0; i < ballCnt; ++ i) {
ball = &pballs[i];
ball->x += ball->dx;
ball->y += ball->dy;
if (ball->x - ball->r <= rect.GetLeft() || ball->x + ball->r >= rect.GetRight()) {
ball->dx = - ball->dx;
}
if (ball->y - ball->r <= rect.GetTop() || ball->y + ball->r >= rect.GetBottom()) {
ball->dy = - ball->dy;
}
}
PaintBalls();
}
//菜单暂停事件
void MyFrame::OnPause(wxCommandEvent &event)
{
if (timer->IsRunning()) {
timer->Stop();
}
}
//菜单恢复事件
void MyFrame::OnResume(wxCommandEvent &event)
{
if (!timer->IsRunning()) {
timer->Start();
}
}
//菜单重新开始事件
void MyFrame::OnRestart(wxCommandEvent &event)
{
wxRect rect = GetRect();
for (int i = 0; i < ballCnt; ++ i) {
Pinball *ball = &pballs[i];
ball->r = RandNumber(15, 50);
ball->x = RandNumber(ball->r, rect.GetWidth() - ball->r);
ball->y = RandNumber(ball->r, rect.GetHeight() - ball->r);
ball->dx = ball->dy = 0;
while (!ball->dx && !ball->dy) {
ball->dx = RandNumber(-8, 8);
ball->dy = RandNumber(-8, 8);
}
ball->colour = wxColour(RandNumber(0x40, 0xff),
RandNumber(0x40, 0xff),
RandNumber(0x40, 0xff),
RandNumber(0x0a, 0xff));
}
timer->Start(10);
}
//菜单关于事件
void MyFrame::OnAbout(wxCommandEvent& event)
{
wxMessageBox(wxT("作者:luoluolzb\r\n时间:2017-12-7"),
wxT("帮助"),
wxOK | wxICON_INFORMATION);
}
//应用类
class MyApp: public wxApp
{
public:
virtual bool OnInit();
};
//自动实例化MyApp对象并赋值给全局变量wxTheApp
DECLARE_APP(MyApp)
//声明可以使用wxGetApp()获取实例对象
IMPLEMENT_APP(MyApp)
//入口函数
bool MyApp::OnInit()
{
srand(time(NULL)); //初始化随机数种子
MyFrame *frame = new MyFrame();
frame->Show();
return true;
}