CommnunityServer2.0由于其鲜明的web2.0特性和友好的用户界面以及强大的功能,吸引了包括我在内的越来越多的爱好者,不过相信对于官方原始版本的贴图和附件功能,一向是个问题,我想,最简单的解决方法就是给他的编辑器换成FCKeditor2.31,利用其可订制的上传文件功能来解决这个问题。
本例说涉及到的文件可以到这里下载。
编译好的dll和fckeditor编辑器
fckeditor2.31.net源代码
说做就做,让我们打开vs2005,建立一个类库项目,比方说Cnfdc.FCKforCS,然后添加引用:
Communityserver.Controls
FredCK.FCKeditorV2
然后建立一个类,名叫FCK.cs
编写如下代码,对fCK按照cs要求的属性来进行封装:
namespace Cnfdc.FckForCs

...{
using CommunityServer.Controls;
using FredCK.FCKeditorV2;
using System;
using System.Configuration;
using System.Web.UI.WebControls;

[Editor("FCK编辑器标准版", "FCK editor")]
public class FCK : FCKeditor, ITextEditor

...{
private int _columns;
private bool _enableHTML = true;
private int _rows;
private string _styleName="Default";

public FCK()

...{
Modal m = new Modal();
m.ModalType = ModalType.Window;

this.Controls.Add(m);

this.ReConfigure();
}

protected override void OnPreRender(EventArgs e)

...{
Configure();
base.OnPreRender(e);
}

public void Configure()

...{
if (this._enableHTML)

...{
base.ToolbarSet = "Default";
}
else

...{
base.ToolbarSet = "Basic";
}
}

public void ReConfigure()

...{
base.Height = Unit.Pixel(350);
if (base.Width.IsEmpty)

...{
base.Width = Unit.Pixel(685);
}
base.BasePath = ConfigurationSettings.AppSettings["FckEditor:BasePath"];
}

public virtual int Columns

...{
get

...{
return this._columns;
}
set

...{
this._columns = value;
}
}

Unit ITextEditor.Height

...{
get

...{
return base.Height;
}
set

...{
base.Height = value;
}
}

string ITextEditor.Text

...{
get

...{
return base.Value;
}
set

...{
base.Value = value;
}
}

Unit ITextEditor.Width

...{
get

...{
return base.Width;
}
set

...{
base.Width = value;
}
}

public virtual bool EnableHtmlModeEditing

...{
get

...{
return this._enableHTML;
}
set

...{
this._enableHTML = value;
}
}

public string GetClientSideMethod

...{
get

...{
return "";
}
}

public virtual bool IsRichTextCapable

...{
get

...{
return base.CheckBrowserCompatibility();
}
}

public virtual int Rows

...{
get

...{
return this._rows;
}
set

...{
this._rows = value;
}
}

public virtual string StyleName

...{
get

...{
if (this._styleName == null)

...{
this._styleName = "Default";
}
return this._styleName;
}
set

...{
this._styleName = value;
base.SkinPath = base.BasePath + "editor/skins/" + value + "/";
}
}


}
}


然后将这个类库编译,拷贝生成的dll到cs的bin目录,同时将fckEditor的源码下载下来,注意要包括.net源码,将代码高亮的类放进去,以便使其中的代码高亮插件生效,然后也重新编译fckeditor,忘记说了,这个工作要放在FCK.cs前面,因为有dll版本依赖。
namespace FredCK.FCKeditorV2

...{
using System;
using System.Collections;
using System.IO;
using System.Text.RegularExpressions;

public class HighLighter

...{
public HighLighter()

...{
this.replaceEnter = false;
}

public string colorText(string tmpCode, string pathToDefFile, string language)

...{
language = language.ToLower();
if ((language == "c#") || (language == "csharp"))

...{
language = "cs";
}
language = language.Replace(""", "");
string text1 = "";
string text2 = "";
bool flag1 = true;
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
try

...{
StreamReader reader1 = new StreamReader(pathToDefFile + language.ToString() + ".def");
string text3 = "";
string text4 = "";
while (reader1.Peek() != -1)

...{
text3 = reader1.ReadLine();
if (text3 != "")

...{
if (text3.Substring(0, 1) == "-")

...{
if (text3.ToLower().IndexOf("keywords") > 0)

...{
text4 = "keywords";
}
if (text3.ToLower().IndexOf("keytypes") > 0)

...{
text4 = "keytypes";
}
if (text3.ToLower().IndexOf("comments") > 0)

...{
text4 = "comments";
}
}
else

...{
switch (text4)

...{
case "keywords":
list1.Add(text3);
break;

case "keytypes":
list2.Add(text3);
break;

case "comments":
text2 = text3;
break;
}
}
}
}
reader1.Close();
}
catch (Exception exception1)

...{
exception1.ToString();
text1 = "<span class="errors">There was an error opening file " + pathToDefFile + language.ToString() + ".def...</span>";
flag1 = false;
throw new ApplicationException(string.Format("There was an error opening file {0}{1}.def", pathToDefFile, language), exception1);
}
if (!flag1)

...{
return text1;
}
int num1 = 0;
ArrayList list3 = new ArrayList();
MatchCollection collection1 = Regex.Matches(tmpCode, text2, RegexOptions.Multiline | RegexOptions.IgnoreCase);
foreach (Match match1 in collection1)

...{
list3.Add(match1.ToString());
tmpCode = tmpCode.Replace(match1.ToString(), "[ReplaceComment" + num1++ + "]");
}
num1 = 0;
ArrayList list4 = new ArrayList();
string text5 = ""((\\")|[^"(\\")]|)+"";
collection1 = Regex.Matches(tmpCode, text5, RegexOptions.Singleline | RegexOptions.IgnoreCase);
foreach (Match match2 in collection1)

...{
list4.Add(match2.ToString());
tmpCode = tmpCode.Replace(match2.ToString(), "[ReplaceString" + num1++ + "]");
}
num1 = 0;
ArrayList list5 = new ArrayList();
collection1 = Regex.Matches(tmpCode, "'.*?'", RegexOptions.Singleline | RegexOptions.IgnoreCase);
foreach (Match match3 in collection1)

...{
list5.Add(match3.ToString());
tmpCode = tmpCode.Replace(match3.ToString(), "[ReplaceChar" + num1++ + "]");
}
string[] textArray1 = new string[list1.Count];
list1.CopyTo(textArray1);
tmpCode = Regex.Replace(tmpCode, @"" + ("(?<replacethis>" + string.Join("|", textArray1) + ")") + @"(?<!//.*)", "<span class="keyword">${replacethis}</span>");
string[] textArray2 = new string[list2.Count];
list2.CopyTo(textArray2);
tmpCode = Regex.Replace(tmpCode, @"" + ("(?<replacethis>" + string.Join("|", textArray2) + ")") + @"(?<!//.*)", "<span class="keytype">${replacethis}</span>");
num1 = 0;
foreach (string text8 in list5)

...{
tmpCode = tmpCode.Replace("[ReplaceChar" + num1++ + "]", "<span class="string">" + text8.ToString() + "</span>");
}
num1 = 0;
foreach (string text9 in list4)

...{
tmpCode = tmpCode.Replace("[ReplaceString" + num1++ + "]", "<span class="string">" + text9.ToString() + "</span>");
}
num1 = 0;
foreach (string text10 in list3)

...{
tmpCode = tmpCode.Replace("[ReplaceComment" + num1++ + "]", "<span class="comment">" + text10.ToString() + "</span>");
}
tmpCode = Regex.Replace(tmpCode, @"(d{1,12}.d{1,12}|d{1,12})", "<span class="integer">$1</span>");
if (this.replaceEnter)

...{
tmpCode = Regex.Replace(tmpCode, " ", "");
tmpCode = Regex.Replace(tmpCode, " ", "<br />" + Environment.NewLine);
}
tmpCode = Regex.Replace(tmpCode, " ", " ");
tmpCode = Regex.Replace(tmpCode, " ", " ");
text1 = "<div class="codestuff">" + Environment.NewLine;
text1 = text1 + "<style type="text/css">" + Environment.NewLine;
text1 = text1 + "<!--" + Environment.NewLine;
text1 = text1 + ".codestuff .keytype { color : #FF9933; font-weight : normal; }" + Environment.NewLine;
text1 = text1 + ".codestuff .keyword { color : #224FFF; font-weight : normal; }" + Environment.NewLine;
text1 = text1 + ".codestuff .integer { color : #FF0032; }" + Environment.NewLine;
text1 = text1 + ".codestuff .comment { color : #008100; }" + Environment.NewLine;
text1 = text1 + ".codestuff .errors { color : #FF0000; font-weight : bold; }" + Environment.NewLine;
text1 = text1 + ".codestuff .string { color : #FF0022; }" + Environment.NewLine;
text1 = text1 + "//-->" + Environment.NewLine;
text1 = text1 + "</style>" + Environment.NewLine;
text1 = text1 + tmpCode;
return (text1 + "</div>" + Environment.NewLine);
}


public bool ReplaceEnter

...{
get

...{
return this.replaceEnter;
}
set

...{
this.replaceEnter = value;
}
}


private bool replaceEnter;
}
}


如果你的站比较大,那么可能就要修改上传文件的方法,加上自动重命名和分月目录,修改Uploader.cs:

/**//*
* FCKeditor - The text editor for internet
* Copyright (C) 2003-2005 Frederico Caldeira Knabben
*
* Licensed under the terms of the GNU Lesser General Public License:
* http://www.opensource.org/licenses/lgpl-license.php
*
* For further information visit:
* http://www.fckeditor.net/
*
* "Support Open Source software. What about a donation today?"
*
* File Name: Uploader.cs
* This is the code behind of the uploader.aspx page used for Quick Uploads.
*
* File Authors:
* Frederico Caldeira Knabben (fredck@fckeditor.net)
*/

using System ;
using System.Globalization ;
using System.Xml ;
using System.Web ;

namespace FredCK.FCKeditorV2

...{
public class Uploader : FileWorkerBase

...{
protected override void OnLoad(EventArgs e)

...{
// Get the posted file.
HttpPostedFile oFile = Request.Files["NewFile"];

// Check if the file has been correctly uploaded
if (oFile == null || oFile.ContentLength == 0)

...{
SendResults(202);
return;
}

int iErrorNumber = 0;
string sFileUrl = "";

// Get the uploaded file name.
//string sFileName = System.IO.Path.GetFileName( oFile.FileName ) ;

//检查建立分月目录
string sFolder = DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString();

System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(System.IO.Path.Combine(this.UserFilesDirectory, sFolder));

if (!dir.Exists)

...{
dir.Create();
}

//根据日期和随机数设置自动重命名文件
Random rd = new Random();
string sFileName = sFolder + "/" + DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(10).ToString();

int iCounter = 0;

while (true)

...{
//防止没有扩展名的处理,弃用内置方法
string sFileExtension = string.Empty;
try

...{
sFileExtension = oFile.FileName.Substring(oFile.FileName.LastIndexOf('.'), oFile.FileName.Length - oFile.FileName.LastIndexOf('.'));

}
catch

...{
//Exception ex = new Exception(oFile.FileName);
//throw ex;
sFileExtension = ".jpg";
}
string sFilePath = System.IO.Path.Combine(this.UserFilesDirectory, sFileName) + sFileExtension;


if (System.IO.File.Exists(sFilePath))

...{
iCounter++;
sFileName =
sFileName +
"(" + iCounter + ")" +
sFileExtension;

iErrorNumber = 201;
}
else

...{
oFile.SaveAs(sFilePath);

sFileUrl = System.IO.Path.Combine(this.UserFilesPath, sFileName + sFileExtension);
break;
}
}

SendResults(iErrorNumber, sFileUrl, sFileName);
}


SendResults Method#region SendResults Method

private void SendResults( int errorNumber )

...{
SendResults( errorNumber, "", "", "" ) ;
}

private void SendResults( int errorNumber, string fileUrl, string fileName )

...{
SendResults( errorNumber, fileUrl, fileName, "" ) ;
}

private void SendResults( int errorNumber, string fileUrl, string fileName, string customMsg )

...{
Response.Clear() ;

Response.Write( "<script type="text/javascript">" ) ;
Response.Write( "window.parent.OnUploadCompleted(" + errorNumber + ",'" + fileUrl.Replace( "'", "\'" ) + "','" + fileName.Replace( "'", "\'" ) + "','" + customMsg.Replace( "'", "\'" ) + "') ;" ) ;
Response.Write( "</script>" ) ;

Response.End() ;
}

#endregion
}
}

然后将重新编译的FredCK.EditerV2.dll也拷贝到cs的bin目录。
接下来将fckeditor的编辑器文件夹拷贝到cs的根目录,修改fckconfig.js

/**//*
* FCKeditor - The text editor for internet
* Copyright (C) 2003-2006 Frederico Caldeira Knabben
*
* Licensed under the terms of the GNU Lesser General Public License:
* http://www.opensource.org/licenses/lgpl-license.php
*
* For further information visit:
* http://www.fckeditor.net/
*
* "Support Open Source software. What about a donation today?"
*
* File Name: fckconfig.js
* Editor configuration settings.
* See the documentation for more info.
*
* File Authors:
* Frederico Caldeira Knabben (fredck@fckeditor.net)
*/

FCKConfig.CustomConfigurationsPath = '' ;

FCKConfig.EditorAreaCSS = FCKConfig.BasePath + 'css/fck_editorarea.css' ;

FCKConfig.DocType = '' ;

FCKConfig.BaseHref = '' ;

FCKConfig.FullPage = false ;

FCKConfig.Debug = false ;
FCKConfig.AllowQueryStringDebug = true ;

FCKConfig.SkinPath = FCKConfig.BasePath + 'skins/default/' ;
FCKConfig.PreloadImages = [ FCKConfig.SkinPath + 'images/toolbar.start.gif', FCKConfig.SkinPath + 'images/toolbar.buttonarrow.gif' ] ;

FCKConfig.PluginsPath = FCKConfig.BasePath + 'plugins/' ;

//添加插件
//FCKConfig.Plugins.Add( 'placeholder', 'zh-cn' ) ;
FCKConfig.Plugins.Add( 'FastSmsTag', 'zh-cn' ); //系统标记插件
FCKConfig.Plugins.Add( 'EYSImageGallery', 'zh-cn' ); //插入媒体
FCKConfig.Plugins.Add( 'InsertCode', 'zh-cn' ); //插入代码
//FCKConfig.Plugins.Add( 'UploadFile', 'zh-cn' ); //插入附件
//FCKConfig.Plugins.Add( 'autogrow' ) ;
//FCKConfig.AutoGrowMax = 400 ;

FCKConfig.ProtectedSource.Add( /<script[sS]*?</script>/gi ) ; // <SCRIPT> tags.
// FCKConfig.ProtectedSource.Add( /<%[sS]*?%>/g ) ; // ASP style server side code <%...%>
// FCKConfig.ProtectedSource.Add( /<?[sS]*??>/g ) ; // PHP style server side code
// FCKConfig.ProtectedSource.Add( /(<asp:[^>]+>[s|S]*?</asp:[^>]+>)|(<asp:[^>]+/>)/gi ) ; // ASP.Net style tags <asp:control>

FCKConfig.AutoDetectLanguage = false ;
FCKConfig.DefaultLanguage = 'zh-cn' ;
FCKConfig.ContentLangDirection = 'ltr' ;

FCKConfig.ProcessHTMLEntities = true ;
FCKConfig.IncludeLatinEntities = true ;
FCKConfig.IncludeGreekEntities = true ;

FCKConfig.FillEmptyBlocks = true ;

FCKConfig.FormatSource = true ;
FCKConfig.FormatOutput = true ;
FCKConfig.FormatIndentator = ' ' ;

FCKConfig.ForceStrongEm = true ;
FCKConfig.GeckoUseSPAN = false ;
FCKConfig.StartupFocus = false ;
FCKConfig.ForcePasteAsPlainText = false ;
FCKConfig.AutoDetectPasteFromWord = true ; // IE only.
FCKConfig.ForceSimpleAmpersand = false ;
FCKConfig.TabSpaces = 0 ;
FCKConfig.ShowBorders = true ;
FCKConfig.SourcePopup = false ;
FCKConfig.UseBROnCarriageReturn = false ; // IE only.
FCKConfig.ToolbarStartExpanded = true ;
FCKConfig.ToolbarCanCollapse = true ;
FCKConfig.IgnoreEmptyParagraphValue = true ;
FCKConfig.PreserveSessionOnFileBrowser = false ;
FCKConfig.FloatingPanelsZIndex = 10000 ;

FCKConfig.ToolbarLocation = 'In' ;

FCKConfig.ToolbarSets["Default"] = [
['Source','DocProps','-','NewPage','Preview','-'],
['Cut','Copy','Paste','PasteText','PasteWord'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
['OrderedList','UnorderedList','-','Outdent','Indent'],
['TextColor','BGColor'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
['Link','Unlink','Anchor'],
['Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak','UniversalKey'],
['InsertMedia','InsertReal'],['InsertCode'],
['Style','FontFormat','FontName','FontSize'],
['FitWindow','-','About']
] ;

FCKConfig.ToolbarSets["Basic"] = [
['Source','-','Cut','Copy','Paste','PasteText','PasteWord'],
['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-'],
['Image','Flash','InsertMedia','InsertReal'],['InsertCode','About']
] ;

FCKConfig.ContextMenu = ['Generic','Link','Anchor','Image','Flash','Select','Textarea','Checkbox','Radio','TextField','HiddenField','ImageButton','Button','BulletedList','NumberedList','Table','Form'] ;

FCKConfig.FontColors = '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,808080,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF' ;

FCKConfig.FontNames = '宋体;隶书;楷体_GB2312;仿宋_GB2312;黑体;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;
FCKConfig.FontSizes = '1/很小;2/较小;3/小;4/中等;5/大;6/较大;7/很大' ;
FCKConfig.FontFormats = 'p;div;pre;address;h1;h2;h3;h4;h5;h6' ;

FCKConfig.StylesXmlPath = FCKConfig.EditorPath + 'fckstyles.xml' ;
FCKConfig.TemplatesXmlPath = FCKConfig.EditorPath + 'fcktemplates.xml' ;

FCKConfig.SpellChecker = 'ieSpell' ; // 'ieSpell' | 'SpellerPages'
FCKConfig.IeSpellDownloadUrl = 'http://iespell.huhbw.com/ieSpellSetup220647.exe' ;

FCKConfig.MaxUndoLevels = 15 ;

FCKConfig.DisableObjectResizing = false ;
FCKConfig.DisableFFTableHandles = true ;

FCKConfig.LinkDlgHideTarget = false ;
FCKConfig.LinkDlgHideAdvanced = false ;

FCKConfig.ImageDlgHideLink = false ;
FCKConfig.ImageDlgHideAdvanced = false ;

FCKConfig.FlashDlgHideAdvanced = false ;

// The following value defines which File Browser connector and Quick Upload
// "uploader" to use. It is valid for the default implementaion and it is here
// just to make this configuration file cleaner.
// It is not possible to change this value using an external file or even
// inline when creating the editor instance. In that cases you must set the
// values of LinkBrowserURL, ImageBrowserURL and so on.
// Custom implementations should just ignore it.
var _FileBrowserLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py
var _QuickUploadLanguage = 'aspx' ; // asp | aspx | cfm | lasso | php

// Don't care about the following line. It just calculates the correct connector
// extension to use for the default File Browser (Perl uses "cgi").
var _FileBrowserExtension = _FileBrowserLanguage == 'perl' ? 'cgi' : _FileBrowserLanguage ;

FCKConfig.LinkBrowser = false ;
FCKConfig.LinkBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
FCKConfig.LinkBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70%
FCKConfig.LinkBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70%

FCKConfig.ImageBrowser = false ;
FCKConfig.ImageBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Image&Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
FCKConfig.ImageBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70% ;
FCKConfig.ImageBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% ;

FCKConfig.FlashBrowser = false ;
FCKConfig.FlashBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ;
FCKConfig.FlashBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; //70% ;
FCKConfig.FlashBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; //70% ;

FCKConfig.LinkUpload = true ;
FCKConfig.LinkUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage ;
FCKConfig.LinkUploadAllowedExtensions = "" ; // empty for all
FCKConfig.LinkUploadDeniedExtensions = ".(php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi)$" ; // empty for no one

FCKConfig.ImageUpload = true ;
FCKConfig.ImageUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage + '?Type=Image' ;
FCKConfig.ImageUploadAllowedExtensions = ".(jpg|gif|jpeg|png)$" ; // empty for all
FCKConfig.ImageUploadDeniedExtensions = "" ; // empty for no one

FCKConfig.FlashUpload = true ;
FCKConfig.FlashUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage + '?Type=Flash' ;
FCKConfig.FlashUploadAllowedExtensions = ".(swf|fla)$" ; // empty for all
FCKConfig.FlashUploadDeniedExtensions = "" ; // empty for no one

FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/msn/' ;
FCKConfig.SmileyImages = ['regular_smile.gif','sad_smile.gif','wink_smile.gif','teeth_smile.gif','confused_smile.gif','tounge_smile.gif','embaressed_smile.gif','omg_smile.gif','whatchutalkingabout_smile.gif','angry_smile.gif','angel_smile.gif','shades_smile.gif','devil_smile.gif','cry_smile.gif','lightbulb.gif','thumbs_down.gif','thumbs_up.gif','heart.gif','broken_heart.gif','kiss.gif','envelope.gif'] ;
FCKConfig.SmileyColumns = 8 ;
FCKConfig.SmileyWindowWidth = 320 ;
FCKConfig.SmileyWindowHeight = 240 ;
主要注意插件的添加和文件上传部分的配置,以及简化工具栏的设置。这个简化版的工具栏可以配合前面提到的快速回复使用哦。
最后,修改cs的web.config,在<appsettings>节加入下面一段
<!--FCK编辑器配置-->
<add key="FckEditor:BasePath" value="/FCKeditor/"/>

打开Communityserver.config,修改<core>节相应的为这一段
textEditorType = "Cnfdc.FckForCs.FCK, Cnfdc.FckForCs"

好了,祈祷一下吧,刷新你的cs,然后到个人资料修改中设置使用的编辑器为:HTML编辑器标准版( 如果看不到的话,就有问题了)
体验一下diy的乐趣吧!
有问题,大家一起探讨!
from : http://blog.csdn.net/lonestone/archive/2006/08/14/1062870.aspx
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?