4.5 容器窗口
容器窗口是用来装载别的可见元素的窗口,所谓可见元素指的是子窗口或者是画在这个窗口上的图案。
wxPanel
wxPanel 是一个在某些方面有点象 dialog 窗口的窗口。这个窗口通常被用来摆放那些除了对话框或者 frame 窗口以外的其它控件窗口。它也常被用来作为 wxNoteBook 控件的页面。它通常使用系统默认的颜色。
和对话框一样,可以使用它的 InitDialog 方法来产生一个 wxInitDialogEvent 事件。如果设置了 wxTAB_TRAVERSAL 类型,那么它通常可以通过使用类似 TAB 键的导航键遍历所有它上面的子控件。
除了默认的构造函数以外,wxPanel 还拥有下面的构造函数:
wxPanel(wxWindow* parent, wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL|wxNO_BORDER,
const wxString& name = wxT("panel"));
用法如下:
wxPanel* panel = new wxPanel(frame, wxID_ANY,
wxDefaultPosition, (500, 300));
wxPanel 的窗口类型
wxPanel 没有额外的窗口类型。
wxPanel 的成员函数
wxPanel 也没有额外的成员函数。
wxNotebook
这个类提供了一个有多个页面的窗口,页面之间可以通过边上的 TAB 按钮来切换。每个页面通常是一个普通的 wxPanel 窗口或者其派生类,当然你完全可以使用别的窗口。
NoteBook 的 TAB 按钮可以包含一个图片,也可以包含一个文本标签。图片是由 wxImageList(参考第 10 章)提供的,是通过在列表中的位置和页面对应的。
使用 notebook 的方法是,创建一个 wxNotebook 对象,然后调用其 AddPage 方法或者 InserPage 方法,传递一个用来作为页面的窗口指针。不要手动释放那些已经被 wxNoteBook 作为页面的窗口,你应该使用 DeletePage 来删除某个页面或者干脆等到 notebook 释放它自己的时候。notebook 会一并释放那些页面。
下面举例说明怎样创建一个有三个页面,包含文本和图片的 TAB 标签的 notebook:
#include "wx/notebook.h"
#include "copy.xpm"
#include "cut.xpm"
#include "paste.xpm"
//创建 notebook
wxNotebook* notebook = new wxNotebook(parent, wxID_ANY,
wxDefaultPosition, wxSize(300, 200));
// 创建图片列表
wxImageList* imageList = new wxImageList(16, 16, true, 3);
imageList->Add(wxIcon(copy_xpm));
imageList->Add(wxIcon(paste_xpm));
imageList->Add(wxIcon(cut_xpm));
// 创建页面
wxPanel1* window1 = new wxPanel(notebook, wxID_ANY);
wxPanel2* window2 = new wxPanel(notebook, wxID_ANY);
wxPanel3* window3 = new wxPanel(notebook, wxID_ANY);
notebook->AddPage(window1, wxT("Tab one"), true, 0);
notebook->AddPage(window2, wxT("Tab two"), false, 1);
notebook->AddPage(window3, wxT("Tab three"), false 2);
下图演示了上述代码在 windows 平台上的结果:
在大多数的平台上,当 TAB 页面数量太多不能被完全显示的时候,都会自动出现导航按钮。但是在 Mac OS 上,这个导航按钮是不会出现的,因此在这个系统上,可以使用的页面数目将受到窗口大小和 TAB 标签大小的限制。
如果你在每个页面上都使用布局控件,并且在创建 notebook 的时候使用默认的大小 wxDefaultSize,那么 wxNotebook 将会自动调整大小以适合它的页面。
Notebook 窗口主题管理
在 Windows Xp 系统中,默认的窗口主题会给 notebook 的页面添加过渡色。虽然这是预期的本地行为,但是它可能会降低性能。出于审美方面的原因,你可能想直接使用单一的色彩,尤其是当 notebook 不是位于一个对话框以内的时候。如果你想阻止这种默认的行为,可以采用以下三种办法:第一:你可以给你的 notebook 指定 wxNB_NOPAGETHEM 类型来禁止某个特定的 notebook 的这种效果,或者你可以使用 wxSystemOptions::SetOption 来在应用程序范围内禁止它,或者你可以使用 SetBackgroundColour 函数来给某个单独的页面禁止它。要在应用程序范围内禁止它,你可以使用下面的代码: wxSystemOptions::SetOption(wxT("msw.notebook.themed-background"), 0); 将它的值设置成 1 可以再次允许这种效果。要让某个单独的页面禁用这种效果可以使用下面的方法:
wxColour col = notebook->GetThemeBackgroundColour();
if (col.Ok())
{
page->SetBackgroundColour(col);
}
在 windows 系统以外的平台,或者如果一个应用程序没有使用主题风格,GetThemeBackgroundColour 都将返回一个未初始化的颜色,因此上面的代码在各个平台都是可以使用的。另外就是上述的这部分代码的语法和行为是有可能在将来的 wxWidgets 版本中发生变化,请参考你本地 wxWidgets 发行版中的 wxNotebook 类的文档来获取最新的信息。
wxNotebook 的窗口类型
wxNotebook 可以拥有下面的额外窗口类型:
wxNB_TOP | 标签放在顶部。 |
---|---|
wxNB_LEFT | 标签放在左面. 不是所有的 WindowsXp 的主题都支持这个选项。 |
wxNB_RIGHT | 标签在右面. 不是所有的 WindowsXp 的主题都支持这个选项。 |
wxNB_BOTTOM | 标签在底部. 不是所有的 WindowsXp 的主题都支持这个选项。 |
wxNB_FIXEDWIDTH | 所有标签宽度相同.仅适用于 windows。 |
wxNB_MULTILINE | 可以有多行的标签. 仅适用于 windows |
wxNB_NOPAGETHEME | 在 windos 上禁用主题风格.以提高性能和提供另外一种审美选择。 |
wxNotebook 的事件
wxNotebook 可以产生 wxNotebookEvent 事件,这个事件可以被它和它的继承者处理。
EVT_NOTEBOOK_PAGE_CHANGED(id,func) | 当前页面已经改变。 |
---|---|
EVT_NOTEBOOK_PAGE_CHANGING(id,func) | 当前页面即将改变。你可以使用 Veto 函数阻止这种改变。 |
wxNotebook 的成员函数
AddPage 增加一个页面,InsertPage 在某个固定位置插入一个页面.你可以使用文本标签或者图片标签或者两者都有,用法如下:
//增加一个使用了文本和图片两种标签都有的页面,并且当前处于未选中状态。
// (其中图片使用的是图片列表中的索引为 2 的那个).
notebook->AddPage(page, wxT("My tab"), false, 2);
DeletePage 函数移除并且释放某个特定的页面,而 RemovePage 函数则仅仅是移除这个页面。DeleteAllPages 函数用来删除所有的页面。当 wxNoteBook 被释放时,它也会自动删除所有的页面。
AdvanceSelection 函数循环选择页面。 SetSelection 函数以基于 0 的索引选择特定的页面. GetSelection 取得当前选中页面的索引或者返回 wxNOT_FOUND。
SetImageList 函数用来给 Notebook 设置一个图标列表,这个函数仅是设置而不绑定图片列表,这意味着在 notebook 控件被删除的时候,这个图片列表控件并不会被删除,如果你希望使用绑定,则可以使用 AssignImageList 函数. GetImageList 函数返回 notebook 相关的图片列表对象.图片列表对象用来提供每个页面标签中使用的图片,详情请参考第 10 章。
GetPage 函数用来返回和某个索引对应的页面窗口指针, GetPageCount 函数则返回页面总数。
SetPageText 和 GetPageText 用来操作页面标签上的文本。
SetPageImage 和 GetPageImage 用来操作页面标签上的图片在图片列表中的索引,
wxNotebook 的替代选择
wxNotebook 是 wxBookCtrlBase 的派生类,这个基类是用来提供用于管理一组页面的所有数据和方法的抽象类。和 wxNotebook 有着相似 API 的类还有两个,一个是 wxListbook,一个是 wxChoicebook,你也可以实现你自己的类,比如你可以实现一个 wxTreebook。
wxListbook 使用一个 wxListCtrl 变量来控制页面;ListCtrl 控件是一种在内部显示一组带有标签的图片的控件. 在 wxListbook 中,相关的 ListCtrl 控件可以显示在上下左右四个方向,默认是在左边。这是 wxNotebook 的一个很有吸引力的替代者。因为即使在 Mac Os X 平台上,ListCtrl 可以管理的项目数量也几乎没有限制,因此 wxListbook 可以管理的页面数也不受窗口大小和标签长度的限制。
wxChoicebook 则使用一个选择控件(一个下拉列表)来管理页面。比较适用于窗口空间比较小的场合。这个控件不会在页面标签处显示图片,而且默认情况下,选择控件显示在整个控件的上方。
上述这两个控件的头文件分别为 wx/listbook.h 和 wx/choicebk.h.它们的事件处理函数的参数类型分别为 wxListbookEvent 和 wxChoicebookEvent 类型,事件影射宏则分别为 EVT_XXX_PAGE_CHANGED(id, func) 和 EVT_XXX_PAGE_CHANGING(id,func),其中 XXX 代表 LISTBOOK 或者 CHOICEBOOK。
你可以使用类似 wxNotebook 定义的那些窗口类型,也可以类似用 wxCHB_TOP 或者 wxLB_TOP 取代 wxNB_TOP 这样的窗口类型,它们的值都是一样的,
wxScrolledWindow
尽管所有的窗口都可以拥有滚动条,但是为了让滚动条工作,还需要一些额外的代码。这个类则为让不同类型的窗口类中的滚动条正确工作提供了足够的灵活性。 wxScrolledWindow 主要实现了那些让窗口可以以一定的单位连续的滚动(而不是不定大小的跳跃),也可以定义在使用翻页键进行翻页的时候的大小。这种实现通常仅适用于类似画图程序中的那种翻页功能,对于一些复杂功能的文本编辑程序则不一定适合。因为富文本编辑器中每一行的高度和宽度都有可能不同。wxGrid 网格控件就是这样的一个例子(在网格控件中,每一行和每一列的宽度都有可能不同),在这种情况下,你应该自己直接从 wxWindow 类实现自己的派生类,从而实现自己的窗口滚动机制。
要适用滚动窗口,你需要提供每次逻辑移动的单位(也就是当处理上滚一行和下滚一行时窗口应该移动的大小)以及整个窗口的虚拟逻辑大小。然后 wxScrollWindow 类就会自己关注是否显示滚动条,以及滚动条上的滑钮应该用多大显示等等这些细节问题。
下面演示了怎样创建一个滚动窗口:
#include "wx/scrolwin.h"
wxScrolledWindow* scrolledWindow = new wxScrolledWindow(
this, wxID_ANY, wxPoint(0, 0), wxSize(400, 400),
wxVSCROLL|wxHSCROLL);
// 设置窗口的虚拟逻辑大小: 1000x1000
// 每次滚动 10 个象素
int pixelsPerUnixX = 10;
int pixelsPerUnixY = 10;
int noUnitsX = 1000;
int noUnitsY = 1000;
scrolledWindow->SetScrollbars(pixelsPerUnitX, pixelsPerUnitY,
noUnitsX, noUnitsY);
第二种设置虚拟大小的方法是使用 SetVirtualSize 函数,它的参数是以象素为单位的虚拟大小。然后再用 SetScrollRate 函数来设置水平和垂直方向上的滚动增量。第三种方法是使用布局控件来布局窗口,滚动窗口会自动计算所有子窗口需要的窗口大小作为窗口的虚大小,你同样需要调用 SetScrollRate 函数来设置滚动增量。
你可以想普通窗口那样使用重画事件,但是在进行任何窗口重画动作之前你应该调用 DoPrepareDC 函数来保证重画动作以当前的窗口原点作为原点,就象下面演示的那样:
void MyScrolledWindow::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
DoPrepareDC(dc);
dc.SetPen(*wxBLACK_PEN);
dc.DrawLine(0, 0, 100, 100);
}
你也可以直接重载 OnDraw 虚函数,wxScrolledWindow 在调用这个函数之前,会首先调用 DoPrepareDC 函数,因此你只需要象下面演示的那样作:
void MyScrolledWindow::OnDraw(wxDC& dc)
{
dc.SetPen(*wxBLACK_PEN);
dc.DrawLine(0, 0, 100, 100);
}
需要注意的是,在别的任何事件处理函数中如果要重画窗口,你同样需要调用 DoPrepareDC 函数。
你也可以象下面这样提供你自己的 DoPrepareDC 函数,这个函数默认的行为只是把设备操作原点移动到当前滚动条开始的位置:
void wxScrolledWindow::DoPrepareDC(wxDC& dc)
{
int ppuX, ppuY, startX, startY;
GetScrollPixelsPerUnit(& ppuX, & ppuY);
GetViewStart(& startX, & startY);
dc.SetDeviceOrigin( - startX * ppuX, - startY * ppuY );
}
关于在 wxScrollWindow 上进行作图的详细情形,包括怎样使用双缓冲区,请参考第 5 章,�重画和打印�中的 wxPaintDC 小节。
wxScrolledWindow 的窗口类型
wxScrolledWindow 类并没有特别的窗口类型,但是通常需要设置 wxVSCROLL|wxHSCROLL 类型,这也是 wxScrolledWindow 的默认类型。在某些平台上因为效率的原因可能不支持这两个类型。
wxScrolledWindow 的事件
wxScrolledWindow 会产生 wxScrollWinEvent 事件(参见下表).这些事件不会在父子窗口关系中传播,因此要处理这种事件,你必须定义自己的滚动窗口派生类或者挂载你自己的事件表。不过在通常情况下,你并不需要覆盖默认的处理函数来自己处理这些事件。
EVT_SCROLLWIN(func) | 处理所有滚动事件。 |
---|---|
EVT_SCROLLWIN_TOP(func) | 处理事件 wxEVT_SCROLLWIN_TOP,滚动到最顶端。 |
EVT_SCROLLWIN_BOTTOM(func) | 处理事件 wxEVT_SCROLLWIN_BOTTOM 滚动到最底端事件。 |
EVT_SCROLLWIN_LINEUP(func) | 处理事件 wxEVT_SCROLLWIN_LINEUP 上滚一行。 |
EVT_SCROLLWIN_LINEDOWN(func) | 处理事件 wxEVT_SCROLLWIN_LINEDOWN 下滚一行。 |
EVT_SCROLLWIN_PAGEUP(func) | 处理事件 wxEVT_SCROLLWIN_PAGEUP 上滚一页。 |
EVT_SCROLLWIN_PAGEDOWN(func) | 处理事件 wxEVT_SCROLLWIN_PAGEDOWN 下滚一页。 |
wxScrolledWindow 的成员函数介绍
CalcScrolledPosition 和 CalcUnscrolledPosition 函数都需要四个参数,前两个整数参数是输入需要计算的点,后两个则是指向整数的指针用来放置计算结果。第一个函数用来计算实际位置到逻辑位置的映射。如果当前的滚动条下滚了 10 个象素,则 0 这个数字作为输入将得到对应输出-10,第二个函数则实现相反的功能。
EnableScrolling 函数用来允许或者禁止垂直或者水平方向的物理滚动。物理滚动的含义是说在收到滚动事件的时候对窗口进行物理上的平移。但是如果应用程序需要不等量的移动(比如,由于字体的不同为了避免滚动的时候显示半行字的情况出现),则需要禁止物理移动,在这种情况下,应用程序需要自己移动对应的子窗口。物理移动在所有支持物理移动的平台上都是默认打开的。当然不是所有的平台都支持物理移动。
GetScrollPixelsPerUnit 函数在两个指向整数的指针中返回水平和垂直方向上的移动单位。返回 0 表示在那个方向上不能滚动。
GetViewStart 函数返回窗口可视部分左上角的座标,单位是逻辑单位,你需要乘以 GetScrollPixelsPerUnit 的返回值以便将结果转换成象素单位。
GetVirtualSize 返回当前设定的以象素为单位的虚拟窗口大小。
DoPrepareDC 将画画设备的原点设置到当前的可见原点。
Scroll 函数将窗口滚动到一个特定的逻辑单位位置(注意这里的单位不是象素)。
SetScrollbars 用来设置移动单位的象素值,各个方向的移动单位总数,水平或者垂直方向的当前滚动位置(可选) 以及是否立即刷新窗口(默认否)等。
SetScrollRate 用来设置滚动单位,相当于单独设置 SetScrollbars 中的移动单位参数。
SetTargetWindow 用来滚动非 wxScrolledWindow 类型的其它窗口。
滚动非 wxScrolledWindow 类型的窗口
如果你想自己实现窗口的滚动行为,你可以直接从 wxWindow 派生你的窗口类,然后使用 SetScrollbar 函数来设置这个窗口的滚动条。
SetScrollbar 函数的参数如下表的说明:
int orientation | 滚动条的类型: wxVERTICAL or wxHORIZONTAL。 |
---|---|
int position | 滚动条滑块的位置,逻辑滚动单位。 |
int visible | 可见部分大小,逻辑滚动单位. 通常会决定滑块的长度。 |
int range | 滚动条的最大长度,逻辑滚动单位。 |
bool refresh | 是否立即刷新窗口。 |
举例来说,如果你想显示一个 50 行文本的文本窗口,使用同样的字体,而窗口的大小只够显示 16 行,你可以使用下面的代码:
SetScrollbar(wxVERTICAL, 0, 16, 50)
注意在上面的例子中,滑块的位置永远不可能大于 50-16=34。
你可以通过用当前窗口除以当前字体下文本的高度来得到当前窗口可以显示多少行这个值。
如果你是自己实现滚动行为,你总是需要在窗口大小发生改变的时候更改滚动条的设置。因此你可以在首次计算滚动条参数的代码中使用 AdjustScrollbars 函数,然后在 wxSizeEvent 的处理事件中使用 AdjustScrollbars 函数。
你可以参考 wxGrid 控件的代码来获得实现自定义滚动窗口的更多灵感。
你也可以参考 wxWidgets 手册中的 wxVScrolledWindow 类,它可以用来建立一个可以在垂直方向进行不固定单位滚动的窗口类。
wxSplitterWindow
这个类用来管理最多两个窗口,如果你想在更多窗口中实现分割,你可以使用多个分割窗口。当前的窗口可以被应用程序分割成两个窗口,比如通过一个菜单命令,也可以通过应用程序命令或者通过分割窗口的用户操作界面(双击分割条或者拖拽分割条使得其中一个窗口的大小变为 0)重新变为一个窗口.其中拖拽分割条的方法将会受到后面会提到的 SetMinimumPaneSize 方法的限制。
在大多数平台上,当分割条被拖拽时,会有一个和背景颜色相反的竖条随之移动以显示分割条的最终位置,你可以通过使用 wxSP_LIVE_UPDATE 窗口类型来使得分割条以实时方式通过直接改变两个窗口的大小来代替那种默认方式。实时方式是 Mac OS X 上默认的也是唯一的方式。
下面的代码演示了怎样创建一个分割窗口来操作两个窗口并且隐藏其中的一个:
#include "wx/splitter.h"
wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY,
wxPoint(0, 0), wxSize(400, 400), wxSP_3D);
leftWindow = new MyWindow(splitter);
leftWindow->SetScrollbars(20, 20, 50, 50);
rightWindow = new MyWindow(splitter);
rightWindow->SetScrollbars(20, 20, 50, 50);
rightWindow->Show(false);
splitter->Initialize(leftWindow);
//去掉下面的注释以便禁止窗口隐藏
// splitter->SetMinimumPaneSize(20);
下面的代码代码演示了创建分割窗口以后怎样使用它:
void MyFrame::OnSplitVertical(wxCommandEvent& event)
{
if ( splitter->IsSplit() )
splitter->Unsplit();
leftWindow->Show(true);
rightWindow->Show(true);
splitter->SplitVertically( leftWindow, rightWindow );
}
void MyFrame::OnSplitHorizontal(wxCommandEvent& event)
{
if ( splitter->IsSplit() )
splitter->Unsplit();
leftWindow->Show(true);
rightWindow->Show(true);
splitter->SplitHorizontally( leftWindow, rightWindow );
}
void MyFrame::OnUnsplit(wxCommandEvent& event)
{
if ( splitter->IsSplit() )
splitter->Unsplit();
}
下图演示了分割窗口在 windows 平台上的例子,在这个例子中,分割窗口没有使用 wxSP_NO_XP_THEME 类型。如果使用了这个类型,分割窗口将会拥有更传统的下沉边框和 3 维外观。
wxSplitterWindow 的窗口类型
wxSP_3D | 使用三维效果的边框和分割条 。 |
---|---|
wxSP_3DSASH | 使用三维效果分割条 。 |
wxSP_3DBORDER | 和 xSP_BORDER 效果相同 |
wxSP_BORDER | 使用标准边框 。 |
wxSP_NOBORDER | 无边框(默认值)。 |
wxSP_NO_XP_THEME | 在 Xp 操作系统上,如果你不喜欢默认的效果,使用三维边框和分割条效果。 |
wxSP_PERMIT_UNSPLIT | 即使设置了最小值也允许窗口被隐藏。 |
wxSP_LIVE_UPDATE | 在分割条移动的时候实时更新窗口。 |
wxSplitterWindow 事件
wxSplitterWindow 使用 wxSplitterEvent 类型的事件处理函数
EVT_SPLITTER_SASH_POS_CHANGING(id,func) | 用于处理 wxEVTCOMMAND_SPLITTER_SASH POS_CHANGING 事件,在分割条位置即将改变的时候产生。调用 Veto 函数阻止分割条移动,或者调用事件的 SetSashPosition 函数来更改分割条的位置。 |
---|---|
EVT_SPLITTER_SASH(id,func) | 用于处理 wxEVTCOMMAND_SPLITTER SASH_POS_CHANGED 事件,分割条的位置已经改变你可以通过事件的 SetSashPosition 函数阻止这种改变或者更改变化的幅度。 |
EVT_SPLITTER_UNSPLIT(id,func) | 用于处理 wxEVT_COMMAND_SPLITTER_UNSPLIT 事件,在有某个窗口被隐藏的时候产生。 |
EVT_SPLITTER_DCLICK(id,func) | 用于处理 wxEVT_COMMAND_SPLITTER_DOUBLECLICKED 事件,在分割条被双击的时候产生. |
wxSplitterWindow 的成员函数
GetMinimumPaneSize 和 SetMinimumPaneSize 函数用于操作分割窗口的最小窗格大小。默认为 0,意味着分割窗口的每一侧的大小都可以被缩减至 0。相当于移除某一部分分割窗口.要阻止这种情形,也为了阻止拖拽分割条的时候超出边界,可以将其设置成一个大于 0 的值比如 20 个象素。虽然这样,如果设置了 wxSP_PERMIT_UNSPLIT 窗口类型,即使最小值设置为大于 0 的数,也还是可以将某个分割窗口隐藏。
GetSashPosition 和 SetSashPosition 用来操作分割条的位置,传递 true 参数给 SetSashPosition 函数导致分割条被立刻刷新。
GetSplitMode 和 SetSplitMode 函数用来设置分割的方向 wxSPLIT_VERTICAL 或者 wxSPLIT_HORIZONTAL。
GetWindow1 和 GetWindow2 用来获取两个分割窗口的指针。
Initialize 函数使用一个窗口指针参数调用,用来显示两个分割窗口中的某一个窗口。
IsSplit 函数用来判断窗口是否处于分割状态。
ReplaceWindow 用来替换被分割窗口控制的两个窗口中的一个。使用这个函数要好过先使用 Unsplit 函数然后再增加另外一个窗口。
SetSashGravity 用一个浮点小数来设置分割比例。0.0 表示只显示右边或者下边的窗口,1.0 表示只显示左边或者上边的窗口。中间的值则表示按照某种比例分配两个窗口的大小。使用 GetSashGravity 函数来获取当前的分割比例。
SplitHorizontally 函数 SplitVertically 使用一个可选的分割尺寸来初始化分割窗口。
Unsplit 去掉指定的那个分割窗口。
UpdateSize 用来使得分割窗口立即刷新(通常情况下,这是在系统空闲的时候完成的)。
布局控件中使用 wxSplitterWindow 的说明
在布局控件中使用分割窗口有一点细微之处需要说明一下。如果你不需要这个分割窗口的分割条是可移动的,你可以在创建两个子窗口的时候指定绝对大小。这将固定这两个子窗口的最小大小,从而使得分割条不能自由移动。如果你希望分割条能正常移动,在创建两个子窗口的时候你就需要使用默认的大小,然后在分割窗口的构造函数中指定其最小大小。然后在将这个分割窗口增加到布局控件的时候,在 Add 函数中使用 wxFIXED_MINSIZE 标记来告诉 wxWidgets 将分割窗口控件当前的大小作为其最小大小。
另外一种情况是,分割窗口没有设定分割条的位置,也没有设定它的子窗口的大小,当布局控件完成布局时,分割窗口不愿意过早的设置分割条的位置,而要等到系统空闲的时候(这是它的默认行为)。在这种情况下,我们可能会看到当窗口刚刚可见的时候分割条复位自己的位置。为了避免出现这种情景,我们应该在对布局控件调用 Fit 之后,马上调用分割窗口的 UpdateSize 函数让其作立即更新。
默认情况下,当用户或者应用程序改变分割窗口的大小时,只有底端(或者右端)的子窗口改变自己的大小以便获取或减小额外的空间,要改变这种默认的行为,你可以使用前面说过的 SetSashGravity 函数指定一个固定的分割比例。
wxSplitterWindow 的替代者
如果在应用程序中你需要使用很多的分割窗口,不妨考虑使用 wxSashWindow.这个窗口允许它的任何边成为一个分割条,以便将其分割成多个窗口。而新分的这些窗口通常是用户创建的 wxSashWindow 的子窗口。
当 wxSashWindow 的分割条被拖动时,会向应用程序发送 wxSashEvent 事件以便事件处理函数可以相应的进行窗口布局。布局是通过一个称为 wxLayoutAlgorithm 的类来完成的,这个类可以根据父窗口的不同提供 LayoutWindow,LayoutFrame, LayoutMDIFrame 等多种不同的排列方法。
你还可以使用 wxSashLayoutWindow 类,这个类通过 wxQueryLayoutInfoEvent 事件来给 wxLayoutAlgorithm 提供布局方向和尺寸方面的信息。
关于 wxSashWindow,wxLayoutAlgorithm 和 wxSashLayoutWindow 更多的信息请参考手册中的相关内容。wxSashWindow 不允许子窗口被移动或者分离,因此在不久的将来,这个类可能被一个通用的支持合并和分离的布局框架体系所代替。
下图演示了 samples/sashtest 目录中的例子在 windows 上执行的效果:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论