让手写输入在Web 上持久留存
摘要:本文为您展示如何回避在Web 站点中移动手写输入时遇到的许多潜在编程问题。示例代码以C# 和JavaScript 编写。
本页内容
简介
四种持久保留方法
在Web 站点内移动持久保留的数据
将手写输入发送到Web 服务
小结
简介
Tablet PC Platform 的Ink API 为您提供许多持久保留手写输入的方法。然而,在Web 站点上使用手写输入时(与手写输入交互、持久保留手写输入、将手写输入从一个Web 页移动到另一个Web 页),存在
一些局限。本文为您展示如何回避在Web 站点中移动手写输入时遇到的许多潜在编程问题。
返回页首
四种持久保留方法
一旦Ink 对象包含Strokes 集合后,就可以将其中的数据以Ink 序列化格式(Ink Serialized Format,ISF) 或可交换的图形格式(GIF) 的形式保存到一个字节数组中。ISF 含有Ink对象中的所有数据,而且可以随时重新载入Ink对象。GIF 字节数组实际上是一个加强的GIF 文件,它有两组数据。第一组字节数组用于表示转换为GIF 的图形。第二组是ISF。事实上,您能够将加强的GIF 文件发送到可以阅读GIF 而不识别ISF 的程序,也可以将其发送到Ink对象,由Ink对象加载文件的ISF 部分。要进一步了解手写输入在HTML 中可用的格式,请参阅Tablet PC Platform SDK 中的“在HTML 中存储Ink”。
ISF 和GIF 也可以与Base64 编码表示形式配对使用:Base64-ISF 和增强Base64 GIF。Base64 编码用于传输二进制数据,它只能承载ASCII 数据。HTML 就是一个典型示例,它不能读取二进制数据。但是,它需要ASCII 数据。
即使将手写输入保存为Base64 格式,也仍然需要返回一个字节数组,并将其转换为ASCII。还有另一种方法可以达到这个目的,就是使用ToBase64String()方法将规则的ISF 或Gif 字节数组转换为ASCII。
这种情况下,不必一开始就使用Base64 作为持久保留格式。采用这种方法的优点是传递的字符串更短。
下列表格以一个非常小的手写输入图形(只是随意画上去的几条线)为例,说明字节数组以及转换后的ASCII 字符串的大小差异。如果要处理大量数据,需要注意此类差异。
表  1. 以不同的格式持久保留示例Ink 对象的字节数组长度和字符串长度。
返回页首
在Web 站点内移动持久保留的数据
在Web 站点上使用启用手写输入的控件时,谨记Web 页和控件之间的所有交互均在客户端脚本中进行。Tablet PC 开发人员中心已经有两篇文章对此进行了详细的阐述,它们是Mobile Ink Jots 3: Ink on the Web 和 Doodling on the Web。
正是由于使用这种客户端脚本的缘故,我们才能在HTML 中移动数据。因此,您必须
将 Ink.Save 方法返回的字节数组转换为ASCII。理论上,这与之前讨论的Base64 编码相似。要进行交互就需要达到最低的通用标准。为此,以下示例中的许多过程均采用这种方法实现:先将Ink对象保存为字节数组(以四种持久保留格式之一的格式),然后再将字节数组转换为Base64 编码字符串。即使字节数组已经是Base64 编码格式,也需要转换为Base64 编码ASCII。
以下各部分说明在Web 站点上移动数据的不同方法,并列举每种方法的优缺点。
传输隐藏值
使用客户端函数时,您不能充分利用ASP.NET Session 对象在两个页面之间移动数据。但可以利用隐藏字段,不过您需要知道使用它并不安全。隐藏字段的内容在页面HTML 源代码中是可见的。千万不要在隐藏字段中存储任何敏感数据,例如签名和社会保障号。客户端脚本可以与隐藏字段交互,从中读取或写入数据。只要隐藏字段的runat参数设置为server,您就可以在服务器端代码(也称为后台代
码)中读取其中的数据。但是,如果不移除窗体的runat=server参数,该设置不起作用,因为这意味着除此之外,您将不能使用大部分Web 服务器控件。的确,在页面之间传输数据还有其他方法,但请注意特殊情况。
如果PageA 使用脚本window.open在一个新窗口中打开PageB,那么PageA 的对象可通
过window.opener对象在PageB 的客户端代码中使用。以下代码(JavaScript) 用于从调用页面获取名为MyHiddenField的隐藏字段值。
Window.opener.document.forms("MyForm").MyHiddenField.Value
如果PageA 使用超链接、窗体的提交动作或服务器传输方法,则在后台代码中可以通
过Request.GetValues(hiddenFieldName)方法使用隐藏字段。该方法返回的实际上是一个字符串数组,要获得真正的值,需要抽取数组中的第一项,如下所示(Visual Basic)。
'Creates an array object to store strings.
Dim MyStringArray() as String
MyStringArray()=Request.GetValues("myHiddenFieldonPageA")
Dim ValuefromPageA as String=MyStringArray(0)
获得服务器端代码中的数据后,可以将其存储在Session对象中,供Web 应用程序的其他部分使用,甚至可以将数据值再存储到另一个页面的隐藏字段中,供客户端代码访问。后文的一些示例使用了这种方法。
现在,您已经理解了其中的一些局限性,但在开始使用Web 页面技术之前,还必须在手写输入控件中完成某些设置。如果您在Web 上阅读过开发人员中心关于手写输入的其他文章,就会明白,最有效的体系结构是尽可能将手写输入控件的功能都留给它自己处理。而您只要通过客户端脚本与该控件进行通讯并公开该功能即可。
以下示例(C#) 是公开持久保留功能的方法,它们在Windows 窗体控件内使用。inkO表示用于使控件启用手写输入的InkOverlay 对象。
返回Base64 ASCII 格式的Gif 持久保留手写输入
public string GetGIFasASCII()
{
// Be sure to return something, even if
// there are no strokes at all.
if (inkO.Ink.Strokes.Count==0)
{
return "empty";
}
byte[] inkBytes=inkO.Ink.Save(PersistenceFormat.Gif);
return Convert.ToBase64String(inkBytes);
}
返回Base64 ASCII 格式的ISF 持久保留手写输入
public string GetISFasASCII()
{
if (inkO.Ink.Strokes.Count==0)
return "empty";
byte[] inkBytes =
inkO.Ink.Save(PersistenceFormat.InkSerializedFormat);
return Convert.ToBase64String(inkBytes);
}
返回ISF 持久保留手写输入的字节数组
public byte[ ] GetISFasByteArray()
{
if (inkO.Ink.Strokes.Count==0)
return new byte[]{0};
byte[]
inkBytes=inkO.Ink.Save(PersistenceFormat.InkSerializedFormat);
return inkBytes;
}
加载任意类型的Base64 ASCII 持久保留手写输入
无论使用哪种持久保留格式,都可以用 Ink.Load 方法加载手写输入数据。即使之后将持久保留的数据转换为Base64 字符串,仍然可使用该方法进行加载。以我所作的测试为例,在以某种可视的方式加载手写输入之前,事先将它变为红,后来我确实看到了新的手写输入。
public void LoadfromBase64ASCII(string ASCIIData)
{
byte[] inkBytes=Convert.FromBase64String(ASCIIData);
inkO.Ink.Load(inkBytes);
this.Invalidate(); // Forces a redraw
}
加载持久保留手写输入的字节数组
以下方法加载仍以原始字节数组保存的所有持久保留数据,该字节数组由Ink.Save方法返回,加载行为与使用的持久保留格式无关。
public void LoadfromInkBytes (byte[] InkData)
{
inkO.Ink.Load(InkData);
this.Invalidate(); // Forces a redraw
}
在下列情况中,有些是无需任何额外的Web 服务器往返过程即可完成的,而另一些确实需要与Web 服务器进行交互。某些情况下,可以使用的持久保留格式可能不止一种,但是我们的目标是使用能够完
如何启用javascript功能
成任务的最有效格式。除此之外,有时可能不必将返回的字节数组转换为文本。
注请密切注意与Web 控件相对应的HTML 控件所在的位置。
虽然这些情况使用的是最简单的方法,但提供了关于高级技术的建议,以便进一步的研究。
将手写输入传输到页面上另一个启用手写输入的控件
在这种情况下使用的是ISF 格式,因为数据由另一个启用手写输入的控件使用。而且,没有必
要回发数据或以HTML 格式传输数据—即,不必将字节数组转换为Base64 ASCII 文本。
在Web 页面上嵌入两个手写输入控件以及一个HTML 按钮。
下列函数(JavaScript) 放在脚本标签的头部。该函数从第一个手写输入控件中获取手写输入数据,再将其载入第二个控件。
function Dupe_ISFBytes()
{
bytes=Form1.inkControlA.GetISFasByteArray();
Form1.inkControlB.LoadfromInkBytes (bytes);
}
将手写输入传输到另一个新浏览器窗口页面上的手写输入控件
这种方法使用纯JavaScript 功能将一个页面上当前的二进制数据发送到另一个页面上。该方法
的优点是能够在另一个页面上启用服务器控件;缺点是需要在新的浏览器窗口中打开另一个页面。
由于该方法使用了JavaScript 的功能,所以不需要在另一个页面上使用隐藏字段将数据从服务
器移动到客户端。因而该页面仍然可以使用服务器控件。但是,要使用JavaScript 函数,您必
须在新的浏览器窗口中打开另一个页面。您还需要在第一个页面上使用一个隐藏控件,在第二个页面上使用脚本强制加载数据。
首先,在第一个页面上嵌入一个手写输入控件。其次,在该页面上放置一个隐藏输入控件,再
将runat=server添加到HTML 中的<input> 标签后面。请注意,该操作不能在控件的属性窗口中进行。然后,在该页面上添加一个HTML 按钮。
将JavaScript 函数InktoNewForm添加到脚本正文标记的起始处。
function InktoNewForm()
{
Form1.InkDataBytes.value=Form1.inkControl.GetISFasByteArray(); window.open("Form2.aspx");
}
InktoNewForm获得ISF 字节数组形式的手写输入数据后,会将其存储到隐藏输入字段,然后再通过JavaScript window.open方法打开另一个页面。如果允许新页面完全从客户端访问隐藏值数据,那么在新浏览器窗口中打开新页面似乎是唯一可行的办法。
接下来,将以下脚本放在客户端脚本Form2的正文标记起始处,然后再构建页面的其余部分。<script language= JavaScript>

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。