在过去,Web程序员经常在他们的Web程序中使用ActiveX控件来实现一些胖客户端才具有的功能。不过现在开发者可以很容易的通过Microsoft.NET Framework来简洁和安全的建立对象,并且方便的在IE浏览器中切入使用。通过在IE浏览器中创建Windows窗体控件,开发者可以实现丰富的web客户端。在这篇文章中,我们将会知道怎样创建Windows窗体控件并且在IE中使用。在浏览器中使用窗体控件过程中,我们会演示怎样通过窗体控件来提供丰富的web客户端显示,而窗体控件用来调用远程Web service获取数据。与此同时,我们也会知道怎样利用.NET安全模型来为我们的窗体控件提供一个安全的运行环境。
如果你有过用Java开发Web程序的经验,那你会很熟悉Java applets。它是一个运行在浏览器中的一个小程序。当浏览器打开包含有Applet 标签的HTML文档时,Java applets就会运行。Windows窗体在web页里的工作方式同Java applets很相似。在这个实现中,你创建窗体控件,并为他加上丰富的Windows窗体控件样式,接着切入到Web页面中。在浏览器加载该Web页面的时候,Windows控件所包含的代码也会被执行。在局域网或者扩展的网络程序中这个将会是很有用的。比如想开发一个企业使用的具有胖客户端特性的基与web的程序。
.NET的一个重要特征就是跟IE紧密结合。比如,我们可以在IE中使用Windows窗体控件,而不需要通知用户需要加另外的东西。这个不需要注册什么.NET CLR就会提供代码安全访问的能力。
当你创建Windows窗体控件,你会有窗体类层次提供的特征。比如,你可以使用Windows窗体控件验证技术来验证输入数据的准确性。同样的,你甚至可以在你的窗体控件中调用Web Service。通过这些技术使用,你可以创建基与.NET平台的丰富的、健壮的、动态应用程序。
 
备注:按照原文重写了代码,把载图替换成了中文,运行环境:操作系统windows2003,.NET Framework 1.1.这里讲几点:调试过程中打开浏览器输入完整地址。如果以文件方式打开将不会显示窗体控件;另外对于进程的调试,可以是单个源文件。不过我运行的是Debug版本下生成的组件,不是Release的,有兴趣读者可以试试。
 
执行
在这节,我们就会明白怎样创建Windows窗体控件并在IE中使用。下面列出了五个步骤来完成这一过程。
         1.创建Windows窗体控件
         2.创建一个带有object 标签的HTML文档,该标签用来标识Windows控件
         3.配置控件的虚拟路径
         4.设置代码访问权限
         5.运行控件
接下来让我们来看看上面的各个步骤。
1.创建一个windows窗体控件
在这一步中,我们创建一个简单的Windows窗体控件。控件实现的功能是显示”Hello World”给用户。我们先来建立一个Windows 控件库项目取名为HelloWorldControl,修改默认的用户控件为HelloWorldCtl。接着在控件中加入一个Label,取名为lblDisplayMessage,同时增加了一个按钮btnClick。当用户点击按钮时,将会执行下面的代码用来显示消息给用户。
private void btnClick_Click(object sender, System.EventArgs e)
{
     this.lblDisplayMessage.Text = "Hello World";
}
接着就是编译他生成一个Assembly。

2.创建HTML页
在这一步中,我们将创建一个HTML文档并在里面插入object标签。整个文档看起来如下:
<html>
 <body>
  <p>Hello World Control
   <OBJECT id="HelloWorldControl1" height="300" width="300" classid="http:HelloWorldControl.dll#HelloWorldControl.HelloWorldCtl"
    VIEWASTEXT>
   </OBJECT>
   <br>
  </p>
 </body>
</html>
在这个标签的classid 属性中,我们指定第一步创建的那个组件的路径以及组件完整限定名。整个完整名称包括命名空间和整个类名。我们可以在上面的代码中清楚的看到组件名和限定名用#分割。这两部分参数组合在一起用来标识控件的唯一性。当然可以通过取名唯一id为HelloWorldControl1来编写客户端脚本。
3.配置虚拟路径
有了HTML页面,现在来建立一个HelloWorldControlHost的虚拟目录,实际目录在D:\My Programs\HellpWorldHost,该目录包含了HelloWorldControl.dll和Hellpworld.htm文件。当设置虚拟目录的时候,需要注意的是设置执行权限为“纯脚本”。如果设置成“脚本和可执行脚本”的权限。那控件可能不会正常工作(我在IIS6下设置成“脚本和可执行脚本”,不正常)。你可以打开虚拟目录的属性来确认设置,设置窗口如下:

4.设置代码访问权限
如果这个web在局域网中访问,他会正常工作。如果该Web是通过Internet来访问,那你需要设置internet Explorer,修改安全属性以允许他运行。你可以把主页加入到受信任的站点。如果需要设置可以通过IE的工具菜单―>Internet选项->安全->受信任的站点,点击上面的站点按钮把你的网站加入其中。接下去,当你打开浏览器查看,就会看到正确执行。
5.运行控件
要运行这个控件,我们在浏览器中查看包含了控件的那个Html页面。假如你在页面上点击这个按钮,那么控件就会显示“Hellp World”信息,执行页面如下:
 
在这个例子中,我们实现了怎样创建件一个Windows窗体控件然后在IE浏览器中显示。在下一节中我们来实现在客户端浏览器上通过窗体控件来访问Web Service。
通过windows窗体控件访问Web Service

窗体控件一个重要优点就是你可以通过它在客户端实现丰富的用户信息。比如说,你可以通过窗体控件对Web服务的访问从而在IE中显示而不需要重新刷新该页面。为了演示这点,我们先来创建一个Web服务,接着再来演示怎样通过窗体控件调用Web服务。
创建Web service
我们创建一个 Visual C# Asp.net web service 新项目,名字取为AuthorsWebService。
建立以后,我们修改服务类名称为AuthorsService,同时在类里面增加一个GetAuthors方法到里面,该方法的代码如下:
[WebMethod]
public DataSet GetAuthors()
{
     string connString = System.Configuration.ConfigurationSettings.AppSettings["connectionString"];
     SqlConnection sqlConn = new SqlConnection(connString);
     DataSet dstAuthors = new DataSet("Authors");           
     SqlDataAdapter adapter = new SqlDataAdapter("Select * from Authors",sqlConn);      
     adapter.Fill(dstAuthors,"Author");       
     sqlConn.Close();
     sqlConn.Dispose();
     return dstAuthors;      
}
上面方法的代码比较简单,我们把数据库连接字符串储存到了Web.config文件的appSettings节点上,如下:
<appSettings>
         <add key="connectionString" value="server=localhost;uid=sa;pwd=thiru;database=Pubs"></add>
</appSettings>
 
上面代码中,
我们创建了一个SqlConnnection实例,同时把上面的连接字符串作为参数传入。接着创建一个SqlDataAdapter对象,传入两个参数――查询字符串和SqlConnnection实例。调用SqlDataAdapter实例的Fill方法来执行数据库查询并把结果填充到DataSet。现在我们完成了Web服务的创建,接下去来建立一个他的一个客户端调用。
创建windows窗体控件作为Web服务客户端
在这里,我们是想用一个窗体控件来调用Web Service,因此新建一个Visual C#窗体控件项目取名AuthorsWebServiceClientControl:。
完成后,修改默认用户控件名称为AuthorsControl.。我们在上面添加了一个DataGrid控件取名GridAuthors 同时添加一个按钮取名BtnClick。注册按钮的点击事件,在事件处理函数中,将会调用WebService。在这之前我们需要添加项目的Web引用,输入刚才创建的Web服务地址。编辑器会生成该服务的代理,添加Web服务引用如下:
 

服务代理创建以后,我们在按钮事件中添加代码:
private void BtnClick_Click(object sender, System.EventArgs e)
{
     this.Cursor = Cursors.WaitCursor;
     AuthorsWebServiceProxy.AuthorsService authorsSvc = new
         AuthorsWebServiceProxy.AuthorsService();
     this.GridAuthors.DataSource = authorsSvc.GetAuthors();