天天看點

細述 wxWindows細述 wxWindows

http://www-128.ibm.com/developerworks/cn/linux/sdk/python/wxwin/

細述 wxWindows

可移植 C++ 和 Python 工具箱簡介
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
文檔選項
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
未顯示需要 JavaScript 的文檔選項
<script language="JavaScript" type="text/javascript"> </script>
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
列印本頁
<script language="JavaScript" type="text/javascript"> </script>
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
将此頁作為電子郵件發送

級别: 初級

Markus Neifer ([email protected]), 軟體工程師

2001 年 2 月 01 日

Markus Neifer 提供了有關 wxWindows -- 一種可移植的 C++ 和 Python GUI 工具箱 -- 的概述。他讨論了庫的體系結構,講述了如何安排多平台檔案處理和目錄分隔字元,并談到 wxHTML、圖像檔案格式和 Unicode。還介紹了一些有幫助的 wxWindows 調試小竅門,以及如何将 MFC 應用程式移植到 Linux。

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細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

要運用的平台

因為 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 災難”。

現在,讓我們看看多平台特性...

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

獨立于體系結構的類型

為避免體系結構的依賴性,該庫提供了各種獨立于體系結構的類型和宏,能夠根據應用程式的尾數來處理位交換。它們包括:

  • 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細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

檔案處理

要為具有不同檔案存儲器概念的不同平台進行編寫總是很困難的。要克服這一問題,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()

,用于将路徑從完整路徑中剝離。

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

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>" );
      
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

圖像

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...
    }
}
      
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

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

類的幫助下編譯庫的本地化版本後使用它。

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

調試

庫提供了各種不同的類、函數和宏來幫助您調試應用程式。如果以調試方式來編譯庫,用于類

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
      
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

将 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(我們也非常願意幫助您:)。

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 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細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

文檔

wxWindows 文檔就目前來說一點也不出色。雖然一些比較“陳舊”的類(例如

wxString

)文檔很齊全,但對最近實作的類(例如

wxGrid

)或更模糊的類(例如

wxGLCanvas

)的描述本應該做得更好。主要文檔提供了對庫及其概念的快速介紹、按照字母順序排列的類引用、程式設計政策、主題概述,以及對 wxHTML 和 wxPython 的某些注釋,提供了 HTML、WinHelp、MS HTML Help 和 PDF 格式(請參閱 參考資料)。

如果您剛剛接觸 wxWindows,應該從主題概述開始。它們提供了許多有關公共主題(例如調試、事件處理、列印等等)的基本資訊和代碼示例。主要文檔還包含了一些技術說明和教程,它們提供的主題資訊範圍從有關了解 wxWindows 的一些非常公共的問題到特定于編譯器的問題。您還将得到大量純文字檔案,包含用于所支援平台的安裝和發行說明。wxWindows 發行版還提供了随文檔一起的大約 50 個樣本應用程式。

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

支援

如 果您在使用庫時遇到問題,在文檔中又找不到答案該怎麼辦?不用擔心。通常您有兩種支援可選:使用郵件清單的免費支援,或商業支援。如果您不幸需要快速解 答,可能最好使用商業支援。雖然核心開發者總是會關注郵件清單,但他們往往很忙碌,無法立即做出響應。但您通常可以在一兩天内得到答案。(如果提的問題不 太尋常或比較複雜,則在再次提出問題之前應該至少等上兩天。)可以從 Sourceforge(請參閱 參考資料 )上的 CVS 源代碼資料庫通路最新的源碼。

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
回頁首

總結

現在您對 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 的專業人員資源組織

關于作者

細述 wxWindows細述 wxWindows
細述 wxWindows細述 wxWindows
Markus Neifer 最初在 LOGO 龜标的幫助下開始程式設計,在此之後他使用過各種版本的 BASIC。在研究 地理資訊期間,他學習了一段時間的 C,但随後很快轉向 C++ 和 Java,因為它們具有面向對象的性質。 他曾在 R&D 部門工作,在那期間, 他發表了有關面向對象的科學軟體開發的文章。 現在,他是地理資訊系統領域中的軟體工程師。可以通過 [email protected] 與他聯系。       

繼續閱讀