zoukankan      html  css  js  c++  java
  • 如何快速实现HTML编辑器.NET组件(转)

    如何快速实现HTML编辑器.NET组件
    --------------------------------------------------------------------------------
    前言
    最近由于工作的需要做了一个HTML编辑器,因为时间比较仓促,做得还很不完善,但是在一次调试的过程中偶然发现了一个相当取巧的方法,可以让你在几分钟内实现一个HTML编辑器,希望写出来会对大家有一些借鉴的意义。
    --------------------------------------------------------------------------------
    摘要
    现在的HTML编辑器主要还是使用JScript技术,MS在这方面有相当完备的支持(比如对一段文字设置加粗只需document.execCommand('bold')),本文主要向大家介绍怎样实现一个HTML编辑器组件(但不会对实现的细节进行过多的描述,具体的JS技术可以查询《JScript 语言参考》)以及怎样实现一个.NET组件。
    --------------------------------------------------------------------------------
    目录
    得到“素材”
    封装成ASP.NET组件
    添加插件
    总结
    关于作者
    相关连接
    --------------------------------------------------------------------------------
    得到“素材”
    首先我们需要得到一个HTML编辑器的原始代码,网上有不少这类的编辑器,如大名鼎鼎的RichTextBox,DOTNET中华网的DotNetTextBox等等,为了避免版权纠纷,以我所做得为例(暂名:UltraTextBox):在编辑器工具栏的空白地方点击鼠标右键-->查看源代码,如图所示。

    把代码拷贝出来保存成一个.htm文件就可以看到效果,是不是感觉很简单的就作了一半?:)
    为了以后讲解方面我们把它保存为editor.aspx文件,在这里注意删除掉__VIEWSTATE一段。
    然后把相应的图标,CSS文件等保存在相应的位置,否则你的界面会很难看,当然你也可以根据需要自己来做图标。
    好了,准备工作基本做完,下面是讲怎样把它封装为.NET组件,方便你在工程中使用。
    --------------------------------------------------------------------------------
    封装成ASP.NET组件
    首先在VS.NET环境里生成一个UltraTextBoxV1组件(也可以称为自定义控件,我习惯称为组件)项目,
    using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.ComponentModel;
    //设置该组件的标记前缀
    [assembly:TagPrefix("gOODiDEA.UltraTextBoxV1", "UTBV1")]
    namespace gOODiDEA.UltraTextBoxV1
    {
        //添加类声明
        [
        DefaultProperty("Text"),
        ValidationProperty("Text"),
        ToolboxData("<{0}:UltraTextBoxV1 runat=server></{0}:UltraTextBoxV1>"),
        ParseChildren(false),
        Designer("gOODiDEA.UltraTextBoxV1.UltraTextBoxV1Designer")
        ]
        public class UltraTextBoxV1: System.Web.UI.Control, IPostBackDataHandler
        {
            private static readonly object ValueChangedEvent = new object();
            //声明一个代理用于处理值被改变的事件,当组件的值更改时发生ValueChanged事件
            public event EventHandler ValueChanged
            {
                add
                {
                    Events.AddHandler(ValueChangedEvent, value);
                }
                remove
                {
                    Events.RemoveHandler(ValueChangedEvent, value) ;
                }
            }
            //触发值被改变事件的方法
            protected virtual void OnValueChanged(EventArgs e)
            {
                if( Events != null )
                {
                    EventHandler oEventHandler = ( EventHandler )Events[ValueChangedEvent] ;
                    if (oEventHandler != null) oEventHandler(this, e);
                }
            }
            //处理回发数据
            bool IPostBackDataHandler.LoadPostData( string postDataKey, System.Collections.Specialized.NameValueCollection postCollection )
            {
                if ( postCollection[postDataKey] != Text )
                {
                    Text = postCollection[postDataKey];
                    return true;
                }
                return false;
            }
            //告诉应用程序该组件的状态已更改
            void IPostBackDataHandler.RaisePostDataChangedEvent()
            {
                OnValueChanged( EventArgs.Empty );
            }

            //我们对一个编辑器主要需要实现下面4个属性,Text,Width,Height,BasePath。

            //Text属性:(从编辑器得到值和把值赋给编辑器)
            [Bindable(true),DefaultValue("")]
            public string Text
            {
                get
                {
                    object o = ViewState["Text"];
                    return ( o == null ) ? String.Empty : ( string )o;
                }
                set
                {
                    ViewState["Text"] = value;
                }
            }

            //Width属性:(编辑器的宽)
            [Bindable(true),Category("Appearence"),DefaultValue("100%")]
            public Unit Width
            {
                get
                {
                    object o = ViewState["Width"];
                    return ( o == null ) ? Unit.Parse( "100%" ) : ( Unit )o ;
                }
                set
                {
                    ViewState["Width"] = value ;
                }
            }

            //Height属性:(编辑器的高)
            [Bindable(true),Category("Appearence"),DefaultValue("385px")]
            public Unit Height
            {
                get
                {
                    object o = ViewState["Height"];
                    return ( o == null ) ? Unit.Parse( "385px" ) : ( Unit )o ;
                }
                set
                {
                    ViewState["Height"] = value ;
                }
            }

            //BasePath属性:(第一步保存的editor.aspx的路径以及以后做的插件的路径)
            [Bindable(true),DefaultValue("../UltraTextBoxV1Sys/Plug-Ins/")]
            public string BasePath
            {
                get
                {
                    object o = ViewState["BasePath"];
                    return (o == null) ? "../UltraTextBoxV1Sys/Plug-Ins/" : (string)o;
                }
                set
                {
                    ViewState["BasePath"] = value;
                }
            }

            //接下来是最重要的怎样把本组件和Editor.aspx结合起来,这里使用的是iframe技术:
            //覆盖Render方法,运行时输出:
            protected override void Render(HtmlTextWriter output)
            {
                System.Web.HttpBrowserCapabilities oBrowser = Page.Request.Browser ;
                //对应的IE版本必须是5.5或以上的版本
                if (oBrowser.Browser == "IE" && oBrowser.MajorVersion >= 5.5 && oBrowser.Win32)
                {
                    string sLink = BasePath + "Editor.aspx?FieldName=" + UniqueID;
                    //如果不使用SetTimeout则会提示找不到对象
                    output.Write(
                    "<IFRAME id=\"{5}\" src=\"{0}\" width=\"{1}\" height=\"{2}\" frameborder=\"no\" scrolling=\"no\"                 onload=\"javascipt:setTimeout('{5}.HtmlEdit.document.body.innerHTML = document.getElementById(\\'{4}
                    \\').value',1000);\" onblur=\"{4}.value = {5}.HtmlEdit.document.body.innerHTML\"></IFRAME>",
                    sLink,
                    Width,
                    Height,
                    Text,
                    UniqueID,
                    ID + "_editor"
                    ) ;
                    //存储编辑器的值
                    output.Write(
                    "<INPUT type=\"hidden\" id=\"{0}\" name=\"{0}\" value=\"{1}\" >",
                    UniqueID,
                    System.Web.HttpUtility.HtmlEncode(Text) ) ;
                }
            }
        }

        //接下来给该组件实现一个设计时的界面:
        public class UltraTextBoxV1Designer : System.Web.UI.Design.ControlDesigner
        {
            public UltraTextBoxV1Designer(){}
            public override string GetDesignTimeHtml()
            {
                UltraTextBoxV1 oControl = ( UltraTextBoxV1 )Component ;
                return String.Format(
                "<TABLE width=\"{0}\" height=\"{1}\" bgcolor=\"#f5f5f5\" bordercolor=\"#c7c7c7\" cellpadding=\"0\" cellspacing=\"0\" border=\"1\"><TR><TD valign=\"middle\" align=\"center\">UltraTextBox 1.1 - <B>{2}</B></TD></TR></TABLE>",
                oControl.Width,
                oControl.Height,
                oControl.ID ) ;
            }
        }
    }


    至此组件部分就基本做完,把它编译后的Dll拷贝你的项目文件夹下,在工具栏-->组件里添加它,你就可以直接拖放进你的页面,在你的工程中使用。
    --------------------------------------------------------------------------------
    添加插件
    这里举两个例子来说明怎样给该编辑器添加插件:
    如果你要给编辑器添加一些功能,如上传图片,插入标签等,则首先应该给它添加一个图标:
    <div class="Btn" TITLE="上传图片" LANGUAGE="javascript" onclick="UTB_InsertImg()">
    <img class="Ico" src="..\images\img.gif" WIDTH="16" HEIGHT="16">
    </div>

    <div class="Btn" TITLE="插入EXCEL表格" LANGUAGE="javascript" onclick="UTB_InsertExcel()">
    <img class="Ico" src="..\images\insertexcel.gif" WIDTH="16" HEIGHT="16">
    </div>
    然后在JScript代码里添加UTB_InsertImg(),UTB_InsertExcel()的实现:
    function UTB_InsertImg()
    {
    //只能在编辑模式下使用
    if ( ! UTB_validateMode() )
    return;
    HtmlEdit.focus();
    //在当前光标处创建一个区域用于插入图片
    var range = HtmlEdit.document.selection.createRange();
    //用模式对话框打开上传页面,把返回值插入到编辑器中
    var arr = showModalDialog(""uploadface.aspx"", """", ""dialogWidth:430px;dialogHeight:280px;help:0;status:0"");
    if (arr != null)
    {
    //得到的返回值应该是形如:<img src="http://61.139.77.178:8088/gOODiDEA/pic01.jpg">
    range.pasteHTML( arr );
    }
    HtmlEdit.focus();
    }

    function UTB_InsertExcel()
    {
    if (!UTB_validateMode())
    return;
    HtmlEdit.focus();
    //在这里其实就是插入一个Microsoft Office Web Components(MSOWC)组件
    var range = HtmlEdit.document.selection.createRange();
    range.pasteHTML(""<object classid='clsid:0002E510-0000-0000-C000-000000000046' id='Spreadsheet1' codebase='file:\\Bob\software\office2000\msowc.cab' width='100%' height='250'><param name='HTMLURL' value><param name='HTMLData' value='&lt;html xmlns:x=&quot;urn:schemas-microsoft-com:office:excel&quot;xmlns=&quot;http://www.w3.org/TR/REC-html40&quot;&gt;&lt;head&gt;&lt;style type=&quot;text/css&quot;&gt;&lt;!--tr{mso-height-source:auto;}td{black-space:nowrap;}.wc4590F88{black-space:nowrap;font-family:宋体;mso-number-format:General;font-size:auto;font-weight:auto;font-style:auto;text-decoration:auto;mso-background-source:auto;mso-pattern:auto;mso-color-source:auto;text-align:general;vertical-align:bottom;border-top:none;border-left:none;border-right:none;border-bottom:none;mso-protection:locked;}--&gt;&lt;/style&gt;&lt;/head&gt;&lt;body&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;&lt;x:ExcelWorkbook&gt;&lt;x:ExcelWorksheets&gt;&lt;x:ExcelWorksheet&gt;&lt;x:OWCVersion&gt;9.0.0.2710&lt;/x:OWCVersion&gt;&lt;x:Label Style='border-top:solid .5pt silver;border-left:solid .5pt silver;border-right:solid .5pt silver;border-bottom:solid .5pt silver'&gt;&lt;x:Caption&gt;Microsoft Office Spreadsheet&lt;/x:Caption&gt; &lt;/x:Label&gt;&lt;x:Name&gt;Sheet1&lt;/x:Name&gt;&lt;x:WorksheetOptions&gt;&lt;x:Selected/&gt;&lt;x:Height&gt;7620&lt;/x:Height&gt;""+
    ""&lt;x:Width&gt;15240&lt;/x:Width&gt;&lt;x:TopRowVisible&gt;0&lt;/x:TopRowVisible&gt;&lt;x:LeftColumnVisible&gt;0&lt;/x:LeftColumnVisible&gt; &lt;x:ProtectContents&gt;False&lt;/x:ProtectContents&gt; &lt;x:DefaultRowHeight&gt;210&lt;/x:DefaultRowHeight&gt; &lt;x:StandardWidth&gt;2389&lt;/x:StandardWidth&gt; &lt;/x:WorksheetOptions&gt; &lt;/x:ExcelWorksheet&gt;&lt;/x:ExcelWorksheets&gt; &lt;x:MaxHeight&gt;80%&lt;/x:MaxHeight&gt;&lt;x:MaxWidth&gt;80%&lt;/x:MaxWidth&gt;&lt;/x:ExcelWorkbook&gt;&lt;/xml&gt;&lt;![endif]--&gt;&lt;table class=wc4590F88 x:str&gt;&lt;col width=&quot;56&quot;&gt;&lt;tr height=&quot;14&quot;&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;'> <param name='DataType' value='HTMLDATA'> <param name='AutoFit' value='0'><param name='DisplayColHeaders' value='-1'><param name='DisplayGridlines' value='-1'><param name='DisplayHorizontalScrollBar' value='-1'><param name='DisplayRowHeaders' value='-1'><param name='DisplayTitleBar' value='-1'><param name='DisplayToolbar' value='-1'><param name='DisplayVerticalScrollBar' value='-1'> <param name='EnableAutoCalculate' value='-1'> <param name='EnableEvents' value='-1'><param name='MoveAfterReturn' value='-1'><param name='MoveAfterReturnDirection' value='0'><param name='RightToLeft' value='0'><param name='ViewableRange' value='1:65536'></object>"");
    HtmlEdit.focus();
    }


    关于怎样实现上传图片在这里就不多讲,CSDN上这类帖子太多了。只是要注意一点,因为使用的是模式对话框,所以在该页面不能有回发事件,操作最好在iframe里做。
    --------------------------------------------------------------------------------
    总结
    谢谢你能看到这里,至此一个简单的HTML编辑器就制作完成了,本文主要讲述了如何得到一个HTML编辑器的代码,如何把它封装成一个.NET组件以及通过两个列子讲解了给它添加插件的方法。从上面的步凑你可以看出制作一个HTML编辑器其实很简单,虽然借鉴了一些别人的代码,但如果你仔细分析一下那些JS脚本,你就会豁然开朗的,如果你有更好的想法希望能告诉我。
    --------------------------------------------------------------------------------

  • 相关阅读:
    web 开发之酷炫--- 酷炫展示
    攻城狮的体检
    科技发烧友之智能路由
    科技发烧友之3d吉米投影
    科技发烧友之单反佳能700d中高端
    上海
    视频会议
    机器学习之信息
    filter
    centos 20T硬盘(超过16T)分区
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/948200.html
Copyright © 2011-2022 走看看