0.前言
我想通过编写一个完整的游戏程序方式引导读者体验程序设计的全过程。我将采用多种方式编写具有相同效果的应用程序,并通过不同方式形成的代码和实现方法的对比来理解程序开发更深层的知识。
了解我编写教程的思路,请参阅体现我最初想法的那篇文章中的“1.编程计划”:
了解不同方式实现同样效果的差异,请阅读以下文章:
在这篇文章里,我主要讲述以下几个方面的内容:
- 使用向导新建一个wxWidgets程序
- 向导为我生成的项目文件中有什么
- 按着我的意愿对向导生成的文件进行修改
- 结束语
1.使用向导新建一个wxWidgets程序
在开始下面的内容之前,我假定你已经安装了CodeBlocks程序开发环境,配置了wxWidgets,测试使用CodeBlocks创建第一个程序成功编译运行,并且了解了C++语言的基础知识和使用wxWiddgets开发C++程序的知识。
如果你还有哪一方面没有做到,请阅读下面的文章:
- 体验Code::Blocks下的C++编程 - lexyao - 博客园:搭设Code::Blocks开发平台(安装)
- 在Windows下为CodeBlocks20.3安装、配置wxWidget3.2.6 - lexyao - 博客园:安装、编译、配置wxWidget,测试在CodeBlocks中使用wxWidget编写的第一个程序
- wxWidgets 跨平台 GUI 编程:系统地讲述使用wxWiddgets开发C++程序的知识
- C 语言教程 | 菜鸟教程:系统地讲述C语言编程的基础知识
- C++ 教程 | 菜鸟教程:系统地讲述C++语言编程的基础知识
使用向导新建一个wxWidgets程序的操作步骤如下:
第一步:打开新建项目向导
这一步跟创建控制台程序是相同的,后续就有差别了。有两种方法:
①主菜单:File->New->Projects
②点击Start Here页面中的Create New Project
第二步:在窗口中选择项目类型wxWidgets project
第三步、按向导的提示完成创建项目的过程
我重点介绍几个向导界面,没有介绍的向导页面你直接点击Next按钮就行了。
向导页面①:
选择wxWidgets 3.2.x。选择哪一个版本要看你安装的是哪一个版本的wxWidgets 库文件,选择了你没有的版本,在编译你的程序时会因为找不到库文件而导致编译失败。
向导页面②:输入项目名称。将来你编译生成的exe应用程序将会使用这个名称。保存这个项目的文件夹也会默认使用这个名称,不过你可以在这个页面中修改保存项目文件的文件夹。
- 在项目名称栏中输入xTetris。将来编译生成的项目文件将会是xTetris.exe
- 将文件路径中自动添加的xTetris改为Tetris。修改之后保存创建的项目文件的文件夹将会是Tetris,而不是默认的xTetris
向导页面③:
在Preferred GUl Builder栏目中选择编写程序时构建GUI界面使用的方法。在这个项目中选择None,将来在项目中使用输入代码的方式构建GUI界面。
在Application Type栏目中选择应用程序的类型。在这个项目中选择Frame Based,也就是说要基于wxFrame创建你的应用程序的主界面。
向导页面④:
在wxWidgets Library Settings栏目中选择wxWidgets库文件的设置。
这是一组多选项,你可以选择其中的任意一个或多个,但你选择的必须是可用的。这一组选项中的每一个选项都对应着你编译wxWidgets库文件时使用的命令行参数。
由于我在编译wxWidgets库文件时的命令行参数使用了SHARED=0 MONOLITHIC=1 UNICODE=1,所以我必须选中wxWidgets is built as a monolithic library和Enable unicode,而不能选中Use wxWidgets DLL。
按向导完成项目创建后,在CodeBlocks左边的栏目中将会看到新创建项目所包含的文件。下图中显示了向导创建的项目中包含的文件的清单。
你可以在文件资源管理器中打开前面在“向导页面②”看到的保存项目文件的文件夹你会看到里面有向导创建的文件。
为了与今后将要创建的项目文件名称有区别,将向导生成的资源文件的文件名由resource.rc改为xTetris.rc。
修改文件名的操作方法是:
在CodeBlocks左边的栏目中要修改的文件名上点击鼠标右键,从弹出的菜单中选择“Rename file…”,输入新的文件名,点击[OK]按钮确认修改。
完成修改后你会发现CodeBlocks左边的栏目中的文件变成了新的文件名,文件资源管理器中的文件名也同步改变了。
第四步、编译运行创建的项目
Code::Blocks工具栏中的编译运行按钮,就会执行编译过程。Code::Blocks下部的窗口中有两个选项卡,分别是编译日志和编译信息。如果编译出错,会在这里出现红色的错误信息。如果是代码错误,编译结束后,点击错误信息,代码窗口会跳转到出错的代码行。
只要不出现错误,编译链接完成后就会运行程序,出现你的应用程序运行后的主界面窗口。
以下是基于wxFrame创建的应用程序的主界面,这个例子中在向导的选择GUI构建方式时,选择了None。
2.向导为我生成的项目文件中有什么
我们只是使用鼠标点击了几下,输入了一个文件名,Code Blocks的向导就为我们创建了一个应用程序。向导给我们创建的文件中有什么呢?下面我们逐个看一看。
2.1 资源文件xTetris.rc
用鼠标双击Code Blocks左边列表中的文件名xTetris.rc,Code Blocks右边的编辑区内便显示出这个文件的内容。
这是一个资源文件文件,内容只有两行。第一行为一个图标定义了一个别名,第二行包含一个资源文件wx.rc。
aaaa ICON "wx/msw/std.ico" #include "wx/msw/wx.rc"
鼠标右击第二行,从菜单中选择打开这个文件,结果会看到下面这个窗口:
Code Blocks找不到这个文件,这个文件不存在吗?
用文件资源管理器在安装wxWidgets的文件夹中搜索“wx.rc”,找到了这个文件。
看到这个文件的路径,你想到了什么?再看一看设置变量wx的界面:
路径的前面部分是变量wx的base,中间是include的默认值“include”,后面是xTetris.rc文件中#include指令后的wx.rc文件的路径。
把这三部分连起来就是包含的文件的完整路径D:\CodeBlocks\wxWidgets-3.2.6\include\wx\msw\wx.rc。
定义的变量wx是给编译器用的,所以可以这么认为:
- Code Blocks不使用变量wx,所以它找不到文件wx.rc
- 编译器使用变量wx,所以它能找到wx.rc
打开wx.rc文件,看看有什么是感兴趣的。
既然正在查看的xTetris.rc文件中有图标文件名,那就关注图标吧,特别是文件第一行所指的图标文件名std.ico。
以下是关于图标的内容:
////////////////////////////////////////////////////////////////////////////// // // Default Icons // // First wx icon in alphabetical order. // // Notice that it also may be used by Explorer as the application icon if the // main program doesn't define any icons preceding this one in alphabetical // order (i.e. any icons defined by it start with "wy", "x", "y" or "z") in // 16*16 or 32*32 sizes. wxICON_AAA ICON "wx/msw/std.ico" //wxDEFAULT_FRAME ICON "wx/msw/std.ico" //wxDEFAULT_MDIPARENTFRAME ICON "wx/msw/mdi.ico" //wxDEFAULT_MDICHILDFRAME ICON "wx/msw/child.ico" // Standard small icons wxICON_SMALL_CLOSED_FOLDER ICON "wx/msw/folder1.ico" wxICON_SMALL_OPEN_FOLDER ICON "wx/msw/folder2.ico" wxICON_SMALL_FILE ICON "wx/msw/file1.ico" wxICON_SMALL_COMPUTER ICON "wx/msw/computer.ico" wxICON_SMALL_DRIVE ICON "wx/msw/drive.ico" wxICON_SMALL_CDROM ICON "wx/msw/cdrom.ico" wxICON_SMALL_FLOPPY ICON "wx/msw/floppy.ico" wxICON_SMALL_REMOVEABLE ICON "wx/msw/removble.ico"
从这段代码中确实发现了std.ico。从文件资源管理器中在D:\CodeBlocks\wxWidgets-3.2.6\include\wx\msw\下也发现了图标文件std.ico,正是新生成的应用程序xTetris.exe使用的图标。
在Code Blocks中编译器可以使用Code Blocks定义的变量wx找到文件wx.rc,而codeBlocks却找不到,这算不算是Code Blocks的缺陷呢?
2.2 两个头文件xTetrisApp.h和xTetrisMain.h
xTetrisApp.h文件的代码如下。
从代码中可以看出以wxApp为基类定义了应用程序的类xTetrisApp,还定义了一个初始化事件处理函数OnInit。
#ifndef XTETRISAPP_H #define XTETRISAPP_H #include <wx/app.h> class xTetrisApp : public wxApp { public: virtual bool OnInit(); }; #endif // XTETRISAPP_H
xTetrisMain.h文件的代码如下。
从代码中可以看出以wxFrame为基类定义了主窗口框架类xTetrisFrame,还定义了以下成员:
- 构造函数和析构函数xTetrisFrame、~xTetrisFrame
- 三个事件处理函数OnClose、OnQuit、OnAbout
- 作为组件ID的常数idMenuQui、idMenuAbout
- 定义事件表的宏DECLARE_EVENT_TABLE
#ifndef XTETRISMAIN_H #define XTETRISMAIN_H #ifndef WX_PRECOMP #include <wx/wx.h> #endif #include "xTetrisApp.h" class xTetrisFrame: public wxFrame { public: xTetrisFrame(wxFrame *frame, const wxString& title); ~xTetrisFrame(); private: enum { idMenuQuit = 1000, idMenuAbout }; void OnClose(wxCloseEvent& event); void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); DECLARE_EVENT_TABLE() }; #endif // XTETRISMAIN_H
2.3 两个C++源代码文件xTetrisApp.cpp和xTetrisMain.cpp
xTetrisApp.cpp文件的代码如下。
这些源代码是约定的格式,不要问为什么是这样,只要记住代码的样式就行了。将来如你自建从一个空文件开始自己创建一个应用程序,也要使用这样的代码,唯一不同的就是将代码中的xTetris替换成你的应用程序的名字。
还有两个常量是可以改动的。
- 一个可以改动的地方是字符串“wxWidgets Application Template”,你已经想到了曾经见过这个字符串,对了,这就是我们创建的应用程序的主窗口标题栏上显示的文字。你可以将它改成任何文字,然后重新编译运行应用程序,看主窗口标题栏中的文字是不是按着你的意愿修改了。
- 另一个可以改动的地方是代表图标的aaaa。这个aaaa是在xTetris.rc文件的第一行定义的。这个aaaa的改动有两种方式。你任选一种方式改动以后重新编译运行应用程序,看主窗口左上角的图标和电脑屏幕下边任务栏的应用程序图标是不是也按着你意愿改变了。
- 你可以将xTetris.rc文件中aaaa后面的std.ico改成drive.ico或者其他图标文件名
- 你可以将xTetris.rc文件中的aaaa改成bbbb,同时将下面代码中的frame->SetIcon(wxICON(aaaa))改成frame->SetIcon(wxICON(bbbb))
#ifdef WX_PRECOMP #include "wx_pch.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif //__BORLANDC__ #include "xTetrisApp.h" #include "xTetrisMain.h" IMPLEMENT_APP(xTetrisApp); bool xTetrisApp::OnInit() { xTetrisFrame* frame = new xTetrisFrame(0L, _("wxWidgets Application Template")); frame->SetIcon(wxICON(aaaa)); // To Set App Icon frame->Show(); return true; }
xTetrisApp.cpp文件的代码如下。
这个文件的代码有点多,在这里就不再分析了,以后用到的地方将会逐步讲解。
#ifdef WX_PRECOMP #include "wx_pch.h" #endif #ifdef __BORLANDC__ #pragma hdrstop #endif //__BORLANDC__ #include "xTetrisMain.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; } BEGIN_EVENT_TABLE(xTetrisFrame, wxFrame) EVT_CLOSE(xTetrisFrame::OnClose) EVT_MENU(idMenuQuit, xTetrisFrame::OnQuit) EVT_MENU(idMenuAbout, xTetrisFrame::OnAbout) END_EVENT_TABLE() xTetrisFrame::xTetrisFrame(wxFrame *frame, const wxString& title) : wxFrame(frame, -1, title) { #if wxUSE_MENUS // create a menu bar wxMenuBar* mbar = new wxMenuBar(); wxMenu* fileMenu = new wxMenu(_T("")); fileMenu->Append(idMenuQuit, _("&Quit\tAlt-F4"), _("Quit the application")); mbar->Append(fileMenu, _("&File")); wxMenu* helpMenu = new wxMenu(_T("")); helpMenu->Append(idMenuAbout, _("&About\tF1"), _("Show info about this application")); mbar->Append(helpMenu, _("&Help")); SetMenuBar(mbar); #endif // wxUSE_MENUS #if wxUSE_STATUSBAR // create a status bar with some information about the used wxWidgets version CreateStatusBar(2); SetStatusText(_("Hello Code::Blocks user!"),0); SetStatusText(wxbuildinfo(short_f), 1); #endif // wxUSE_STATUSBAR } xTetrisFrame::~xTetrisFrame() { } void xTetrisFrame::OnClose(wxCloseEvent &event) { Destroy(); } void xTetrisFrame::OnQuit(wxCommandEvent &event) { Destroy(); } void xTetrisFrame::OnAbout(wxCommandEvent &event) { wxString msg = wxbuildinfo(long_f); wxMessageBox(msg, _("Welcome to...")); }
3.按着我的意愿对向导生成的文件进行修改
3.1修改主窗口标题
xTetrisApp.cpp文件中的字符串“wxWidgets Application Template”改为“多彩俄罗斯方块xTetris”。编译运行,你会发现程序主窗口标题没有显示汉字,而是看不懂的乱码。
为什么会这样呢?这字符串编码的问题。
你将原来代码中的(0L, _("wxWidgets Application Template"))改成(0L, _("多彩俄罗斯方块xTetris"))会显示乱码,而改成(0L, _T("多彩俄罗斯方块xTetris"))就能正常显示汉字了。
用同样的方法,你可以将xTetrisApp.cpp文件中的字符串修改一下,看一看效果。
例如:将SetStatusText(_("Hello Code::Blocks user!"),0)改为SetStatusText(_T("欢迎使用多彩俄罗斯方块!"),0)。
在修改SetStatusText(_("Hello Code::Blocks user!"),0)的时候你会发现,这一段创建和设置状态条的代码是灰色的。
显示成灰色表示CodeBlocks认为这一段代码在当前的设置下是不可用的。按着代码的字面意思,当定义wxUSE_STATUSBAR=0的时候这段代码不可用,而定义wxUSE_STATUSBAR=1则代码可用。
查找wxUSE_STATUSBAR的定义,在文件D:\CodeBlocks\wxWidgets-3.2.6\lib\gcc_lib\mswud\wx\setup.h中找到了以下代码,这证明这段代码应该是可用的,而CodeBlocks识别成了不可用。
是不是说这也是CodeBlocks的一个缺陷呢?
#define wxUSE_STATUSBAR 1
4.结束语
今天展示了在CodeBlocks中使用向导创建的应用程序。
向导建立的是一个应用程序的框架,今后将在这个框架中逐步添加更多的内容,最终形成一个有实际意义的应用程序。
在从一个无用的框架积累到一个有实际意义的应用程序的过程中,每一步都会掌握一个新的知识点。通过日积月累,积累编程的经验,掌握编程的技巧,从而为编写更好的应用程序打下良好的基础。