ASP.NET 图片剪辑控件

代码下载: Anders_Web_Controls_v1_2.zip

介绍
在创建一个自定义的ASP.NET控件时有很多不同的方式。用户只需要将控件拖拽到页面上使用即可。控件本身应该是自包含的,包括注册客户端脚本,CSS和图像等。
本文将引导你创建一个自定义的控件,包含脚本,CSS图像等,并告诉你如何为每个控件初始化JavaScript代码。
 


具体实现
我们要做的第一件事情是创建Web资源。把所有用到的资源(CSS,JS,IMG)按不同的目录存放。然后将每个文件设置为嵌入资源。(右击/属性 在属性对话框选择 嵌入式资源)
下一步是在AssemblyInfo.cs中嵌入资源:
 

//Cropping logic
[assembly: WebResource("Anders.Web.Controls.js.cropper.js", "text/javascript")]
 
//Script lib
[assembly: WebResource("Anders.Web.Controls.js.lib.builder.js", "text/javascript")]
[assembly: WebResource("Anders.Web.Controls.js.lib.dragdrop.js", "text/javascript")]
[assembly: WebResource("Anders.Web.Controls.js.lib.effects.js", "text/javascript")]
[assembly: WebResource("Anders.Web.Controls.js.lib.prototype.js", "text/javascript")]
 
[assembly: WebResource("Anders.Web.Controls.css.cropper.css",
                       "text/css", PerformSubstitution = true)]
 
[assembly: WebResource("Anders.Web.Controls.img.marqueeHoriz.gif", "image/gif")]
[assembly: WebResource("Anders.Web.Controls.img.marqueeVert.gif", "image/gif")]
 

注意在css资源中我们使用了 PerformSubstitution 属性。该属性指示是否在此资源中引用其他Web资源分析url,并替换该资源的完整路径。这里主要是为了处理css中定义的背景图片。


background: transparent url('<%=WebResource(
            "Anders.Web.Controls.img.marqueeHoriz.gif")%>') repeat-x 0 0;
 

 
下一步是创建一个剪辑控件的类让它继承自CompositeControl。在.NET自定义控件中它是一个可重用的强大的抽象类。
类还继承了IPostBackDataHandler,这样可以注册控件的回发处理控制。

private Image image = new Image();
private HiddenField cropCords = new HiddenField();
private CropAreaCordinates cropArea = new CropAreaCordinates();
 
protected override void CreateChildControls()
{
    EnsureChildControls();
    CheckForHandler();
   
    image.ID = "cropImage";
    cropCords.ID = "cords";
 
    Controls.Add(cropCords);
    Controls.Add(image);
 
    base.CreateChildControls();
}
 

Image将是控件的主要界面。HiddenField将存储剪裁的坐标,可以使用PostBack回传给控件。
我们需要设置子控件的id,因为这些将不能自动生成。自id将继承父id的前缀。
 
因为继承了IPostBackDataHandler接口,所以我们的类必须实现LoadPostData方法。

public bool LoadPostData(string postDataKey,
       System.Collections.Specialized.NameValueCollection postCollection)
{
    string v = postCollection[postDataKey + "$cords"];
    if (!string.IsNullOrEmpty(v))
    {
        string[] values = v.Split(';');
        cropArea.X = int.Parse(values[0]);
        cropArea.Y = int.Parse(values[1]);
        cropArea.Width = int.Parse(values[2]);
        cropArea.Height = int.Parse(values[3]);
 
        //This values are not saved in client hiddenfield,
        //we retrive them from viewstate instead
        cropArea.MinWidth = MinWidth;
        cropArea.MinHeight = MinHeight;
        return true;
    }
    else
        return false;
}
 

在OnPreRender方法中实现客户端脚本和属性的初始化。

protected override void OnPreRender(EventArgs e)
{
    if (CropEnabled)
    {
        InitClientCrop();
        InitImages();
 
        float h = (float)CroppedImageHeight / (float)CroppedImageWidth;
        IFormatProvider culture = new CultureInfo("en-US", true);
        string height = h.ToString(culture);
 
        image.Attributes["onload"] = string.Format("InitCrop(this.id,
              {0},{1},{2},{3},{4},{5}, '{6}', {7}, {8}, {9});",
            AllowQualityLoss ? 0 : cropArea.MinWidth,
            AllowQualityLoss ? 0 : cropArea.MinHeight,
            cropArea.X,
            cropArea.Y,
            cropArea.Width,
            cropArea.Height,
            cropCords.ClientID,
            CaptureKeys.ToString().ToLower(),
            MaintainAspectRatio ? 1 : 0,
            MaintainAspectRatio ? height : "0"
        );               
        image.ImageUrl = string.Format("{0}?cropCacheId={1}", httpHandlerPath, CacheKey);
        cropCords.Value = string.Format("{0};{1};{2};{3}", cropArea.X,
                          cropArea.Y, cropArea.Width, cropArea.Height);
        Page.RegisterRequiresPostBack(this);
    }
    else
        image.Attributes.Remove("onload");
    base.OnPreRender(e);
}
 

首先,我们在InitClientCrop方法中初始化客户端脚本,在InitImages方法中初始化图片并显示。
我们想在一个页面使用控件的多个实例,所以我们必须为每个控件单独初始化脚本。这里使用客户端的onload事件来处理图片元素。onload事件将在web浏览器完成页面加载后载入图片。
 
脚本资源注册向这样:首先我们获取资源文件的绝对路径。

string protoTypePath = this.Page.ClientScript.GetWebResourceUrl(typeof(ImageCropper),
                       "Anders.Web.Controls.js.lib.prototype.js");
 

然后,我们在页面使用ClientScriptManager类的RegisterClientScriptInclude方法注册。

this.Page.ClientScript.RegisterClientScriptInclude("prototype.js", protoTypePath);

 
我们还需要在页面注册CSS文件:

if (Page.Header.FindControl("cropCss") == null)
{
    HtmlGenericControl cssMetaData = new HtmlGenericControl("link");
    cssMetaData.ID = "cropCss";
    cssMetaData.Attributes.Add("rel", "stylesheet");
    cssMetaData.Attributes.Add("href",
        Page.ClientScript.GetWebResourceUrl(typeof(ImageCropper),
        "Anders.Web.Controls.css.cropper.css"));
    cssMetaData.Attributes.Add("type", "text/css");
    cssMetaData.Attributes.Add("media", "screen");
    Page.Header.Controls.Add(cssMetaData);
}
 

既然可以使用一个以上的控件,我们使用FindControl方法检查是否有其他的控件已经注册了css。
 
在Web.confg中注册 HttpHandler

<add path="CropImage.axd" verb="*"
  type="Anders.Web.Controls.ImageCropperHttpHandler" validate="false" />
 

当ASP.NET 请求具体的路径"cropImage.axd"时, 将实例化type属性中定义的类。

public class ImageCropperHttpHandler : IHttpHandler
{
    public bool IsReusable
    {
        get { return true; }
    }
 
    public void ProcessRequest(HttpContext context)
    {
        string cacheId = context.Request.QueryString["cropCacheId"];
        byte[] buffer = context.Cache[cacheId] as byte[];
        context.Response.ContentType = "image/jpeg";
        context.Response.OutputStream.Write(buffer, 0, buffer.Length);
       
    }
}
 

使用HttpHandlers的唯一缺点就是,需要在Web.config中配置。因此,我们添加了一个方法来检测用户是否在Web.config中进行配置。

private void CheckForHandler()
{
    if (httpHandlerPath == null)
    {
        HttpHandlersSection handlerSection =
          WebConfigurationManager.GetWebApplicationSection("system.web/httpHandlers")
          as HttpHandlersSection;
        bool foundHandler = false;
        Type type = typeof(ImageCropperHttpHandler);
        string handlerName = type.ToString();
        string fullHandlerName = type.AssemblyQualifiedName;
        foreach (HttpHandlerAction action in handlerSection.Handlers)
            if (action.Type == handlerName || action.Type == fullHandlerName)
            {
                foundHandler = true;
                httpHandlerPath = action.Path.StartsWith("~") ?
                                  string.Empty : "~/" + action.Path;
                break;
            }
 
        if (!foundHandler)
            throw new ApplicationException(string.Format("The HttpHandler {0} is" +
                      " not registered in the web.config", handlerName));
    }
}
 

英文原文链接:http://www.codeproject.com/KB/custom-controls/ImageCroppingControl.aspx

posted @ 2011-07-29 16:46  敏捷学院  阅读(426)  评论(0编辑  收藏  举报