标签:
本教程由Gxl117翻译并将继续维护,这是本教程的第一稿,假设发现错误请与我(Email:gxl117@yahoo.com.cn)联系让我能及时修正它。之后还会对这个教程进行很多其它的扩充,欢迎广大网友提供意见。
本教程遵循GPL协议公布。
本许可授权你制作和公布本教程的拷贝,但在所有拷贝上要保留本版权声明和许可声明。
假设你准备出版本号文档,请告之译者,以确保你获得本文档的最新版本号。
对本文档的适用范围不作担保,它不过作为一个免费的资源提供。因此,这里提供的这些信息的作者和维护者无法做出这些信息一定正确的保证。
Copyright © 2001-2002 Franky Braem
You are allowed to copy and to print this book as long as you don‘t exploit the information commercially. The author of this book makes no warranty of any kind, expressed or implied, with regard to the programs or the documentation contained in this book.
文件夹
List of Figures
List of Tables
List of Examples
Table of Contents
你希望使用C++编写的同一个程序能够执行在 Windows, Linux 或者 Unix上吗? 当每个平台都有它们自己的framework,外观、行为或者SDK时,这差点儿是不可能的。当然你也肯定不想为每个平台都重写你的程序,这将是极难维护的。
wxWindows是一个解决方式。wxWindows为你隐藏了所有平台相关的代码。它是一个与平台无关的framework,它有例如以下特点:
它是非常全面的,拥有非常多有用的类。It is very complete. There are many utility classes.
它仍然在高速的发展中。It is still heavily developed.
支持非常多的编译器与平台: Windows, Linux, Mac, Unix.
拥有大量的文档。There‘s a lot of documentation.
个人与商业机构都能够自由的使用它。It‘s free for personal and commercial use.
只要可能wxWindows就使用本地SDK。这表示假设一个程序是在Windows下编译的将有典型的windows程序的外观与行为, 当它在Linux下编译时它将拥有linux程序的外观与行为。
Julian Smart 1992年在Edinburgh大学的人工智能程序学院開始开发wxWindows。在1995年 Markus Holzem完毕了Xt版本号的移植。在1997年Windows 和 GTK+ 的移植版整合并放入了 CVS 档案库.
这第一个样例是众所周知的Hello World程序。这个程序是一个在状态栏里显示"Hello World"的窗体。
每个wxWindow程序都要有一个继承自wxApp的对象。每个程序都要用OnInit()方法来实例化,你能够在这创建主窗体。 例 1.4 是 HelloWorldApp的定义:
Example 1.4. HelloWorldApp.h - The HelloWorldApp definition
#ifndef INCLUDED_HELLOWORLDAPP_H #define INCLUDED_HELLOWORLDAPP_H /** * HelloWorldApp类 * 这个类显示一个状态栏中包括文本"Hello World"的窗体 */ class HelloWorldApp : public wxApp { public: virtual bool OnInit(); }; DECLARE_APP(HelloWorldApp) #endif // INCLUDED_HELLOWORLDAPP_H
对于主窗体我们使用wxFrame类。这个类提供了一个能够调整大小与位置的窗体。它有粗的边框与一个标题栏。另外你能够让它有一个菜单条、工具栏、状态栏。例 1.5 是HelloWorldApp的实现.
例 1.5. HelloWorldApp.cpp - HelloWorldApp的实现
//对支持预编译编译器要包括"wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "HelloWorldApp.h" IMPLEMENT_APP(HelloWorldApp) /* 程序从这里開始运行,相似非wxWindows程序中的main() */ bool HelloWorldApp::OnInit() { wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, _T("Hello World")); frame->CreateStatusBar(); frame->SetStatusText(_T("Hello World")); frame->Show(TRUE); SetTopWindow(frame); return true; }
当你的编译器支持预处理器时,你能够使用wxprec头文件。当它不支持时,你应该包括wx.h,它包括了全部必须的wxWindows头文件。你相同也能够为每个控件分别包括相相应的头文件。(译者注:在Linux之下使用wxFrame的构造函数对当中的字符串要使用wxChar进行显式转换,对于多字节字符的支持能够使用宏wxT(string)来解决)
宏 DECLARE_APP 和 IMPLEMENT_APP 为我们作下列操作:
当平台须要时,它创建一个 main() 或者 WinMain() 方法。
它建立一个全局方法 wxGetApp(). 你能够使用这个函数去得到一个程序对象的引用:
你可能会奇怪为什么在程序的不论什么地方都没有删除frame变量的代码。由于frame被设置为程序的顶层窗体所以程序将在退出时自己主动的删除 frame。
有一些糟糕的编译器不同意NULL隐式的转换到wxFrame*,所以这就是我们为什么要显示的作它,不过出于稳妥的考虑(不过假设你真的在使用这种编译器的话,我建议你还是更新它吧)。 同一时候这样作也更有利于程序的移植。
在frame建立之后,使用CreateStatusBar来创建一个状态栏。状态栏的文字内容设置为"Hello World".调用show()来显示frame。Show()是一个wxFrame从wxWindow类继承的方法。
当OnInit返回false时,程序将马上停止。假设在程序初始化期间一些事情发生了错误,你能够利用它来停止程序。
文件夹
wxFrame类提供给我们一个框架窗体。框架窗体是一个能够改变大小的窗体,它有粗的边框与一个标题栏。另外你能够让它有一个菜单条、工具栏、状态栏。框架能够作为其他控件的窗体器,但不能包括还有一个窗体或对话框。wxFrame是从wxWindow类派生来的。
在这一章里我们将创建一个小小的文本编辑器。
通常你能够通过继承wxFrame来创建你自己的类。这样你能够向你自己的frame类中加入功能。 例2.1 就是这样作的,它的实如今例 2.2中。
#ifndef _TEXTFRAME_H #define _TEXTFRAME_H class TextFrame : public wxFrame { public: /** * 构造函数. 用来创建新的TextFrame */ TextFrame(const wxChar *title, int xpos, int ypos, int width, int height); /** * 析构函数 */ ~TextFrame(); }; #endif //_TEXTFRAME_H
TextFrame的构造函数继承自wxFrame的构造函数。
例 2.2. TextFrame 的实现
// 对支持预编译编译器要包括"wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "TextFrame.h" TextFrame::TextFrame(const wxChar *title, int xpos, int ypos, int width, int height) : wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height)) { } TextFrame::~TextFrame() { }
wxFrame(wxWindow* parent,
wxWindowId id,
const wxString& title,
const wxPoint& pos= wxDefaultPosition,
const wxSize& size= wxDefaultSize,
long style= wxDEFAULT_FRAME_STYLE,
const wxString& name= "frame");
parent 是一个指向父窗体的指针,当框架没有父窗体时使用NULL。
id 是唯一的窗体标识号,当你不须要它时使用-1.
title 是框架的标题,它将显示在框架的标题栏中。
pos 是框架的位置。WxDefaultPosition表示默认值。
size 是框架的大小。 WxDefaultSize?硎臼褂媚现怠?
style 是框架的风格。
表 2.1. wxFram风格
wxDEFAULT_FRAME_STYLE | wxMINIMIZE_BOX, wxMAXIMIZE_BOX, wxRESIZE_BOX, wxSYSTEM_MENU 和 wxCAPTION的组合。 |
wxICONIZE | 以最小化方式显示窗体(仅用于windows) |
wxCAPTION | 显示标题 |
wxMINIMIZE | 与wxICONIZE同样 |
wxMINIMIZE_BOX | 框架将有一个最小化button |
wxMAXIMIZE | 框架以最大化方式显示(仅用于windows) |
wxMAXIMIZE_BOX | 框架将有一个最大化button |
wxSTAY_ON_TOP | 框架将位于其他窗体的上层(仅用于windows) |
wxSYSTEM_MENU | 框架拥有一个系统菜单。 |
wxSIMPLE_BORDER | 显示一个没有边框的框架(仅用于GTK与Windows) |
wxRESIZE_BORDER | 显示一个可调整大小的边框(仅用与Unix) |
wxFRAME_FLOAT_ON_PARENT | The frame will be above the parent window in the z-order and is not shown in the task bar. (Windows and GTK only) |
wxFRAME_TOOL_WINDOW | 显示一个小的标题栏(仅用于Windows) |
name 是窗体的名字。这个參数是用来将一个条目与一个名称相关联的。这同意用户去为每一个窗体设置Motif资源值。
2.3. TextEditorApp.h - TextEditorApp 的定义
#ifndef TEXTEDITORAPP_H #define TEXTEDITORAPP_H class TextEditorApp : public wxApp { public: /** * 程序初始化 */ virtual bool OnInit(); }; DECLARE_APP(TextEditorApp) #endif // TEXTEDITORAPP_H
例 2.4. TextEditorApp.cpp - TextEditorApp 的实现
// 对支持预编译编译器要包括"wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "TextEditorApp.h" #include "TextFrame.h" IMPLEMENT_APP(TextEditorApp) bool TextEditorApp::OnInit() { TextFrame *frame = new TextFrame("Simple Text Editor", 100, 100, 400, 300); frame->Show(TRUE); SetTopWindow(frame); return true; }
如今已经创建了一个窗体框架,你须要加入一些控件来处理文本。类wxTextCtrl将是我们所须要的。框架类已经包括了这个控件。
例 2.5 是一个新的TextFrame类的定义。仅仅有一件事是改变的,它加入了一个wxTextCtrl类型的成员。这个成员是在构造函数中初始化的。
例 2.5. TextFrame 的又一次定义
#ifndef _TEXTFRAME_H #define _TEXTFRAME_H class TextFrame : public wxFrame { public: /** * 构造函数. 用来创建新的TextFrame */ TextFrame(const wxChar *title, int xpos, int ypos, int width, int height); /** * 析构函数 */ ~TextFrame(); private: wxTextCtrl *m_pTextCtrl; };
#endif //_TEXTFRAME_H
例 2.6 是更新后的TextFraem类的构造函数。TextFrame是wxTextCtrl成员的父类。所以你应该传递this指针。字符串"Type some text..."将作为默认的文本。注意wxTextCtrl的构造函数看上去与wxFrame的相仿。这是由于每个类都是从wxWindow继承来的所以有同样的构造函数模式。
另外,这里没有删除wxTextCtrl指针的代码。这里不须要它(实际上是不同意),由于当父类TextFrame撤消时它的全部子类都会自己主动的删除。
wxTE_MULTILINE 是文本控件专用的窗体风格。这样的风格表示wxTextCtrl同意多行。
例2.6.TextFrame 的实现
// 对支持预编译编译器要包括"wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "TextFrame.h" TextFrame::TextFrame(const wxChar *title, int xpos, int ypos, int width, int height) : wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height)) { m_pTextCtrl = new wxTextCtrl(this, -1, wxString("Type some text..."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); } TextFrame::~TextFrame() { }
当你 build 这个项目时,你将拥有一个能够输入一些文本的窗体,你能够尝试在这个窗体中剪切、粘贴文本,你将会出现这些短短的代码已经为你作非常多事了。
通常,我们总向自己的程序加入菜单条来帮助用户操作程序, wxWindows 为菜单条提供了以下的类:wxMenuBar 和 wxMenu.
每个菜单都须要一个独立的ID。这是通过一个枚举类型来完毕的。而不能使用#define定义的常量(比方:#define MENU_FILE_MENU 1)由于这不能保证你有独一无二的ID。它十分easy漏掉一些值而且当你想插入新的ID时这会变的十分难以维护。
请參考wxWindows 手冊, wxWin 提前定义了一些你在使用文档/视图 framework 时会用到的ID。
#ifndef _TEXTFRAME_H #define _TEXTFRAME_H class TextFrame : public wxFrame { public: /** * Constructor. Creates a new TextFrame */ TextFrame(const wxChar *title, int xpos, int ypos, int width, int height); /** * Destructor */ ~TextFrame(); private: wxTextCtrl *m_pTextCtrl; wxMenuBar *m_pMenuBar; wxMenu *m_pFileMenu; wxMenu *m_pInfoMenu; enum { MENU_FILE_OPEN, MENU_FILE_SAVE, MENU_FILE_QUIT, MENU_INFO_ABOUT }; }; #endif //_TEXTFRAME_H
菜单条是在TextFrame的构造函数中创建的。一个菜单项是使用wxMenu的Append方法加入到菜单中的。要注意&号是怎样指出哪个字符是快捷键的。当菜单创建后你还要使用wxMenuBar的Append方法把它加入到菜单条。
// For compilers that supports precompilation , includes "wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "TextFrame.h" TextFrame::TextFrame(const wxChar *title, int xpos, int ypos, int width, int height) : wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height)) { m_pTextCtrl = new wxTextCtrl(this, -1, wxString("Type some text..."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); m_pMenuBar = new wxMenuBar(); // File Menu m_pFileMenu = new wxMenu(); m_pFileMenu->Append(MENU_FILE_OPEN, "&Open"); m_pFileMenu->Append(MENU_FILE_SAVE, "&Save"); m_pFileMenu->AppendSeparator(); m_pFileMenu->Append(MENU_FILE_QUIT, "&Quit"); m_pMenuBar->Append(m_pFileMenu, "&File"); // About menu m_pInfoMenu = new wxMenu(); m_pInfoMenu->Append(MENU_INFO_ABOUT, "&About"); m_pMenuBar->Append(m_pInfoMenu, "&Info"); SetMenuBar(m_pMenuBar); } TextFrame::~TextFrame() { }
为框架加入一个状态栏是非常easy的。使用wxFrame类中的CreateStatusBar方法来创建状态栏,它接受一个整形參数作为状态栏中的区域个数,使用SetStatusText方法来改变各域中的文本内容。
CreateStatusBar(3); SetStatusText("Ready", 0);
Example 2.9 创建一个有三个域的状态栏。第一个域包括文本"Ready"。
状态栏可用来显示对一个菜单项的描写叙述。例2.10对上一节中的向菜单条中加入菜单项的例2.8作了更改,以使菜单项与状态栏关联。当一个菜单项被选择时,相关的描写叙述就会显示在状态栏的第一个域中。
例2.10包括功能描写叙述的菜单项
// 文件菜单
m_pFileMenu = new wxMenu();
m_pFileMenu->Append(MENU_FILE_OPEN, "&Open", "Opens an existing file");
m_pFileMenu->Append(MENU_FILE_SAVE, "&Save", "Save the content");
m_pFileMenu->AppendSeparator();
m_pFileMenu->Append(MENU_FILE_QUIT, "&Quit", "Quit the application");
m_pMenuBar->Append(m_pFileMenu, "&File");
// 关于菜单
m_pInfoMenu = new wxMenu();
m_pInfoMenu->Append(MENU_INFO_ABOUT, "&About", "Shows information about the application");
m_pMenuBar->Append(m_pInfoMenu, "&Info");
如今frame上已经有了菜单,当用户选择一个菜单时我们要用一种方法来实现它的对应动作。每选择一个菜单都会产生一个事件。怎样让一个动作与这个事件相关联呢?一个技巧就是将一个类的方法与事件相关联。在wxWindows的早期版本号中这是通过使用回调函数或者通过重载虚拟函数来实现的。从wxWindows2.0開始改为使用事件表。在这一节里我们仅解释通过菜单产生的事件。关于事件处理的具体过程我们将在第三章解释。
要处理事件的每一个类都须要声明一个事件表。宏DECLARE_EVENT_TABLE用来完毕这项工作。每一个事件都必须有一个已经实现了的方法。每一个方法都有一个參数用来包括事件的信息。从菜单获得的事件是一个wxCommandEvent类型的数据。例2.11是类TextFrame的完整定义。
#ifndef _TEXTFRAME_H #define _TEXTFRAME_H class TextFrame : public wxFrame { public: /** * Constructor. Creates a new TextFrame */ TextFrame(const wxChar title, int xpos, int ypos, int width, int height); /** * Destructor */ ~TextFrame(); /** * Processes menu File|Open */ void OnMenuFileOpen(wxCommandEvent &event); /** * Processes menu File|Save */ void OnMenuFileSave(wxCommandEvent &event); /** * Processes menu File|Quit */ void OnMenuFileQuit(wxCommandEvent &event); /** * Processes menu About|Info */ void OnMenuInfoAbout(wxCommandEvent &event); protected: DECLARE_EVENT_TABLE() private: wxTextCtrl *m_pTextCtrl; wxMenuBar *m_pMenuBar; wxMenu *m_pFileMenu; wxMenu *m_pInfoMenu; enum { MENU_FILE_OPEN, MENU_FILE_SAVE, MENU_FILE_QUIT, MENU_INFO_ABOUT }; }; #endif //_TEXTFRAME_H
事件表是放在实现文件里的,wxWindows通过一些宏来帮助的完毕事件表的声明。宏BEGIN_EVENT在事件表声明的開始处使用,由于在一个程序中可能不止一个事件表,要将事件处理过程相关的类名传递给宏。将一个方法与事件关联要使用EVT_MENU宏。这个宏须要菜单ID与事件名。在事件表的最后用宏END_EVENT_TABLE作结束标记。例2.12显示了完整的实现文件。
Example 2.12. TextFrame.cpp - The full implementation
// For compilers that supports precompilation , includes "wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "TextFrame.h" TextFrame::TextFrame(const wxChar *title, int xpos, int ypos, int width, int height) : wxFrame((wxFrame *) NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height)) { m_pTextCtrl = new wxTextCtrl(this, -1, wxString("Type some text..."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); CreateStatusBar(); m_pMenuBar = new wxMenuBar(); // File Menu m_pFileMenu = new wxMenu(); m_pFileMenu->Append(MENU_FILE_OPEN, "&Open", "Opens an existing file"); m_pFileMenu->Append(MENU_FILE_SAVE, "&Save", "Saves the file"); m_pFileMenu->AppendSeparator(); m_pFileMenu->Append(MENU_FILE_QUIT, "&Quit, "Close the application"); m_pMenuBar->Append(m_pFileMenu, "&File"); // About menu m_pInfoMenu = new wxMenu(); m_pInfoMenu->Append(MENU_INFO_ABOUT, "&About", "Shows info about the application"); m_pMenuBar->Append(m_pInfoMenu, "&Info"); SetMenuBar(m_pMenuBar); } TextFrame::~TextFrame() { } BEGIN_EVENT_TABLE(TextFrame, wxFrame) EVT_MENU(MENU_FILE_OPEN, TextFrame::OnMenuFileOpen) EVT_MENU(MENU_FILE_SAVE, TextFrame::OnMenuFileSave) EVT_MENU(MENU_FILE_QUIT, TextFrame::OnMenuFileQuit) EVT_MENU(MENU_INFO_ABOUT, TextFrame::OnMenuInfoAbout) END_EVENT_TABLE void TextFrame::OnMenuFileOpen(wxCommandEvent &event) { wxLogMessage("File Open Menu Selected"); } void TextFrame::OnMenuFileSave(wxCommandEvent &event) { wxLogMessage("File Save Menu Selected"); } void TextFrame::OnMenuFileQuit(wxCommandEvent &event) { Close(FALSE); } void TextFrame::OnMenuInfoAbout(wxCommandEvent &event) { wxLogMessage("File About Menu Selected"); }
文件夹
在上一章里已经学习了怎样处理菜单事件。这章将解释事件处理是怎样工作的,同一时候解释了怎样去处理其他事件。
事件是出如今程序内部或外部的一些事情。一个事件可能是通过用户或是其他程序、操作系统等来触发的。这时须要一个机制来让程序对期望的事件产生反应。
在wxWindows的早期版本号中,程序的事件处理是全然通过回调函数或者重载虚拟函数来实现的。从wxWindows2.0開始转而使用事件表了。如例3,事件表告诉wxWindows将事件映射到成员函数。事件表是在实现文件(cpp)中声明的。
BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(wxID_EXIT, MyFrame::OnExit) EVT_SIZE(MyFrame::OnSize) EVT_BUTTON(BUTTON1, MyFrame::OnButton1) END_EVENT_TABLE()
上面的事件表告诉wxWindows当它接收到一个WM_SIZE事件时调用MyFrame的成员函数OnSize。 宏 BEGIN_EVENT_TABLE 声明wxFrame和它的子类MyFrame拥有这个事件表。
处理事件的成员函数不能是虚拟的。实际上事件处理器将忽略虚拟声明。事件处理函数有相似的形式:返回类型为void而且接受一个事件參数。这个參数的类型与详细的事件相关。对于size事件,使用的类型是wxCommandEvent。当控件变的更复杂时它们使用自己的事件类。
在类定义中,必须有一个DECLARE_EVENT_TABLE宏。參见例2.11。
全部这些宏隐藏了复杂的事件处理系统。
当接收到一个事件时,wxWindows首先调用窗体上产生事件的对象上的wxEventHandler的ProcssEvent处理器。wxWindow(和其他的窗体类)继承自wxEventHander。ProcessEvent查找事件表里的每个事件而且调用零或多个事件处理器函数。以下是处理一个事件的步骤:
当对象关闭时(包含wxEvtHandler的SetEvtHandle)函数跳转到第六步。
假设对象是一个wxWindow对象,ProcessEvent在窗体的wxValidator上递归调用。假设返回真函数退出。
SearchEventTable是事件处理器调用的函数。当它失败时,開始在基类 上尝试直到没有很多其他的事件表或者发现了一个合适的函数时这个函数退出。被发现的函数開始运行。
查找过程应用于整个事件处理器链,当应用成功时(表示事件处理完成)函数退出。
当对象是一个wxWindow对象时,而且事件为wxCommandEvent类型时,ProcessEvent向上递归应用于父窗体的事件处理器。当它返回真,函数退出。这能够让一个button的父亲来处理button的点击而不是让button自己来处理。
最后ProcessEvent 在wxApp对象上调用。
ProcessEvent在发现一个能够处理事件的函数后退出。这表示当你的类对一个事件起反应时,下层的类不会得到这个事件。有时我们不希望这样。这个问题能够依据基类的事件类型用wxEvent类的Skip方法来解决,使事件处理器的查找继续进行。
以下的样例展示了事件跳转的用处。例3.2是一个文本控件的定义,它仅仅接受数字字符。
class NumTextCtrl : public wxTextCtrl
{
public:
NumTextCtrl(wxWindow *parent);
void OnChar(wxKeyEvent& event);
protected:
DECLARE_EVENT_TABLE()
};
当NumericTextCtrl接收到一个键盘事件时,就进行keycode检查。假设输入的是数字,基类wxTextCtrl就能够处理这个事件。这就是我们要对?飧鍪录褂锰脑颉D惚匦朐谡獾饔?Skip方法,否则基类不会处理不论什么键。
// For compilers that supports precompilation , includes "wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "NumTextCtrl.h" #include <ctype.h> NumTextCtrl::NumTextCtrl(wxWindow *parent) : wxTextCtrl(parent, -1) { } void NumTextCtrl::OnChar(wxKeyEvent& event) { if ( isdigit(event.GetKeyCode()) ) { // Numeric characters are allowed, so the base class wxTextCtrl // is allowed to process the event. This is done using the Skip() method. event.Skip(); } else { // Character is not allowed. wxBell(); } } BEGIN_EVENT_TABLE(NumTextCtrl, wxTextCtrl) EVT_CHAR(NumTextCtrl::OnChar) END_EVENT_TABLE()
一些事件是能够禁止的。当你禁止一个事件时,这个事件不会被进一步处理。例3.4演示了,当一个文本控件内的文本改变后怎样禁止这个简单文本编辑器的关闭事件。这表示当在用户还没有保存改变后的文本内容时这个窗体不能被关闭。
void TextFrame::OnClose(wxCloseEvent& event) { bool destroy = true; if ( event.CanVeto() ) { if ( m_pTextCtrl->IsModified() ) { wxMessageDialog *dlg = new wxMessageDialog(this, "Text is changed!/nAre you sure you want to exit?", "Text changed!!!", wxYES_NO | wxNO_DEFAULT); int result = dlg->ShowModal(); if ( result == wxID_NO ) { event.Veto(); destroy = false; } } } if ( destroy ) { Destroy(); }
当CanVeto返回false时程序作什么呢?你将不能禁止这个事件你的程序将会退出。
考虑以下的问题:每一个菜单命令都必须被记录。一个解决方式是创建一个在每一个命令事件处理函数中调用的函数。这样的方法带来的问题是使维护变得十分困难。当加入一个新的菜单而且没有调用这个函数时,这个菜单命令将不被记录。
解决问题是去创建一个新的事件处理器并加入到一个wxWindow类。要完毕它须要创建一个从wxEvtHandler派生的新类。在新类中处理事件与一个正常的窗体是同样的。
例 3.5. LogEventHandler.h -LogEventHandler的定义
#ifndef _LogEventHandler_H #define _LogEventHandler_H class LogEventHandler : public wxEvtHandler { public: LogEventHandler() : wxEvtHandler() { } virtual ~LogEventHandler() { } protected: DECLARE_EVENT_TABLE() void OnMenu(wxMenuEvent &event); private: }; #endif // _LogEventHandler_H
例3.6. LogEventHandler.cpp - LogEventHandler的实现
// For compilers that supports precompilation , includes "wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "LogEventHandler.h" void LogEventHandler::OnMenu(wxMenuEvent &event) { wxLogMessage("Someone selected a menu item"); event.Skip(); } BEGIN_EVENT_TABLE(LogEventHandler, wxEvtHandler) EVT_MENU_RANGE(-1, -1, LogEventHandler::OnMenu) END_EVENT_TABLE()
在宏EVT_MENU_RANGE里,全部的菜单事件都能够被处理。前两个參数用来指定要处理的菜单的ID范围。-1表示处理全部的菜单项。不要忘记在事件上调用Skip,否则不会有不论什么事件传递到类wxWindow的事件处理器。
下一步是把新的事件处理器压入处理器栈。这是使用wxWindow的PushEventHandler来完毕的?R诱簧弦瞥录砥魇褂?PopEventHandler。
PushEventHandler(new LogEventHandler());
PopEventHandler 有一个布尔类型的參数,当这个參数为真时,wxWindows删除事件处理器。注意在没有事件处理器被取出时,wxWndows将在窗体撤消时尝试删除事件处理器。这在訪问在栈上创建的事件处理器时会发生一个訪问错误。能够在一个类撤消之前调用使用false參数的PopeventHandler来避免这个问题。
Table of Contents
在第二章的样例中有打开与存储一个文本文件的菜单命令。这时要使用一个通用对话框wxFileDialog来让用户选择或者输入一个文件名称。在使用通用对话框时,用户得到一个统一的界面。这能够让用户无论在什么样的程序中都能够看到相似的对话框。
wxWindows提供了下列通用对话框。
wxFileDialog 一个存储或打开文件的对话框。
wxColourDialog 一个选择颜色的对话框。
wxFontDialog 选择字体的对话框。
wxPrintDialog 用于打印与设置打印机的对话框。
wxDirDialog 选择文件夹的对话框。
wxTextEntryDialog 请求用户输入一行文本的对话框。
wxMessageDialog 用于显示一行或多行信息,可包括OK,Yes,No,与Cancelbutton。
wxSingleChoiceDialog 显示一个包括字符串列表的对话框,而且同意用户选择当中一个。
wxWindows 是交叉平台的FrameWork。当一个通用对话框在某个特别的平台上不能使用时,wxWindow将显示一个一般对话框。
在以下的每个对话框的样例中,将使用Destroy方法来取代用删除指针的方法来撤消窗体。这是为了稳定的目的。WxWindows控件应该总是在堆上创建而且使用Destroy方法来安全的移除。由于wxWindows有时会延迟删除,直到全部事件都被处理完毕。这样wxWindows能够避免将事件发送到一个不存在的窗体上。
wxFileDialog 为用户提供一个当用户在打开或者储存一个文件时能够选择或者输入文件名称的对话框。一个全局方法wxFileSelector相同能够用来让用户选择一个文件。详情请看章节 “wxFileSelector”. .
#include <wx/filedlg.h>
wxFileDialog(wxWindow* parent,
const wxString& message= "Choose a file",
const wxString& defaultDir= "",
const wxString& defaultFile= "",
const wxString& wildcard= "",
long style= 0,
const wxPoint& pos= wxDefaultPosition);
parent 拥有这个对话框的窗体。
message 对话框的标题。
defaultDir 默认文件夹。
defaultFile 默认文件名称。
wildcard 是一些相似 "*.*" or "*.txt"之类的字符串。这是用来过滤文件的。它的语法为 描写叙述|后缀。例 "All files(*.*)|*.*|Text files(*.txt)|*.txt|Bitmap files(*.bmp)|*.bmp".
style 对话框的类型。
表 4.1. wxFileDialog 风格
wxCHANGE_DIR | 改变当前文件夹 |
wxFILE_MUST_EXIST | 输入的文件必须存在 |
wxHIDE_READONLY | 隐藏仅仅读文件 |
wxMULTIPLE | 仅仅是一个打开对话框,允?硌≡穸喔鑫募? |
wxOPEN | 仅仅是一个打开对话框。 |
wxOVERWRITE_PROMPT | 当一个文件将被覆写时询问已确定。 |
wxSAVE | 一个保存对话框。 |
pos 没有使用。
public void SetDirectory(const wxString& dir);
public wxString GetDirectory();
设置与得到当前文件夹
public void SetFilename(const wxString& name);
public wxString GetFilename();
设置与得到当前文件名称
public const void GetFilenames(wxArrayString& files);
使用所选择的文件名称来添充文件名称数组。这个函数仅仅用于wxMULTIPLE风格的对话框。其他的使用GetFilename。
public void SetFilterIndex(int filterIndex);
public int GetFilterIndex();
设置与得到给出的过滤器列表的索引。在对话框显示之前,这个索引决定对话框显示时首先使用的过滤器。在显示之后这个索引由用户选择。
public void SetMessage(const wxString& message);
public wxString GetMessage();
设置与等到新的对话框标题。
public void SetPath(const wxString& path);
public wxString GetPath();
设置与得到当前路径(文件夹与文件名称)
public void SetStyle(long style);
public long GetStyle();
设置与得到对话框的风格,參看“Constructor”
public void GetPaths(wxArrayString& paths);
用所选择的文件绝对路径名来填充路径数组。这个函数仅仅用于wxMULTIPLE风格的对话框。其他的使用GetPath。
public void SetWildcard(const wxString& wildCard);
public wxString GetWildcard();
设置与得到wildcard參见“Constructor”. .
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
在第二章的文本编辑器样例中,使用ShowModal来显示一个对话框。”Modal”表示在对话框关闭之前程序的其他窗体不能得到焦点。使用ShowModal 显示对话框时,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。 GetFilename 是用来得到选择的文件的文件名称。GetPath 将返回所选择文件的完整路径(文件夹与文件名称)。在使用wxTextCtrl控件时载入与保存文件是很easy的。方法 LoadFile 和 SaveFile分别用于载入与保存文件。
例 4.1. wxFileDialog的使用
void TextFrame::OnMenuFileOpen(wxCommandEvent &event) { wxFileDialog *dlg = new wxFileDialog(this, "Open a text file", "", "", "All files(*.*)|*.*|Text Files(*.txt)|*.txt", wxOPEN, wxDefaultPosition); if ( dlg->ShowModal() == wxID_OK ) { m_pTextCtrl->LoadFile(dlg->GetFilename()); SetStatusText(dlg->GetFilename(), 0); } dlg->Destroy(); } void TextFrame::OnMenuFileSave(wxCommandEvent &event) { wxFileDialog *dlg = new wxFileDialog(this, "Save a text file", "", "", "All files(*.*)|*.*|Text Files(*.txt)|*.txt", wxSAVE, wxDefaultPosition); if ( dlg->ShowModal() == wxID_OK ) { m_pTextCtrl->SaveFile(dlg->GetPath()); SetStatusText(dlg->GetFilename(), 0); } dlg->Destroy(); }
wxFileSelector 弹出一个文件选择框。当用户忽略它时返回一个空字符串。
wxString wxFileSelector(const wxString& message,
const wxString& defaultPath= "",
const wxString& defaultFile= "",
const wxString& defaultExtension= "",
const wxString& wildcard= "*.*",
int flags= 0,
wxWindow* parent= NULL,
int x= -1,
int y= -1);
message 文件选择器的标题。
defaultPath 默认路径i
defaultFile 默认文件
defaultExtension 默认的后缀。当用户省略后缀时这个后缀将自己主动加入到文件后。当没有指定wildcard时,wxWindows自己主动附加一个过滤器。
wildcard (參见 wxFileDialog 构造函数).
flags 是对话框的风格。參见wxFileDialog 构造函数。不支持 wxMULTIPLE风格
parent 父窗体
x 选择器的x轴位置。
y 选择器的y轴位置。
例4.2 要求用户选择一个 JavaScript 文件。
例4.2. wxFileSelector的使用。
wxString selection = wxFileSelector("Open a Javascript file", "", "", "js", "All files(*.*)|*.*|JavaScript Files(*.js)|*.js|Text Files(*.txt)|*.txt", wxOPEN, this);
wxColourDialog实现了一个供用户选择颜色的窗体。WxColourDialog是与wxColourdata共同使用的。WxColourData是用来在对话框中设置当前颜色并用来得到选择的颜色。
#include <wx/colordlg.h>
wxColourDialog(wxWindow* parent,
wxColourData* data= NULL);
parent i是我们这个对话框的父窗体。
data 包括颜色信息。它包括默认颜色,定制颜色而且在windows之下你能够告诉它显示一个包括自己定义颜色选择控件的填充对话框。
public wxColourData& GetColourData();
得到与这个对话框关联的coloudata的引用。
public void SetTitle(const wxString& title);
public wxString GetTitle();
设置或得到对话框的标题
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
这个类包括与wxColourDialog相关的信息。
wxColourData();
默认构造函数
wxColourData(const wxColourData& data);
拷贝构造函数
public void SetChooseFull(bool flag);
public bool GetChooseFull();
在windows上,这种方法显示一个包括自己定义颜色选择控件的对话框,默认值为true。
public void SetColour(wxColour& colour);
public wxColour& GetColour();
设置或者得到选择的颜色。
public void SetCustomColour(int i,
wxColour& colour);public wxColour GetCustomColour(int i);
设置或得到给定位置的自己定义颜色。I必须在0与15之间。
例4.3 为程序加入一个菜单项同意用户选择其他的背景颜色。当前的背景色被赋给colourData。假设程序是执行在windows下的话将显示一个填充对话框。
例4.3.wxColourDialog的使用
void TextFrame::OnMenuOptionBackgroundColor(wxCommandEvent &event) { wxColourData colourData; wxColour colour = m_pTextCtrl->GetBackgroundColour(); colourData.SetColour(colour); colourData.SetChooseFull(true); wxColourDialog *dlg = new wxColourDialog(this, &colourData); if ( dlg->ShowModal() == wxID_OK ) { colourData = dlg->GetColourData(); m_pTextCtrl->SetBackgroundColour(colourData.GetColour()); m_pTextCtrl->Refresh(); } dlg->Destroy(); }
wxGetColourFromUser 显示颜色选择对话框并返回用户选择的颜色或者在用户取消对话框时返回一个无效的颜色。使用wxColour的OK方法来測试颜色是否有效。
wxColour wxGetColourFromUser(wxWindow* parent= NULL,
const wxColour& colInit= wxNullColour);
parent 选择器的父窗体。
colInit 初始颜色。
例4.4 要示用户选择一个颜色
例4.4. wxGetColourFromUser的使用
wxColour colour = wxGetColourFromUser(); if ( colour.Ok() ) { // 用户选择的颜色 }
wxFontDialog是供用户选择字体的对话框。这个对话框与wxFontData,wxFont和wxColour 一起使用。WxFontData用于设置对话框内的当前字体并得到选择的字体。
#include <wx/fontdlg.h>
wxColourDialog(wxWindow* parent,
wxFontData* data= NULL);
parent 对话框的?复翱?
data 包括字体信息。它包括默认字体、当前字体颜色等信息。
public wxFontData& GetFontData();
得到与对话框关联的
fontdata
的引用。
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
wxFontData();
默认构造函数
public void EnableEffects(bool flag);
public bool GetEnableEffects();
在 Windows上, 指出是否使用字体效果比方下划线、斜体等。
public void SetAllowSymbols(bool flag);
public bool GetAllowSymbols();
在 Windows上,指出能否够选择符号字体。
public void SetColour(const wxColour& colour);
public wxColour & GetColour();
设置或得到字体颜色。
public void SetShowHelp(bool flag);
public bool GetShowHelp();
On 在windows上,指出是否显示”帮助“button。
public void SetInitialFont(const wxFont& font);
public wxFont GetInitialFont();
得到或设置对话框使用的原始字体。
public wxFont GetChosenFont();
得到选择的字体。
public void SetRange(int minRange,
int maxRange);
在windows上,指出字体大小最大与最小值。默认情况下为0到无限。
Example 例4.5 为第二章的文本编辑器实现了一个新的菜单项来改变编辑器内的字体。首先fontdata用当前的字体与颜色填充,当程序在Windows上执行时,用户将看到帮助button。当用户选择了字体时,fontdata将被赋与新的字体与文本控件的前景色。
例4.5. wxFontDialog的使用
void TextFrame::OnMenuOptionFont(wxCommandEvent& event) { wxFontData fontData; wxFont font; wxColour colour; font = m_pTextCtrl->GetFont(); fontData.SetInitialFont(font); colour = m_pTextCtrl->GetForegroundColour(); fontData.SetColour(colour); fontData.SetShowHelp(true); wxFontDialog *dlg = new wxFontDialog(this, &fontData); if ( dlg->ShowModal() == wxID_OK ) { fontData = dlg->GetFontData(); font = fontData.GetChosenFont(); m_pTextCtrl->SetFont(font); m_pTextCtrl->SetForegroundColour(fontData.GetColour()); m_pTextCtrl->Refresh(); } dlg->Destroy(); }
TODO.
wxDirDialog用来选择一个文件夹
#include <wx/dirdlg.h>
wxDirDialog(wxWindow* parent,
const wxString& message= "Choose a directory",
const wxString& defaultPath= "",
long style= 0,
const wxPoint& pos= wxDefaultPosition);
parent 父窗体指针
message 标题
defaultPath 默认路径
style 不使用
pos 不使用
public void SetMessage(const wxString& message);
public wxString GetMessage();
得到与设置对话框标题
void SetPath(const wxString& path);
public wxString GetPath();
得到与设置当前路径
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
例 4.6 显示了设置新工作文件夹的菜单动作的实现。WxGetCwd用来用户得到当前的工作文件夹。当用户选择一个文件夹时你能够使用GetPath方法来得到文件夹名。WxSetWorkingDirectory是用来设置新的工作文件夹。
例4.6. wxDirDialog的使用。
void TextFrame::OnMenuOptionDirectory(wxCommandEvent& event) { wxDirDialog *dlg = new wxDirDialog(this, "Select a new working directory", wxGetCwd()); if ( dlg->ShowModal() == wxID_OK ) { wxSetWorkingDirectory(dlg->GetPath()); } dlg->Destroy(); }
wxDirSelector 弹出一个文件夹选择框。
wxString wxDirSelector(const wxString& message,
const wxString& defaultPath= "",
long style= 0,
const wxPoint& pos= wxDefaultPosition,
wxWindow* parent= NULL);
message 标题
defaultPath 默认路径i
style 对话框的风格,參见wxDirDialogis
pos 对话框位置。
Parent 父窗体。
例4.7 要求用户选择一个文件夹。
例 4.7. Using wxDirSelector的使用
wxString selection = wxDirSelector("Select a folder"); if ( ! selection.empty() ) { // The user selected a folder. }
wxTextEntryDialog 请求用户输入一行文本的对话框。
#include <wx/textdlg.h>
wxTextEntryDialog(wxWindow* parent,
const wxString& message,
const wxString& caption= "Please enter text",
const wxString& defaultValue= "",
long style= wxOK | wxCANCEL | wxCENTRE,
const wxPoint& pos= wxDefaultPosition);
parent 父窗体。
message 对话框中显示的信息。
DefaultValue 默认文本。
caption 标题
style 对话框的风格。能够使用wxTextCtrl的风格。
Table表 4.2. wxTextEntryDialog 的风格styles
wxCANCEL | 显示cancelbutton |
wxCENTRE | 中央对话框 |
wxOK | 显示OKbutton |
pos 对话框的位置
void SetValue(const wxString& val);
public wxString GetValue();
得到与设置文本区域的值。Get/Set the value of the text field.
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
例 4.8 显示一个对话框提示用户输入一个密码。
例 4.8. wxTextEntryDialog的使用
wxTextEntryDialog *dlg = new wxTextEntryDialog(this, "Enter your password", "Enter your password", "", wxOK | wxCANCEL | wxCENTRE | wxTE_PASSWORD); if ( dlg->ShowModal() == wxID_OK ) { // Check the password } else { // Stop the application } dlg->Destroy();
wxGetTextFromUser 弹出一个同意用户输入一些文本的对话框。
wxString wxGetTextFromUser(const wxString& message,
const wxString& caption= "Input text",
const wxString& defaultValue= "",
wxWindow* parent= NULL,
int x= -1,
int y= -1,
bool centre= true);
message 对话框中显示的信息。信息中能够包括换行符
caption 标题
defaultValue 默认文本。
parent 父窗体。
x 对话框的X轴位置
y 主轴位置。
centre: 当为真时对话框位于中央,其他情况为左对齐。
例4.9 要求用户输入一些文本。a
wxString text = wxGetTextFromUser("Please, enter some text");
wxGetPasswordFromUser 弹出一个输入password的对话框。
wxString wxGetPasswordFromUser(const wxString& message,
const wxString& caption= "Input text",
const wxString& defaultValue= "",
wxWindow* parent= NULL);
message 对话框中显示的信息。信息中能够包括换行符
caption 标题
defaultValue 默认文本
parent 父窗体
例4.10. wxGetPasswordFromUser的使用
wxString pwd = wxGetPasswordFromUser("Please, enter your password");
wxMessageDialog 能够用来显示一行或多行信息,能够包括OK、Yes、No或者Cancelbutton。
#include <wx/msgdlg.h>
wxMessageDialog(wxWindow* parent,
const wxString& message,
const wxString& caption= "Message box",
long style= wxOK | wxCANCEL | wxCENTRE,
const wxPoint& pos= wxDefaultPosition);
parent父窗体。
message 对话框中显示的信息,能够是多行文本。
caption 标题。
style 对话框的风格。
表4.3. wxMessageDialog的风格。 styles
wxOK | 显示OK button. |
wxCANCEL | 显示 Cancel button. |
wxYES_NO | 显示Yes 与 No button. |
wxYES_DEFAULT | 与 wxYES_NO共同使用,能够让Yesbutton作为默认button。这是默认的行为。 |
wxNO_DEFAULT | Used with 同wxYES_NO共同使用,让Nobutton为默认。 |
wxCENTRE | 让信息位于中央,不是窗体位于中央。 |
wxICON_EXCLAMATION | 显示一个惊叹号图标。 |
wxICON_HAND | 显示一个错误图标。 |
wxICON_ERROR | 与上同样。 |
wxICON_QUESTION | 显示问号图标。 |
wxICON_INFORMATION | 显示信息(i)图标。 |
pos 对话框的位置。
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
Example 3.4 显示 wxMessageDialog 询问用户是否真的退出程序。
wxMessageBox 显示一个信息框。返回值为 wxYES, wxNO, wxCANCEL, wxOK中的一个 。
wxMessageBox(const wxString& message,
const wxString& caption= "Message box",
int style= wxOK | wxCENTRE,
wxWindow* parent,
int x= -1,
int y= -1);
message 显示的信息。
caption 标题
style 风格。參见wxMessageDialog
parent 父窗体。
x x轴位置。
y y轴位置。
在windows上本地的MessageBox函数是不使用wxCENTRE风格的。而在通用函数中是使用的。这是由于本地函数不能将文本居中。当通用函数使用时不显示符号。
#include <wx/choicdlg.h>
wxSingleChoiceDialog(wxWindow* parent,
const wxString& message,
const wxString& caption,
int n,
const wxString* choices,
char ** clientData= (char**) NULL,
long style= wxCHOICEDLG_STYLE,
const wxPoint& pos= wxDefaultPosition);
parent 父窗体。
message 对话框中显示的信息。
caption 标题。
n 条目编号。
choices 是一个字符串数组。
clientData
style 对话框风格。
表4.4. wxSingleChoiceDialog 风格
wxOK | 显示 OK button. |
wxCANCEL | 显示 Cancel button. |
wxCENTRE | 在非Windows上将信息居中. |
wxCHOICEDLG_STYLE | wxOK | wxCANCEL | wxCENTRE |
pos 对话框的位置。
public void SetSelection(int sel);
设置已选项
public int GetSelection();
返回已选项的索。
public wxString GetStringSelection();
返回已选项。
public int ShowModal();
显示对话框,当用户按下OK时返回wxID_OK。其他情况返回wxID_CANCEL。
样例中显示一个对话框让用户选择自己所在的国家。
例4.11. wxSingleChoiceDialog的使用。
wxString countries[] = { "Belgium", "United Kingdom", "U.S.A.", "France" }; wxSingleChoiceDialog *dlg = new wxSingleChoiceDialog(NULL, "Where do you live?", "Select a country", 4, countries); if ( dlg->ShowModal() == wxID_OK ) { wxMessageBox("You live in " + dlg->GetStringSelection()); } dlg->Destroy();
wxGetSingleChoice 显示 wxSingleChoiceDialog并返回选择的字符串。
wxString wxGetSingleChoice(const wxString& message,
const wxString& caption,
const wxArrayString& choices,
wxWindow * parent= (wxWindow *) NULL,
int x= -1,
int y= -1,
bool centre= TRUE,
int width= wxCHOICE_WIDTH,
int height= wxCHOICE_HEIGHT);
wxString wxGetSingleChoice(const wxString& message,
const wxString& caption,
int n,
const wxString * choices,
wxWindow * parent= (wxWindow *) NULL,
int x= -1,
int y= -1,
bool centre= TRUE,
int width= wxCHOICE_WIDTH,
int height= wxCHOICE_HEIGHT);
wxGetSingleChoiceIndex 显示 wxSingleChoiceDialog 并返回选择的索引。当没有不论什么选项被选择时返回-1。
int wxGetSingleChoiceIndex(const wxString& message,
const wxString& caption,
const wxArrayString& choices,
wxWindow * parent= (wxWindow *) NULL,
int x= -1,
int y= -1,
bool centre= TRUE,
int width= wxCHOICE_WIDTH,
int height= wxCHOICE_HEIGHT);
int wxGetSingleChoiceIndex(const wxString& message,
const wxString& caption,
int n,
const wxString * choices,
wxWindow * parent= (wxWindow *) NULL,
int x= -1,
int y= -1,
bool centre= TRUE,
int width= wxCHOICE_WIDTH,
int height= wxCHOICE_HEIGHT);
wxGetSingleChoiceData 显示wxSingleChoiceDialog 并返回与所选项关联的数据。
void* wxGetSingleChoiceData(const wxString& message,
const wxString& caption,
const wxArrayString& choices,
void ** client_data,
wxWindow * parent= (wxWindow *) NULL,
int x= -1,
int y= -1,
bool centre= TRUE,
int width= wxCHOICE_WIDTH,
int height= wxCHOICE_HEIGHT);
void* wxGetSingleChoiceData(const wxString& message,
const wxString& caption,
int n,
const wxString * choices,
void ** client_data,
wxWindow * parent= (wxWindow *) NULL,
int x= -1,
int y= -1,
bool centre= TRUE,
int width= wxCHOICE_WIDTH,
int height= wxCHOICE_HEIGHT);
wxCHOICE_WIDTH 的定义是 200, wxCHOICE_HEIGHT 的定义是150.
文件夹Table of Contents
对话框是一个包括标题栏的窗体。这个窗体能够移动,能够包括控件与其他窗体。对话框能够是模态或非模态的。模态对话框在显示时程序里的其他窗体被锁,一直到对话框退出才干解锁。
WxDialog是全部对话框的基类。你能够自己定义一个继承自wxDialog的对话框。
wxDialog(wxWindow* parent,
wxWindowId id,
const wxString& title,
const wxPoint& pos= wxDefaultPosition,
const wxSize& size= wxDefaultSize,
long style= wxDEFAULT_DIALOG_STYLE,
const wxString& name= "dialogBox");
parent 父窗体的指针,当对话框没有父窗体时使用NULL
id 独立的窗体ID。假设不须要它使用-1。
title 显示在标题栏里的标题。
pos 对话框的位置。使用wxDefaultPosition时为默认位置。
size 窗体的大小。默认大小为wxDefaultSize。
style 对话框的风格。is the style of the dialog.
表5.1. wxDialog 的风格。
wxDEFAULT_DIALOG_STYLE | wxSYSTEM_MENU 与 wxCAPTION的组合。在Unix系统上 wxSYSTEM_MENU 是不使用的。 |
wxCAPTION | 显示标题。 |
wxMINIMIZE | 与 wxICONIZE同样 |
wxMINIMIZE_BOX | 能够最小化. |
wxMAXIMIZE | 以最大化显示。(仅仅适用于Windows)The |
wxMAXIMIZE_BOX | 能够最大化。 |
wxSTAY_ON_TOP | 对话框将出如今其他窗体之上。(仅适用于Windows) |
wxSYSTEM_MENU | 显示一个系统菜单。 |
wxSIMPLE_BORDER | 无边框(仅用于GTK与Windows) |
wxRESIZE_BORDER | 可拖拽缩放的边框。(仅用于Unix) |
name 窗体的名字。这个參数与一个选项相关联。这同意用户为一个单独的窗体设置Motif资源值。
当你要在程序中使用对话框时,wxWindows须要一个资源文件。在你不须要额外的图标时,它的使用就象你将在例5.1中看到的那样简单。
例5.1. 一个简单的资源文件。
#include "wx/msw/wx.rc"
例5.2 展示了在早先开发的简单文本编辑器中显示关于信息对话框的定义。例5.3是它的实现。
例 5.2. AboutDialog.h – 关于对话框的定义。
#ifndef _ABOUTDIALOG_H #define _ABOUTDIALOG_H class AboutDialog : public wxDialog { public: /** * 构造函数 */ AboutDialog(wxWindow *parent); /** * 析构函数 */ virtual ~AboutDialog() { } /** * 设置对话框中的文本。 */ void SetText(const wxString& text); private: wxStaticText *m_pInfoText; wxButton *m_pOkButton; }; #endif
例 5.3. AboutDialog.cpp - 关于对话框的实现
// For compilers that supports precompilation , includes "wx/wx.h" #include "wx/wxprec.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "AboutDialog.h" AboutDialog:: AboutDialog(wxWindow *parent) : wxDialog(parent, -1, "About Simple Text Editor", wxDefaultPosition, wxSize(200, 200), wxDEFAULT_DIALOG_STYLE) { m_pInfoText = new wxStaticText(this, -1, "", wxPoint(5, 5), wxSize(100, 100), wxALIGN_CENTRE); m_pOkButton = new wxButton(this, wxID_OK, "Ok", wxPoint(5, 40)); } void AboutDialog::SetText(const wxString& text) { m_pInfoText->SetLabel(text); }
在样例中没有事件处理的代码,它不是必须的,由于全部的事都是通过wxWindows默认的事件处理机制完毕的。当用户点击由wxID_OK或wxID_CANCEL标识出的button时对话框是自己主动退出的。例5.4是当用户点击关于菜单时用于显示对话框的代码。
例 5.4.显示对话框。
void TextFrame::OnMenuInfoAbout(wxCommandEvent &event) { AboutDialog *dlg = new AboutDialog(this); dlg->SetText("(c) 2001 S.A.W. Franky Braem/nSimple Text Editor/n"); dlg->ShowModal(); }
图5.1. 关于对话框。
假设不使用样例中的OK或Cancelbutton代码时,默认的事件处理是不使用的。这时要撤消对话框必须在EVT_CLOSE事件中调用Destroy。当对话框没被撤消时程序仍然执行。
上个样例中创建的对话框布局可能不是用户所希望的,让文本与button都位于中央可能会更好一些。另外假设文本的大小改变会出现什么?怎样让文本下的button位于中央呢?
wxWindows 提供了两种方法来解决布局的问题。在wxWindows的第一个版本号中使用constraints,从第二版開始使用sizers。尽管constraints在当前版本号中仍然能够使用,但sizers是wxWindows进行控件布局的首选。WxSizer是全部sizers的抽象基类。WxSizer不能直接使用,必须用一个派生类来取代,通常的派生类有: wxBoxSizer, wxStaticBoxSizer, wxNotebookSizer, wxGridSizer 与 wxFlexGridSizer.
Sizers使用的布局算法能够与Java、GTK……之中的不论什么一个来比較。主要的原理是每一个sizer的项目报告它所请求的最小大小,父窗体的大小按须要进行改变。这表?靖复翱诘拇笮〔荒苡煽⒄呃粗付ǎ贝翱诎桓?sizer时会要求sizer返回一个建议大小,sizer则去询问它所包括的子构件的建议大小,这些构件能够是一个窗体,其他sizer或者空白空间。父窗体依据回答自己主动计算大小。
这让sizer十分适合写多平台的程序。考虑以下的问题:在Unix, Motif, Windows中的字体大小并不全然同样。你应该怎样设置对话框的原始大小呢?解决方法是让sizer来为你处理这个问题。
当窗体有一个sizer时布局算法并非自己主动调用的。要在窗体显示之前调用包括sizer窗体上的Layout方法。在窗体缩放时也必须同一时候调用Layout。这能够通过调用包括tue參数的SetAutoLayout来省略。
void Add(wxWindow * window,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Add 方法用来将一个窗体加入到sizer条目的后面。
void Insert(int before,
wxWindow * window,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Insert 用来在berfore之前插入一个窗体。
void Prepend(wxWindow * window,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Prepend 用来设置一个窗体成为条目列表的第一项。
void Remove(wxWindow * window);
Remove 用于从条目列表中移除一个窗体。
option 与wxBoxSizer一直使用. 0表示条目在sizer主向(创建sizer时指定的方向)内的大小不许改变,1表示能够在sizer主向内缩放。
flag 用来设置标志能够用“或”操作符来组合使用。
表 5.2. wxSizer 的边框标志
wxTOP | 边框在顶部 |
wxBOTTOM | 边框在底部 |
wxLEFT | 边框在左 |
wxRIGHT | 边框在右 |
wxALL | 边框在全部面上。 |
表5.3. wxSizer 的行为标志
wxGROW or wxEXPAND | 条目能够缩放 |
wxSHAPED | 条目能够成比例缩放 |
wxALIGN_CENTER or wxALIGN_CENTRE | 条目在中央 |
wxALIGN_LEFT | 条目左对齐 |
wxALIGN_TOP | 条目上对齐 |
wxALIGN_RIGHT | 条目右对齐 |
wxALIGN_CENTER_HORIZONTAL | 条目在水平向中央 |
wxALIGN_CENTER_VERTICAL | 条目在垂直向的中央。 |
border 定义边框的宽度。
userData 同意一个额外对象附加到sizer条目上。能够通过派生类使用。
Sizers 能够嵌套
void Add(wxSizer * sizer,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Add 方法用来将一个sizer加入到sizer条目的后面。
void Insert(int before,
wxSizer * sizer,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Insert 在条目 before之前插入一个sizer。
void Prepend(wxSizer * sizer,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Prepend 用来设置一个sizer成为条目列表的第一项
void Remove(wxSizer * sizer);
Remove 用于从条目列表中移除一个sizer。
很多其他參数信息參见“Sizers和 windows”
Spacer用来在控件之间插入空白。当spacer在两个条目之间时同意扩展。结果将使用第一个条目保持左对齐其他条目保持右对齐。
void Add(int width,
int height,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Add方法用来将一个spacer加入到sizer条目的后面。
void Insert(int before,
int width,
int height,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Insert 将一个spacer插入before条目之前。
void Prepend(int width,
int height,
int option= 0,
int flag= 0,
int border= 0,
wxObject* userData= NULL);
Prepend设置一个spacer 为条目列表的第一个条目。
很多其他參数细节參见 “Sizers 与 windows”
WxBoxSizer用来依据不同的标志将控件排成一行或一列。它能够水平或垂直伸展。
wxBoxSizer(int orient);
orient 方向。
表 5.4. wxBoxSizer 的方向
wxHORIZONTAL | 水平 |
wxVERTICAL | 垂直。 |
在以下的样例中,创建了一个充满对话框的sizer。它的主向是垂直。全部其他sizer都是这个sizer的子控件,全部是水平向的。它们能够在水平方向扩展,但垂直方向则不能。第二个sizer用来对OKbutton布局,这将能够让button与对话框边框间保持固定的边界。在加入button时指定边框的大小为20。
例 5.5. wxBoxSizer的使用
AboutDialog::AboutDialog(wxWindow *parent) : wxDialog(parent, -1, "About Simple Text Editor", wxDefaultPosition, wxSize(200, 200), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxBoxSizer *dialogSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *textSizer = new wxBoxSizer(wxHORIZONTAL); m_pInfoText = new wxStaticText(this, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); // The text can grow horizontally. textSizer->Add(m_pInfoText, 1, 0); wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL); m_pOkButton = new wxButton(this, wxID_OK, "Ok", wxPoint(-1, -1)); // The button can grow horizontally, not vertically. // The button has a left and right border with size 20 buttonSizer->Add(m_pOkButton, 1, wxLEFT | wxRIGHT, 20); // The sizers can‘t change their vertical size. They can only grow horizontally. dialogSizer->Add(textSizer, 0, wxGROW); dialogSizer->Add(buttonSizer, 0, wxGROW); SetSizer(dialogSizer); SetAutoLayout(TRUE); Layout(); }
图 5.2. 使用 wxBoxSizer的关于对话框。
网格sizer是一个拥有相同大小单元的两维表格布局控件。每一个单元格的宽与高就是是控件的最大宽度与最大高度。当一个网格sizer创建时,它须要知道须要多少行与列。假设这些參数中有一个为0,则这个值由网格sizer计算得出。相同也必须指定行与列之间的间隔。
wxGridSizer(int rows,
int cols,
int vgap,
int hgap);wxGridSizer(int cols,
int vgap= 0,
int hgap= 0);
rows 指定行数
cols 指定列数
vgap 指定列之间的间隔。
hgap 指定行之间的间隔。
以下的样例展示了怎样用wxGridSizer来实现对关于对话框中控件的布局。样例将建立丙行与一列,行与列之间的间隔是10。
例5.6.wxGridSizer的使用
AboutDialog::AboutDialog(wxWindow *parent) : wxDialog(parent, -1, "About Simple Text Editor", wxDefaultPosition, wxSize(200, 200), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxGridSizer *dialogSizer = new wxGridSizer(2, 1, 10, 10); m_pInfoText = new wxStaticText(this, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); dialogSizer->Add(m_pInfoText, 0, wxALIGN_CENTER); m_pOkButton = new wxButton(this, wxID_OK, "Ok", wxPoint(-1, -1)); dialogSizer->Add(m_pOkButton, 0, wxALIGN_CENTER); SetSizer(dialogSizer); SetAutoLayout(TRUE); Layout(); }
曲线网格sizer 是一个二维表格布局控件,它全部在同一行中的单元格都有同样的宽度而且同一列中的单元格都有同样的高度。
假设你须要在对话框中的控件上加入标签,网格sizer是很实用的。图5.3展示了一个正确使用wxFlexGridSizer的样例。在第一列中包括标签,最宽的那个标签决定了第一列的列宽。这能够保证控件是垂直对齐的。创建这样的对话框的代码显示在例5.7中。创建了两行与两列,当加入控件到sizer时,它们是从左到右,从上到下放置的。
wxFlexGridSizer(int rows,
int cols,
int vgap,
int hgap);wxFlexGridSizer(int cols,
int vgap= 0,
int hgap= 0);
參数说明參见 “wxGridSizer”
图5.3. wxFlexGridSizer的使用
wxFlexGridSizer *dialogSizer = new wxFlexGridSizer(2, 2, 10, 10); dialogSizer->Add(new wxStaticText(this, -1, "Username"), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(new wxTextCtrl(this, ID_USER_NAME), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(new wxStaticText(this, -1, "Password"), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(new wxTextCtrl(this, ID_PASSWORD), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(new wxStaticText(this, -1, "Retype Password"), 0, wxALIGN_CENTRE_VERTICAL); dialogSizer->Add(new wxTextCtrl(this, ID_PASSWORD2), 0, wxALIGN_CENTRE_VERTICAL); SetSizer(dialogSizer); SetAutoLayout(TRUE); Layout();
wxStaticBoxSizer 继承自wxBoxSizer。它的工作与box sizer同样。但它在sizer周围画出一个静态框。
wxStaticBoxSizer(wxStaticBox* box,
int orient);
box 是一个wxStaticBox指针。静态框不是通过sizer来完毕的,它必须通过开发人员来完毕。
orient box sizer的方向,參见“wxBoxSizer”
wxNotebookSizer 是专门在wxNotebook上工作的sizer。
Sizer是能够嵌套的。下一个样例展示了一个组合了wxBoxSizer与wxFlexGridSizer的对话框。图5.4显示了执行结果。WxBoxSizer用来在对话框中其他控件下方的中央放置一个OKbutton。
例 5.8. sizer的嵌套
wxBoxSizer *dialogSizer = new wxBoxSizer(wxVERTICAL); wxFlexGridSizer *controlSizer = new wxFlexGridSizer(2, 2, 10, 10); controlSizer->Add(new wxStaticText(this, -1, "Username"), 0, wxALIGN_CENTRE_VERTICAL); controlSizer->Add(new wxTextCtrl(this, -1), 0, wxALIGN_CENTRE_VERTICAL); controlSizer->Add(new wxStaticText(this, -1, "Password"), 0, wxALIGN_CENTRE_VERTICAL); controlSizer->Add(new wxTextCtrl(this, -1), 0, wxALIGN_CENTRE_VERTICAL); controlSizer->Add(new wxStaticText(this, -1, "Retype Password"), 0, wxALIGN_CENTRE_VERTICAL); controlSizer->Add(new wxTextCtrl(this, -1), 0, wxALIGN_CENTRE_VERTICAL); wxBoxSizer *buttonSizer = new wxBoxSizer(wxVERTICAL); buttonSizer->Add(new wxButton(this, wxID_OK, "Ok")); dialogSizer->Add(controlSizer); dialogSizer->Add(20, 20); dialogSizer->Add(buttonSizer, 0, wxALIGN_CENTRE); SetSizer(dialogSizer); SetAutoLayout(TRUE); Layout();
图5.4.Sizer的嵌套
标签:
原文地址:http://www.cnblogs.com/gcczhongduan/p/4374710.html