QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1603|回复: 4

(转)wxWindows一些网文

[复制链接]
发表于 2005-4-26 20:57:11 | 显示全部楼层 |阅读模式
最近看了Borland C++BuilderX的报道,发现这次的版本使用的是wxWindows做为FrameWork。十分惊讶,因为我在一年以前就使用wxWindows了。不过在当时,包括最近有关它的国内报道还是很少。
  wxWindows是一个C++的扩展库。是一个OpenSource项目,而且支持多平台。所以,你完全可以从OpenSource的网站上免费获得各个平台的版本和源代码。而对于wxWindows的官方网站www.wxWindows.org我一年来从未一睹其芳容,——网站无法访问。但是尽管如此,并不影响我们获得它。这多亏了OpenSource的力量。
  wxWindows最吸引我的是它简洁的代码——几行简单的代码,随心所欲的派生。一个窗口就诞生了。一个用API要近100行的效果。用wxWindows最多十几行就可以解决问题。我想这也或许是Borland选择它的原因之一吧。wxWindows对于各种常用控件和繁琐的功能都分别封装成了类。使用的时候只要加一行代码就可以使用了。像

wxButton *p_b = new wxButton(frame,-1,"Button");

就是在frame窗口中绘制一个写有Button的按钮。以后的访问只要使用

p_b->//要调用的函数

就可以对按钮进行操作了。我想直接用API就没有那么方便了吧。其实在简单的背后,wxWindows为你默默的做了许多的工作。虽然你也可以在wxWindows中对这些工作全面接手。但是,有些时候根本没有必要那么做。当然,如果你对wxWindows的控件不满意的话,完全可以用wxWindows派生出自己的控件。比如你对主窗口不满意——只有一块深灰色。你完全可以生成一个自己的主窗口,方法如下:

Class MyFrameublic wxFrame
{
public:
MyFrame(int width,int height);
};
MyFrame::MyFrame(int width,int height)
:wxFrame((wxFrame)*NULL,wxPoint(0,0),wxSize(width,height))
{
//你为MyFrame所添加的控件等。
}

从上面的代码,可以看出。wxWindows灵活的类管理。
  我钟情于wxWindows的另一个理由是它与C++标准库的兼容和健全的非窗口类。比如,在wxWindows中我最喜欢的是wxString,它是我见到的最健全的String类之一。它不但可以与wx完全兼容,也可以与C++标准兼容。在C++中,wxString更像一个灵活多变的Char列。你可以像Char那样使用它。而无需考虑内存的事先分配等问题。而且,在某些方面,它比char更强大。
  当然,对于多平台的支持也是我喜欢它的原因。wxWindows有多平台的版本。我使用的是MSW的。当然也有 Mac X11 GTK MGL等许多平台的。如果你要让你的代码在其他的平台上使用。那么你只要在编译的时候修改一下附带的语句。将有关平台的参数改变一下就可以了。对于代码,只要没有使用在特定平台下的功能,就能不修改代码直接使用。当然,wxWindows不只是对各个操作系统有支持。由于它是OpenSource的。所以,通常,其他非C++语言也会使用它的。比如 wxPython就是wxWindows对Python的版本。wxPerl是对Perl的版本。在这些不同的语言中的wxWindows,力求保持它原有的编程风格和思路,而且他们也做到了。所以,你会wxWindows就等于会了wxPython,wxPerl。说到这里,我想说一些题外话。我也用python+wxPython做一些桌面的小玩具,不仅如此,在我要用wxWindows开发界面的时候,会使用wxPython先事先写好界面的代码。然后,确定好后,再机械的灌到我的C++代码中。由于Python是解释性语言,所以与C++相比少了编译,连接的开发周期。写完代码直接运行就可以了。所以,节省了不少的开发时间。这不失为一种减少开发周期,加快开发速度的好方法。下面我们来看看wxPython和wxWindows在实现相同功能上有多大的相同。
//C++ Source
#include <wx/wx.h>

class MainApp:public wxApp
{
public:
virtual bool OnInit(void);
private:
wxFrame *mainFrame;
};
IMPLEMENT_APP(MainApp)

bool MainApp::OnInit(void)
{
mainFrame = new wxFrame((wxFrame*) NULL,-1,"Hello wxWindows");
mainFrame->Show(TRUE);
SetTopWindow(mainFrame);
return TRUE;
}


#Python Source
from wxPython.wx import *

class MainApp(wxApp):
def OnInit(self):
  mainFrame=wxFrame(NULL,-1,"Hello wxWindows")
  mainFrame.Show(true)
  self.SetTopWindow(mainFrame)
  return true
app=MainApp(0)
app.MainLoop()

从上面的代码,我们可以看到。对于wxWindows和wxPython的界面实现方法几乎是相同的。不同的只是在有关变量的声明,和C++与Python自身的语法不同。
  接下来,说说wxWindows支持的C++的IDE环境。既然Borland C++BuildX已经使用了wxWindows那么Borland的C++编译器应该支持吧。其实,事实也是如此。Borland C++ 4.5和5.0都支持。对于使用最广的VC的IDE环境自然也必须支持了。支持的有1.5,4.0,5.0和6.0。当然,其实.Net下也可以使用wxWindows。至少我使用下来没有问题。另外,使用GCC的Dev-CPP也对它有很好的支持,甚至还为wxWindows专门打了一个包。直接使用Dev-CPP的包管理就可以安装并使用了。以上只是一些可以使用wxWindows的IDE环境,还有很多,在此不一一介绍了。有关更多的介绍,可以看看wxWindows的自带文档,在里面有详细的介绍和对于不同环境的安装方法。
  对于wxWindows中值得称赞的是它的说明文档。可以这样说,它的自带的文档从教程到查询文档一应俱全。要知道,作为一个开源项目,免费维护的项目,文档能够如此详细和完整真是难得。所以,在没有中文文档的时候,我就是阅读这些英文文档来学习的。而且,直到现在,我每次看这些文档的时候都会有许多新的感悟。而且,另一个值得说明的是,wxWindows 2.4.0,wxWindows 2.4.1等这些不同版本的wxWindows虽然之间有很多的改进。但是,使用的介绍文档等几乎没有改变。这也正说明了它语法的稳定。不至于一个新的版本会造成过去代码的不可用。所以,你完全不用担心你的代码由于版本的问题,会造成他人在阅读和编译上的困难。
  对于,多平台的运行机制。我想我也要简单介绍一下。毕竟我想这个也是我们需要关注的问题。如果,你仔细看看wxWindows的include/wx目录,你会看到有诸如 msw unix 等目录。其实,在你导入wxWindows文件的时候,wxWindows会更具不同的平台选择不同的文件。下面是include/wx/button.h中63行的一段代码。

#if defined(__WXUNIVERSAL__)
    #include "wx/univ/button.h"
#elif defined(__WXMSW__)
    #include "wx/msw/button.h"
#elif defined(__WXMOTIF__)
    #include "wx/motif/button.h"
#elif defined(__WXGTK__)
    #include "wx/gtk/button.h"
#elif defined(__WXMAC__)
    #include "wx/mac/button.h"
#elif defined(__WXPM__)
    #include "wx/os2/button.h"
#elif defined(__WXSTUBS__)
    #include "wx/stubs/button.h"
#endif

由上面的代码,可以看到,如果你向编译器传送的是__WXMSW__的时候,button.h会从msw文件夹中继续导入button.h。这就是wxWindows支持多平台的方法。所以,wxWindows的运行机制,更像是一个解释器的运行机制。不论平台如何改变,编写的人无需考虑平台的问题,解释器会更具不同的平台,将相同的代码转换成不同的命令。
  当然,世界上的任何事物都是由两面性的,像wxWindows也有它的缺点。首先,使用wxWindows的界面,往往体积比较大,基本在1M以上。而且,会随界面的复杂而上升。不过,这主要取决于你使用的头文件的多少。通常不会有突变的情况。当然,这也不是不可以改变的。如果用ZIP等压缩一下的话,通常都会只有原来的50%或者更低30%我像,这或许是取决于编译器和代码自身的问题。应该可以解决的。另外,wxWindows的简化也会给使用的人带来不少的麻烦。比如:

wxNotebook *p_note = new wxNotebook(frame,-1);
p_note->AddPage(new wxPanel(frame,-1),"1");
p_note->AddPage(new wxPanel(frame,-1),"2");
p_note->DeletPage(0);

如果,你没有使用过或者刚使用wxWindows,一定会以为这个代码会造成内存泄漏。因为,没有显式删除new生成的内存空间。最初我也是这样想的,但是后来才发现。wxWindows会自动为你在DeletPage(0)时删除new占用的空间。对于用惯C++的人来说,这的确会造成一些混乱。不过,这也是wxWindows的好心被人误解了吧。最后的问题是wxWindows在某些方面的不灵活。比如,要设计一个不规则的窗口就几乎是不太可能的。而且,不如wxTextCtrl中的右键菜单是英文的,修改他的确也有些麻烦。以上是我使用wxWindows时发现的一些问题。不过,既然Borland使用了wxWindows。我想wxWindows会越来越更完善的。
  最后,感谢各位的阅读。希望各位前辈能为小生的文章多多指教。我想以后wxWindows不只是C++BuildX的专利。你也可以在你喜欢的IDE中使用wxWindows。


STUDIO软件开发组
 楼主| 发表于 2005-4-26 20:57:44 | 显示全部楼层
wxWindows  Frame程序简化版

前几天给出了一个最简单的Hello World 程序, 由于这几天我还在学习wxWindows, 所以把今天做的第一个Frame框架程序写出来,给大家分享.

1.  新建一个Win32 Application,名字为Frame,然后选择Empty Project,点Finish完成.
2.  Insert 一个Class, Class Type为Generic Class,名字为 CMyApp ,基类信息中Deviced From 填入wxApp,类别为Public(默认),弹出对话框点OK.
3.  在ClassView中双击CMyApp的构造函数CMyApp(),在MyApp.cpp中加入#include "wx\wx.h"
4.  在ClassView中右键单击CMyApp,选择添加成员函数,加入一个Public的virtual bool OnInit()成员函数.
5.  修改CMyApp的OnInit()如下
    bool CMyApp::OnInit()
    {
     wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, _T("我的第一个框架窗口"),wxPoint(100,100),wxSize(400,300));
     // 创建状态栏
     frame->CreateStatusBar();
     frame->SetStatusText(_T("状态栏就绪"));
     // 显示窗口
     frame->Show(TRUE);
     SetTopWindow(frame);
     return true;
    }
6.  在CMyApp:CMyApp(){}前面加入IMPLEMENT_APP(CMyApp),看下面:
    IMPLEMENT_APP(CMyApp)
    CMyApp::CMyApp()
    {
   
    }
7   这个时候你如果点编译按钮的话,会出现一个致命错误(Fatal Error)
    fatal error C1083: Cannot open include file: 'wx/setup.h': No such file or directory
    怎么解决?看下面
8.  设置好Settings
    win32 Debug配置
    C++选项卡
    预处理定义为: _DEBUG,WIN32,_WINDOWS,_MT,WINVER=0x400,_wxUSE_GUI,__WXDEBUG__,WXDEBUG=1
    额外包含头文件目录为: $(WXWIN)\lib\mswd
    预编译头文件选择 Automatic use of precompiled headers
    Code Generation 中的Use Runtime library 选择 Debug MultiThreaded DLL
    Link选项卡
    在对象代码模块最后,添加comctl32.lib rpcrt4.lib wsock32.lib wxmswd.lib , 这4个库
////////////////////////
//源文件附在后面
//////////////////
// MyApp.h: interface for the CMyApp class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MYAPP_H__08DC4B2E_BCC2_48EC_A02A_D82513125055__INCLUDED_)
#define AFX_MYAPP_H__08DC4B2E_BCC2_48EC_A02A_D82513125055__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CMyApp : public wxApp  
{
public:
virtual bool OnInit();
CMyApp();
virtual ~CMyApp();

};
DECLARE_APP(CMyApp)
#endif // !defined(AFX_MYAPP_H__08DC4B2E_BCC2_48EC_A02A_D82513125055__INCLUDED_)
//-------------------------------------------------------------------------
// MyApp.cpp: implementation of the CMyApp class.
//
//////////////////////////////////////////////////////////////////////
#include "wx\wx.h"
#include "MyApp.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_APP(CMyApp)
CMyApp::CMyApp()
{

}

CMyApp::~CMyApp()
{

}

bool CMyApp::OnInit()
{
wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, _T("我的第一个框架窗口"),wxPoint(100,100),wxSize(400,300));
// 创建状态栏
frame->CreateStatusBar();
frame->SetStatusText(_T("状态栏就绪"));
// 显示窗口
frame->Show(TRUE);
SetTopWindow(frame);
return true;
}




作者Blog:http://blog.csdn.net/huyoo/
回复

使用道具 举报

 楼主| 发表于 2005-4-26 22:11:41 | 显示全部楼层
将 MFC 应用程序移植到 Linux
http://www-128.ibm.com/developerworks/cn/linux/guitoolkit/l-mfc/
循序渐进使用 wxWindows 的指南

Markus Neifer
软件开发人员
2002 年 4 月

将 Windows 应用程序移植到 Linux 不必涉及再培训的痛苦经历。Markus Neifer 演示了如何使用 wxWindows 移植 MFC,指导读者使用 wxWindows 这一开放源码工具箱,并循序渐进地向读者介绍了一个完整的移植示例。
您可能仍然在维护用微软基础类库(Microsoft Foundation Classes(MFC))构建的旧的 Windows 应用程序,而现在却有客户要求 Linux 版本,该怎么办呢?在您的团队中可能有技术熟练的 MFC 开发人员,但如何达到加速 Linux 开发呢?别急;本文就是针对您这种情况而写的。依靠 wxWindows(一种用于 C++ 和 Python 的可移植 GUI 工具箱)的帮助,我将以多文档界面(Multiple Document Interface (MDI))文本编辑器为例向您演示如何将仅 Windows 的 MFC 应用程序移植到 Linux。类似这样的小型应用程序有助于我们将讨论集中在移植框架的具体细节上,从而避免我们迷失在代码的汪洋中。可以在本文后面的 参考资料一节中获取完整的 MFC 应用程序和 wxWindows 应用程序的源代码。

文档/视图概述
我将演示的应用程序使用众所周知的文档/视图体系结构,因为它可以象大多数应用程序一样处理文档。即使您的应用程序不使用文档/视图体系结构,我也建议您读下去。只要您已在转向这种框架,您就可能想要添加这项功能。

在我的关于 wxWindows 的 前一篇文章中,曾经指出过 MFC 和 wxWindows 之间具有某些相似性。字符串类 CString 、 wxString 和事件系统之间都非常相似。但还不止这些相似性。wxWindows 工具箱还提供对文档/视图体系结构的类 MFC 支持。

我将从核心类的比较开始。下表列出了两种框架的文档/视图体系结构所涉及的类。

表 1. 文档/视图类比较
类  MFC 类  wxWindows 类  
文档(Document) CDocument wxDocument
视图(View) CView wxView
编辑视图(Edit view) CEditView n/a
模板类(Template class) CMultiDocTemplate wxDocTemplate
MDI 父框架(MDI parent frame) CMDIFrameWnd wxDocMDIParentFrame
MDI 子框架(MDI child frame) CMDIChildWnd wxDocMDIChildFrame
文档管理器(Document manager) n/a wxDocManager


除编辑视图类以外,每个 MFC 类都有其对应的 wxWindows 类。(最后一项中 MFC 的部分为空,因为 MFC 没有独立的文档管理器类。由应用程序类 CWinApp 内部处理文档。)下列 UML 图演示了这些类之间的关系:

图 1. MFC 类


图 2. wxWindows 类


应用程序
每个框架都提供一个表示应用程序本身的类。MFC 应用程序类声明了一个构造器、一个用于初始化的方法、一个用于事件处理的方法和一个消息映射表。您需要这个消息映射表声明和事件处理方法,因为应用程序的“about”对话框将由该类处理。

应用程序类:MFC

class CPortMeApp : public CWinApp
{
public:
    CPortMeApp();
    virtual BOOL InitInstance();
    afx_msg void OnAppAbout();
    DECLARE_MESSAGE_MAP()
};



注:最初创建 MFC 应用程序时,我使用 Microsoft Visual Studio 所包含的应用程序向导来创建,但在我的代码片段中,我将不给出由向导生成的、有时会使人迷惑的注释( //{{AFX_MSG 及类似的东西)。完整的源代码,请参阅 ZIP 压缩文档。

对应的 wxWindows 类看起来略微有些不同。它也声明了一个构造器及一个用于初始化的方法,但却不需要任何东西来处理消息。如同您随后将看到的一样,在主框架类中处理“about”对话框。

应用程序类:wxWindows

class PortedApp : public wxApp
{
  public:
    PortedApp();
    bool OnInit();
    int OnExit();
  protected:
    wxDocManager* m_docManager;
};


正如下面所描述的那样,这个类需要一个 wxDocManager 属性来处理在初始化方法 OnInit() 中创建的模板。应用程序退出时,清理方法 OnExit() 将删除这个 wxDocManager 对象。

所有应用程序都需要其入口点(也称为 main() 或 WinMain() )。在实现这一点的方法上,两种框架略微有些不同。在 MFC 中,象这样创建应用程序类的静态对象:


CPortMeApp theApp;



在 wxWindows 中,则象这样使用 IMPLEMENT_APP() 宏:


IMPLEMENT_APP(PortedApp)



如果对该宏所做的事情感兴趣,请查看头文件 wx/app.h 中它的定义,在可下载的源代码中找到该头文件。基本上,它是为所使用的平台插入适当的入口点函数。创建了应用程序类的对象之后,需要对其进行初始化。对于 MFC,Microsoft 建议不使用应用程序对象的构造器来初始化对象。而是应该使用其 InitInstance() 方法。要执行任何清理,请实现 ExitInstance() 方法。

虽然应用程序初始化有很多事情要做,这里我将只着重讨论与文档/视图有关的代码。要建立文档/视图框架, InitInstance() 方法必须创建一个 CMultiDocTemplate ,如下所示:

创建文档/视图代码:MFC

CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
    IDR_PORTMETYPE,
    RUNTIME_CLASS(CPortMeDoc),
    RUNTIME_CLASS(CChildFrame),
    RUNTIME_CLASS(CPortMeView));



wxWindows 应用程序提供 OnInit() 方法来做任何初始化工作,并提供 OnExit() 用于清理。要在 wxWindows 应用程序中建立文档/视图框架, OnInit() 方法必须象这样创建 wxDocTemplate :

创建文档/视图代码:wxWindows

m_docManager = new wxDocManager();

wxDocTemplate* pDocTemplate;
pDocTemplate = new wxDocTemplate(
    m_docManager, "Pom", "*.pom", "", "pom", "Pom Doc", "Text View",
    CLASSINFO(PortedDoc),
    CLASSINFO(PortedView));



MFC 和 wxWindows 所做的事情基本上相同。框架需要关于哪个文档同哪个视图有关以及这个组合处理哪种文档的信息。类型包括文档的描述性名称以及这类文档的文件扩展名。两种框架都使用模板来处理这一问题(请注意这与标准 C++ 模板没有什么关系)。

MFC CMultiDocTemplate 也保存关于同文档相关联的子框架的信息,并且该模板被添加到管理该模板的应用程序对象中。wxWindows wxDocTemplate 额外需要一个管理模板的 wxDocManager 对象。请记住, wxDocManager 是 wxWindows 应用程序的应用程序类的一个属性。

完成文档/视图框架初始化之后,就创建了应用程序的主框架。在 MFC 应用程序的 InitInstance() 方法中,按如下创建一个主框架:

创建主框架:MFC

CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
    return FALSE;

m_pMainWnd = pMainFrame;

pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();



调用 pMainFrame->LoadFrame(IDR_MAINFRAME) 从资源文件装入所有关于主框架的信息。

在 wxWindows 中,可以从资源文件建立菜单、对话框以及控件,或者可以在代码中创建它们。我更喜欢在代码中创建它们,但如果您愿意将代码同资源分离,就应该看一看 wxWindows 资源系统(请参阅 wxWindows 文档中的主题概述)。

创建主框架:wxWindows

m_mainFrame = new MainFrame(m_docManager, (wxFrame*) NULL, "DocView Demo",
                            wxPoint(0, 0), wxSize(500, 400),
                            wxDEFAULT_FRAME_STYLE);

// Set up menu bar...

m_mainFrame->SetMenuBar(menu_bar);
m_mainFrame->Centre(wxBOTH);
m_mainFrame->Show(TRUE);

SetTopWindow(m_mainFrame);



在查看应用程序初始化完成后发生了什么事情之前,让我向您演示每个框架的文档和视图类。

文档
文档保存应用程序处理的基于文件的数据。它负责从文件装入该数据,并在必要的时候将该数据保存回文件。该 MFC 类的声明类似于这样:

文档类声明:MFC

class CPortMeDoc : public CDocument
{
  protected:
    CPortMeDoc();
    DECLARE_DYNCREATE(CPortMeDoc)

  public:
    virtual BOOL OnNewDocument();
    virtual void Serialize(CArchive& ar);

    virtual ~CPortMeDoc();
    DECLARE_MESSAGE_MAP()
};



请注意:该类有一个受保护(protected)的构造器。决不要直接创建该类的任何对象;相反,框架使用序列化来创建文档。因此,需要使用 DECLARE_DYNCREATE() 宏。wxWindows 类的声明类似于这样:

文档类声明:wxWindows

class PortedDoc : public wxDocument
{
  public:
    virtual bool OnSaveDocument(const wxString& filename);
    virtual bool OnOpenDocument(const wxString& filename);
    virtual bool IsModified() const;
    virtual void Modify(bool mod);

  private:
    DECLARE_DYNAMIC_CLASS(PortedDoc)
};



DECLARE_DYNAMIC_CLASS() 宏是必需的,因为 wxWindows 就象 MFC 一样动态地创建该类的对象。

视图
如果 MFC 应用程序处理文本文档,那么从 CEditView 派生视图类是一个好主意。该类已经在其客户机窗口内提供了基本的编辑功能和文本控件。这里我遵循自己的建议,MFC 视图类的声明类似于这样:

视图类声明:MFC

class CPortMeView : public CEditView
{
  protected:
    CPortMeView();
    DECLARE_DYNCREATE(CPortMeView)

  public:
    CPortMeDoc* GetDocument();
    virtual void OnDraw(CDC* pDC);
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

    virtual ~CPortMeView();
    DECLARE_MESSAGE_MAP()
};



在 wxWindows 中,(还)没有专门的编辑视图。但是创建您自己的编辑视图却很容易。只需在视图框架内有一个由 wxTextCtrl 派生的文本控件。视图类将控件和框架都当作类属性来处理。因此 wxWindows 声明类似于这样:

视图类声明:wxWindows

class PortedView : public wxView
{
  public:
    MyTextCtrl* textsw;

    PortedView();

    bool OnCreate(wxDocument* doc, long flags);
    void OnDraw(wxDC* dc);
    bool OnClose(bool deleteWindow = TRUE);

  private:
    wxMDIChildFrame* CreateChildFrame(wxDocument* doc, wxView* view);

    wxFrame* frame;

    DECLARE_DYNAMIC_CLASS(PortedView)
};



除了常见的用于窗口创建、窗口重画以及窗口关闭的事件处理程序之外,该类还有一个创建框架并填充其菜单栏的方法。

虽然拥有公共(public)属性不是一个好主意,但是为简单起见,我在这里还是这么做。在您的应用程序中应该避免这么做(我将在以后的版本中除去它)。

主框架
既然已经有了处理和显示数据的文档和视图类,并且也有了处理文档/视图框架的应用程序类,现在需要一个主框架类来同用户交互。同样,两种框架提供类似的功能,而实际实现有略微不同。MFC 主框架类将一个状态栏和一个工具栏作为属性保存,同时 MFC 主框架类还提供一些方法来处理窗口创建,以及声明消息映射表。请注意:该类是从 CMDIFrameWnd 派生而来的,因为该应用程序有一个 MDI 界面。

主框架类:MFC

class CMainFrame : public CMDIFrameWnd
{
public:
        CMainFrame();
        virtual ~CMainFrame();

        virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:
        CStatusBar  m_wndStatusBar;
        CToolBar    m_wndToolBar;

        afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

        DECLARE_MESSAGE_MAP()

private:
        DECLARE_DYNAMIC(CMainFrame)
};



wxWindows 主框架类将菜单作为属性保存,还具有创建其工具栏的方法,以及声明一个事件表外加一个处理应用程序的 about 对话框的方法。因为这个应用程序有一个 MDI 界面,所以该类是从 wxDocMDIParentFrame 派生而来。

主框架类:wxWindows

class MainFrame : public wxDocMDIParentFrame
{
  public:
    wxMenu* editMenu;

    MainFrame(wxDocManager* manager, wxFrame* frame, const wxString& title,
              const wxPoint& pos, const wxSize& size, long type);

    void OnAbout(wxCommandEvent& event);
    void RecreateToolbar();

  private:
    DECLARE_CLASS(MainFrame);
    DECLARE_EVENT_TABLE();
};



全部工作原理
移植完成了。我来回顾一下实现这一点所需做的事情。MFC 应用程序类(派生自 CWinApp )移植到派生自 wxApp 的应用程序类,包括初始化代码。将 MFC 文档类(派生自 CDocument )移植到派生自 wxDocument 的文档类。将 MFC 视图类(派生自 CView )移植到派生自 wxView 的文档类。除了这些同文档/视图有关的类之外,将 MFC 主框架类(派生自 CMDIFrameWnd )移植到派生自 wxDocMDIParentFrame 的类。

在其目前的版本中,该应用程序已经能够做很多工作。可以处理多个文本文件。可以打开、编辑并保存这些文件,并且应用程序保持最近打开文件的历史记录。如果不得不从头编写这些功能,那么将需要更多行代码 ― 更多行代码意味着要测试和维护更多行。在两种框架中,都使用了专门的命令标识符来处理常用的同文档/视图有关的命令。常用的文件命令是新建、打开和保存。常用的编辑命令是剪切、复制和粘贴。其它经常使用的命令有打印命令(这个应用程序中还没有实现该命令)和帮助命令。下表列出了这两种框架结构的文档/视图体系结构所包含的命令标识符。

表 2. 标准的命令标识符
MFC  wxWindows  
ID_FILE_OPEN wxID_OPEN
ID_FILE_CLOSE wxID_CLOSE
ID_FILE_NEW wxID_NEW
ID_FILE_SAVE wxID_SAVE
ID_FILE_SAVE_AS wxID_SAVEAS
ID_EDIT_CUT wxID_CUT
ID_EDIT_COPY wxID_COPY
ID_EDIT_PASTE wxID_PASTE
ID_APP_EXIT wxID_EXIT
ID_EDIT_UNDO wxID_UNDO
ID_EDIT_REDO wxID_REDO
ID_HELP_INDEX wxID_HELP
ID_FILE_PRINT wxID_PRINT
ID_FILE_PRINT_SETUP wxID_PRINT_SETUP
ID_FILE_PRINT_PREVIEW wxID_PREVIEW


窗口管理器
如果您对 Linux 开发真的很感兴趣,则可能已经做了一些研究,发现 Linux 上有不同的窗口管理器。曾经是 MFC 开发人员的您可能觉得这很奇怪。在进行 Windows 开发时,您无须操心不同的窗口管理器,因为只有一个窗口管理器。

开始 wxWindows 开发时,您可能想知道您的应用程序是否将运行在两个主流的窗口管理器 ― K 桌面环境(K Desktop Environment (KDE))和 GNOME ― 之上。我已经在 Microsoft Windows NT 4.0、使用公共桌面环境(Common Desktop Environment (CDE))的 Sun Solaris 2.6 以及使用 KDE 的 Linux 2.2 上使用了 wxWindows 工具箱,没有任何问题。由于 wxWindows 仅仅是一个建立在其它低级别 GUI 工具箱上的高级别层次,所以可以选择如何构建 Linux 应用程序。可以使用 Motif 版本(或者还要更好一些的,免费 Lesstif)或者 wxWindows 的 GTK+ 版本。GTK+ 是 GNOME 使用的基础窗口构件工具箱,但是它在 KDE 下也运行得非常好。我建议您使用 GTK+ 版本,因为它通常更新,有许多开发人员对它进行开发,而且有用户在使用它。因此,如果您希望获得更多帮助,则可以求助于邮件列表或新闻组,询问关于 GTK+ 版本的问题。

下面是前前后后的抓屏,可以让您对移植的应用程序有一个大致的认识。

图 3. 原始的 MFC 应用程序


图 4. Windows 上的 wxWindows 应用程序


图 5. Linux/KDE 上的 wxWindows 应用程序


真实的故事
wxWindows 工具箱不只是书呆子的另一个玩具。它成熟、稳定,并且人们在实际应用程序中用它来解决实际问题。

wxWindows 项目创始人 Julian Smart 目前致力于 Red Hat,他已经将 eCos 配置工具(eCos Configuration Tool)移植到了 wxWindows。eCos 配置工具是一个配置 eCos 嵌入式操作系统的图形工具。人们已将最初的 MFC 应用程序移植到了 wxWindows,尤其是在 Linux 上(参阅 参考资料)。 SciTech Software 的人员也已经使用 wxWindows 来全部重新开发用于 SciTech Display Doctor 产品的前端 GUI。IBM 已经获得了 SciTech Display Doctor 的一个专门版本的许可证,IBM 现在将其作为 IBM 所有基于 OS/2 Warp 的操作系统(包括 Warp Client、Workspace On Demand 及 Warp Server for e-business)的主要显示驱动程序来分发。SciTech Software 对 wxWindows 社区做出了积极的贡献,它提交了扩展包 wxApplet、wxUniversal 和 wxMGL。使用 wxMGL,wxWindows 应用程序甚至可以运行在 DOS 和其它嵌入式操作系统之上,例如 QNX、RT-Target、SMX 等等。SciTech Software 全力资助 wxUniversal 和 wxMGL 项目(参阅 参考资料)。

结束语
本文演示了使用 wxWindows 工具箱将 MFC 文档/视图框架的 Windows 应用程序移植到 Linux 的基本原理。wxWindows 工具箱同 MFC 框架有一些相似性,从而帮助 MFC 开发人员可以达到加速 Linux 开发。有了这些基础知识,您应该能够将最棒的应用程序移植到 Linux。但不要忘了:wxWindows 不是只能用于 Linux。也许该是考虑在其它 UNIX 或者甚至 Macintosh 上来运行您的应用程序一个版本的时候了。
回复

使用道具 举报

 楼主| 发表于 2005-4-26 22:15:37 | 显示全部楼层
跨平台C++程序开发的利器
跨平台C++程序开发的利器
wxWindows原来叫做wxWidgets,是由Julian Smart于1992年还在英国爱丁堡大学人工智能应用研究所开始的一个项目。Julian Smart现在是Anthemion软件公司的技术总监。1995年的时候,Markus Holzem发布了一个移植到Xt (X Toolkit)的版本。1997年五月,Windows版本和GTK+版本被合并。

简单地说,wxWidgets提供了用于可在多平台上开发GUI应用程序的一整套简单易学易用的API。wxWidgets支持的多平台包括Windows 3.1/95/98/NT/2000/XP、带有Motif 1.2版本以上的Unix、带有GTK+的Unix/Linux/*BSD、Mac等等。开发者只需要用自己使用的系统平台的编译器编译源程序,并链接上相应的库文件,生成的程序代码即具有该平台的外观和界面。在这些GUI之上,wxWidgets还提供了在线帮助、网络编程、流处理、多种常用图形格式支持、数据库支持、HTML察看和打印,等等各种强大的功能。

wxWidgets支持的Windows上的多种流行编译器包括:

Visual C++ 1.5, 4.0, 5.0, 6.0
Borland C++ 4.5, 5.0
Borland C++ Builder 1.0, 3.0
Watcom C++ 10.6 (Win32)
Cygwin
MinGW32
Metrowerks CodeWarrior 4
wxWidgets的一大吸引力是它的wxWidgets 2 licence类型是属于L-GPL (Library General Public Licence)的,也就是说,使用它开发的软件并不要求一定得公开源码。这样,无论是免费软件的开发者、GPL类型软件开发者,还是纯粹商业软件开发者都可以免费使用这个软件包。

相比之下,TrollTech的Qt似乎正是因为此因素而影响了它的受接受程度,因为用Qt开发商用软件者所需交纳的费用对于个人开发者来说还是比较昂贵的,而且分单平台、二平台、三平台(即Qt/X11、Qt/Windows和Qt/Mac都包含在内了)三个不同产品包,又分Professional和Enterprise不同Edition亦即不同价位,而且开发人员数不同价格也不同。

从这点说来,wxWidgets是绝对具有优势的。

另外Qt似乎是起源于Linux上的开发,后来推展到Windows、Mac等其它平台;而wxWidgets恰好相反,始于Windows,其后移植到Unix等其它平台。不过这一点本人尚未深入去调查具体情况,所以姑且听之吧。

http://www.silu.org/articles/article.php?articleid=9
回复

使用道具 举报

发表于 2005-4-27 17:27:58 | 显示全部楼层
还不错。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-6 03:37 , Processed in 0.042472 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表