UI Framework-1: Native Controls
Native Controls
BackgroundDespite the fact that views provides facilities for custom layout, rendering and event processing, in many situations we have found it desirable to use the controls provided by the host operating system (Windows to begin with). This is because these widgets already have many desirable properties: a system-native appearance that reflects the latest and greatest of the host operating system (e.g. using the same Win32 API as Windows XP on Windows Vista, native buttons receive glow animations when highlighted), handling for accessibility, focus, etc. Implementing new controls using views and Skia would be possible but it would take a long time to replicate all of this functionality, and we would have to update it for each new operating system release as well. So for areas of our UI where it wasn't important to have a distinctive, custom look, we have fallen back to native controls.
Historic AbstractionHistorically, NativeControls have been used like so:
![]() A base class, NativeControl, is the root of all NativeControls, like buttons, checkboxes, tree views, etc. This View subclass is Windows-specific and has a child View that is a HWNDView. This HWNDView hosts a HWND (NativeControlContainer) that is the parent of the actual native control HWND. The parent is responsible for receiving messages sent from the child HWND (e.g. WM_COMMAND, WM_NOTIFY etc) and forwarding these back to the NativeControl. This structure with the additional HWND was thought necessary because the assorted Windows common controls communicate message notifications to the client app by sending messages to the parent window. Back when Chrome had several different ViewContainer/root widget types, it made sense to encapsulate this handling at the NativeControl level. These days, there is only one root HWND type to be concerned with - WidgetWin, so it actually makes more sense to have it receive control notifications and forward them back to the NativeControl, rather than having to carry around all these extra HWNDs.
Another problem with this abstraction is related to the fact that Chrome has many different kinds of Buttons. Because NativeButton has no shared base class with the other Button base (BaseButton), much of the API ends up being slightly different. It'd be desirable to share a base class and then implement any of the NativeButton-specific methods in the derived class. However this is not possible due to this structure.
A final point of note: some NativeControl subclasses like CheckBox are a combination of system native controls and views components. To get proper transparent rendering behind the text label of a checkbox, the CheckBox has two child views - one which is the native windows control rendering only the checkmark section, and a views::Label child which renders the text. This structure has to be accommodated in any proposed modifications to this design.
Proposed DesignFirst of all, for any proposed design it's desirable to keep the API simple for users since native controls are used in very many places throughout Chrome. Ideally, using a native control is as simple as constructing one and adding it to your view hierarchy, which is the usage model that exists today for the windows-specific native controls and the views controls.
To achieve this, we use the PIMPL idiom to hide the native control implementation from the client in a setup like this:
![]() In this world, NativeButton is a class derived from a base Button class just as the other Button classes are (e.g. TextButton, etc). It overrides various methods that require interaction with the native control, such as making the button appear as the default button in a dialog box etc. The interesting thing here is that the NativeButton itself is cross-platform code. The platform-specific details of implementing a native control are encapsulated behind a platform-neutral NativeControl interface implemented, in this example, by a new class NativeControlWin, a subclass of HWNDView that hosts the actual Windows native control. We avoid having an extra HWND here by stashing a pointer to the NativeControlWin on the attached HWND, and have the message handler in WidgetWin attempt to forward the message to the NativeControlWin directly if it finds such an association. The NativeButton implements a listener interface that receives higher level notifications from the NativeControl implementation about messages received from the operating system. Since NativeControl is an interface not a class, it must provide a GetView accessor for the View that is to be parented as a child of the NativeButton, CheckBox or other view.
In this way, NativeButton can share a base class with other button types. A similar relationship can exist for other native controls where this is applicable, e.g. scroll bars, tree views, etc.
More Complex ControlsFor controls more complex than buttons like, for example, TreeViews, there can be more elaborate code in NativeControlWin subclasses that handle messages from the native UI control and notify the view on the right half of the diagram as needed. Keeping the views on the right half of diagram platform neutral hides the complexity of maintaining platform-specific controls from consumers in the application - e.g. there is no need for ifdefs or factory methods at the call sites - the views can just be constructed directly and added to the view hierarchy:
void FooView::Init() {
button_ = new views::NativeButton;
button_->SetListener(this);
AddChildView(button_);
}
...
void FooView::Layout() {
button_->SetBounds(0, 0, width(), height());
}
vs the more baroque:
void FooView::Init() {
button_ = views::NativeButton::CreateNativeButton();
button_->SetListener(this);
AddChildView(button_->GetView());
}
...
void FooView::Layout() {
button_->GetView()->Layout(0, 0, width(), height());
}
|
UI Framework-1: Native Controls的更多相关文章
- Hybrid UI framework shootout: Ionic vs. Famo.us vs. F7 vs. OnsenUI
1 Introduction In the past 2 years I’ve been working intensively on mobile applications, mostly hybr ...
- 00 - Vue3 UI Framework - 阅读辅助列表
阅读列表 01 - Vue3 UI Framework - 开始 02 - Vue3 UI Framework - 顶部边栏 03 - Vue3 UI Framework - 首页 04 - Vue3 ...
- [转]Ionic – Mobile UI Framework for PhoneGap/Cordova Developers
本文转自:http://devgirl.org/2014/01/20/ionic-mobile-ui-framework-for-phonegapcordova-developers/ Ionic i ...
- 05 - Vue3 UI Framework - Button 组件
官网基本做好了,接下来开始做核心组件 返回阅读列表点击 这里 目录准备 在项目 src 目录下创建 lib 文件夹,用来存放所有的核心组件吧.然后再在 lib 文件夹下创建 Button.vue 文件 ...
- 01 - Vue3 UI Framework - 开始
写在前面 一年多没写过博客了,工作.生活逐渐磨平了棱角. 写代码容易,写博客难,坚持写高水平的技术博客更难. 技术控决定慢慢拾起这份坚持,用作技术学习的阶段性总结. 返回阅读列表点击 这里 开始 大前 ...
- 03 - Vue3 UI Framework - 首页
顶部边栏做完了,接下来开始做官网的首页 返回阅读列表点击 这里 创建视图文件夹 让我们先新建一个 src/views 文件夹,用来存放官网的主要视图 然后在该文件夹下新建两个 vue 文件,作为我们的 ...
- 07- Vue3 UI Framework - Switch 组件
为了更好的提升用户体验,我们这里再做一个很常用的开关组件 switch 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 switch 组件应分为选中/未被选中,两种状态 可以通过 ...
- 08 - Vue3 UI Framework - Input 组件
接下来再做一个常用的组件 - input 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 input 组件有两种类型,即 input 和 textarea 类型 当类型为 ...
- 09 - Vue3 UI Framework - Table 组件
接下来做个自定义的表格组件,即 table 组件 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 基于原生 table 标签的强语义 允许用户自定义表头.表体 可选是否具有边框 ...
随机推荐
- Linux安装软件的几种方式
Linux下软件安装的方式主要有源码安装,rpm安装,yum安装,而常用的安装包主要有以下三种: tar包:例如software-1.2.3-1.tar.gz.它是使用UNIX系统的打包工具tar打包 ...
- ksh简介
-- Start 什么是 Shell 如果把 Linux 比作一个蛋,那么 Shell 就是蛋壳,我们需要通过 Shell 来使用系统. Shell 的种类 最早的 Shell 是 Bourne Sh ...
- xshell同时发送多条命令
1.如图,勾选撰写栏 勾选全部会话 下面的是一个很方便的小技巧.分屏 如下图垂直排列 水平排列等等
- excel文件使用html导出
<table><tr><td>1</td></tr><tr><td>2</td></tr>& ...
- linux批处理笔记
最近不得不用到Linux批处理,于是把要用到的程序反复研究了一下. #!/bin/bash是指此脚本使用/bin/bash来解释执行. -le -ge分别是小于和大于,这个倒是和latex里面的命令很 ...
- Angular4集成ng2-file-upload
在Github上找到了一个支持Angular4好用的文件上传组件ng2-file-upload,这里简单介绍一下这个库的集成使用方案. 本文基于该组件的1.2.1版. 1. 安装 安装非常简单, ...
- QT笔记 -- (4) 为QLabel添加鼠标响应方法2
1.实现 bool eventFilter(QObject *target,QEvent *event) 函数内容如下: bool eventFilter(QObject *target,QEvent ...
- HDU 1856 More is better【并查集】
解题思路:将给出的男孩的关系合并后,另用一个数组a记录以find(i)为根节点的元素的个数,最后找出数组a的最大值 More is better Time Limit: 5000/1000 MS (J ...
- [SCOI2009]windy数 数位dp
Code: #include<cmath> #include<iostream> #include<cstdio> using namespace std; con ...
- HDU 1667 The Rotation Game (A*迭代搜索)
题目大意:略 每次选择一个最大深度K,跑IDA* 估价函数H=8-中间8个格里出现次数最多的数的个数x,即把它填满这个数最少需要8-x次操作,如果dep+H>K,就跳出.. 深搜的时候暴力修改, ...

