细述 wxWindows

xiaoxiao2021-03-01  85

wxWindows 库,无论是否作为动态链接库 (DLL) 来编译它,都有可能有非常小的执行体。它还提供了用于多平台开发的各种特性:可以获得 OpenGL 接口以及对 HTML、Unicode 和国际化的内建支持。它可以帮助您将应用程序从仅用于 Windows 的 MFC(Microsoft Foundation Classes)移植到其它平台,比方说,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 directory path_list.Add( "." ); // Add one directory above current working directory path_list.Add( ".." ); // Add directories from environment variable PATH to the list path_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 fun if ( 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() call wxDebugContext::SetCheckpoint(); wxString *thing = new wxString; wxDate* date = new wxDate; // non-object allocation char *ordinaryNonObject = new char[1000]; // more ... // Print number of object and non-object allocations wxDebugContext::Dump(); // Print allocation statistics wxDebugContext::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 4 13:32:45: ..\..\..\samples\memcheck\memcheck.cpp(89): wxDate at $DD40D0, size 24 13: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 24 13:32:45: 5 objects of class nonobject, total size 4256 13:32:45: 13:32:45: Number of object items: 1 13:32:45: Number of non-object items: 5 13: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 { // Implementation protected: 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_MAP END_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 的 Microsoft Visual 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 与他联系。

<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES--> 相关资源:Office2016专业增强版中文免费正式版(附安装教程)64位
转载请注明原文地址: https://www.6miu.com/read-4150247.html

最新回复(0)