# 4.4 頂層窗口
頂層窗口直接被放置在桌面上而不是包含在其它窗口之內。如果應用程序允許,他們可以被移動或者重新改變大小。總共有三種基礎的頂層窗口類型。 wxFrame和wxDialog都是從一個虛類wxTopLevelWindow繼承來的。另外一個wxPopupWindow功能相對簡單,是直接從 wxWindow繼承過來的。一個dialog既可以是模式的也可以是非模式的,而frame通常都是非模式的。模式對話框的意思是說當這個對話框彈出時,應用程序除了等待用戶關閉這個對話框以外不再作別的事情。對于那些要等待用戶響應以后才能繼續的操作來說。這是比較合適的。但是尋找替代的解決方案通常也不是一件壞事。舉例來說,在工具條上設置一個字體選項可能比彈出一個模式的對話框讓用戶選擇字體更能是整個應用程序看上去更流暢。
頂層窗口通常都擁有一個標題欄,這個標題欄上有一些按鈕或者菜單或者別的修飾用來關閉,或者最小化,或者恢復這個窗口。而frame窗口則通常還會擁有菜單條,工具條和狀態條。但是通常對話框則沒有這些。在Mac OS X上,frame窗口的菜單條通常不是顯示在frame窗口的頂部而是顯示在整個屏幕的頂部。
不要被"頂層窗口"的叫法和wxApp::GetTopWindow函數給搞糊涂了。wxWidgets使用后者來得到應用程序的主窗口,這個主窗口通常是你在應用程序里創建的第一個frame窗口或者dialog窗口。
如果需要,你可以使用全局變量wxTopLevelWindows來訪問所有的頂層窗口,這個全局變量是一個wxWindowList類型.
wxFrame
wxFrame是主應用程序窗口的一個通用的選擇。下圖演示了常見的各個frame窗口元素。frame窗口擁有一個可選的標題欄(上面有一些類似關閉功能的按鈕),一個菜單條,一個工具欄,一個狀態欄。剩下的區域則稱為客戶區,如果擁有超過一個子窗口,那么他們的尺寸和位置是由應用程序決定的。你應該通過第7章中會講到的窗口布局控件來作相關的事情。或者如果只有兩個子窗口的話,你可以考慮使用一個分割窗口。后者我們稍后就會講到。
.tmp)
在某些平臺上不允許直接繪制frame窗口,因此你應該增加一個wxPanel作為容器來放置別的子窗口控件,以便可以通過鍵盤來遍歷各個控件。
frame窗口是允許包含多個工具條的,但是它只會自動放置第一個工具條。因此你需要自己明確的布局另外的工具條。
你很應該基于wxFrame實現你自己的frame類而不是直接使用wxFrame類,并且在其構造函數中創建自己的菜單條和子窗口。這會讓你更方便處理類似wxEVT_CLOSE事件和別的命令事件。
你可以給frame窗口指定一個圖標以便讓系統顯示在任務欄上或者文件管理器中。在windows平臺上,你最好指定一組16x16和 32x32并且擁有不同顏色深度的圖標。在linux平臺上也一樣,windows系統上的圖標已經足夠。而在Max OsX上,你需要更多的不同顏色和深度的圖標。關于圖標和圖標列表的更多信息,可以參考第10章,???在應用程序中使用圖片???。
除了默認的構造函數以外,wxFrame還擁有下面的構造函數
```
wxFrame(wxWindow* parent, wxWindowID id, const wxString& title,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE,
const wxString& name = wxT("frame"));
```
例如:
```
wxFrame* frame = new wxFrame(NULL, ID_MYFRAME,
wxT("Hello wxWidgets"), wxDefaultPosition,
wxSize(500, 300));
frame->Show(true);
```
注意在你顯式的調用Show函數之前,frame是不會被顯示的。以便應用程序有機會在所有的子窗口還沒有被顯示的時候進行窗口布局。
沒有必要給這個新建的frame窗口指定父窗口。如果指定了父窗口并且指定了wxFRAME_FLOAT_ON_PARENT類型位,這個新建的窗口將會顯示在它的父窗口的上層。
要刪除一個frame窗口,應該使用Destroy方法而不是使用delete操作符,因為Destroy會在處理完這個窗口的所有事件以后才真正釋放這個窗口。調用Close函數會導致這個窗口收到wxEVT_CLOSE事件,這個事件默認的行為是調用Destroy方法。當一個 frame窗口被釋放時。它的所有的子窗口都將被釋放,誰叫他們自己不是頂層窗口呢。
當最后一個頂層窗口被釋放的時候,應用程序就退出了(這種默認的行為可以通過調用wxApp:: SetExitOnFrameDelete改變)。你應該在你的主窗口的wxEVT_CLSE事件處理函數中調用Destroy釋放其它的頂層窗口(比如一個查找對話框之類),否則可能出現主窗口已經關閉但是應用程序卻不退出的情況。
frame窗口沒有類似dialog窗口那樣的wxDialog::ShowModal方法可以禁止其它頂層窗口處理消息,然后,還是可以通過別的方法達到類似的目的。一個方法是通過創建一個wxWindowDisabler對象,另外一個方法是通過wxModalEventLoop對象,傳遞這個frame窗口的指針作為參數,然后調用Run函數開始一個本地的事件循環,然后調用Exit函數(通常是在這個Frame窗口的某個事件處理函數里)退出這個循環。
下圖演示了一個用戶應用程序的frame窗口在windows上運行的樣子。這個frame窗口擁有一個標題欄,一個菜單條,一個五彩的工具欄,在frame窗口的客戶區有個分割窗口,底端有一個狀態條,正顯示著當用戶的鼠標劃過工具條上的按鈕或者菜單項的時候顯示的提示。
.tmp)
wxFrame的窗口類型比特位
Frame窗口比起基本窗口類,增加了下面一些類型:
| wxDEFAULT_FRAME_STYLE | 其值為 wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX. |
|:--- |:--- |
| wxICONIZE | 以最小化的方式顯示窗口。目前只適用于Windows平臺. |
| wxCAPTION | 在窗口上顯示標題. |
| wxMINIMIZE | 和wxICONIZE的意義相同. 也只適用于Windows平臺. |
| wxMINIMIZE_BOX | 顯示一個最小化按鈕. |
| wxMAXIMIZE | 以最大化方式顯示窗口. 僅適用于Windows. |
| wxMAXIMIZE_BOX | 在窗口上顯示最大化按鈕. |
| wxCLOSE_BOX | 在窗口上顯示關閉按鈕. |
| wxSTAY_ON_TOP | 這個窗口顯示在其它所有頂層窗口之上.僅適用于Windows. |
| wxSYSTEM_MENU | 顯示系統菜單. |
| wxRESIZE_BORDER | 邊框可改變大小. |
| wxFRAME_TOOL_WINDOW | 窗口的標題欄比正常情況要小,而且在windows平臺上,這個窗口不會在任務欄上顯示. |
| wxFRAME_NO_TASKBAR | 創建一個標題欄是正常大小,但是不在任務欄顯示的窗口。目前支持windows和linux。需要注意在windows平臺上,這個窗口最小化時將會最小化到桌面上,這有時候會讓用戶覺得不習慣,因此這種類型的窗口最好不要使用wxMINIMIZE_BOX類型。 |
| wxFRAME_FLOAT_ON_PARENT | 擁有這種類型的窗口總會顯示在它的父窗口的上層。使用這種類型的窗口必須擁有非空父窗口,否則可能引發斷言錯誤. |
| wxFRAME_SHAPED | 擁有這種類型的窗口可以通過調用SetShape函數來使其呈現不規則窗口外貌. |
下表列出的是frame窗口的擴展類型,需要使用wxWindow::SetExtraStyle函數才可以設置擴展類型
| wxFRAME_EX_CONTEXTHELP | 在windows平臺上,這個擴展類型導致標題欄增加一個幫助按鈕。當這個按鈕被點擊以后,窗口會進入一種上下文幫助模式。在這種模式下,任何應用程序被點擊時,將會發送一個wxEVT_HELP事件。 |
|:--- |:--- |
| wxFRAME_EX_METAL | 在Mac OS X平臺上,這個擴展類型將會導致窗口使用金屬外觀。請小心使用這個擴展類型,因為它可能會假定你的應用程序用戶默認安裝類聲卡之類的多媒體設備。 |
wxFrame的事件
下表列出了frame窗口比基本窗口類增加的事件類型:
| EVT_ACTIVATE(func) | 用來處理wxEVT_ACTIVATE事件, 在frame窗口被激活或者去激活的時候產生.處理函數的參數類型為wxActivateEvent. |
|:--- |:--- |
| EVT_CLOSE(func) | 用來處理wxEVT_CLOSE事件, 在應用程序準備關閉窗口的時候產生. 處理函數的參數類型是wxCloseEvent。這個類型支持Veto函數調用以阻止這個事件的進一步處理. |
| EVT_ICONIZE(func) | 用來處理wxEVT_ICONIZE事件, 當窗口被最小化或者被恢復普通大小的時候產生.處理函數的參數類型為wxIconizeEvent. 通過使用IsIconized函數來判斷究竟是最小化事件還是恢復事件. |
| EVT_MAXIMIZE(func) | 用來處理wxEVT_MAXIMIZE事件, 當窗口被最大化或者從最大化恢復的時候產生. 處理函數的參數類型為wxMaximizeEvent. 通過IsMaximized函數判斷究竟是最大化還是從最大化狀態恢復. |
wxFrame的成員函數
下面將介紹wxFrame類的主要的成員函數。因為wxFrame類是從wxTopLevelWindow和wxWindow繼承過來的,請同樣參考這兩個類的成員函數。
CreateStatusBar函數在frame窗口的底部創建一個擁有一個或多個域的狀態欄. 可以使用SetStatusText函數來設置狀態欄上的文字,使用SetStatusWidths函數來設置狀態欄每個域的寬度(參考本章稍后對 wxStatusBar的介紹). 使用舉例:
```
frame->CreateStatusBar(2, wxST_SIZEGRIP);
int widths[3] = { 100, 100, -1 };
frame->SetStatusWidths(3, widths);
frame->SetStatusText(wxT("Ready"), 0);
```
CreateToolBar 函數在frame窗口的菜單條下創建一個工具欄. 當然你也可以直接創建一個wxToolBar實例,然后調用wxFrame::SetToolBar函數以便讓frame類來管理你剛創建的toolbar.
GetMenuBar用來SetMenuBar操作frame和綁定的菜單條.一個frame窗口只可以有一個菜單條。如果你新創建了一個,那么就的那個將被刪除和釋放。
GetTitle和SetTitle函數用來訪問窗口標題欄上的文本.
Iconize函數使得frame窗口最小化或者從最小化狀態恢復.你可以使用IsIconized函數檢查當前的最小化狀態.
Maximize函數使得frame窗口最大化或者從最大化狀態恢復. 你可以用IsMaximized函數來檢查當前的最大化狀態.
SetIcon函數可以設置在frame窗口最小化的時候顯示的圖標。各個平臺的窗口管理器也可能把這個圖標用于別的用途,比如顯示在任務條上或者在顯示在窗口瀏覽器中。你還可以通過SetIcons函數指定一組不同顏色和深度的圖標列表.
SetShape函數用來給frame窗口設置特定的顯示區域。目前支持這個函數的平臺有Windows, Mac OS X, 和GTK+以及打開某種X11擴展功能的X11版本.
ShowFullScreen函數使用窗口在全屏和正常狀態下切換,所謂全屏狀態指的是frame窗口將隱藏盡可能多的修飾元素,而盡可能把客戶區以最大化的方式顯示。可以使用IsFullScreen函數來檢測當前的全屏狀態.
不規則的Frame窗口
如果你希望制作一個外貌奇特的應用程序,比如一個時鐘程序或者一個媒體播放器,你可以給frame窗口指定一個不規則的區域,只有這個區域范圍內的部分才會被顯示出來。下圖演示了一個沒有任何標題欄,狀態欄,菜單條的frame窗口,它的重畫函數顯示了一個企鵝,這個窗口被設置了一個區域使得只有這個企鵝才會顯示。
.tmp)
顯示一個有著奇特外觀的程序的代碼并不復雜,你可以在附帶光盤的samples/shaped目錄里找到一個使用不同圖片的完整的例子。總的來說,當窗口被創建時,它加載了一幅圖片,并且使用這幅圖片的輪廓創建了一個區域。在GTK+版本上,設置窗口區域的動作必須在發送了窗口創建事件之后,所以你需要使用宏定義區別對待GTK+的版本。下面的例子演示了你需要怎樣對事件表,窗口的構造函數和窗口的創建事件處理函數進行修改:
```
BEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
EVT_MOTION(ShapedFrame::OnMouseMove)
EVT_PAINT(ShapedFrame::OnPaint)
#ifdef __WXGTK__
EVT_WINDOW_CREATE(ShapedFrame::OnWindowCreate)
#endif
END_EVENT_TABLE()
ShapedFrame::ShapedFrame()
: wxFrame((wxFrame *)NULL, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxSize(250, 300),
| wxFRAME_SHAPED
| wxSIMPLE_BORDER
| wxFRAME_NO_TASKBAR
| wxSTAY_ON_TOP
)
{
m_hasShape = false;
m_bmp = wxBitmap(wxT("penguin.png"), wxBITMAP_TYPE_PNG);
SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
#ifndef __WXGTK__
// On wxGTK we can't do this yet because the window hasn't
// been created yet so we wait until the EVT_WINDOW_CREATE
// event happens. On wxMSW and wxMac the window has been created
// at this point so we go ahead and set the shape now.
SetWindowShape();
#endif
}
// Used on GTK+ only
void ShapedFrame::OnWindowCreate(wxWindowCreateEvent& WXUNUSED(evt))
{
SetWindowShape();
}
```
為了創建一個區域模板,我們從一幅圖片的創建了一個區域,其中的顏色參數用來指定需要透明顯示的顏色,然后調用frame窗口的SetShape函數設置這個區域模板。
```
void ShapedFrame::SetWindowShape()
{
wxRegion region(m_bmp, *wxWHITE);
m_hasShape = SetShape(region);
}
```
為了讓這個窗口可以通過鼠標拖拽來實現在窗口上的移動,我們可以通過下面的鼠標移動事件處理函數:
```
void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
{
wxPoint pt = evt.GetPosition();
if (evt.Dragging() && evt.LeftIsDown())
{
wxPoint pos = ClientToScreen(pt);
Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
}
}
```
而重畫事件處理函數就比較簡單了,當然在你的真實的應用程序里,你可以在其中放置更多的圖形元素。
```
void ShapedFrame::OnPaint(wxPaintEvent& evt)
{
wxPaintDC dc(this);
dc.DrawBitmap(m_bmp, 0, 0, true);
}
```
你也可以參考wxWidgets的發行版中的samples/shaped目錄中的例子。
小型frame窗口
在Window平臺和GTK+平臺上,你可以使用wxMiniFrame來實現那些必須使用小的標題欄的窗口,例如,來實現一個調色板工具。下圖(譯者注:這個圖片應該是搞錯了,是下一個例子中的圖片,不過作者的翻譯源使用的就是這個圖片,沒有辦法了。)演示了windows平臺上的這種小窗口的樣子。而在Max Os X平臺上,這個小窗口則是直接使用的普通的frame窗口代替。其它方面wxMiniFrame和wxFrame都是一樣的。
.tmp)
wxMDIParentFrame
這個窗口類繼承自wxFrame,是wxWidgets的MDI(多文檔界面)體系的組成部分。MDI的意思是由一個父窗口管理零個或多個子窗口的一種界面架構。這種MDI界面結構依平臺的不同而有不同的外觀,下圖演示了兩種主要的外觀。在windows平臺上,子文檔窗口是排列在其父窗口內的一組frame窗口,這些文檔窗口可以被平鋪,層疊或者把其中的某一個在父窗口的范圍內最大化以便在某個時刻僅顯示一個文檔窗口。 wxWidgets會自動在主菜單上增加一組菜單用來控制文檔窗口的這些操作。MDI界面的一個優點是使得整個應用程序界面相對來說顯得不那么零亂。這一方面是由于因為所有的文檔窗口被限制在父窗口以內,另外一個方面,父窗口的菜單條會被活動的文檔窗口的菜單條替代,這使得多個菜單條的雜亂性也有所減輕。
.tmp)
而在GTK+平臺上,wxWidgets則通過TAB頁面控件來模擬多文檔界面。在某個時刻只能有一個窗口被顯示,但是用戶可以通過TAB頁面在窗口之間進行切換。在Mac Os上,MDI的父窗口和文檔窗口則都使用和普通的Frame窗口一樣的外觀,這符合這樣的一個事實就是在Mac Os上,文檔總是在一個新的窗口中被打開。
在那些MDI的文檔窗口包含在父窗口之中的平臺上,父窗口將把它的所有的文檔窗口排列在一個子窗口中,而這個窗口可以和frame窗口中的其它控件子窗口和平共處。在上圖中,父窗口將一個文本框控件和那些文檔窗口進行了這樣的排列。更詳細的情形請參考wxWidgets發行版本的 samples/mdi目錄中的例子。
除了父窗口的菜單條外,每一個文檔窗口都可以有自己的菜單條。當某個文檔窗口被激活時,它的菜單條將顯示在父窗口上,而沒有子文檔窗口被激活時,父窗口顯示自己的菜單條。在構建子文檔窗口的菜單條時,你應該主要要包含那些同樣命令的父窗口的菜單項,再加上文檔窗口自己的命令菜單項。父窗口和文檔窗口也可以擁有各自的工具條和狀態欄,但是這兩者并沒有類似菜單條這樣的機制。
wxMDIParentFrame類的構造函數和wxFrame類的構造函數是完全一樣的.
wxMDIParentFrame的窗口類型
wxMDIParentFrame類額外的窗口類型列舉如下:
| --- | --- |
| wxFRAME_NO_WINDOW_MENU | Under Windows, removes the Window menu that is normally added automatically. |
wxMDIParentFrame的成員函數
下面列出了wxMDIParentFrame類除了wxFrame的函數以外的主要成員函數。
ActivateNext和ActivatePrevious函數激活前一個或者后一個子文檔窗口。
Cascade和Tile層疊或者平鋪所有的子窗口. ArrangeIcons函數以圖標的方式平鋪所有最小化的文檔窗口.這三個函數都只適用于Windows平臺.
GetActiveChild獲取當前活動窗口的指針(如果有的話).
GetClientWindow函數返回那個包含所有文檔窗口的子窗口的指針.這個窗口是自動創建的,但是你還是可以通過重載 OnCreateClient函數來返回一個你自己的繼承自wxMDIClientWindow的類的實例。如果你這樣作,你就需要使用兩步創建的方法創建這個多文檔父窗口類.
wxMDIChildFrame
wxMDIChildFrame窗口應該總被創建為一個wxMDIParentFrame類型窗口的子窗口. 正如我們前面已經提到的那樣,依平臺的不同,這種類型的窗口既可以是在其父窗口范圍內的一組窗口列表,也有可能是在桌面上自由飛翔的普通的frame窗口。
除了父窗口必須不能為空,它的構造函數和普通的frame的構造函數是一樣的。
```
#include "wx/mdi.h"
wxMDIParentFrame* parentFrame = new wxMDIParentFrame(
NULL, ID_MYFRAME, wxT("Hello wxWidgets"));
wxMDIChildFrame* childFrame = new wxMDIChildFrame(
parentFrame, ID_MYCHILD, wxT("Child 1"));
childFrame->Show(true);
parentFrame->Show(true);
```
wxMDIChildFrame的窗口類型
wxMDIChildFrame和wxFrame的窗口類型是一樣的。盡管如此,不是所有的窗口類型的值在各個平臺上都是有效的。
wxMDIChildFrame的成員函數
wxMDIChildFrame的除其基類wxFrame以外的主要成員函數列舉如下:
Activate函數激活本窗口,將其帶到前臺并且使得其父窗口顯示它的菜單條。
Maximize函數將其在父窗口范圍內最大化(僅適用于windows平臺).
Restore函數使其從最大化的狀態恢復為普通狀態(僅適用于windows平臺)。
wxDialog
對話框是一種用來提供信息或者選項的頂層窗口。他可以有一個可選的標題欄,標題欄上可以有可選的關閉或者最小化按鈕,和frame窗口一樣,你也可以給它指定一個圖標以便顯示在任務欄或者其它的地方。一個對話框可以組合任何多個非頂層窗口或者控件,舉例來說,可以包含一個wxNoteBook控件和位于底部的兩個確定和取消按鈕。正如它的名字所指示的那樣,對話框的目的相比較于整個應用程序的主窗口,只是為了給用戶提示一些信息,提供一些選項等。
有兩種類型的對話框:模式的或者非模式的。一個模式的對話框在應用程序關閉自己之前阻止其它的窗口處理來自應用程序的消息。而一個非模式的對話框的行為則更像一個frame窗口。它不會阻止應用程序中的別的窗口繼續處理消息和事件。要使用模式對話框,你應該調用ShowModal函數來顯示對話框,否則就應該象frame窗口那樣,使用Show函數來顯示對話框。
模式對話框是wxWindow派生類中極少數允許在堆棧上創建的對象之一,換句話說,你既可以使用下面的方法使用模式對話框:
```
void AskUser()
{
MyAskDialog *dlg = new MyAskDialog(...);
if ( dlg->ShowModal() == wxID_OK )
...
dlg->Destroy();
}
```
也可以直接使用下面的方法:
```
void AskUser()
{
MyAskDialog dlg(...);
if ( dlg.ShowModal() == wxID_OK )
...
//這里不需要調用Destroy()函數
}
```
通常你應該從wxDialog類派生一個你自己的類,以便你可以更方便的處理類似wxEVT_CLOSE這樣的事件以及其它命令類型的事件。通常你應該在派生類的構造函數中創建你的對話框需要的其它控件。
和wxFrame類一樣,如果你的對話框只有一個子窗口,那么wxWidgets會自動為你布局這個窗口,但是如果有超過一個子窗口,應用程序應該自己負責窗口的布局(參考第7章)
當你調用Show函數時,wxWidgets會調用InitDialog函數來發送一個wxInitDialog事件到這個窗口,以便開始對話框數據傳輸和驗證以及其它的事情。
除了默認的構造函數,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 = wxT("dialog"));
```
例如:
```
wxDialog* dialog = new wxDialog(NULL, ID_MYDIALOG,
wxT("Hello wxWidgets"), wxDefaultPosition,
wxSize(500, 300));
dialog->Show(true);
```
在調用Show(true)函數或者ShowModal函數之前,對話框都是不可見的,以便其可以以不可見的方式進行窗口布局。
默認情況下,如果對話框的父窗口為NULL,應用程序會自動指定其主窗口為其父窗口,你可以通過指定wxDIALOG_NO_PARENT類型來創建一個無父無母的孤兒dialog類,不過對于模式對話框來說,最好不要這樣作。
和wxFrame類一樣,最好不要直接使用delete操作符刪除一個對話框,取而代之使用Destroy或者Close。以便在對話框的所有事件處理完畢以后才釋放對話框,當你調用Cloes函數時,默認發送的wxEVT_CLOSE事件的處理函數其實也是調用了Destroy函數.
需要注意,當一個模式的對話框被釋放的時候,它的某個事件處理函數需要調用EndModal函數,這個函數的參數是導致這次釋放的那個事件所屬窗口的窗口標識符(例如wxID_OK或者wxID_CANCEL).這樣才能使得應用程序退出這個模式對話框的事件處理循環,從而使得調用 ShowModal的代碼能夠釋放這個窗口。而這個標識符則作為ShowModal函數的返回值。我們舉下面一個OnCancel函數為例:
```
//wxID_CANCEL的命令事件處理函數
void MyDialog::OnCancel(wxCommandEvent& event)
{
EndModal(wxID_CANCEL);
}
//顯示一個模式對話框
void ShowDialog()
{
//創建這個對話框
MyDialog dialog;
// OnCancel函數將會在ShowModal執行的過程中被調用。
if (dialog.ShowModal() == wxID_CANCEL)
{
...
}
}
```
下圖展示了幾個典型的對話框,我們會在第9章闡述它們的創建過程。當然,對話框可以遠比圖中的那些更復雜,例如下面第二個圖中的那樣,它包含一個分割窗口,一個樹形控件以便顯示不同的面板(panels),以及一個扮演屬性編輯器的網格控件
.tmp)
.tmp)
wxDialog的窗口類型
除了基本窗口類型以外,wxDialog還有下面一些窗口類型可以使用:
| wxDEFAULT_DIALOG_STYLE | 其值等于wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX. |
|:--- |:--- |
| wxCAPTION | 在對話框上顯示標題. |
| wxMINIMIZE_BOX | 在標題欄顯示最小化按鈕. |
| wxMAXIMIZE_BOX | 在標題欄顯示最大化按鈕. |
| wxCLOSE_BOX | 在標題欄顯示關閉按鈕. |
| wxSTAY_ON_TOP | 對呼框總在最前. 僅支持windows平臺. |
| wxSYSTEM_MENU | 顯示系統菜單. |
| wxRESIZE_BORDER | 顯示可變大小邊框. |
| wxDIALOG_NO_PARENT | 如果創建對話框的時候父窗口為NULL,則應用程序會使用其主窗口作為對話框的父窗口,使用這個類型可以使得在這種情況下,對話框強制使用NULL作為其父窗口。模式窗口不推薦強制使用NULL作為父窗口。 |
下表解釋了對話框類額外的擴展窗口類型。雖然wxWS_EX_BLOCK_EVENTS類型是窗口基類的窗口類型,但是由于它是對話框類的默認擴展類型,我們在這里也進行了描述。
| wxDIALOG_EX_CONTEXTHELP | 在Windows平臺上,這個擴展類型使得對話框增加一個查詢按鈕.如果這個按鈕被按下,對話框將進入一種幫助模式,在這種模式下,無論用戶點擊哪個子窗口,都將發送一個wxEVT_HELP事件. 這個擴展類型不可以和wxMAXIMIZE_BOX和wxMINIMIZE_BOX類型混用. |
|:--- |:--- |
| wxWS_EX_BLOCK_EVENTS | 這是一個默認被設置的擴展類型。意思是阻止命令類型事件向更上一級的窗口傳播.要注意調用SetExtraStyle函數可以重置這個擴展類型. |
| wxDIALOG_EX_METAL | 在Mac OS X平臺上,這個擴展類型導致對話框使用金屬外觀.不要濫用這個類型,因為它默認用戶的機器有各種多媒體硬件 |
wxDialog事件
下表解釋了相對于窗口基類來說額外的對話框事件:
| EVT_ACTIVATE(func) | 用于處理wxEVT_ACTIVATE事件,在對話框即將激活或者去激活的時候產生。處理函數的參數類型是wxActivateEvent。 |
|:--- |:--- |
| EVT_CLOSE(func) | 用戶處理wxEVT_CLOSE事件,在應用程序或者操作系統即將關閉窗口的時候產生.處理函數的參數類型是wxCloseEvent,這個事件可以調用Veto函數來放棄事件的后續處理. |
| EVT_ICONIZE(func) | 用來處理wxEVT_ICONIZE事件, 在窗口被最小化或者從最小化狀態恢復的時候產生.處理函數的參數類型是wxIconizeEvent. 調用IsIconized來檢測到底是最小化還是從最小化恢復. |
| EVT_MAXIMIZE(func) | 用來處理wxEVT_MAXIMIZE事件,這個事件在窗口被最大化或者從最大化狀態恢復的時候產生,處理函數的參數類型是wxMaximizeEvent.調用IsMaximized函數確定具體的狀態類型. |
| EVT_INIT_DIALOG(func) | 用于處理wxEVT_INIT_DIALOG事件,在對話框初始化自己之前被產生。處理函數的參數類型是wxInitDialogEvent.wxPanel也會產生這個事件.默認執行的操作是調用TransferDataToWindow. |
- 第一章 介紹
- 1.1 為什么要使用wxWidgets?
- 1.2 wxWidgets的歷史
- 1.3 wxWidgets社區
- 1.4 wxWidgets和面向對象編程
- 1.5 wxWidgets的體系結構
- 1.6 許可協議
- 第一章小結
- 第二章 開始使用
- 2.1 一個小例子
- 2.2 應用程序類
- 2.3 Frame窗口類
- 2.4 事件處理函數
- 2.5 Frame窗口的構造函數
- 2.6 完整的例子
- 2.7 wxWidgets程序一般執行過程
- 2.8 編譯和運行程序
- 第二章小結
- 第三章 事件處理
- 3.1 事件驅動編程
- 3.2 事件表和事件處理過程
- 3.3 過濾某個事件
- 3.4 掛載事件表
- 3.5 動態事件處理方法
- 3.6 窗口標識符
- 3.7 自定義事件
- 第三章小結
- 第四章 窗口的基礎知識
- 4.1 窗口解析
- 4.2 窗口類概覽
- 4.3 基礎窗口類
- 4.4 頂層窗口
- 4.5 容器窗口
- 4.6 非靜態控件
- 4.7 靜態控件
- 4.8 菜單
- 4.9 控制條
- 第四章小結
- 第五章繪畫和打印
- 5.1 理解設備上下文
- 5.2 繪畫工具
- 5.3 設備上下文中的繪畫函數
- 5.4 使用打印框架
- 5.5 使用wxGLCanvas繪制三維圖形
- 第五章小節
- 第六章處理用戶輸入
- 6.1 鼠標輸入
- 6.2 處理鍵盤事件
- 6.3 處理游戲手柄事件
- 第六章小結
- 第七章使用布局控件進行窗口布局
- 7.1 窗口布局基礎
- 7.2 窗口布局控件
- 7.3 使用布局控件進行編程
- 7.4 更多關于布局的話題
- 第七章小結
- 第八章使用標準對話框
- 8.1信息對話框
- 8.2 文件和目錄對話框
- 8.3 選擇和選項對話框
- 8.4 輸入對話框
- 8.5 打印對話框
- 第八章小結
- 第九章創建定制的對話框
- 9.1 創建定制對話框的步驟
- 9.2 一個例子:PersonalRecordDialog
- 9.3 在小型設備上調整你的對話框
- 9.4 一些更深入的話題
- 9.5 使用wxWidgets資源文件
- 第九章小結
- 第十章使用圖像編程
- 10.1 wxWidgets中圖片相關的類
- 10.2 使用wxBitmap編程
- 10.3 使用wxIcon編程
- 10.4 使用wxCursor編程
- 10.5 使用wxImage編程
- 10.6 圖片列表和圖標集
- 10.7 自定義wxWidgets提供的小圖片
- 第十章小結
- 第十一章剪貼板和拖放操作
- 11.1 數據對象
- 11.2 使用剪貼板
- 11.3 實現拖放操作
- 第十一章小結
- 第十二章高級窗口控件
- 12.1 wxTreeCtrl
- 12.2 wxListCtrl
- 12.3 wxWizard
- 12.4 wxHtmlWindow
- 12.5 wxGrid
- 12.6 wxTaskBarIcon
- 12.7 編寫自定義的控件
- 第十二章小結
- 第十三章數據結構類
- 13.1 為什么沒有使用STL?
- 13.2 字符串類型
- 13.3 wxArray
- 13.4 wxList和wxNode
- 13.5 wxHashMap
- 13.6 存儲和使用日期和時間
- 13.7 其它常用的數據類型
- 第十三章小結
- 第十四章文件和流操作
- 14.1 文件類和函數
- 14.2 流操作相關類
- 第十四章小結
- 第十五章內存管理,調試和錯誤處理
- 15.1 內存管理基礎
- 15.2 檢測內存泄漏和其它錯誤
- 15.3 構建自防御的程序
- 15.4 錯誤報告
- 15.5 提供運行期類型信息
- 15.6 使用wxModule
- 15.7 加載動態鏈接庫
- 15.8 異常處理
- 15.9 調試提示
- 第十五章小結
- 第十六章編寫國際化程序
- 16.1 國際化介紹
- 16.2 從翻譯說起
- 16.3 字符編碼和Unicode
- 16.4 數字和日期
- 16.5 其它媒介
- 16.6 一個小例子
- 第十六章小結
- 第十七章編寫多線程程序
- 17.1 什么時候使用多線程,什么時候不要使用
- 17.2 使用wxThread
- 17.3 用于線程同步的對象
- 17.4 多線程的替代方案
- 第十七章小結
- 第十八章使用wxSocket編程
- 18.1 Socket類和功能概覽
- 18.2 Socket及其基本處理介紹
- 18.3 Socket標記
- 18.4 使用Socket流
- 18.5 替代wxSocket
- 第十八章小結
- 第十九章使用文檔/視圖框架
- 19.1 文檔/視圖基礎
- 19.2 文檔/視圖框架的其它能力
- 19.3 實現Undo/Redo的策略
- 第十九章小結
- 第二十章完善你的應用程序
- 20.1 單個實例和多個實例
- 20.2 更改事件處理機制
- 20.3 降低閃爍
- 20.4 實現聯機幫助
- 20.5 解析命令行參數
- 20.6 存儲應用程序資源
- 20.7 調用別的應用程序
- 20.8 管理應用程序設置
- 20.9 應用程序安裝
- 20.10 遵循用戶界面設計規范
- 20.11 全書小結