当前位置: 首页 > 编程日记 > 正文

MS UI Automation Introduction

MS UI Automation Introduction

2014-09-17

MS UI Automation是什么

UIA架构

UI自动化模型

UI自动化树概述

UI自动化控件模式概述

UI 自动化属性概述

UI 自动化事件概述

示例

使用UISpy工具

UI自动化提供者

常见问题分析解决

控件无法识别

Timing issue

本地化问题

自动化技术和自动化框架

参考

MS UI Automation是什么[1]


返回

UI Automation 就是用另一个程序来控制UI 程序,模拟用户操作。他包含三步骤:

  1. 找到UI 元素
  2. 模拟用户操作
  3. 检查UI属性和行为

微软UI Automation技术提供了很好的实现模型。简单来讲,它就是几个dll,提供了一套API及其相应的模式,让软件的开发者遵循该模式去实现相应的interface,从而使测试人员更方便的编写UI Automation。

UIA架构[1]


返回

MS UIA明确定义了两个role:UIA Provider即软件本身,也可称为服务器端,UIA Client即自动化脚本和相关的assistive technology applications,见图1。

  • UIA Provider: 开发人员确定控件行为并实现对应的UIA control pattern(注意:对于标准控件而言,默认是支持UIA的,而对于自定义的控件,需要实现该控件的行为对应于UIA所定义的interface。)
  • UIA Client:相对而言,UIA Client则简单了很多,只需调用相关的UIA API去完成自动化测试脚本。

图1 架构简易图

图2 官方架构图

在图2中,Applications是软件本身,也可成为服务器端,Accessibility Tool是客户端,即测试软件或测试工具(如UISpy.exe)。

从图2可得知UIAutomation Core是通信基础代码,而且Applications和Accessibility Tool是通过管道通信的。

UIA主要有4个组件

组件                                       

描述                                       

提供程序 API(UIAutomationProvider.dll 和 UIAutomationTypes.dll)                                       

定义了各种行为的interface,例如,假设有个自定义的控件,开发人员觉得它需要支持Dock行为,就需要实现IDockProvider接口。            

客户端 API(UIAutomationClient.dll 和 UIAutomationTypes.dll)                                       

定义了各种控件模式,以及一些用来支持更好的定位控件的辅助条件搜索类                                  

UiAutomationCore.dll                                       

处理提供程序与客户端之间的通信的基础代码(有时也称为 UI 自动化核心)。                                       

UIAutomationClientsideProviders.dll                                       

一组用于标准旧版本控件的 UI 自动化提供程序。(WPF 控件为 UI 自动化提供本机支持。)此支持自动提供给客户端应用程序。                    

图3 UIA dll 使用

常用命名空间:

namespace                                          

引用的 DLL                                       

读者                                       

System.Windows.Automation

UIAutomationClient;UIAutomationTypes                                       

UI 自动化客户端开发人员;用于查找 AutomationElement 对象、注册 UI 自动化事件以及与 UI 自动化控件模式一起使用。                                       

System.Windows.Automation.Provider

UIAutomationProvider;UIAutomationTypes                                       

除 WPF 之外的框架的 UI 自动化提供程序开发人员。                                       

System.Windows.Automation.Text

UIAutomationClient;UIAutomationTypes                                       

除 WPF 之外的框架的 UI 自动化提供程序开发人员;用于实现 TextPattern 控件模式。                                       

System.Windows.Automation.Peers

PresentationFramework                                       

WPF 的 UI 自动化提供程序开发人员。

UI自动化模型[2]


返回

UI 自动化将 UI 的每一部分作为一个 AutomationElement 向客户端应用程序公开。

元素包含在树结构中,以桌面作为根元素。

AutomationElement 对象公开它们所表示的 UI 元素的通用属性。  其中一个属性是控件类型,它将其基本外观和功能定义为一个可识别的实体:例如按钮或复选框。

此外,元素还公开控件模式,以提供特定于这些元素的控件类型的属性。  控件模式还公开方法,使客户端能够获取有关元素的进一步信息并提供输入。

注意:控件类型和控件模式之间并不是一一对应的关系。  多个控件类型可以支持同一个控件模式,一个控件可以支持多个控件模式,每个控件模式公开其行为的不同方面。 例如,一个组合框至少具有两个控件模式:一个表示其展开和折叠功能,另一个表示选择机制

UI 自动化还通过事件向客户端应用程序提供信息。  与 WinEvent 不同的是,UI 自动化事件并不基于广播机制。 UI 自动化客户端注册特定的事件通知,并且可以请求将特定的 UI 自动化属性和控件模式信息传入其事件处理程序中。 此外,UI 自动化  事件包含到引发该事件的元素的引用。 提供程序可以通过有选择地引发事件来改善性能,具体取决于所有客户端是否在侦听。

UI自动化树概述[3]

在UIA中,程序UI的每一个部分都被认为是一个AutomationElement类,他们是一个树状的结构,Desktop被认为是每个windows based app的UIA树状图的根,从类的定义中,我们也可以看到一个AutomationElement类中有一个static的RootElement属性。

该树的结构中,一共有3中View Model,分别为Raw View, Control View和Content View:

Raw View提供的信息最多,也是其他view的基础,最贴近于程序本身的编程结构;

Control View是Raw View的子集,它最贴近于最终用户所能感知的UI结构,但是它不包含不能和用户相互交互的一些UI,例如listview的header,toolbar等等;

Content View则是Control View的一个子集,它只包含能和用户直接交互真实信息的控件,比如接受键盘输入的Textbox,选择不同值的Combobox;而诸如lable等控件则不会包含在其中。

UI自动化控件模式概述[4]

控件模式需实现定义控件中可用的一项独立功能所需的方法、属性、事件和关系:

  • UI 自动化元素与其父元素、子元素以及同级元素之间的关系描述了 UI 自动化树内元素的结构。
  • UI 自动化客户端使用方法可以操作控件。
  • 属性和事件提供了有关控件模式功能的信息以及有关控件状态的信息。

UIA大概一共定义了38种pattern,代表了常用的控件行为,他们也会提供一些具体的功能性的属性。

  • 对于UIA Provider来说,所做的事情就是定义控件相关的行为,找到该行为对应的模式,并实现该模式;
  • 对于client而言,即访问相关的方法和属性,来实现自动化。

如某个控件需要有InvokePattern,则provider和client相对应的则为:

控件模式类 (Client)                                      

提供程序接口(Provider)                                      

说明                                       

InvokePattern

IInvokeProvider

用于可被调用的控件,如按钮。

UI 自动化属性概述[5]

每个property都由一个数字和名字来标识,provider用数字ID来确定属性请求(出于安全原因,UI 自动化提供程序将从 Uiautomationtypes.dll 中包含的一组单独的类中获取这些对象。);而client则用AutomationProperty类获取具体的某一属性的内容。

UI 自动化事件概述[6]

UIA是采用订阅模型,而不是以前的广播事件模型。定义了四种事件类型:Property change,Element action,Structure change和Global desktop change。

客户端的 UI 自动化事件

示例[8]


返回

下面这个示例用测试程序完成以下操作:

  1. 打开Calculater.exe;
  2. 找到button '3', '+', '5', '-', '2', '=', 并模拟点击它们。这样,计算器屏幕上会显示‘3+5-2’,并计算结果;
  3. 找到计算器屏幕,得到计算结果;
  4. 比较计算结果和预期结果是否一致。一致,则pass;反之,则fail。
  1 //Reference UIAutomationClient and UIAutomationTypes
  2 
  3 using System;
  4 using System.Windows.Automation;
  5 using System.Windows;
  6 
  7 namespace CalcClient
  8 {
  9     class CalcAutomationClient
 10     {
 11         AutomationElement calcWindow = null; //Main UI Window element
 12         //The following ID can be obtained from tool: UI Spy     
 13         string resultTextAutoID = "150"; //ID for Text element of output window
 14         string btn5AutoID = "135"; //ID for button 5
 15         string btn3AutoID = "133"; // ID for button 3
 16         string btn2AutoID = "132"; // ID for button 2
 17         string btnPlusAutoID = "93"; // ID for button +
 18         string btnSubAutoID = "94"; // ID for button -
 19         string btnEqualAutoID = "121"; // ID for button =
 20 
 21         static void Main(string[] args)
 22         {
 23             CalcAutomationClient autoClient = new CalcAutomationClient();
 24 
 25             //Create callback for new Window open event. Test should run only when the main Window shows.
 26             AutomationEventHandler eventHandler = new AutomationEventHandler(autoClient.OnWindowOpenOrClose);
 27             //Attach the event with desktop element and start listening.
 28             Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, eventHandler);
 29 
 30             //Start caculator. When new window opens, the new window open event should fire.
 31             System.Diagnostics.Process.Start("calc.exe");
 32 
 33             //Wait execution
 34             Console.ReadLine();
 35         }
 36 
 37         void OnWindowOpenOrClose(object src, AutomationEventArgs e)
 38         {
 39             if (e.EventId != WindowPattern.WindowOpenedEvent)
 40             {
 41                 return;
 42             }
 43 
 44             AutomationElement sourceElement;
 45 
 46             try
 47             {
 48                 sourceElement = src as AutomationElement;
 49 
 50                 //Check the event source is caculator or not.
 51                 //In production code, string should be read from resource to support localization testing.
 52                 if (sourceElement.Current.Name == "Calculator")
 53                 {
 54                     calcWindow = sourceElement;
 55                 }
 56             }
 57             catch (ElementNotAvailableException)
 58             {
 59                 return;
 60             }
 61 
 62             //Start testing
 63             ExecuteTest();
 64         }
 65 
 66         void ExecuteTest()
 67         {
 68             //Execute 3+5-2
 69             //Invoke ExecuteButtonInvoke function to click buttons
 70             ExecuteButtonInvoke(btn3AutoID);
 71             ExecuteButtonInvoke(btnPlusAutoID);
 72             ExecuteButtonInvoke(btn5AutoID);
 73             ExecuteButtonInvoke(btnSubAutoID);
 74             ExecuteButtonInvoke(btn2AutoID);
 75             System.Threading.Thread.Sleep(1000);
 76             ExecuteButtonInvoke(btnEqualAutoID);
 77 
 78             //Invoke GetCurrentResult function to read caculator output
 79             if (GetCurrentResult() == "6")
 80             {
 81                 Console.WriteLine("Execute Pass!");
 82                 return;
 83             }
 84 
 85             Console.WriteLine("Execute Fail!");
 86         }
 87 
 88         void ExecuteButtonInvoke(string automationID)
 89         {
 90 
 91             //Create query condition object, there are two conditions.
 92             //1. Check AutomationID
 93             //2. Check Control Type
 94             Condition conditions = new AndCondition(
 95                 new PropertyCondition(AutomationElement.AutomationIdProperty, automationID),
 96                  new PropertyCondition(AutomationElement.ControlTypeProperty,
 97                                  ControlType.Button));
 98 
 99             AutomationElement btn = calcWindow.FindAll(TreeScope.Descendants, conditions)[0];
100 
101             //Obtain the InvokePattern interface
102             InvokePattern invokeptn = (InvokePattern)btn.GetCurrentPattern(InvokePattern.Pattern);
103 
104             //Click button by Invoke interface
105             invokeptn.Invoke();
106         }
107 
108         string GetCurrentResult()
109         {
110 
111             Condition conditions = new AndCondition(
112                 new PropertyCondition(AutomationElement.AutomationIdProperty, resultTextAutoID),
113                  new PropertyCondition(AutomationElement.ControlTypeProperty,
114                                  ControlType.Text));
115 
116             AutomationElement btn = calcWindow.FindAll(TreeScope.Descendants, conditions)[0];
117 
118             //Read name property of Text control. The name property is the output.
119             return btn.Current.Name;
120         }
121     }
122 }
View Code

使用UISpy工具

UISpy可以当作Client,找到Server所提供的属性、控件模式,也可对Server进行模拟操作。

图4 UISpy attached to Calculator

UI自动化提供者

在UIA架构中提到:对于标准控件而言,默认是支持UIA的,而对于自定义的控件,需要实现该控件的行为对应于UIA所定义的interface。

这里提到的实现UIA所定义的interface,就是UIA provider。UIA provider可在根据实际情况在服务器端和客户端实现,示例如下:

客户端:

Client-Side UI Automation Provider -  WinForm Sample

服务器端:

Server-Side UI Automation Provider - WinForm Sample

Server-Side UI Automation Provider - WPF Sample

常见问题分析解决[8]


返回

控件无法识别

  1. 如果是因为自动化测试工具的限制,比如对于WinForm的控件,有些自动化工具就不能识别,碰到这种情况,最好是看这个工具有没有扩展可以用,比如Silktest的.Net Framework扩展。如果不行,那只能换自动化测试工具了。所以这个凸显出在做自动化测试以前,选择自动化测试工具的重要性。
  2. 如果是因为控件比较复杂,自动化工具可以识别,但是无法操作。这时我们可以通过Window API以及消息的方式来做,比如自己去调Window API来操作窗口,或者请开发实现一下消息的接口来给自动化工具调用等
  3. 跟开发沟通,让他们的控件支持IAccessible接口,然后我们通过MSAA来操作(如果是WPF控件,则需要实现UIAutomation定义的一些接口)。不过一般情况下,除了微软这样对软件的Accessible要求很高的公司,其它公司很少会花费时间来实现这个接口……。 另外扯一句,产品的Accessible的程度,实质上决定了一个公司能对产品做自动化测试的程度。
  4. 如果以上方法都不行,那只有最后一个双刃剑可以用了,就是鼠标键盘模拟。理论上来说,只要用户可以操作的东西,只要有界面,就可以通过鼠标键盘模拟来实现(君不见N多游戏外挂的键盘鼠标模拟大法)。就如双刃剑一样,这种做法是杀敌一千,自损八百。因为鼠标键盘模拟非常依赖于当前激活的窗口以及光标位置和焦点位置,而且同步起来很困难。这也造成了后期维护成本很高。

Timing issue

提倡第一种方法。

  1. Waiter/EventDriven
  2. Retry sleep a small interval value
  3. Thread.Sleep a long time

本地化问题

Avoid localize issue, read resource string

自动化技术和自动化框架[8]


返回

前面提到了UIA作为全新UI自动化测试技术的优势,但这并不能解决所有的UI 自动化问题。 自动化框架正是为了自动化技术没有完全解决的问题。比如:

  • 自动化中的同步和等待。 对于稍复杂的UI 程序,测试程序往往需要根据测试目标的状态决定 下一步的操作。 比如测试文件另存为功能的时候,若保存路径是网络路径,可能会因为网络延迟导致整个UI停顿比较长的时间。这个时候测试,程序如果不顾当前状态而简单地执行下一步操作,比如新建文件, 很可能会因为UI延迟而失败。 正确的做法是,测试程序应该等待文件保存成功返回后,再进行下一步操作。 这就是自动化中同步和等待的一个例子。实现同步和等待有多种方法,最简单粗暴的做法是硬编码一个长时间的 Sleep在测试代码中。 稍微好一点的做法可以采取小时间片的轮询状态检查, 或者反复重试。 借助 UIA的Event Pattern,可以尝试捕获另存为窗口的关闭WindowClosedEvent。 如果要做得完善一点, 可以把多种方法结合, 另外再额外检查目标程序的CPU使用情况,消息循环是否有回应,设定超时时间等等。
  • 冗繁的编码过程。 对于一个UI窗口,里面可能有几十个子控件或者子窗口。 在编写测试代码的时候, 如果对这些子元素的获取,操作不能简化, 势必导致代码冗繁,难以维护。 借助自动代码生成和ORM (Object Role Modeling)等技术, 可以解决这个问题。 比如可以用工具把窗口及其子元素的关系和搜索条件都序列化到XML文件中, 然后采用ORM技术即可在代码中轻松获取子元素。
  • 多语言和本地化测试。多语言和本地化的测试对UI来说显得尤为重要。 UI程序往往通过资源文件来定义所显示的内容, 这就要求自动化测试要可以方便读取和定位程序的资源文件, 来支持多语言和本地化测试。
  • 支持工具和辅助函数的匮乏。 对于大的项目研发, 通过好的工具来减小开发成本是非常必要的。 就UI自动化来说, 如果自动化测试用例可以通过一次录制,多次播放来做的话,成本会减少很多。 在VS2010中就提供了这样的录制-播放功能。 详细视频可以参考How to create record and playback Test Cases in Visual Studio Beta2。
  • 区分功能性测试和用户真实行为模拟。 前面提到, 就点击按钮功能来说, 可以通过SendKey来模拟鼠标操作, 或者通过Windows Message来直接触发点击事件。 这两种不同方法各有优劣。 比如当按钮被其它元素遮挡, 通过SendKey进行模拟就会导致失败,而直接发送Windows Message还是会成功。 孰优孰劣取决于要达到的目的。 如果单纯为了测试按钮点击后导致的结果,通过Windows Message来模拟就省去了很多麻烦。 相反, 如果是界面测试, 通过SendKey来模拟就可以让按钮被遮挡的bug暴露出来, 而Windows Message则不能发现这样的问题。

所以,单纯的某个自动化技术或者方法也无法满足需求。为了解决上述问题,各种自动化测试框架逐渐涌现和发展。微软内部有多个不同的自动化框架,设计理念和侧重点各有不同。 Visual Studio 2010将加入对自动化测试的支持。 在CodePlex上面, 也可以找到多种框架,比如White和UI Automation Verify。

参考

[1] MS UI Automation简介

[2] UI 自动化概述

[3] UI 自动化树概述

[4] UI 自动化控件模式概述

[5] UI 自动化属性概述

[6] UI 自动化事件概述

[7] 使用 UI 自动化进行自动化测试

[8] UI Automation - under the hood

转载于:https://www.cnblogs.com/Ming8006/p/3977271.html

相关文章:

spring+mybatis事务的readonly属性无效

在Spring配置事务中设置的read-only"true"不起作用,仍可以执行写操作;但是其他的正常。查看了一下DataSourceTransactionManager这个类的doBegin方法中没有判断read-only。HibernateTransactionManager.doBegain方法中则有一判断 if(!definiti…

ue5新手零基础学习教程 Unreal Engine 5 Beginner Tutorial - UE5 Starter Course

ue5新手零基础学习教程 Unreal Engine 5 Beginner Tutorial - UE5 Starter Course! 教程大小解压后:4.96G 语言:英语中英文字幕(机译)时长:4小时56分 1920X1080 mp4 虚幻引擎5新手教程!在这个教程中&…

C语言科学计算器思路,大神教你如何用C语言实现科学计算器

i;*leni;return temp;}/*功能:翻译操作数* 如果运算符非法,则返回0,合法则返回非零标志*/int translateopt(char *p,int *len){char fu[NUM_OPT][LEN_OPT]{"","-","*","/","^","(&qu…

BZOJ4292 : [PA2015]Równanie

注意到f(n)不会超过1459&#xff0c;于是暴力枚举f(n)&#xff0c;检验nk*f(n)是否合法即可。 #include<cstdio> long long k,a,b,t;int i,j,ans; int main(){scanf("%lld%lld%lld",&k,&a,&b);for(i1;i<1459&&k<b/i;i){tk*i;if(a<…

Docker入门六部曲——Stack

原文链接&#xff1a;http://www.dubby.cn/detail.html?id8739 准备知识 安装Docker&#xff08;版本最低1.13&#xff09;。阅读完Docker入门六部曲——Swarm&#xff0c;并且完成其中介绍的内容。拷贝一份docker-compose.yml。确保你的虚拟机都是可用的&#xff0c;使用do…

SVD神秘值分解

SVD分解 SVD分解是LSA的数学基础&#xff0c;本文是我的LSA学习笔记的一部分&#xff0c;之所以单独拿出来&#xff0c;是由于SVD能够说是LSA的基础&#xff0c;要理解LSA必须了解SVD&#xff0c;因此将LSA笔记的SVD一节单独作为一篇文章。本节讨论SVD分解相关数学问题&#xf…

ebook download websites (to be continue...)

http://free-ebook-collection.blogspot.com/转载于:https://www.cnblogs.com/jerryhong/archive/2008/10/24/1318469.html

Blender模块化建筑环境地形场景制作视频教程 Creating modular environments

Blender模块化建筑环境地形场景制作视频教程 Creating modular environments Blender模块化建筑环境地形场景制作视频教程 Creating modular environments 流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz 语言&#xff1a;英语中英文字幕&…

文件系统演示C语言,基于C语言的简单文件系统的实现

1 题目介绍通过具体的文件存储空间的管理、文件物理结构、目录结构和文件操作的实现&#xff0c;加深对文件系统内部的数据结构、功能以及实现过程的理解。在内存中开辟一个虚拟磁盘空间作为文件存储分区&#xff0c;在其上实现一个简单的基于多级目录的单用户单任务系统中的文…

深度学习 vs 机器学习 vs 模式识别

http://www.csdn.net/article/2015-03-24/2824301 【编者按】本文来自CMU的博士&#xff0c;MIT的博士后&#xff0c;vision.ai的联合创始人Tomasz Malisiewicz的个人博客文章&#xff0c;阅读本文&#xff0c;你可以更好的理解计算机视觉是怎么一回事&#xff0c;同时对机器学…

2022-2028年中国乙丙橡胶行业市场全景调查及投资潜力研究报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国乙丙橡胶行业市场行业相关概述、中国乙丙橡胶行业市场行业运行环境、分析了中国乙丙橡胶行…

ubuntu 下利用ndiswrapper安装无线网卡驱动

本文转载自 http://kangxincai.is-programmer.com/posts/10488.html 首先 安装 ndiswrapperubuntu下也就是 ndisgtk (用于安装无线网卡驱动)sudo apt-get install ndisgtk安装好了之后&#xff0c;找到你的无线网卡在windows下的驱动文件(含有.inf的目录)&#xff08;可以从网…

TSP问题——动态规划

Traveling Salesman Problem Description&#xff1a; Time Limit: 4sec Memory Limit:256MB 有编号1到N的N个城市&#xff0c;问从1号城市出发&#xff0c;遍历完所有的城市并最后停留在N号城市的最短路径长度。 Input&#xff1a;…

Blender从头到尾创建一辆宝马轿车视频教程

Blender从头到尾创建一辆宝马轿车视频教程 Blender: Create Realistic BMW 507 From Start to Finish 流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;44.1 KHz 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09;|大…

OC学习笔记之Foundation框架NSNumber、NSValue和NSDate(转)

一、NSNumber OC数组类NSArray&#xff0c;它只能存放 OC的对象&#xff0c;对于基本的数据类型确无能为力&#xff0c;但是实际编程中经常要把基本的数据如int、float&#xff0c;结构体存放的OC数组中&#xff0c;怎么办&#xff1f;这里的 NSNumber就有用了&#xff0c;它能…

android读取xml 字符串,Android 读取本地Xml文件,并转换成String

问题不是解析本地 xml 文件&#xff0c;而是要将 xml 文件中的所有内容(包含格式&#xff0c;标签等)&#xff0c;直接转换成 String。与前端H5页面交互时&#xff0c; iOS 在请求远程 xml 文件耗时太长(有时需要4~5s)&#xff0c;所以采用本地下载&#xff0c;然后传给前端的方…

Docker入门六部曲——容器

原文链接&#xff1a;http://www.dubby.cn/detail.html?id8734 准备 已经安装好Docker 1.13或者以上的版本。读完的上一篇文章&#xff08;基本引导&#xff09;。简单的测试一下你的本地环境是否已经OK了&#xff1a;docker run hello-world。 介绍 让我们开始构建一个Doc…

window.name实现的跨域数据传输

2019独角兽企业重金招聘Python工程师标准>>> 这篇文章是对 JavaScript跨域总结与解决办法 的补充。 有三个页面&#xff1a; a.com/app.html&#xff1a;应用页面。a.com/proxy.html&#xff1a;代理文件&#xff0c;一般是一个没有任何内容的html文件&#xff0c;需…

ajax frameworks(转贴)

Thinking in AJAX(三) —— AJAX框架汇总 引 此文原出于AJAX Patterns网站的一篇《Ajax Frameworks》的wiki文章&#xff0c;很早前我就注意到&#xff0c;后来在国内也有人翻译了&#xff0c;不过最近发现此wiki还是在不断添加维护中&#xff0c;截止此文发布前&#xff0c;作…

Maya角色面部表情动画制作视频教程 Maya: Facial Rigging

Maya角色面部表情动画制作视频教程 Maya: Facial Rigging Maya角色面部表情动画制作视频教程 Maya: Facial Rigging Maya角色面部表情动画制作视频教程 Maya: Facial Rigging MP4 |视频:h264&#xff0c;1280x720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 语言&#x…

(一三〇)UITextField的光标操作扩展

简介 在iOS开发中&#xff0c;有时候需要完全自主的定义键盘&#xff0c;用于完整的单词输入&#xff0c;例如计算机应用中&#xff0c;需要一次性的输入sin(&#xff0c;在移动光标时要完整的跳过sin(&#xff0c;在删除时也要完整的删除&#xff0c;这就需要对光标的位置进行…

android 多个占位符,Android多语言支持:由于占位符计数不同导致的字符串格式问题...

我正在制作一个法语Android应用程序,我正在努力支持英语.我使用“占位符”来格式化我的字符串,因此我可以将它们调整为男性和女性用户.例如,我的s​​trings.xml文件中的这个字符串&#xff1a;Les %1$s sont compliqu%2$ss...将成为“Les hommessontcompliqus”(“男人很复杂”…

Docker入门六部曲——Swarm

原文链接&#xff1a;http://www.dubby.cn/detail.html?id8738 准备工作 安装Docker&#xff08;版本最低1.13&#xff09;。安装好Docker Compose&#xff0c;上一篇文章介绍过的。安装好Docker Machine&#xff0c;上一篇文章也提到了&#xff0c;Mac和Windows已经预先安装…

Ubuntu 查看磁盘空间大小命令转

df -hDf命令是linux系统以磁盘分区为单位查看文件系统&#xff0c;可以加上参数查看磁盘剩余空间信息&#xff0c;命令格式&#xff1a;df -hl显示格式为&#xff1a; 文件系统 容量 已用 可用 已用% 挂载点 Filesystem Size Used Avail Use% Moun…

MSSQLid清零

truncate table [cellphone2016].[dbo].[tp_phone_9]转载于:https://www.cnblogs.com/wangchuang/p/5259615.html

Blender 3D插图插画设计视频教程 Fantastic 3D illustration with Blender

Blender 3D插图插画设计视频教程 Fantastic 3D illustration with Blender Blender 3D插图插画设计视频教程 Fantastic 3D illustration with Blender Blender 3D插图插画设计视频教程 Fantastic 3D illustration with Blender Brellias |时长:1h 30m |视频:H264 1920x1080 |音…

Linux搜索文件&搜索文件名&替换文件内容

locate是Linux系统提供的一种快速检索全局文件的系统命令,它并不是真的去检索所以系统目录,而是检索一个数据库文件locatedb(Ubuntu系置/var/cache/locate/locatedb),该数据库文件包含了系统所有文件的路径索引信息,所以查找速度很快。time结尾的选项,其单位为天,min结尾的选项其单位为分钟,这些选项的值都为一个正负整数, 如+7,表示,7天以前被访问过的文件,-7表示7天以内被访问过的文件,7表示恰好7天前被访问的文件。:快速返回某个指定命令的位置信息。

Lock和Synchronize区别详解

synchronized是Java中的一个关键字,当我们调用它时会从在虚拟机指令层面加锁,关键字为monitorenter和monitorexitLock是Java中的一个接口,它有许多的实现类来为它提供各种功能,加锁的关键代码为大体为Lock和unLock;synchronized可对实例方法、静态方法和代码块加锁,相对应的,加锁前需要获得实例对象的锁或类对象的锁或指定对象的锁。说到底就是要先获得对象的监视器(即对象的锁)然后才能够进行相关操作。

android usb 触摸屏 apk,Android插入USB设备,自动弹出提示运行apk

USB HOST模式开发下可能会遇到这个问题。第一步是在AndroidManifest.xml文件中修改,主意下面红色字体......一般调用的activity都是Main和Lanunch入口&#xff0c;加入上面的action后&#xff0c;在SDK中以Run As Android Application时&#xff0c;仅执行安装动作&#xff0c;…

sskeychain使用(轻量级框架)

原文地址&#xff1a;http://www.ithao123.cn/content-2407927.html keychain的主要功能就是帮助用户安全地记住他的密码&#xff0c;keychain保存的密码文件都是经过加密的&#xff0c;其它人不能直接通过打开keychain的文件获得保存在keychain中的密码。在mac上可以安装钥匙串…