# 4.3 基础窗口类
虽然你不一定有机会直接使用基础窗口类(wxWindow),但是由于这个类是很多窗口控件的基类,它实现的很多方法在它的子类型中都可以直接拿来使用,所以有必要介绍一下这个基础窗口类。
窗口类wxWindow
wxWindow窗口类既是一个重要的基类,也是一个你可以直接在代码中使用的类。当然,前者使用的频度要比后者大很多。
和前面提到的一样,wxWindow也可以使用单步创建或者两步创建两种方式。单步创建的构造函数原型如下:
```
wxWindow(wxWindow* parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString& name = wxT("panel"));
```
可以象下面这样使用:
```
wxWindow* win = new wxWindow(parent, wxID_ANY,
wxPoint(100, 100), wxSize(200, 200));
```
窗口类型
每一个窗口类都可以使用定义在下表中的这些窗口基类中的窗口类型。这些类型中不是所有的类些都被所有的控件所支持。例如对于边框的类型。如果在创建窗口的时候你没有指定窗口的边框类型,那么在不同的平台上将会有不同的边框类型的缺省值。在windows平台上,控件边框的缺省值为 wxSUNKEN_BORDER,意为使用当前系统风格的边框。你可以使用类似wxNO_BORDER这样的值来覆盖系统的默认值。
| wxSIMPLE_BORDER | 在窗口周围显示一个瘦边框. |
|:--- |:--- |
| wxDOUBLE_BORDER | 显示一个双层边框. |
| wxSUNKEN_BORDER | 显示一个凹陷的边框,或者使用当前窗口风格设置. |
| wxRAISED_BORDER | 显示一个凸起的边框. |
| wxSTATIC_BORDER | 显示一个适合静态控件的边框. 只支持Windows平台. |
| wxNO_BORDER | 不显示任何边框. |
| wxTRANSPARENT_WINDOW | 定义一个透明窗口 (意思是这个窗口不接收paint事件).只支持windows平台. |
| wxTAB_TRAVERSAL | 使用这个类型允许非Dialog窗口支持使用TAB进行遍历. |
| wxWANTS_CHARS | 使用这个类型来允许窗口接收包括回车和TAB在内的所有的键盘事件。TAB用来在Dialog类型的窗口中遍历各控件。如果没有设置这个类型,这些特殊的按键事件将不会被产生。 |
| wxFULL_REPAINT_ON_RESIZE | 在默认情况下,在窗口客户区大小发生改变时,wxWidgets并不会重画整个客户区。设置这个类型将使得wxWidgets改变这种默认的作法,而保持整个客户区的刷新 |
| wxVSCROLL | 显示垂直滚动条. |
| wxHSCROLL | 显示水平滚动条. |
| wxALWAYS_SHOW_SB | 如果一个窗口有滚动条,那么在不需要滚动条的时候(当窗口足够大不需要使用滚动条的时候),禁止滚条而不隐藏滚动条。这个类型目前只支持Windows平台和wxWidgets的wxUniversal版本. |
| wxCLIP_CHILDREN | 只支持Windows平台,用于消除由于擦除子窗口的背景而引起的闪铄. |
下表列出了窗口的扩展类型,这些扩展类型不能直接和类型混用,而要使用wxWindow::SetExtraStyle函数来进行设置。
| wxWS_EX_VALIDATE_RECURSIVELY | 在默认情况下,Validate,transferDataToWindow,和transferDataFromWindow只在窗口的直接子窗口上才可以使用。如果设置了这个扩展类型,那么将可以递归的在各个子窗口上使用。 |
|:--- |:--- |
| wxWS_EX_BLOCK_EVENTS | wxCommandEvents事件将会在无法在当前事件表中找到匹配的时候在其父窗口中尝试匹配,设置这个扩展属性可以阻止这个行为。Dialog类型的窗口默认设置了这个类型,但是如果SetExtraStyle被应用程序类调用过的话,默认设置可能被覆盖. |
| wxWS_EX_TRANSIENT | 不要使用这个窗口作为其它窗口的父窗口.这个类型一定只能用于瞬间窗口;否则,如果使用它作为一个dialog或者frame类型窗口的父窗口,如果父窗口在子窗口之前释放,可能导致系统崩溃。 |
| wxWS_EX_PROCESS_IDLE | 这个窗口应该处理所有的idle事件,包括那些设置了wxIDLE_PROCESS_SPECIFIED模式的idle事件。 |
| wxWS_EX_PROCESS_UI_UPDATES | 这个窗口将处理所有的Ui刷新事件,包括那些设置了wxUPDATE_UI_PROCESS_SPECIFIED的UI刷新事件。参考第9章获得和界面刷新有关的更多的内容. |
窗口事件
窗口类和它的派生类可以产生下面的事件(鼠标,键盘和游戏手柄产生的事件将会在第6章描述)。
| EVT_WINDOW_CREATE(func) | 用于处理wxEVT_CREATE事件, 这个事件在窗口刚刚被产生的时候生成,处理函数的参数类型是wxWindowCreateEvent. |
|:--- |:--- |
| EVT_WINDOW_DESTROY(func) | 用于处理wxEVT_DELETE事件,在这个窗口即将被删除的时候产生,处理函数的参数类型是wxWindowDestroyEvent. |
| EVT_PAINT(func) | 用于处理wxEVT_PAINT事件,在窗口需要被刷新的时候产生.处理函数的参数类型是wxPaintEvent. |
| EVT_ERASE_BACKGROUND(func) | 用于处理wxEVT_ERASE_BACKGROUND事件,在窗口背景需要被更新的时候产生. 处理函数的参数是wxEraseEvent. |
| EVT_MOVE(func) | 用于处理wxEVT_MOVE事件, 在窗口移动的时候产生.处理函数的参数类型是wxMoveEvent. |
| EVT_SIZE(func) | 用于处理wxEVT_SIZE事件, 在窗口大小发生变化以后产生.处理函数的参数类型是wxSizeEvent. |
| EVT_SET_FOCUS(func)EVT_KILL_FOCUS(func) | 用于处理wxEVT_SET_FOCUS和wxEVT_KILL_FOCUS事件,在窗口得到或者失去键盘焦点的时候产生. 处理函数参数类型是wxFocusEvent. |
| EVT_SYS_COLOUR_CHANGED(func) | 用于处理wxEVT_SYS_COLOUR_CHANGED事件,当用户在控制面板里更改了系统颜色的时候产生(只支持windows平台). 处理函数参数类型为wxSysColourChangedEvent. |
| EVT_IDLE(func) | 用于处理wxEVT_IDLE事件,在空闲事件产生.处理函数参数类型位wxIdleEvent. |
| EVT_UPDATE_UI(func) | 用于处理wxEVT_UPDATE_UI事件,在系统空闲时间产生用来给窗口一个更新自己的机会. |
wxWindow类的成员函数
因为wxWindow类是其它所有窗口类的基类,它拥有很多的成员函数。我们不可能在这里作一一的说明,只能拣其中最重要的一些作简要的说明。不过我们还是推荐你浏览一下wxWidgets手册中的相关部分,以便能够彻底了解wxWindow类提供的所有功能,以及要使用这个功能你需要提供的参数等。
CaptureMouse函数可以捕获所有的鼠标输入(将其限制在本窗口以内),ReleaseMouse则可以释放前一次的捕获.在绘图程序中,这两个函数是很有用的。它可以让你在鼠标移动到窗口边缘的时候来滚动窗口的客户区,而不是任由鼠标跑到别的窗口并且激活别的窗口。另外的两个函数GetCapture用来获取当前正在使用的捕获设备(如果是被当前的应用程序设置的话),而HasCapture可以用来检测是否鼠标正被这个窗口捕获。
Centre, CentreOnParent和CentreOnScreen三个函数可以让窗口调整自己的位置使其位于屏幕或者是其父窗口的正中间位置。
ClearBackground函数将使用当前的背景色清除当前窗口.
ClientToScreen和ScreenToClient可以将座标在相对于屏幕左上角和相对于客户区左上角之间进行互相转换.
Close函数产生一个wxCloseEvent事件,这个事件通常的处理过程将关闭窗口,释放内存。当然如果应用程序为这个事件定义了特殊的处理函数,那么窗口也有可能不被关闭和释放。
ConvertDialogToPixels和ConvertPixelsToDialog函数可以对数值进行对话框单位和象素单位之间的转换。这在基于字体大小以便应用程序的显示更合理的操作中是很有用的.
Destroy函数将安全的释放窗口.使用这个函数代替直接调用delete操作符因为这个函数下不同的窗口类型的表现是不一样的。对于对话框和frame这样的顶层窗口来说,这个函数会将窗口放入一个等待删除的额窗口列表中,等到这个窗口的所有的事件都处理完毕的时候才会被删除,这可以避免一些事件在已经不存在的窗口上被执行.
Enable允许或者禁止窗口和它的子窗口处理输入事件。在禁止状态下一些窗口会有不同的颜色和外观。Disable函数和Enable函数使用false作为参数的效果是完全一样的。
FindFocus函数是一个静态函数,用它可以找到当前拥有键盘焦点的窗口。
FindWindow函数可以通过标识符或者名字在它的窗口关系树中寻找某个窗口. 返回值可能是它的一个子窗口或者它自己.如果你可以确定你要找的窗口的类型,可以安全的使用wxDynamicCast进行类型强制转换,转换的结果将是一个指向那个类型的指针或者是NULL:
```
MyWindow* window = wxDynamicCast(FindWindow(ID_MYWINDOW), MyWindow);
```
Fit函数会自动改变窗口的大小以便刚好可以容纳它的所有子窗口.这个函数应用被应用在使用基于sizer的布局的时候。FitInside函数是一个类似的函数,区别在于它使用的是虚大小(应用在那些包含滚动条的窗口).
Freeze和Thaw,这两个函数的作用是告诉wxWidgets,在这两个函数之间进行的刷新界面的操作是允许被优化的。举例来说,如果你要在一个文本框控件逐行中加入多行文本,则可以用这个方法来优化显示效果,避免闪烁,这两个函数已经在GTK+版本的wxTextCtrl控件上实现,也适用于 Windows和Max Os X平台的所有类.
GetAcceleratorTable和SetAcceleratorTable用来获取和设置某个窗口的加速键表.
GetBackgroundColour和SetBackgroundColour用来访问窗口的背景颜色属性。这个属性被 wxEVT_ERASE_BACKGROUND事件用来绘制窗口背景.如果你更改了背景颜色设置,你应该调用Refresh或者 ClearBackground函数来刷新背景. SetOwnBackgroundColour的作用和SetBackgroundColour基本相同,但是前者不会更改当前窗口的子窗口的背景属性.
GetBackgroundStyle和SetBackgroundStyle用来设置窗口的背景类型. 默认的窗口背景类型是wxBG_STYLE_SYSTEM,它的含义是wxWidgets按照系统默认设置来进行背景绘制。系统默认的背景绘制方法根据控件的不同而不同,比如wxDialog的默认背景绘制方法是什么纹理绘制的方法,而wxListBox则是使用固定颜色的绘制方法。如果你设置了窗口的背景绘制方法类型是wxBG_STYLE_COLOUR,那么wxWidgets会全部用单一颜色的方法绘制背景。而如果你将其设置为 wxBG_STYLE_CUSTOM, wxWidgets将不进行任何的背景绘制工作,你可以自己在擦除背景事件中或者重画事件中自己绘制背景.如果你希望自己绘制背景,请一定设置 wxBG_STYLE_CUSTOM为背景类型,否则很容易引起画面的闪烁.
GetBestSize函数以象素为单位返回窗口最合适的大小(因为每个窗口类都需要实现DoGetBestSize函数).这个函数用来提示Sizer系统不要让这个窗口的尺寸太小以致不能正确的显示和使用。举例来说,对于静态文本控件来说,不要让它的字符只能显示一半。对于包含其它子窗口的窗口比如wxPanel来说,这个尺寸等于对这个窗口调用Fit函数以后的尺寸的大小。
GetCaret和SetCaret函数用来访问或者设置窗口的光标.
GetClientSize和SetClientSize用来访问和设置窗口的客户区大小,单位是象素. 客户区大小指的是不包括边框和修饰的区域,或者说你用户可以绘制或者用来放置子窗口的区域.
GetCursor和SetCursor函数用来访问和设置窗口的鼠标指针.
GetDefaultItem函数返回一个指向这个窗口默认的子按钮的指针或者返回NULL。默认子按钮是当用户按回车键的时候默认激活的按钮,可以通过wxButton::SetDefault函数进行设置.
GetDropTarget和SetDropTarget函数用来取得或者设置和窗口关联的wxDropTarget对象,这个对象用来处理和控制窗口的拖放操作. 我们将在第11章"剪贴板和拖放"中详细介绍拖放有关的操作。
GetEventHandler和SetEventHandler函数用来访问和设置窗口的第一事件表.默认情况下,窗口的事件表就是窗口自己,但是你可以指定不同的事件表,也可以通过PushEventHandler和PopEventHandler函数设置一个事件表链。然后让不同的事件表处理不同的事件. wxWidgets将搜索整个事件表链来寻找匹配的事件处理函数处理新收到的事件,详情请参阅第3章,“事件处理”.
GetExtraStyle和SetExtraStyle函数用来获取和设置窗口的扩展类型位。扩展类型宏通常以wxWS_EX_开头.
GetFont和SetFont函数获取和设置和窗口相关的字体. SetOwnFont和SetFont的功能相似,唯一的区别在于前者设置的字体不会被子窗口继承.
GetForegroundColour和SetForegroundColour函数用来操作窗口的前景颜色属性. 和SetOwnForegroundColour函数的区别仅在于是否改变子窗口的这个属性。
GetHelpText和SetHelpText用来获取和设置窗口相关的上下文帮助.这个文本属性实际上存储在当前的wxHelpProvider实现中,而不是存在于窗口类中.
GetId和SetId用来操作窗口标识符.
GetLabel函数返回窗口相关联的标签.具体的含义取决的特定的窗口类.
GetName和SetName用来操作窗口名称,这个名字不需要是唯一的。这个名称对wxWidgets来说没有什么意义,但是在Motif系统中被用于窗口资源的名称.
GetParent返回窗口的父窗口.
GetPosition以象素单位返回相对于父窗口的窗口左上角座标。
GetRect返回一个wxRect对象 (参考第13章, "数据结构和类型"),其中包含了象素单位的这个窗口的大小和位置信息.
GetSize和SetSize函数获取和设置窗口象素单位的窗口长宽.
GetSizer和SetSizer函数用来操作这个窗口绑定的最顶级的窗口布局对象.
GetTextExtent用于返回当前字体下某个字符串的象素长度.
GetToolTip和SetToolTip用来操作这个窗口的tooltip对象.
GetUpdateRegion函数返回窗口自上次Paint事件以来需要刷新的区域.
GetValidator和SetValidator函数用来操作这个窗口可选的wxValidator对象。详情请参考第9章.
GetVirtualSize返回窗口的虚大小,通常就是和滚动条绑定的那个大小.
GetWindowStyle和SetWindowStyle用来操作窗口类型比特位。
InitDialog函数发送一个wxEVT_INIT_DIALOG事件来来开始对话框数据传送.
IsEnabled用来检测当前窗口的使能状态.
IsExposed用来检测一个点或者一个矩形区域是否位于需要刷新的范围。
IsShown用来指示窗口是否可见.
IsTopLevel用来指示窗口是否是顶层窗口(仅用于wxFrame或者wxDialog).
Layout函数用来在窗口已经指定一个布局对象的情况下更新窗口布局。参考第7章.
Lower函数用来将窗口移到窗口树的最低层,而Raise则把窗口移动到窗口树的最顶层.这两个函数既可以用于顶层窗口,也可以用于子窗口.
MakeModal函数禁用其它所有的顶层窗口,以便用户只能和当前这个顶层窗口交互.
Move函数用来移动窗口.
MoveAfterInTabOrder更改窗口的TAB顺序到作为参数的窗口的后面, 而MoveBeforeInTabOrder则将其挪到参数窗口的前面.
PushEventHandler压入一个事件表到当前的事件表栈, PopEventHandler函数弹出并且返回事件表栈最顶层的事件表. RemoveEventHandler则查找事件表栈中的一个事件表并且将其出栈.
PopupMenu函数在某个位置弹出一个菜单.
Refresh和RefreshRect函数导致窗口收到一个重画事件(和一个可选的擦除背景事件).
SetFocus函数让本窗口收到键盘焦点.
SetScrollbar函数用来设置窗口内建的滚动条的属性.
SetSizeHints函数用来定义窗口的最小最大尺寸,依次窗口尺寸增量的大小,仅对顶层窗口适用.
Show函数用来显示和隐藏窗口; Hide函数的作用相当于适用false作为参数调用Show函数.
transferDataFromWindow和transferDataToWindow获取和传输数据到窗口对象,并且在没有被重载的情况下会调用验证函数.
Update立即重画窗口已经过期的区域.
UpdateWindowUI函数发送wxUpdateUIEvents事件到窗口,以便给窗口一个更新窗口元素(比如工具条和菜单)的机会.
Validate使用当前的验证对象验证窗口数据.
wxControl类
wxControl是一个虚类。它继承自wxWindow,用来作为控件的基类: 所谓控件指的是那些可以显示数据项并且通常需要响应鼠标或者键盘事件的那些窗口类.
wxControlWithItems类
wxControlWithItems也是一个虚类,用来作为wxWidgets的一些包含多个数据项的控件(比如wxListBox, wxCheckListBox,wxChoice和wxComboBox等)的基类。使用这个基类的目的为了给这些具有相似功能的控件提供一致的API函数。
wxControlWithItems的数据项拥有一个字符串和一个和这个字符串绑定的可选的客户数据。客户数据可以是两种类型,要么是无类型指针(void*),这意味这这个控件只帮忙存储客户数据但是永远不会使用客户数据。另外一种是有类型(wxClientData)指针,对于后一种情况,客户数据会在控件被释放或者数据项被清除的时候被自动释放。同一个控件的所有数据项必须拥有同样的客户区数据类型:要么是前者,要么是后者。客户区数据的类型是在第一次调用Append函数或者,SetClientData函数或者SetClientObject函数的时候被确定的。如果要使用有类型指针客户数据,你应该自定义一个继承自wxClientData的类,然后将它的实例指针传递给Append函数或者 SetClientObject函数。
wxControlWithItems的成员函数
Append函数给这个控件增加一个或者一组数据项. 如果是增加一个数据项,你可以用第二个参数指定有类型客户数据指针或者无类型客户数据指针。比如:
```
wxArrayString strArr;
strArr.Add(wxT("First string"));
strArr.Add(wxT("Second string"));
controlA->Append(strArr);
controlA->Append(wxT("Third string"));
controlB->Append(wxT("First string"), (void *) myPtr);
controlC->Append(wxT("First string"), new MyTypedData(1));
```
Clear函数清除控件所有数据项并且清除所有的客户数据.
Delete函数使用基于0的索引清除一个数据项以及它的客户数据。
FindString返回一个和某个字符串基于0的数据项的索引。如果找不到则返回wxNOT_FOUND.
GetClientData和GetClientObject返回某个数据项的客户区数据指针(如果有的话). SetClientData和SetClientObject则可以用来设置这个指针.
GetCount数据项的总数.
GetSelection返回选中的数据项或wxNOT_FOUND. SetSelection则用来设置某个数据项为选中状态.
GetString用来获取某个数据项的字符串; SetString则用来设置它.
GetStringSelection用来返回选中的数据项的字符串或者一个空的字符串; SetStringSelection则用来设置选中的字符串。你应该先调用FindString函数保证这个字符串是存在于某个数据项的,否则可能引发断言失败.
Insert在控件数据项的某个位置插入一个数据项(可以包含也可以不包含客户数据).
IsEmpty则用来检测一个控件的数据项是否为空.
- 第一章 介绍
- 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 全书小结