wxWidgets学习 (1) -- Hello World 详解
wxWidgets 是一個(gè)跨平臺(tái)的 C++ GUI 框架,和 qt 其實(shí)是一類東西。
簡單介紹一下wxWidgets的優(yōu)點(diǎn):
一、原生界面
wx 不像 java swing 這樣,在所有平臺(tái)都使用相同的外觀,也不像qt那樣靠模仿平臺(tái)外觀達(dá)到“以假亂真”的效果,wx就是對(duì)平臺(tái)API的封裝。
二、完全免費(fèi)
使用wxWidgets編寫軟件,不論是個(gè)人還是商業(yè)用途,都是完全免費(fèi)的,假如你修改了wxWidgets的代碼,則必須公開出來。
三、可移植性和發(fā)布
這兩點(diǎn)放在一起說,因?yàn)樗鼈兊墓餐c(diǎn)都是可以很方便的把程序拿到其他設(shè)備上使用。跨平臺(tái)就是一份代碼,不需要修改就能在其他平臺(tái)上編譯成可執(zhí)行文件運(yùn)行。發(fā)布方便是指可以編譯成單個(gè)可執(zhí)行文件并靜態(tài)鏈接,用戶只需下載一個(gè)exe,不需要附加一堆dll,也不需要什么特殊的運(yùn)行環(huán)境。我測試過編譯好的exe可以在win2003, xp, win7 和 win10運(yùn)行。
四、其他
wxWidgets相對(duì)其他框架來說可能比較小眾,但是不用擔(dān)心,wxWidgets社區(qū)非常活躍,github上托管的項(xiàng)目每天都會(huì)更新,也有非常棒的官方文檔。
缺點(diǎn):
環(huán)境部署比較麻煩,程序體積相對(duì)原生api編譯的程序大得多,沒有非常好用的可視化開發(fā)環(huán)境。
關(guān)于開發(fā)環(huán)境部署,這里不會(huì)詳細(xì)介紹,按照 官網(wǎng) 的教程來做就可以了,上面的步驟非常詳細(xì)。我用的是MinGW32位編譯器,wxWidgets 3.0.4版本,我的編譯指令是這樣的:
mingw32-make.exe -j4 -f makefile.gcc SHARED=0 MONOLITHIC=1 BUILD=release-j4 使用4個(gè)cpu,SHARED=0 是靜態(tài)鏈接。
下面步入正題,Hello World 程序的分析。
Hello world 例程是官方教程里的第一個(gè)程序,可以作為以后編寫其他程序的框架。
下面是使用32位mingw編譯的同一個(gè)exe(7MB)在不同版本windows上運(yùn)行的結(jié)果
官方例程 Hello world 詳解
首先,必須包含wxWidgets的頭文件,可以只包含用到的類,也可以像新手教程那樣包含wx/wx.h這個(gè)頭文件,它內(nèi)部包含了大多數(shù)常用的頭文件。在支持預(yù)編譯的系統(tǒng)上,可以使用wx/wxprec.h加快編譯速度。
#include <wx/wxprec.h> #ifndef WX_PRECOMP #include <wx/wx.h> #endif // WX_PRECOMP創(chuàng)建一個(gè)wxWidgets的第一步,是派生wxApp類,并重寫OnInit函數(shù)
class MyApp : public wxApp { public:virtual bool OnInit(); };接下來,創(chuàng)建主窗口類,從 wxFrame 派生出子類。主窗口有菜單按鈕,底部狀態(tài)欄。在窗口類里聲明了構(gòu)造函數(shù)和三個(gè)菜單的點(diǎn)擊事件。wxDECLARE_EVENT_TABLE 是一個(gè)宏,聲明這個(gè)宏使得主窗口能夠響應(yīng)“事件”(比如鼠標(biāo)雙擊按鈕或點(diǎn)擊菜單)。
class MyFrame : public wxFrame { public:// 構(gòu)造函數(shù)設(shè)置標(biāo)題、窗口坐標(biāo),窗口尺寸MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);private:// 響應(yīng)菜單點(diǎn)擊事件void OnHello(wxCommandEvent &event);void OnExit(wxCommandEvent &event);void OnAbout(wxCommandEvent &event);// 聲明這個(gè)宏會(huì)創(chuàng)建一個(gè)類內(nèi)的靜態(tài)事件表(static event table)// 在實(shí)現(xiàn)文件中,使用 wxBEGIN_EVENT_TABLE 和 wxEND_EVENT_TABLE 宏// 添加一些 EVT_xxx 宏來捕獲事件wxDECLARE_EVENT_TABLE(); };關(guān)于事件綁定的一點(diǎn)疑問:我在其他教程里了解到,可以用 Bind 函數(shù)為控件綁定事件,類似這樣
button->Bind(wxEVT_BUTTON, &MyApp::on_button_clicked(), this);
但是我在自己的開發(fā)環(huán)境里嘗試這樣做卻報(bào)錯(cuò)了,說是找不到這個(gè)函數(shù),即使使用最新版wxWidgets也是如此,不知道原因。
下一步,為了響應(yīng)菜單事件,必須給每個(gè)菜單指定一個(gè)獨(dú)一無二的“ID”
const int ID_Hello = 1; // Hello 菜單的ID,必須是唯一的值另外兩個(gè)菜單分別是“退出”和“幫助”,這兩個(gè)是默認(rèn)菜單,無需指定ID,使用默認(rèn)的即可。
有了控件ID,就可以實(shí)現(xiàn)事件表(event table)了
這些宏的作用是把三個(gè)菜單各自的點(diǎn)擊事件轉(zhuǎn)發(fā)(routed)到主窗口類 MyFrame 中定義的處理函數(shù)中。
所有常用的事件都有預(yù)定義的宏,如 EVT_MENU。如果控件ID設(shè)置為 wxID_ANY 則處理函數(shù)會(huì)被調(diào)用,不論點(diǎn)擊的是哪個(gè)菜單。
wxWidgets的主函數(shù)在 wxIMPLEMENT_APP 宏內(nèi)調(diào)用
wxIMPLEMENT_APP(MyApp);接下來是先前定義的成員函數(shù)的實(shí)現(xiàn)
/** 函數(shù)實(shí)現(xiàn)部分 **/// OnInit的主要工作是創(chuàng)建主窗口 bool MyApp::OnInit() {// 創(chuàng)建 MyFrame 窗口,設(shè)置標(biāo)題,窗口位置,窗口大小MyFrame *frame = new MyFrame("Hello world", wxPoint(50,50), wxSize(450, 340));frame->Show(true); // 顯示窗口return true; // 返回true表示繼續(xù)進(jìn)程,false表示立即終止程序 }// 主窗口構(gòu)造函數(shù),調(diào)用 wxFrame 構(gòu)造函數(shù)時(shí)第一個(gè)參數(shù)是空指針,表示沒有父窗口 MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size): wxFrame(nullptr, wxID_ANY, title, pos, size) {wxMenu *menuFile = new wxMenu; // File 菜單// File菜單添加Hello子菜單,支持ALT+H加速鍵和CTRL+H快捷鍵menuFile->Append(ID_Hello,"&Hello...\tCtrl-H","光標(biāo)移動(dòng)到Hello菜單上底部狀態(tài)欄顯示的文字");menuFile->AppendSeparator(); // 水平分割線menuFile->Append(wxID_EXIT); // 退出子菜單wxMenu *menuHelp = new wxMenu; // Help 菜單menuHelp->Append(wxID_ABOUT); // “關(guān)于”子菜單wxMenuBar *menuBar = new wxMenuBar; // 菜單欄控件menuBar->Append(menuFile, "&File");menuBar->Append(menuHelp, "&Help");SetMenuBar(menuBar); // 設(shè)置菜單欄CreateStatusBar(); // 創(chuàng)建底部狀態(tài)欄SetStatusText("歡迎使用 wxWidgets!"); // 設(shè)置狀態(tài)欄文字 }void MyFrame::OnExit(wxCommandEvent &event) {Close(true); // 關(guān)閉主窗口,true表示無需詢問,如果沒有其他主窗口,應(yīng)用程序?qū)⑼顺?}// 點(diǎn)擊“關(guān)于”,彈出消息對(duì)話框 void MyFrame::OnAbout(wxCommandEvent &event) {wxMessageBox("This is a wxWidgets's Hello world sample","About Hello World",wxOK | wxICON_INFORMATION); }// 點(diǎn)擊Hello菜單,彈出日志對(duì)話框 void MyFrame::OnHello(wxCommandEvent &event) {wxLogMessage("Hello world from wxWidgets!"); }以上是 Hello world 的全部內(nèi)容,我個(gè)人感覺這個(gè)框架相比直接擼Windows API 還是簡單多了。
下面是 Hello world 完整代碼
總結(jié)
以上是生活随笔為你收集整理的wxWidgets学习 (1) -- Hello World 详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ const对象仅在文件内有效
- 下一篇: wxWidgets学习 (2) -- 事