当前位置: 首页 > 编程日记 > 正文

如何快速实现HTML编辑器.NET组件

作者:未知   请作者速与本人联系


得到“素材”
首先我们需要得到一个HTML编辑器的原始代码,网上有不少这类的编辑器,如大名鼎鼎的RichTextBox,为了避免版权纠纷,以我所做得为例(暂名: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/"
οnlοad=/"javascipt:setTimeout('{5}.HtmlEdit.document.body.innerHTML = document.getElementById(//'{4} //').value',1000);/" οnblur=/"{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" οnclick="UTB_InsertImg()">
<img class="Ico" src="../images/img.gif" WIDTH="16" HEIGHT="16">
</div>
<div class="Btn" TITLE="插入EXCEL表格" LANGUAGE="javascript" οnclick="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脚本,你就会豁然开朗的,如果你有更好的想法希望能告诉我。

相关文章:

罗永浩力荐,丁磊豪送的学习神器:手机查词真不如这支AI词典笔?

销量确实称得上火爆。尽管999元的直播优惠价价格并不低&#xff0c;但这支有道词典笔专业版在快手直播间还是经历了返场&#xff0c;最终20000多台一抢而空。 为这款产品站台的正是网易CEO丁磊&#xff0c;6月11日是他网上卖货的首秀&#xff0c;不过更重要的是&#xff0c;那天…

Thinking in java中关于Exception的一道面试题.

今天看到Thinking in Java中一个关于Exception的例子:最后看到有一篇总结的比较好的文章, 这里拿来记录下, 文章地址是:http://blog.csdn.net/salerzhang/article/details/46581457 感谢原作者. 1 class Annoyance extends Exception {}2 class Sneeze extends Annoyance {}3 …

使用 .NET 框架轻松开发完美的 Web 窗体控件

作者&#xff1a;David S. Platt 出自&#xff1a;微软 本文假定您熟悉 Visual Basic .NET、C# 和 HTML 下载本文的代码&#xff1a; WebC.exe (274KB) 摘要 预建的自定义控件可以简化和加快应用程序的设计&#xff0c;并使您能够维护 UI 的一致性。但是&#xff0c;预先打…

史上最强女游戏程序员

也许你听说过John Carmack 和Tim Sweeney等大牛的名字&#xff0c;而向来游戏工业都是阳盛阴衰&#xff0c;适逢国际妇女节&#xff0c;今天我为大家介绍游戏业界一位史上最强女游戏程序员&#xff1a;Corrinne Yu。 简历 以下是她在游戏业界内的简历 微软Halo团队首席引擎架构…

重磅日程公布!与百名大咖在线交流技术,2天20个AI论坛不可错过

当全球都在面向 AI 变革时&#xff0c;AI 不再是触不可及&#xff0c;它需要产业化落地&#xff0c;为社会创造价值。在这一轮技术革命、技术浪潮中&#xff0c;开发者们成为构建任何一家AI企业的核心竞争力。不过&#xff0c;不同于此前只懂开发语言、数据结构便可轻松躲过新技…

Python取出列表相应值的位置(表处理)

#需求在一个列表中&#xff0c;取出相应值的位置方法1&#xff1a;#脚本示例[rootlocalhost opt]# cat list.py #!/usr/bin/env python #_*_ coding:utf-8 _*_ name[!,#,*,Eric,wsyht,jack,jack,a,b,c,d,1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6,2332,4,2,6,2] first_pos 0 for …

rhel5.5安装xwindow

rhel5.5安装xwindow 1安装xwindow yum groupinstall "X Window System" 2、安装GNOME桌面环境 yum groupinstall "GNOME Desktop Environment" 3、卸载GNOME桌面环境 yum groupremove "GNOME Desktop Environment"转载于:https://blog.51cto…

使用 ASP.NET 加密口令

作者&#xff1a;未知 请作者速与本人联系当我们在网站上建立数据库时&#xff0c;保护用户的信息安全是非常必要的。多数用户不愿意让别人知道自己的信息&#xff0c;同时网管也不想因为安全问题而丢失网站的信誉。无论对于谁&#xff0c;安全问题都是非常重要的。为了解决这…

算法鼻祖高德纳,82 岁仍在写《计算机程序设计的艺术》

作者 | 年素清编辑 | 伍杏玲出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;高德纳&#xff08;Donald Ervin Knuth&#xff09;被誉为现代计算机科学的鼻祖&#xff0c;毕生致力于编译程序、属性文法和运算法则等领域的前沿研究&#xff0c;共出版专著17部&#x…

centos查看特定程序占用端口情况

ps axu |grep 程序名&#xff0c;找到特定程序的pidnetstat -nltp |grep pid即可。转载于:https://blog.51cto.com/zhukeqiang/1811735

关于页面刷新的问题

在做.net开发时&#xff0c;经常能碰到这样的情况&#xff0c;页面很长&#xff0c;而我们一般用的都是服务器端控件&#xff0c;用服务器端控件有这样一个缺点&#xff0c;就是控件每次都要和服务器交互&#xff0c;而产生页面的刷新&#xff0c;试想一下&#xff0c;如果页面…

技术直播:程序员副业的修炼指南!(限免报名)

面试造飞机&#xff0c;上班拧螺丝&#xff0c;每天想辞职&#xff0c;但无奈副业还“大器晚成”的样子&#xff01;那可能是你还没有选对副业&#xff01;滴滴 ~福利卡&#xff01;&#xff01;&#xff01;CSDN学院邀请汤小洋老师开设技术直播课《程序员副业之路-三大终极秘籍…

Linux 双网卡绑定测试

Linux 双网卡绑定测试 先介绍一下情况&#xff0c;服务器A和服务器B都是CentOS 4.6的系统&#xff0c;现在要做HA Cluster&#xff0c;为了避免裂脑的发生&#xff0c;要提高心跳链路的可靠性&#xff0c;下图是现时的连接情况&#xff0c;服务器A的eth2、eth3分别和服务器B的e…

第六章练习题和知识面扩充

作业题&#xff1a;1. 自动获取IP地址的命令是什么&#xff1f;您知道在什么情况下&#xff0c;您的Linux才可以自动获取IP地址&#xff1f;2. 远程连接Linux服务器&#xff0c;需要Linux服务器开启sshd服务&#xff0c;那么sshd服务默认监听哪个端口&#xff1f;这个端口是否可…

一文详解面向多级多模态场景的召回引擎

作者| 阿里文娱开发专家 崇懿、阿里文娱开发专家慧善责编 | 屠敏头图 | CSDN 下载自视觉中国出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;优酷视频搜索在文本搜索系统的基础上&#xff0c;不断探索视频搜索的方案&#xff0c;在多模态输入、多级多模态索引、跨模…

对比.Net PetShop和Duwamish来探讨Ado.Net的数据库编程模式

作者:卢彦.NET PetShop和Duwamish简单介绍相信大家一定听说过有名的"宠物店大战"&#xff0c;没错&#xff0c;本文的主角之一就是获胜方.NET PetShop&#xff0c;微软号称以27倍的速度和1/4的代码量遥遥领先于基于J2EE的PetStore宠物商店。虽然SUN也曾对此抱怨过不满…

如何直接将HTML代码加载到TWebBrowser

wbRecvContent//为 webbrowser控件 procedure TFrmMain.ShowHtmlCentent(slt: TStrings); var aMemory: TMemoryStream; pbuf: PAnsiChar; begin aMemory : TMemoryStream.Create(); try aMemory.Clear; slt.SaveToStream(aMemory); aMemory.Seek(0, soBeginning); wbRecvConte…

JavaScript基础(一) 数据类型

动态类型 JavaScript 是一种弱类型或者说动态语言。这意味着你不用提前声明变量的类型&#xff0c;在程序运行过程中&#xff0c;类型会被自动确定。 数据类型 最新的 ECMAScript 标准定义了 7 种数据类型: 6 种 原始类型: BooleanNullUndefinedNumberStringSymbol (ECMAScript…

DataGrid入门经典(C#)

作者&#xff1a;未知 请作者速与本人联系这篇文章主要介绍如何在DataGrid控件中实现编辑、删除、分类以及分页操作。为了实现我们的意图&#xff0c;我们使用SqlServer2000自带的NorthWind数据库。程序分为两部分&#xff1a; 1.包含HTML代码的.ASPX文件 2.包含所有逻辑及…

(札记)Altera Stratix IV系列FPGA TRUE LVDS RX input termination 在Quartus工程中的设置方法...

Altera Stratix IV系列FPGA Row bank的TRUE LVDS_RX支持oct&#xff08;on chip termination),所以设计的时候不需要外接一个100ohm电阻。备注&#xff1a;我使用的是友晶科技&#xff08;Terasic&#xff09;的DE4。 所以当我们使用到Stratix iv系列FPGA的row bank的lvds的时候…

直播:AI时代,普通程序员该如何转人工智能(限免报名)

常常有小伙伴在后台反馈&#xff1a;想了解人工智能&#xff0c;但是该怎么学&#xff1f;自学难度大又没有效果&#xff0c;该怎么办&#xff1f;CSDN为了解决这个难题&#xff0c;联合唐宇迪老师为大家带来了一场精彩的直播【年薪百万AI工程师亲授&#xff1a;小白实战培养计…

沃通免费SSL证书申请指南

我们在做一些exchange或lync项目的时候很多时候都会用到公网证书&#xff0c;比如&#xff1a;我们做exchange2013和Office 365混合部署&#xff0c;或者通过SEM暂存迁移或CEM直接转换迁移的时候都需要用到公网证书,下面为大家介绍1个免费的SSL证书及申请的方法&#xff0c;希望…

使用VS.NET2003编写存储过程

作者&#xff1a;未知 请作者速与本人联系数据表定义了如何在数据库中存储数据&#xff0c;但没有说明如何存取数据。我们还需要了解读写记录以便从表中再次调用选定行和列的详细信息。开发人员通常会在其代码中编写一些特殊的查询语句&#xff0c;用于读写数据。这不仅会导致…

谈Linux的安全设置

如今系统的安全变的越来越重要了&#xff0c;这里我想把我平时比较常使用的一些linux下的基本的安全措施写出来和大家探讨一下&#xff0c;让我们的Linux系统变得可靠。 1、BIOS的安全设置 这是最基本的了&#xff0c;也是最简单的了。一定要给你的BIOS设置密码&#…

亮风台提出用完全可训练的图匹配方法,优于最新SOTA | CVPR 2020

出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 6月14日-19日&#xff0c;CVPR 2020在线上举行&#xff0c;据了解&#xff0c;本届大会共收到6656篇投稿&#xff0c;接收论文1470篇&#xff0c;录用率约22%&#xff0c;低于ICCV 2019论文录用率&#xff08;25%&…

数组与纠结的排序篇

数组之纠结的排序 1.数组是什么&#xff1f; 数组&#xff1a;所谓数组&#xff0c;就是相同数据类型的元素按一定顺序排列的集合&#xff0c;就是把有限个类型相同的变量用一个名字命名&#xff0c;然后用编号区分他们的变量的集合&#xff0c;这个名字称为数组名&#xff0c;…

ASP.NET结合COM组件发送Email

在开发电子邮件发送程序的时候&#xff0c;我们经常需要使用到相应的组件&#xff0c;其实不需要第三方的组件&#xff08;例如&#xff1a;Jmail&#xff09;照常可以做到发送Email的功能。 在系统目录&#xff08;如c:/winnt或c:/windows&#xff09;的system32子目录中可以找…

卡巴循环30天不限次数循环试用工具

本文需评论之后方可查看&#xff01; echo off title 卡巴循环30天不限次数循环试用工具 echo off echo 卡巴循环30天不限次数循环试用工具 echo. echo echo 卡巴斯基6/7/8试用过期时清除系统中使用痕迹&#xff0c;就象新系统重新安装卡巴一样 echo 1、在屏幕右下角红V卡巴图…

微软CEO纳德拉对话沈向洋:那些未来可期的计算机视觉研究与应用

编者按&#xff1a;6月16日&#xff0c;CVPR 2020 大会以全球连线的形式如期开幕。在大会的首场主题演讲中&#xff0c;微软公司 CEO 萨提亚纳德拉与微软公司前执行副总裁沈向洋进行了一场精彩的炉边对谈&#xff0c;分享了对计算机视觉、人工智能研究与应用前景的思考与展望。…

SoapUI进行REST请求,POST方法提交到数据库的数据乱码问题

一开始以为要把json字符串的key和value一个一个的加进去&#xff0c;结果总是报 300&#xff0c;参数错误&#xff0c;后来才发现&#xff08;https://www.joecolantonio.com/2013/08/31/soapui-how-to-post-json-to-a-rest-service-2/&#xff09;可以直接在下面粘贴就好了&am…