墨迹博客 Web 示例
Ink Blog 示例应用程序演示如何创建具有墨迹书写功能的托管 UserControl 类,并在 Microsoft Internet Explorer 中托管该控件。 该示例还演示了一种使用 HTTP 通过网络发送墨迹数据的技术,以及用于在服务器上持久保存墨迹的技术。
注意
必须安装 ASP.NET Microsoft Internet Information Services (IIS) 才能运行此示例。 确保计算机满足 ASP.NET 应用程序在计算机上运行所需的要求。
注意
如果在安装了 Microsoft Windows XP Tablet PC Edition Development Kit 1.7 的非平板电脑计算机上运行此示例,则墨迹标题的文本识别功能将不起作用。 这是因为安装了 Tablet PC SDK 1.7 的非 Tablet PC 计算机缺少识别器。 应用程序的其余部分按所述执行。
概述
墨迹博客示例创建启用墨迹的 Weblog。 InkBlogWeb 是一个 ASP.NET 应用程序。 墨迹输入是通过从 ASP.NET 页引用的用户控件来完成的。
用户控件检测客户端计算机上是否安装了 Tablet PC 平台组件。 如果是这样,用户控件将在网页上向用户显示两个启用墨迹的区域:一个用于为博客文章墨迹书写标题,另一个用于条目正文。 如果未安装平板电脑平台组件,则会向用户提供条目标题和正文的标准文本框控件。
用户完成创建条目后,单击“添加博客”按钮,文章将发送到 Web 服务器进行存储。 在服务器上,应用程序保存标题文本和发布日期,以及对图形交换格式 (GIF) 文件的引用。 GIF 文件(也保存到服务器)包含强化 GIF 文件中正文中的墨迹数据。 有关强化 GIF 格式的详细信息,请参阅 以 HTML 格式存储墨迹。
InkBlog 解决方案中有两个项目: InkBlogControls 项目和 InkBlogWeb 项目。
InkBlogControls 项目
InkBlogControls 项目是一个 UserControl 项目,其中包含在网页上启用墨迹书写的用户控件的代码。 此控件(InkArea 控件)的代码位于 InkArea.cs 文件中。
类 InkArea
继承自 UserControl 类。 控件的 InkArea
构造函数调用帮助程序方法 CreateInkCollectionSurface
。
public InkArea()
{
// Standard template code
try
{
inputArea = CreateInkCollectionSurface();
}
catch (FileNotFoundException)
{
inputArea = new TextBox();
((TextBox)inputArea).Multiline = true;
}
inputArea.Size = this.Size;
// Add the control used for collecting blog input
this.Controls.Add(inputArea);
}
方法 CreateInkCollectionSurface
通过尝试创建 InkCollector 类的实例来确定 Tablet PC 墨迹书写组件在客户端上是否可用。 如果对方法的调用 CreateInkCollectionSurface
成功,该方法将返回 一个 Panel 对象作为控件。
protected Control CreateInkCollectionSurface()
{
try
{
Panel inkPanel = new Panel();
inkPanel.BorderStyle = BorderStyle.Fixed3D;
inkCollector = new InkCollector(inkPanel);
((InkCollector)inkCollector).Enabled = true;
return inkPanel;
}
catch
{
throw;
}
}
如果构造函数因找不到墨迹书写平台文件而失败,则将控件 InputArea
实例化为 TextBox 控件,而不是 InkCollector 控件。 然后,构造函数将控件的大小调整为父用户控件的大小,并将其添加到父级的 Controls 集合中。
InkArea 控件类实现三个有趣的公共属性:InkData、TextData 和 WebEnabled。
InkData 属性是只读的,并提供对序列化墨迹数据的访问权限(如果客户端支持墨迹书写)。 如果客户端不支持墨迹书写,InkData 属性将获取一个空字符串。 InkData 属性调用帮助程序方法 SerializeInkData,以确定客户端是否支持墨迹书写。
protected String SerializeInkData()
{
Debug.Assert(InkEnabled, null, "Client must be ink-enabled");
// Obtain the ink associated with this control
Ink ink = ((InkCollector)inkCollector).Ink;
// Serialize the ink
if (ink.Strokes.Count > 0)
{
byte[] inkDataBytes = ink.Save(PersistenceFormat.Gif);
return Convert.ToBase64String(inkDataBytes);
}
// Default to returning the empty string.
return String.Empty;
}
SerializeInkData
在 方法中,在获取 Ink 对象时,强制转换为 InkCollector 是必需的,因为 inputArea
声明为 Control。 如果 Ink 对象包含任何笔划,则墨迹数据将作为 GIF (使用 PersistenceFormat 枚举值) 指定的字节数组中inkDataBytes
保存。 然后, 方法将字节数组转换为 Base64 编码的字符串并返回此字符串。
假设客户端可以执行识别, TextData
属性返回 RecognitionResult 对象,该对象将墨迹数据传递给手写识别器。 如果客户端不识别墨迹,则返回文本框内容,如以下代码所示。
public string TextData
{
get
{
if (this.WebEnabled)
{
return RecognizeInkData();
}
else
{
return ((TextBox)inputArea).Text;
}
}
}
属性 TextData
调用帮助程序方法 RecognizeInkData
(如以下代码所示)来执行识别。 当系统上存在识别引擎时, RecognizeInkData
该方法返回包含 RecognitionResult 对象的 TopString 属性的字符串。 否则,返回空字符串。
protected String RecognizeInkData()
{
// Obtain the ink associated with this control
Ink ink = ((InkCollector)inkCollector).Ink;
if (ink.Strokes.Count > 0)
{
// Attempt to create a recognition context and use it to
// retrieve the top alternate.
try
{
RecognizerContext recognizerContext = new RecognizerContext();
RecognitionStatus recognitionStatus;
recognizerContext.Strokes = ink.Strokes;
RecognitionResult recognitionResult = recognizerContext.Recognize(out recognitionStatus);
if (recognitionStatus == RecognitionStatus.NoError) && ( null != recognitionResult) )
{
return recognitionResult.TopString;
}
}
catch (Exception)
{
// An exception will occur if the client does not have
// any handwriting recognizers installed on their system.
// In this case, we default to returning an empty string.
}
}
return String.Empty;
}
属性 InkEnabled
是一个只读布尔值,指示客户端计算机上是否支持墨迹书写。
控件类的另一个重要公共成员 InkArea
是 DisposeResources
方法。 此方法在内部调用 Dispose
方法,以确保清理用户控件利用的所有资源。 使用 InkArea
控件的任何应用程序在使用完 控件后都必须调用 DisposeResources
方法。
InkBlogWeb 项目
InkBlogWeb 项目是一个 Web 安装程序部署项目,它引用 InkArea
控件以提供博客功能。 有关 Web 安装程序部署项目的详细信息,请参阅 Web 安装项目的部署。
有两个实现博客示例的 .aspx 文件:Default.aspx 和 AddBlog.aspx。 Default.aspx 是 InkBlogWeb 应用程序的默认页面。 此页面的代码隐藏文件为 Default.aspx.cs。 此页面提供指向包含新博客条目表单的页面的链接,并显示任何现有的博客条目。 在对新的博客条目表单页面 AddBlog.aspx 进行以下检查之后,将介绍此过程。
AddBlog.aspx 及其代码隐藏文件 AddBlog.aspx.cs 包含用于创建新博客条目的逻辑和用户界面代码。 AddBlox.aspx 通过使用 HTML OBJECT 元素引用在 InkBlogControls 项目中创建的 InkArea 控件类的两个实例,如以下示例所示。 一个 id
实例具有 inkBlogTitle 属性,另一个实例具有 inkBlogBody 的 id 属性。
<OBJECT id="inkBlogTitle" classid="InkBlogControls.dll#InkBlog.InkArea" width="400" height="48" VIEWASTEXT>``</OBJECT>``<br/>``<OBJECT id="inkBlogBody" classid="InkBlogControls.dll#InkBlog.InkArea" width="400" height="296" VIEWASTEXT>``</OBJECT>
InkBlogControls.dll程序集必须与引用程序集的 .aspx 页位于同一目录中。 Web 安装程序部署项目可确保情况如此,部署项目中存在“InkBlogControls 的主要输出”项就证明了这一点。
标题控件的高度仅为 48 像素,以便于为标题输入单行墨迹。 正文控件高度为 296 像素,为多行或绘图的大型博客文章腾出空间。
InkArea 控件通过标准 HTML BUTTON 元素的 onclick 事件处理程序连接到客户端脚本函数 AddBlog。
<button id="BUTTON1" type="button" onclick="AddBlog()">Add Blog</button>
页面上还有一个 HTML 窗体,其中包含三个隐藏的 INPUT 元素:BlogTitleText、BlogBodyText 和 BlogBodyInkData。 此表单用于将博客条目数据发布回服务器。 AddBlog.aspx 是为表单定义的后退处理程序。
在 Microsoft JScript<实体 type=“reg”/>-中编写的 AddBlog 函数从 InkArea 控件中提取博客数据,并将结果发布到服务器。
function AddBlog()
{
// Extract the blog's title data as ink and text
form.BlogTitleText.value = inkBlogTitle.TextData;
// Extract the blog's body data as ink and text
form.BlogBodyText.value = inkBlogBody.TextData;
form.BlogBodyInkData.value = inkBlogBody.InkData;
form.submit();
}
当数据到达服务器时,AddBlog.aspx.cs 中的代码会检查Page_Load事件处理程序,以查看 HttpRequest 对象的 Form 属性是否包含任何数据。 如果是这样,它将基于当前系统时间创建文件名,将表单数据放入三个字符串变量中,并将数据写入 HTML 文件和包含墨迹数据的 GIF 文件(如果存在),如以下代码所示。
if ( (String.Empty != inkBody) )
{
// Use helper method to create a GIF image file from ink data
CreateGif(imagePath, fileName, inkBody);
// Create an HTML fragment to reference the image file
content = "<img src=\"Blogs/Images/" + fileName + ".gif\"></img>";
}
else
{
// If no ink data is available create an HTML fragment that contains
// the blog's text directly.
content = "<P>" + textBody + "</P>";
}
// Use helper method to create the blog web page on the server
CreateHtm(blogPath, fileName, blogTitle, content);
有关帮助程序方法的更多详细信息,请参阅示例源代码。
运行示例
默认情况下,Tablet PC SDK 1.7 安装 Ink 博客 Web 示例。 若要运行示例,请在 Internet Explorer 中导航到 https://localhost/TabletPCSDK_WebSamples/InkBlogWeb/Default.aspx. 如果运行的是 Windows Server 2003,请将计算机名称替换为“localhost”。
注意
编译的 Web 示例不是通过 SDK 的默认安装选项安装的。 必须完成自定义安装并选择“预编译的 Web 示例”子选项才能安装它们。
还可以通过在 Microsoft Visual Studio<entity type=“reg”/> .NET 中打开并生成项目,然后将其部署到运行 IIS 的单独计算机来运行示例。
对示例进行故障排除
在运行或托管示例时可能导致困难的三个方面是权限和识别。
权限
此示例需要尝试创建新博客条目的帐户的虚拟根文件夹中的写入权限。 默认情况下,Tablet PC SDK 1.7 中提供的示例的编译版本具有满足此要求的正确权限集。
如果使用提供的 Web 安装程序部署项目生成和部署示例,则必须授予 %MACHINENAME%\Users 组对 InkBlogWeb 虚拟根 (指向的文件系统文件夹的写访问权限,例如 C:\InetPub\WWWRoot\InkBlogWeb) 。 用户组包括 IIS 使用的匿名帐户,因此允许 ASP.NET 应用程序将新的博客条目写入文件系统。 另一种方法是删除对虚拟根的匿名访问并强制进行身份验证。
识别
必须安装手写识别器才能识别博客标题中的墨迹。 如果你从操作系统不是 Windows XP Tablet PC Edition 但安装了 Tablet PC SDK 1.7 的计算机访问 InkBlog 应用程序,则可以在 InkArea 控件中用墨迹书写,但识别引擎将不存在,并且不会为你的博客条目显示任何标题。 不过,正文中的墨迹内容仍会显示。
计算机配置
如果已在计算机上安装 ASP.NET 和.NET Framework,然后卸载并重新安装 IIS,则脚本映射将中断,ASP.NET 将不起作用。 如果发生这种情况,可以使用 ASP.NET IIS 注册工具 (Aspnet_regiis.exe -i) 修复 ASP.NET 脚本映射。
相关主题