|
Introduction
About two years ago I was creating a project for university. It was a complex of five programs that were related to testing (checking knowledge I mean). One of them contained a text editor. But unfortunately, I didn't know how to do that, that's why it was very simple. So, after these two years, I decided to rewrite my program in C# .NET (initially, it was written in VB.NET) and create a new powerful text editor. You can see part of it here.
Background
I spent a lot of time(!) searching the Internet for controls like this, but the best ones are shareware and others did not fit my needs. So, what does this control have? I tried to make it look like Microsoft Word and I think that there are some similarities. The ruler lets you change the following: left and right margins, left indent, hanging indent and right indent. You also can disable margins (their values are set to 1). You can see how it looks in the picture above.
Also, you can add tabs by clicking on the control with the left mouse button. But it is allowed only inside the area bounded by margins. If you want to remove a tab, just drag it off from the control.
The editor lets you use lists, underline styles, advanced char styles (you can create your own links, that are not words starting with "http://" or even "www"), OLE functionality is also available. I want to thank Oscar Londoño for his article Inserting Images into a RichTextBox Control (The OLE Way). It helped me a lot to deal with OLE. This project contains his code.
Using the Code
You can use the code according to the CPOL.
Projects are created as Windows Applications, but you can easily convert them into *.dll or just embed code into your project.
Unfortunately, I removed Visual Studio 2005, so, sorry but I can't create and upload a Visual Studio 2005 project. But you can import all required files into a Visual Studio 2005 project without any problems. However, note that Visual Studio 2008 added some new namespaces (like LINQ) that Visual Studio 2005 does not "understand". Just remove them. That's all. You are ready.
Points of Interest
One thing that shocked me is that Microsoft has released RichTextBox 6.0! (It is distributed with Microsoft Office 2007) but... with one exception. There is no documentation about its features. All that I've found is a list of added functions. You can find it here. There are also descriptions for all released versions of RichTextBox.
History
- 7 January 2008: Initial release
- 16 January 2008: Projects for Visual Studio 2005 and 2008 posted instead of standalone control.
- 26 January 2008: Posted completed
AdvancedTextEditor project. It is available for Visual Studio 2005 and Visual Studio 2008.
- 10 February 2008: Fixed
PrintDialog bug. It didn't receive focus when shown. Now it's OK. Thanks to Chris Schucker for bug report and recommendations.
- 22 February 2008: Added new functionality (full text justification, underline styles and colors and other)
- 24 February 2008: Fixed bug with conversion from millimeter to pixel and vice versa Thanks to Chris Schucker. Also corrected bug which caused incorrect display of the indents.
- 19 March 2008: Version 2.0 released. A lot of changes including lists, OLE, underline styles, etc.
Additions
I understand that I am not able to include everything into the control, that's why you can freely add something useful or change code to fit your needs. But, please inform me about that, just email me at krasssss@mail.ru. It's just to let anyone use an upgraded (and corrected) version of that control. Of course, advisors will be mentioned.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 76 (Total in Forum: 76) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi Aleksei. Hyperlinks that have spaces included do not work as expected. E.g. the hyperlink file:\\c:\documents and settings\frank\somefile.txt. The text left of the first space is highlighted but the link does not work. Any ideas? (besides removing the spaces)
Cheers, Frank
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello. Actually, this is an issue of the RichTextBox. Well, I found a solution. Firstly, it's easier to use arbitrary links (like, click here, instead of file://somefile).
You sould add a function to the ExtendedRichTextBox, which will instert hyperlinks. Here is what I use:
internal void InsertHyperlink(string text, string address, Color linkColor) { if (address == null) return; if (address == "") return; if (text == "") text = address;
string _val = "", _val2 = ""; string s = @"{\rtf1\ansi\ansicpg1251\deff0\deflang1049" + //{\fonttbl{\f0\fnil\fcharset1200 Times New Roman;}}" + Environment.NewLine + @"{\colortbl ;\red" + linkColor.R.ToString() + @"\green" + linkColor.G.ToString() + @"\blue" + linkColor.B.ToString() + ";}" + Environment.NewLine + @"{\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1 "; string s1 = "\\pard \\protect {\\field{\\*\\fldinst{HYPERLINK \""; string s2 = "\" }}{\\fldrslt{\\cf1\\ul "; string s3 = "}}}\\cf0\\ulnone\\f0 ";
_val2 = "\\uc0 "; for (int i = 0; i < address.Length; i++) { _val2 += "\\u" + ((short)address[i]).ToString() + " "; }
_val = s + s1 + _val2 + s2;
_val2 = "\\uc0 "; for (int y = 0; y < text.Length; y++) { _val2 += "\\u" + ((short)text[y]).ToString() + " "; }
_val += _val2 + s3 + Environment.NewLine + "\\protect0 " + Environment.NewLine + "}";
this.SelectedRtf = _val; }
It's not perfect, but working. It uses MS Word style hyperlinks (it uses HYPERLINK keyword defined inside field). After adding the code above provide the link text (caption), address (this is the path to your file) and optionally the color of the link.
One more thing. On my computer there was a problem. Method above worked only if there was some text after the link. . It was somehow unexpected. Fortunatly I found the solution. You have to handle the LinkClicked event in the WndProc in the following way:
if (m.Msg == 8270) { NativeMethods.ENLINK lParam;
lParam = m.GetLParam(typeof(NativeMethods.ENLINK)) as NativeMethods.ENLINK;
if (lParam != null) { if (lParam.msg == 513) { string str = this.CharRangeToString(lParam.charrange); if (!string.IsNullOrEmpty(str)) { m.Result = (IntPtr)1; OnLinkClicked(new LinkClickedEventArgs(str)); } else base.WndProc(ref m); } else base.WndProc(ref m); } else base.WndProc(ref m); }
It happens that way: user clicks the link, we handle it, than we get its address (this should be you filename) and convert it into a string. After that we rise the OnLinkClicked event and passing the address to it. All you need to do is just to decide what to do it LinkClicked proc.
Fortunately, definition for ENLINK, TEXTRANGE, NMHDR and CHARRANGE you can find in the MSDN. And here is the definitions for CharRangeToString function:
private class CharBuffer { // Fields internal char[] buffer; internal int offset;
// Methods internal CharBuffer(int size) { if (size > 8196 || size < 0) { this.buffer = new char[0]; return; }
try { this.buffer = new char[size]; } catch (Exception) { } }
public IntPtr AllocCoTaskMem() { if (this.buffer.Length == 0) return IntPtr.Zero;
IntPtr destination = Marshal.AllocCoTaskMem(this.buffer.Length * 2); Marshal.Copy(this.buffer, 0, destination, this.buffer.Length); return destination; }
public string GetString() { int offset = this.offset; while ((offset < this.buffer.Length) && (this.buffer[offset] != '\0')) { offset++; } string str = new string(this.buffer, this.offset, offset - this.offset); if (offset < this.buffer.Length) { offset++; } this.offset = offset; return str; }
public void PutCoTaskMem(IntPtr ptr) { Marshal.Copy(ptr, this.buffer, 0, this.buffer.Length); this.offset = 0; }
public void PutString(string s) { int count = Math.Min(s.Length, this.buffer.Length - this.offset); s.CopyTo(0, this.buffer, this.offset, count); this.offset += count; if (this.offset < this.buffer.Length) { this.buffer[this.offset++] = '\0'; } } } private string CharRangeToString(NativeMethods.CHARRANGE c) { NativeMethods.TEXTRANGE lParam = new NativeMethods.TEXTRANGE(); lParam.chrg = c;
int size = (c.cpMax - c.cpMin) + 1; CharBuffer buffer = new CharBuffer(size); IntPtr ptr = buffer.AllocCoTaskMem(); if (ptr == IntPtr.Zero) { return ""; } lParam.lpstrText = ptr; int num1 = (int)NativeMethods.SendMessage(new HandleRef(this, this.Handle), 1099, 0, lParam); buffer.PutCoTaskMem(ptr); if (lParam.lpstrText != IntPtr.Zero) { Marshal.FreeCoTaskMem(ptr); } return buffer.GetString(); }
I hope this will help you. For me this works perfect. But remember that when you insert the hyperlink that way, you mark it protected, so you can't edit it directly in the RichTextBox. And changing the hyperlinks is another topic.
Good luck.
Cheers, Alex.
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Aleksei, great peice of work! but was wondering how you change the indentations on the ruler to match the page margin, let me explain in more detail
For example:
If i change the ruler margins to 1 Inch(25.4mm) each side id expect the Ruler indetation pegs to adjust to the edge of the newly set margin, however you must change the ruler indentation settings to affect these, which in turn alters the Rich Text box indentation level therefore messing with the print
So what im asking is how can i set the ruler margins and change the ruler indents posistion without changing the Rich text box's indentation level?
Any Ideas?
Thanks
modified on Sunday, December 21, 2008 3:50 AM
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi
Your control is very useful for me but there is a little problem. I have some rtf formatted text and now I want to display this text in the text editor
this.ateAdditionalNote.TextEditor.Rtf = text;
Unfortunately no text is displayed in the control although the property (TextEditor.Rtf) has the right value. When I save the text in a file and open it in MS Word, the text is displayed correctly.
Do I have to call some kind of refresh method or something similar?
Thank you for your help!
Michael Hachen
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hm. I can't tell you exactly, what can be wrong with it. For me it works fine. What kind of text are you assigning to Rtf property (I mean formatting)?
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
OK I figured it out. If I set the Rtf property BEFORE the text editor is shown (.Show() or .ShowDialog()) the property is set but the text won't be displayed. If I set the Rtf property AFTER the editor is shown, the text will be displayed correctly.
Strange but I can live with it...
Mike Hachen
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am glad that you've found the solution.
If you have any problems, do not hesitate to contact me.
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
There is in your code a region called "Old Style Formating", but it seems to appears that this piece of code is never used, is it true ?
Because i will adapt your font code to my program in vb.net and have some problems to make the translation.
Thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello!
Yes, this region was used in the first version of the component, but now it is obsolete. So, you can remove it or keep as an example. All formatting options may be changed through SelectionFont2 and SelectionCharStyle. In about 2 days I plan to upload updated version with many improvements and bug fixies.
Regards, Alex.
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
G'day Aleksei. I'm trying to translate you code from C# to vb using Lutz Roeder's .Net Reflector. The ruler translation seems to go OK but the Enhanced Editor is giving me some trouble. After translating I can build the dll containing both controls. I then add them to a form and all seems to go well. However, after saving and closing this form I cannot open it again in the designer view. It return the following errors;
One or more errors encountered while loading the designer. The errors are listed below. Some errors can be fixed by rebuilding your project, while others may require code changes.
The variable 'CharStyle1' is either undeclared or was never assigned. The variable 'CharStyle1' is either undeclared or was never assigned. The variable 'CharStyle1' is either undeclared or was never assigned. The variable 'CharStyle1' is either undeclared or was never assigned. The variable 'CharStyle1' is either undeclared or was never assigned. The variable 'ParaLineSpacing1' is either undeclared or was never assigned. The variable 'ParaLineSpacing1' is either undeclared or was never assigned. The variable 'ParaListStyle1' is either undeclared or was never assigned. The variable 'ParaListStyle1' is either undeclared or was never assigned. The variable 'ParaListStyle1' is either undeclared or was never assigned. The variable 'ParaListStyle1' is either undeclared or was never assigned.
Checking the InitializeComponent part of the form doesn't reveale an error. After removing the coding for the Editor the form is displayed again.
If I try to add your ExtendedRichTextBox control to my problem I reveice the same errors. Any suggestions?
Cheers, Frank
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It's all about Visual Studio 'manners'. For me, it demands all objects to be marked public. And if they are internal designer fails. Also, you may check if [Serializable()] (<Serializable> _ in VB) attribute is set. Try this out and let me know.
Regards, Alex
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
G'day. I translated it to VS2008 and I don't get this error anymore. I didn't try your suggestion, sorry for that. How did you intent to use the OffsetType? The line this.TextEditor.SelectionOffsetType = ExtendedRichTextBox.OffsetType.Subscript; doesn't seem te be enough. Do I have to set the offset like this?
this.TextEditor.SelectionCharOffset = -5;
Cheers, Frank
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
How much of this is posible in VB? i'm making a similar thing in VB 2008 EE, so i was wondering if you could give me any help in that direction? Maybe even a vb project file ?
Also: Where did you find your undo, redo icons? and did you make the U, I, B... Etc. icons yourself? if not where did oyu get them ?
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Unfortunately, I don't have VB project, because everything is written in C#. But you can convert it into VB with no doubt. You can make it manually or use converters. I'm sure that there are many of them in the Internet.
If you need any assistance, you're welcome.
P.S. Icons are taken from Microsoft Image Library. I got it with the trial version of VS 2008 Pro.
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
it might be a bit to long to write it all again so maybe you could just look at this: http://www.vbforums.com/showthread.php?p=3293834#post3293834 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi,
sorry to ask.
I want to use the ruler for milimeter on the screen, one horizontal, one vertical. When I have a display with 1920*1200, which value for the zoomfactor?
When I set the factor to 1, it's displaying too big on the screen.
I tried some things to get the right factor, but I didn't get a right value/display.
Can somebody help me?
Greetings, Peter
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello, Peter.
That is known issue. The probles is that Ruler does not support zoom change (for now). I am currently working on that. I hope to upgrade the project soon.
Alex
Alex KraS
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Alex, I am researching control and have question.
How can I add pagebreak command (\page) to the RTF programatically?
My target is: I'd like to do merging 2 rtf files (or rtf texts) and need to divide them withg pagebreak.
Thank you. Regards, Oleg.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
Unfortunately, I removed VS2005 from my PC. That's why I can't create VS2005 project.
But you can easily include all required files from VS2008 into your VS2005 project - they are fully compatible.
If you have any troubles, you're welcome to ask for a help.
Regards, Alex.
Alex KraS
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|