细述 wxWindows
来源:互联网 发布:阿里云业务发展渠道 编辑:程序博客网 时间:2024/05/16 10:06
细述 wxWindows
可移植 C++ 和 Python工具箱简介
文档选项未显示需要 JavaScript的文档选项
打印本页
将此页作为电子邮件发送
级别: 初级
Markus Neifer (markusneifer@my-deja.com), 软件工程师
2001 年 2 月 01 日
MarkusNeifer 提供了有关 wxWindows -- 一种可移植的 C++ 和 Python GUI 工具箱 --的概述。他讨论了库的体系结构,讲述了如何安排多平台文件处理和目录分隔字符,并谈到 wxHTML、图像文件格式和Unicode。还介绍了一些有帮助的 wxWindows 调试小窍门,以及如何将 MFC 应用程序移植到 Linux。
wxWindows 库,无论是否作为动态链接库 (DLL)来编译它,都有可能有非常小的执行体。它还提供了用于多平台开发的各种特性:可以获得OpenGL 接口以及对 HTML、Unicode和国际化的内建支持。它可以帮助您将应用程序从仅用于 Windows 的MFC(Microsoft FoundationClasses)移植到其它平台,比方说,Linux。wxWindows的一个主要目的是在尽可能多的平台上运行,这样才能支持几乎每种可用的C++ 编译器。它还没有使用标准 C++的全部特性(例如名称空间、std::string 类和 STL 容器)。但标准 C++已被列在日程中,并且已经有了一些对于新类型转换语法和 std::string的支持。
简要历史
Julian Smart 于 1992 年在爱丁堡大学 (University of Edinburgh)人工智能应用学院开始了 wxWindows 的研究。1995 年,Markus Holzem发布了其到 Xt(X 工具箱)的 wxWindows 移植。停了一段时间后,1997 年5 月,Windows 和 GTK+ 移植被合并,并放入 CVS 资源库,所有对wxWindows 做出贡献的人都可以使用它。到 97 年底,Julian Smart开始分发 wxWindows 的 CD-ROM,包括完整的源码、编译器材料等等。
目前 wxWindows 在 GPL下发布,但有一个例外:可以分发不带有源代码的二进制可执行文件。这对于商业项目来说是个不错的选择。它有各种UNIX 版 和 Microsoft Windows 版,以及 Macintosh OS 版。到 OS/2和其它操作系统的移植也正在开发中。现在,让我们开始进入具有丰富内容的正文...
回页首
要运用的平台
因为 wxWindows 随时可以使用本机控件,所以它采取与大多数其它多平台GUI 库不同的方式来对待小窗口部件。可以仿效那些不可用的控件,例如Unix下的树控件。这将为应用程序的用户提供类似的外观和感觉。wxWindows库当前支持以下平台:
- Windows 3.1,Windows 95/98,Windows NT
- 带有 Motif/Lesstif 的大多数 UNIX 版本
- 带有 GTK+ 的大多数 UNIX 版本
- Mac
仅带非 GUI 类的 wxBase 库也可以在 UNIX/Win32 和 BeOS下构建(有一些限制)。即使您不是将 wxWindows 作为 DLL编译,也可以获得非常小的可执行文件。例如,使用 Windows 平台的Microsoft Visual C++ 所编译的最小的样本应用程序小于 400 KB。因为wxWindows 的可执行程序很小,所以通常可以避免所谓的“DLL灾难”。
现在,让我们看看多平台特性...
回页首
独立于体系结构的类型
为避免体系结构的依赖性,该库提供了各种独立于体系结构的类型和宏,能够根据应用程序的尾数来处理位交换。它们包括:
- wxInt32(32 位有符号整数)
- wxInt16(16 位有符号整数)
- wxInt8(8 位有符号整数)
- wxUint32(32 位无符号整数)
- wxUint16 = wxWord(16 位无符号整数)
- wxUint8 = wxByte(8 位无符号整数)
位交换宏可用于整数和无符号整数(其中的 xx 代表 16 或 32,BE代表大尾数法,LE 代表小尾数法。)
- wxINTxx_SWAP_ON_BE()
- wxUINTxx_SWAP_ON_BE()
- wxINTxx_SWAP_ON_LE()
- wxUINTxx_SWAP_ON_LE()
- wxINTxx_SWAP_ALWAYS()
- wxUINTxx_SWAP_ALWAYS()
这里的用法很直接,如下例所示:
32 位带符号整数变量的字节交换
wxInt32 old_var = 0xF1F2F3F4;wxInt32 new_var = wxINT32_SWAP_ALWAYS( old_var )
除了这些宏以外,wxWindows 还提供了 #define
来定义机器(库在其上编译)的当前尾数。以下是它的一例:
使用 #define
if ( wxBYTE_ORDER == wxLITTLE_ENDIAN ){ // Do stuff for little endian machine...}else{ // Do stuff for big endian machine...}
回页首
文件处理
要为具有不同文件存储器概念的不同平台进行编写总是很困难的。要克服这一问题,wxWindows有一些函数用于多平台文件处理。首先,让我们看一些用于基本文件操作(例如复制、删除和重命名)的函数。
基本文件操作
wxString old_report = "smithers_00.doc"wxString new_report = "my_smithers.doc";if ( wxCopyFile( old_report, "smithers_00.bak" ) == true ){ if ( wxRemoveFile( old_report ) == true ) { if ( wxRenameFile( new_report, old_report ) == false ) { // Doh! } }}
另一个为不同平台进行编写所带来的严重问题是目录分隔字符,但使用 wxPathList
类的话就可以完全避免这一问题。 wxPathList
包含了搜索文件所用的目录列表。如果希望查找某一文件,只需要将文件名传递给 wxPathList
类,它就会搜索预先定义的目录。
wxPathList 类
wxPathList path_list;// Add current working directorypath_list.Add( "." );// Add one directory above current working directorypath_list.Add( ".." );// Add directories from environment variable PATH to the listpath_list.AddEnvList( "PATH" );wxString path = path_list.FindValidPath( "homer.bmp" );
wxWindows中还有两个有用的函数: wxFileNameFromPath()
,用于将文件名从完整路径中剥离,以及 wxPathOnly()
,用于将路径从完整路径中剥离。
回页首
HTML
Vaclav Slavik 的 wxHTML 库对基本 HTML 进行语法分析并产生HTML。它并没有完全实现 HTML标准,但它的功能对于处理联机帮助已经足够了,它还可以使用标记处理程序进行扩展。要显示HTML,需要创建一个类为 wxHtmlWindow
的对象。然后调用它的方法来设置相关的框架和相关的状态栏,前者用来实际地显示HTML,后者用来显示由 HTML 语法分析器所生成的消息。
wxHTML
wxHtmlWindow html_window = new wxHtmlWindow( this );html_window->SetRelatedFrame( this, "HTML : %%s" );html_window->SetRelatedStatusBar( 0 );
然后,可以通过使用以下函数来装入 HTML 页面:
装入 HTML
html_window->LoadPage( "burns.htm" );
也可以通过以下函数来显示 HTML 代码
显示 HTML
html_window->SetPage( "<html><body>Hello, Monty!</body></html>" );
回页首
图像
wxImage
类使用图像格式处理程序来装入各种不同的图像文件格式。可以通过实现自己的图像格式处理程序,扩展 wxImage来装入新的图像格式。现有的图像格式处理程序使用众所周知的库,例如 Sam Leffler 的 libTIFF 库或独立 JPEG 小组的JPEG 库。有一些用于 BMP、PNG、JPEG、GIF、PCX、PNM 和 TIFF 的处理程序。可以通过使用应用程序启动代码中wxImage 类的静态方法 AddHandler() 来激活每个图像格式处理程序。
wxImages
bool MyApp::OnInit(){ wxImage::AddHandler( new wxPNGHandler ); // more ...}
要使用所有现有的图像格式处理程序,只需要调用函数 wxInitAllImageHandlers()
而不是上面显示的 AddHandler()
方法。
在其它平台上使用应用程序中的工具栏位图时要特别小心。在 Windows上,您将看到 Windows 位图格式,但 Linux 位图通常是pixmaps,在这种情况下,就不能完全避免有条件的编译。让我们看一些样本代码。
#if defined(__WXGTK__) || defined(__WXMOTIF__) #include "maggie.xpm"#endif// more ...void MyApp::UseBitmap(){ wxBitmap bitmap( wxBITMAP( maggie )); // more ...}
理解了吗?所有效果都是由 wxBITMAP()
宏实现的。对于Windows 和 OS/2,它将使用应用程序资源中名为 'maggie' 的位图来创建 wxBitmap
对象。对于所有其它平台,它将使用称为'maggie_xpm' 的 pixmap 来创建 wxBitmap
对象。
当可以使用 wxDC::DrawBitmap()
在设备上下文中绘制位图时,必须为图像操作使用 wxImage
对象,如下所示。
图像操作
wxImage* p_image = new wxImage( bitmap );// Have some funif ( p_image->Ok() ){ if ( p_image->GetHeight() > 50 && p_image->GetWidth() > 50 ) { unsigned char red = p_image->GetRed( 50, 50 ); unsigned char green = p_image->GetGreen( 50, 50 ); unsigned char blue = p_image->GetBlue( 50, 50 ); // Secure but might be slow p_image->SetRGB( 50, 50, red, green, blue ); // If you want fast action use a pointer... unsigned char* data = p_image->GetData(); // Manipulate the data... }}
回页首
Unicode 和国际化(i18n)
开发适用于国际市场的软件时,不能指望每个人都能阅读以英文表示的应用程序消息。但广泛使用的ANSI代码又不能处理所有语言符号。(例如,它不能处理中文。)而同时编写ANSI 和 Unicode 又有些复杂,您可以从下例中领略到这一点:
ANSI 和 Unicode
#ifdef USE__UNICODE wchar_t wide_char = L'h'; wchar_t const* wide_string = L"Hello, World!"; int length = wcslen( wide_string );#else char ansi_char = 'h'; char const* ansi_string = "Hello, World!"; int length = strlen( ansi_string );#endif
而使用 wxWindows Unicode 能力就只需要编写以下代码:
wxT() 宏以及 wxChar 和 wxString
wxChar wx_char = wxT( '*' );wxString wx_string = wxT( "Hello, World!" );int length = wx_string.Len();
wxT()
宏以及 wxChar
和 wxString
类将处理所有问题。该库在内部对所有消息使用这种方法。当前有捷克语、丹麦语、德语、法语、意大利语和俄语译文可用,但您可以在 wxLocale
类的帮助下编译库的本地化版本后使用它。
回页首
调试
库提供了各种不同的类、函数和宏来帮助您调试应用程序。如果以调试方式来编译库,用于类 wxObject
(wxWindows 中大多数类的基类)的 new
和 delete
操作符就已经重新定义,可以存储有关在堆上分配的对象的额外信息。使用这些信息,可以用类 wxDebugContext
来获得有关对象分配、内存泄露、覆盖和正在写入的详细信息。
// Start logging for Dump() callwxDebugContext::SetCheckpoint();wxString *thing = new wxString;wxDate* date = new wxDate;// non-object allocationchar *ordinaryNonObject = new char[1000];// more ...// Print number of object and non-object allocationswxDebugContext::Dump();// Print allocation statisticswxDebugContext::PrintStatistics();
对 wxDebugContext::Dump()
的调用将弹出一个包含分配列表的窗口。您可以在下面看到这样一个列表,这是我用 wxWindows 提供的 memcheck 样本创建的。
调用 wxDebugContext::Dump()
13:32:45: ----- Memory dump of memcheck at Tue Dec 26 13:32:45 2000 -----13:32:45: ../../../samples/memcheck/memcheck.cpp(88): non-object data at $DD3DC0, size 413:32:45: ../../../samples/memcheck/memcheck.cpp(89): wxDate at $DD40D0, size 2413:32:45: ../../../samples/memcheck/memcheck.cpp(92): non-object data at $DD4118, size 1000
对 wxDebugContext::PrintStatistics()
的调用将提供一些统计信息,如下所示。
调用 wxDebugContext::PrintStatistics()
13:32:45: ----- Memory statistics of memcheck at Tue Dec 26 13:32:45 2000 -----13:32:45: 1 objects of class wxDate, total size 2413:32:45: 5 objects of class nonobject, total size 425613:32:45: 13:32:45: Number of object items: 113:32:45: Number of non-object items: 513:32:45: Total allocated size: 4280
回页首
将 MFC应用程序移植到 Linux
wxWindows 库也可以将 MFC 应用程序移植到 Linux和其它操作系统。您将在下面的代码摘录中看到,wxWindows 字符串类 wxString
与 MFC 字符串类 CString
有某些相似性。
wxString
wxString s1 = "Hello, World!";wxString s2 = "Hello";if ( s1.IsEmpty() == false ){ s2.Empty(); s2 = s1.Left( 5 ); int pos = s1.Find( ',' ); s2 += s1.Mid( pos, 2 ); s2 += s1.Right( 6 );}
wxWindows 的事件系统也与 MFC非常相似,消息映射表都是将事件处理程序方法映射到事件系统。在wxWindows 中,这些称为事件表。事件表宏与 MFC的消息映射只有一点差别。在下面的源代码中显示了主要差异。
头文件的 MFC 代码
class CButtonCtrl : public COleControl{// Implementationprotected: LRESULT OnOcmCommand( WPARAM wParam, LPARAM lParam ); DECLARE_MESSAGE_MAP()};
实现文件的 MFC 代码
BEGIN_MESSAGE_MAP( CButtonCtrl, COleControl ) //{{AFX_MSG_MAP( CButtonCtrl ) ON_MESSAGE( OCM_COMMAND, OnOcmCommand ) //}}AFX_MSG_MAPEND_MESSAGE_MAP()
头文件的 wxWindows 代码
class MyButton : public wxButton{ void OnButton( wxMouseEvent& event )private: DECLARE_EVENT_TABLE()};
实现文件的 wxWindows 代码
BEGIN_EVENT_TABLE( MyButton, wxButton ) EVT_BUTTON( -1, MyButton::OnButton )END_EVENT_TABLE()
如您所见,并没有什么不同。在邮件列表中已经有相当一部分人成功地将他们现有的MFC 应用程序移植到 wxWindows(我们也非常愿意帮助您:)。
回页首
标准C++
wxWindows 还没有使用标准 C++ 技术(例如 std::string
、STL 或名称空间),因为这样会大量减少wxWindows可在其上进行编译的平台数。(只有很少一些编译器完全支持标准 C++的最新特性。)但随着标准 C++ 越来越受到普遍支持,wxWindows开发小组会将对标准 C++的支持集成到它的库中。让我们看看他们都做了哪些工作。
以标准 C++ 编写进行的安全向下类型转换
class A { virtual void foo() {};};class B : public A {};A* p_A = new B();B* p_B = dynamic_cast ( p_A );
如果有任何错误, p_B
将包含 0 指针。在 wxWindows中,您将发现一个基于宏的系统用于运行时类型信息,但对于上述 C++代码,必须按以下方法使用 wxDynamicCast()
宏:
用于标准 C++ 的wxDynamicCast() 宏
B* p_B = wxDynamicCast( p_A, B );
如果类型转换失败, p_B
将包含 0指针。对于支持新类型转换语法的实现,宏扩展为 dynamic_cast<>
。但不幸的是,宏只对指针起作用,而不对引用起作用。除了 wxDynamicCast()
宏以外,还有 wxStaticCast()
和 wxConstCast()
宏。
wxWindows 字符串类 wxString
提供了 90% 的标准字符串类方法。这里有些示例:
wxWindows' wxString
wxString s1 = "Hello, World!";wxString s2 = "Hello";s2.erase();for ( size_t i = 0; i < s1.length(); ++i ) s2 += s1[i];if ( s1.compare( s2 ) == 0 ) { // Strings are equal}
请注意,如果在这里将 wxString
typedef
为 std::string
,就可以同时为 wxWindows 和标准 C++编写。
回页首
文档
wxWindows文档就目前来说一点也不出色。虽然一些比较“陈旧”的类(例如 wxString
)文档很齐全,但对最近实现的类(例如 wxGrid
)或更模糊的类(例如 wxGLCanvas
)的描述本应该做得更好。主要文档提供了对库及其概念的快速介绍、按照字母顺序排列的类引用、编程策略、主题概述,以及对wxHTML 和 wxPython 的某些注释,提供了 HTML、WinHelp、MS HTML Help和 PDF 格式(请参阅 参考资料)。
如果您刚刚接触wxWindows,应该从主题概述开始。它们提供了许多有关公共主题(例如调试、事件处理、打印等等)的基本信息和代码示例。主要文档还包含了一些技术说明和教程,它们提供的主题信息范围从有关了解wxWindows的一些非常公共的问题到特定于编译器的问题。您还将得到大量纯文本文件,包含用于所支持平台的安装和发行说明。wxWindows发行版还提供了随文档一起的大约 50 个样本应用程序。
回页首
支持
如果您在使用库时遇到问题,在文档中又找不到答案该怎么办?不用担心。通常您有两种支持可选:使用邮件列表的免费支持,或商业支持。如果您不幸需要快速解答,可能最好使用商业支持。虽然核心开发者总是会关注邮件列表,但他们往往很忙碌,无法立即做出响应。但您通常可以在一两天内得到答案。(如果提的问题不太寻常或比较复杂,则在再次提出问题之前应该至少等上两天。)可以从Sourceforge(请参阅 参考资料 )上的 CVS源代码数据库访问最新的源码。
回页首
总结
现在您对 wxWindows究竟是什么,它为多平台开发提供了哪些产品和服务应该有了一定认识。但当然,这些不是全部。拿当前的wxStudio 项目为例,它使用 wxWindows 开发类似于 IDE 的 MicrosoftVisual Studio。或者 wxCVS 项目,它将是用于 CVS系统的多平台图形界面。或者 wxDesigner,它是由 Robert Roebling开发的一种 RAD 工具,用于构建 wxWindows对话框。您应该会发现,wxWindows社区正在不断成长,因此在下一次将要开发多平台项目时请关注一下它。
所有提到的产品名都是其相应拥有者的 商标或注册商标。
参考资料
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文.
- 仔细查看 wxWindows主页
- 阅读有关 Sourceforge 上的wxWindows信息
- wxStudio是创建免费、跨平台集成开发环境的研究计划
- wxDesigner 有 Windows 和UNIX 版可用
- wxPROs 是 wxWindows 和wxPython 的专业人员资源组织
关于作者
Markus Neifer 最初在 LOGO龟标的帮助下开始编程,在此之后他使用过各种版本的 BASIC。在研究地理信息期间,他学习了一段时间的 C,但随后很快转向 C++ 和Java,因为它们具有面向对象的性质。 他曾在 R&D部门工作,在那期间, 他发表了有关面向对象的科学软件开发的文章。现在,他是地理信息系统领域中的软件工程师。可以通过 markusneifer@my-deja.com与他联系。
- 细述 wxWindows
- 细述 wxWindows
- wxWindows
- wx网罗系列之翔实:细述wxWindows
- 关于 wxWindows
- 接触wxWindows
- wxWindows文档
- wxwindows编译
- wxwindows qt
- wxWindows入门
- 浅谈 wxWindows FrameWork
- 浅谈 wxWindows FrameWork
- 欢迎来到wxWindows
- 体验wxWindows安装
- JSLIU 的 wxWindows 入门
- wxWindows 应用程序向导Wizard
- 加入wxWindows邮件列表
- wxWindows的OpenGL全屏
- 让数据库中始终保持N条记录.sql语句实现
- sql UNION 和 UNION ALL 的区别 ZT_亢龙有悔
- WILL YOU FADE AWAY?
- wxWindows一些网文
- 正则表达式
- 细述 wxWindows
- 三款记事本替代工具 哪个最好用?
- 从孙子兵法论SOA
- JavaScript面向对象编程
- LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 && CVT1100: 重复的资源 解决方法
- 关于list-(3) 约瑟夫
- (1)struts2--login.jsp(1)
- C语言鼠标操作方法及源码
- 2008.10.21 一个程序只包含一个源程序文件的情况