Did you in the past need to incorporate some HTML validating editor into your .NET desktop client? I did, so I started to look around for some components and found one, which is free and widely used, tinyMCE form Moxito.
One complication is that this one uses a browser to render edited content and is completely written in JScript, so one have to “hack” some browser control.
I’ll describe how to incorporate an Internet Explorer ActiveX into .NET form, join needed soap of tinyMCE into work file and load this work file into Internet Explorer ActiveX.
As I said,
tinyMCE is JScript wrapper over browser textarea control.
One possible solution is to use some browser control, load it with content and let the browser do the work with JScript. Let’s assume, we’re on Windows platform, so Internet Explorer is incorporated in the system.
So what we need is to store somewhere
tinyMCE package, generate work HTML file, which contains edited text and links to tinyMCE scripts.
I decided to use users application folder, special subfolder will be created and
tinyMCE package like a workfile will be stored.
Last thing to solve is to look over
tinyMCE and check what it needs to work. And it’s not too much, in minimal version only few lines of code.
Let’s take a simple example based on
tinyMCE package examples:
mode : "textareas,save",
theme : "simple"
<!—tiny MCE section -->
<form method="post" action="http://tinymce.moxiecode.com/dump.php?example=true">
<textarea id="elm1" name="elm1" rows="15" cols="80" style="width: 80%">
This is Edited Text
Looking around this snippet, one can see we need to construct settings section and tiny MCE section. Settings are needed for tinyMCE to tell what plugins to load, what encoding and format of the text we need, etc., and the second section is textarea element encapsulated in form element, and this is what tinyMCE hooks and use as editing area.
Last point about “design” - it has to be reusable around few applications, so I encapsulated everything in one form class
FrmHTMLBrowser, which is enabled to view or edit text. Why not in control? Well, tinyMCE is not pure control, we have to use some “hacks” with temp files, so it is a bit safer and more robust to use modal dialog box. Programmers, who will use this form, will be forced to use it more carefully and declaratively, not allowed to just paste control in designer wherever they think is fine.
One little thing to think about - browser needs to be JScript in path or subpath where workfile resides. That's why we have to place everything in one place. Basically, no matter where, if in ApplicationData\LocalSettings or \Temp or wherever else, but in one place.
Think also about running your application on terminal services - that's why I chose user
ApplicationData. No problem with interfering forms.
Note: Problem with interfering forms will arise when the same applications will run concurrently in the same user profile and will be of the same editor type (same Type parameter in EditText). But this is not my case, if yours, try to use more specific storage or workfile indexing (find first "free" name). tinyMCE package can be shared, that's not a problem.
Using the Code
I used some helper methods to get everything to work in
This one gets a path to temporary storage where work file and
tinyMCE package are stored. It actually returns subfolder M_WORKPATH in
public void PrepareTinyMCE()
tinyMCE already exists, if not, unzips package using
public Stream GetResourceFile(string File)
gets stream from embedded resources.
public string EditText(string Text, string Type, string CSSFile)
Public method for editing text, covers and calls
Type allows you to store work file with different name, so you can simultaneously call few
edit forms in one running user profile (theoretically, it’s not this case while form is shown modal) .
private void showText(bool edit)
Here, HTML work file with links to tinyMCE Jscript is constructed and stored into a temporary file.
There’s a little bit custom code in this method, CSS replacement. The method looks in settings for [CSS] string and replaces it with passed path to CSS. Why is this useful? Well, when you’ll use this form, e.g., as editor for product descriptions over multiple regional databases of multiple companies, You’ll need to pass different CSSs got from database, for example.
After constructing work page and preparing
tinyMCE package browser is navigated to work file by calling:
User stores text by pressing Save button in
tinyMCE, that’s why in setting section, it’s declared tinyMCE has to use save plugin. One more hack, when save is used, one needs to cancel postback action of the form, otherwise will get tinyMCE error message. Looking into implementation leads to simple solution in showText :
sb.AppendLine("<form method=\"\" action=\"\" onsubmit=\"return false;\">");
That’s it, smart guys in Moxito think about it, cancelling
onsubmit will cancel error message too.
Last thing, how to get edited text back?
m_text = ((mshtml.IHTMLDocument3)axBrowser.Document).getElementById("elm1").innerText;
Retyping root DOM document of the Internet Explorer control to
IHTMLDocument3 allows you to access document elements represented by DOM model, so it’s easy to get content of textarea
FrmHTMLBrowser class to create editor enabled window just as in the example.
tinyMCE and settings are stored in resources as embedded resource, you can of course modify this solution and use disk storage or whatever you imagine.
FrmHTMLBrowser as you need, you'll get content of the editor back.
FrmHTMLBrowser brw = new FrmHTMLBrowser();
ctlRtf.Text = brw.EditText(ctlRtf.Text, "tempfilename", "yourCSS.css");
Here in "
tempfilename", you can specify name of work file, yourCSS.css will specify path to CSS file (of course again, it'll be copied into the work folder and make a relative path to package) , which will be used by
tinyMCE to fillup
Points of Interest
It's not my point of interest, HTML editors. Rather HW, Neural Networks, signal processing. But as in real life, I needed some HTML editor, and this one is very good and free under GPL.
- Implemented, tested 2008/07/07