using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
//using WhelkMud.Interfaces;
namespace AyaNova
{
#region Control enums
///
/// Specifies the style of underline that should be
/// applied to the text.
///
public enum UnderlineStyle
{
///
/// No underlining.
///
None = 0,
///
/// Standard underlining across all words.
///
Normal = 1,
///
/// Standard underlining broken between words.
///
Word = 2,
///
/// Double line underlining.
///
Double = 3,
///
/// Dotted underlining.
///
Dotted = 4,
///
/// Dashed underlining.
///
Dash = 5,
///
/// Dash-dot ("-.-.") underlining.
///
DashDot = 6,
///
/// Dash-dot-dot ("-..-..") underlining.
///
DashDotDot = 7,
///
/// Wave underlining (like spelling mistakes in MS Word).
///
Wave = 8,
///
/// Extra thick standard underlining.
///
Thick = 9,
///
/// Extra thin standard underlining.
///
HairLine = 10,
///
/// Double thickness wave underlining.
///
DoubleWave = 11,
///
/// Thick wave underlining.
///
HeavyWave = 12,
///
/// Extra long dash underlining.
///
LongDash = 13
}
///
/// Specifies the color of underline that should be
/// applied to the text.
///
///
/// I named these colors by their appearance, so some
/// of them might not be what you expect. Please email
/// me if you feel one should be changed.
///
public enum UnderlineColor
{
/// Black.
Black = 0x00,
/// None.
None = 0x00,
/// Blue.
Blue = 0x10,
/// Cyan.
Cyan = 0x20,
/// Lime green.
LimeGreen = 0x30,
/// Magenta.
Magenta = 0x40,
/// Red.
Red = 0x50,
/// Yellow.
Yellow = 0x60,
/// White.
White = 0x70,
/// DarkBlue.
DarkBlue = 0x80,
/// DarkCyan.
DarkCyan = 0x90,
/// Green.
Green = 0xA0,
/// Dark magenta.
DarkMagenta = 0xB0,
/// Brown.
Brown = 0xC0,
/// Olive green.
OliveGreen = 0xD0,
/// Dark gray.
DarkGray = 0xE0,
/// Gray.
Gray = 0xF0
}
// Enum for possible RTF colors
public enum RtfColor
{
Black, Maroon, Green, Olive, Navy, Purple, Teal, Gray, Silver,
Red, Lime, Yellow, Blue, Fuchsia, Aqua, White
}
#endregion
public class ExtendedRichTextBox : RichTextBox
{
#region Private fields and constructors
private int _Updating = 0;
private int _OldEventMask = 0;
private ToolTip myToolTip;
public ExtendedRichTextBox()
{
//required for my own link code
this.DetectUrls = true;
this.myToolTip = new ToolTip();
this.ContextMenu = new ContextMenu();
// this.LinkClicked += new LinkClickedEventHandler(MudRichTextBox_LinkClicked);
// Initialize default text and background colors
textColor = RtfColor.Black;
highlightColor = RtfColor.White;
// Initialize the dictionary mapping color codes to definitions
rtfColor = new Dictionary();
rtfColor[RtfColor.Aqua] = RtfColorDef.Aqua;
rtfColor[RtfColor.Black] = RtfColorDef.Black;
rtfColor[RtfColor.Blue] = RtfColorDef.Blue;
rtfColor[RtfColor.Fuchsia] = RtfColorDef.Fuchsia;
rtfColor[RtfColor.Gray] = RtfColorDef.Gray;
rtfColor[RtfColor.Green] = RtfColorDef.Green;
rtfColor[RtfColor.Lime] = RtfColorDef.Lime;
rtfColor[RtfColor.Maroon] = RtfColorDef.Maroon;
rtfColor[RtfColor.Navy] = RtfColorDef.Navy;
rtfColor[RtfColor.Olive] = RtfColorDef.Olive;
rtfColor[RtfColor.Purple] = RtfColorDef.Purple;
rtfColor[RtfColor.Red] = RtfColorDef.Red;
rtfColor[RtfColor.Silver] = RtfColorDef.Silver;
rtfColor[RtfColor.Teal] = RtfColorDef.Teal;
rtfColor[RtfColor.White] = RtfColorDef.White;
rtfColor[RtfColor.Yellow] = RtfColorDef.Yellow;
// Initialize the dictionary mapping default Framework font families to
// RTF font families
rtfFontFamily = new Dictionary();
rtfFontFamily[FontFamily.GenericMonospace.Name] = RtfFontFamilyDef.Modern;
rtfFontFamily[FontFamily.GenericSansSerif.Name] = RtfFontFamilyDef.Swiss;
rtfFontFamily[FontFamily.GenericSerif.Name] = RtfFontFamilyDef.Roman;
rtfFontFamily[FF_UNKNOWN] = RtfFontFamilyDef.Unknown;
// Get the horizontal and vertical resolutions at which the object is
// being displayed
using (Graphics _graphics = this.CreateGraphics())
{
xDpi = _graphics.DpiX;
yDpi = _graphics.DpiY;
}
HideCaret(Handle);
}
#endregion
#region Elements required to create an RTF document
/* RTF HEADER
* ----------
*
* \rtf[N] - For text to be considered to be RTF, it must be enclosed in this tag.
* rtf1 is used because the RichTextBox conforms to RTF Specification
* version 1.
* \ansi - The character set.
* \ansicpg[N] - Specifies that unicode characters might be embedded. ansicpg1252
* is the default used by Windows.
* \deff[N] - The default font. \deff0 means the default font is the first font
* found.
* \deflang[N] - The default language. \deflang1033 specifies US English.
* */
private const string RTF_HEADER = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033";
/* RTF DOCUMENT AREA
* -----------------
*
* \viewkind[N] - The type of view or zoom level. \viewkind4 specifies normal view.
* \uc[N] - The number of bytes corresponding to a Unicode character.
* \pard - Resets to default paragraph properties
* \cf[N] - Foreground color. \cf1 refers to the color at index 1 in
* the color table
* \f[N] - Font number. \f0 refers to the font at index 0 in the font
* table.
* \fs[N] - Font size in half-points.
* */
private const string RTF_DOCUMENT_PRE = @"\viewkind4\uc1\pard\cf1\f0\fs20";
private const string RTF_DOCUMENT_POST = @"\cf0\fs17}";
private string RTF_IMAGE_POST = @"}";
// Represents an unknown font family
private const string FF_UNKNOWN = "UNKNOWN";
// Specifies the flags/options for the unmanaged call to the GDI+ method
// Metafile.EmfToWmfBits().
private enum EmfToWmfBitsFlags
{
// Use the default conversion
EmfToWmfBitsFlagsDefault = 0x00000000,
// Embedded the source of the EMF metafiel within the resulting WMF
// metafile
EmfToWmfBitsFlagsEmbedEmf = 0x00000001,
// Place a 22-byte header in the resulting WMF file. The header is
// required for the metafile to be considered placeable.
EmfToWmfBitsFlagsIncludePlaceable = 0x00000002,
// Don't simulate clipping by using the XOR operator.
EmfToWmfBitsFlagsNoXORClip = 0x00000004
};
#endregion
#region Windows API
private const int WM_VSCROLL = 0x115;
private const int WM_HSCROLL = 0x114;
private const int SB_LINEUP = 0;
private const int SB_LINEDOWN = 1;
private const int SB_PAGEUP = 2;
private const int SB_PAGEDOWN = 3;
private const int SB_THUMBPOSITION = 4;
private const int SB_THUMBTRACK = 5;
private const int SB_TOP = 6;
private const int SB_BOTTOM = 7;
private const int SB_ENDSCROLL = 8;
private const int WM_SETREDRAW = 0x0B;
private const int EM_SETEVENTMASK = 0x0431;
private const int EM_SETCHARFORMAT = 0x0444;
private const int EM_GETCHARFORMAT = 0x043A;
private const int EM_GETPARAFORMAT = 0x043D;
private const int EM_SETPARAFORMAT = 0x0447;
private const int EM_SETTYPOGRAPHYOPTIONS = 0x04CA;
private const int CFM_UNDERLINETYPE = 0x800000;
private const int CFM_BACKCOLOR = 0x4000000;
private const int CFE_AUTOBACKCOLOR = 0x4000000;
private const int SCF_SELECTION = 0x01;
private const int PFM_ALIGNMENT = 0x08;
private const int TO_ADVANCEDTYPOGRAPHY = 0x01;
// These are the scroll bar constants.
private const int SBS_HORIZ = 0;
private const int SBS_VERT = 1;
// Get which bits.
private const int SIF_RANGE = 0x0001;
private const int SIF_PAGE = 0x0002;
private const int SIF_POS = 0x0004;
private const int SIF_DISABLENOSCROLL = 0x0008;
private const int SIF_TRACKPOS = 0x0010;
private const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, int lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, ref CHARFORMAT2 lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int SendMessage(HandleRef hWnd, int msg, int wParam, ref PARAFORMAT2 lParam);
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
private static extern int SetWindowTheme(
HandleRef hWnd,
[MarshalAs(UnmanagedType.LPWStr)]
string pszSubAppName,
[MarshalAs(UnmanagedType.LPWStr)]
string pszSubIdList);
///
/// The HideCaret function removes the caret from the screen.
///
[DllImport("user32.dll")]
protected static extern bool HideCaret(IntPtr hWnd);
///
/// This will find the scroll position of the specified window.
///
/// the window to send the message to
/// the number of the sroll bar to look at
///
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern int GetScrollInfo(HandleRef hWnd, int nBar, ref SCROLLINFO info);
///
/// Contains information about character formatting in a rich edit control.
///
/// works with all Rich Edit versions.
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMAT
{
public int cbSize;
public uint dwMask;
public uint dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] szFaceName;
}
///
/// Contains information about character formatting in a rich edit control.
///
/// requires Rich Edit 2.0.
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMAT2
{
public int cbSize;
public uint dwMask;
public uint dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] szFaceName;
public short wWeight;
public short sSpacing;
public int crBackColor;
public int LCID;
public uint dwReserved;
public short sStyle;
public short wKerning;
public byte bUnderlineType;
public byte bAnimation;
public byte bRevAuthor;
}
///
/// Contains information about paragraph formatting in a rich edit control.
///
/// works with all Rich Edit versions.
[StructLayout(LayoutKind.Sequential)]
private struct PARAFORMAT
{
public int cbSize;
public uint dwMask;
public short wNumbering;
public short wReserved;
public int dxStartIndent;
public int dxRightIndent;
public int dxOffset;
public short wAlignment;
public short cTabCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public int[] rgxTabs;
}
///
/// Contains information about paragraph formatting in a rich edit control.
///
/// requires Rich Edit 2.0.
[StructLayout(LayoutKind.Sequential)]
private struct PARAFORMAT2
{
public int cbSize;
public uint dwMask;
public short wNumbering;
public short wReserved;
public int dxStartIndent;
public int dxRightIndent;
public int dxOffset;
public short wAlignment;
public short cTabCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public int[] rgxTabs;
public int dySpaceBefore;
public int dySpaceAfter;
public int dyLineSpacing;
public short sStyle;
public byte bLineSpacingRule;
public byte bOutlineLevel;
public short wShadingWeight;
public short wShadingStyle;
public short wNumberingStart;
public short wNumberingStyle;
public short wNumberingTab;
public short wBorderSpace;
public short wBorderWidth;
public short wBorders;
}
///
/// Contains information the scroll bar positions.
///
/// works with all Rich Edit versions.
[StructLayout(LayoutKind.Sequential)]
private struct SCROLLINFO
{
public int cbSize;
public int fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}
// Definitions for colors in an RTF document
private struct RtfColorDef
{
public const string Black = @"\red0\green0\blue0";
public const string Maroon = @"\red128\green0\blue0";
public const string Green = @"\red0\green128\blue0";
public const string Olive = @"\red128\green128\blue0";
public const string Navy = @"\red0\green0\blue128";
public const string Purple = @"\red128\green0\blue128";
public const string Teal = @"\red0\green128\blue128";
public const string Gray = @"\red128\green128\blue128";
public const string Silver = @"\red192\green192\blue192";
public const string Red = @"\red255\green0\blue0";
public const string Lime = @"\red0\green255\blue0";
public const string Yellow = @"\red255\green255\blue0";
public const string Blue = @"\red0\green0\blue255";
public const string Fuchsia = @"\red255\green0\blue255";
public const string Aqua = @"\red0\green255\blue255";
public const string White = @"\red255\green255\blue255";
}
// Control words for RTF font families
private struct RtfFontFamilyDef
{
public const string Unknown = @"\fnil";
public const string Roman = @"\froman";
public const string Swiss = @"\fswiss";
public const string Modern = @"\fmodern";
public const string Script = @"\fscript";
public const string Decor = @"\fdecor";
public const string Technical = @"\ftech";
public const string BiDirect = @"\fbidi";
}
#endregion
#region Property: SelectionUnderlineStyle
///
/// Gets or sets the underline style to apply to the current selection or insertion point.
///
/// A that represents the underline style to
/// apply to the current text selection or to text entered after the insertion point.
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public UnderlineStyle SelectionUnderlineStyle
{
get
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
// Get the underline style
SendMessage(new HandleRef(this, Handle), EM_GETCHARFORMAT, SCF_SELECTION, ref fmt);
if ((fmt.dwMask & CFM_UNDERLINETYPE) == 0)
{
return UnderlineStyle.None;
}
else
{
byte style = (byte)(fmt.bUnderlineType & 0x0F);
return (UnderlineStyle)style;
}
}
set
{
// Ensure we don't alter the color
UnderlineColor color = SelectionUnderlineColor;
// Ensure we don't show it if it shouldn't be shown
if (value == UnderlineStyle.None)
color = UnderlineColor.Black;
// Set the underline type
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = CFM_UNDERLINETYPE;
fmt.bUnderlineType = (byte)((byte)value | (byte)color);
SendMessage(new HandleRef(this, Handle), EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
}
}
#endregion
#region Property: SelectionUnderlineColor
///
/// Gets or sets the underline color to apply to the current selection or insertion point.
///
/// A that represents the underline color to
/// apply to the current text selection or to text entered after the insertion point.
[Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public UnderlineColor SelectionUnderlineColor
{
get
{
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
// Get the underline color
SendMessage(new HandleRef(this, Handle), EM_GETCHARFORMAT, SCF_SELECTION, ref fmt);
if ((fmt.dwMask & CFM_UNDERLINETYPE) == 0)
{
return UnderlineColor.None;
}
else
{
byte style = (byte)(fmt.bUnderlineType & 0xF0);
return (UnderlineColor)style;
}
}
set
{
// If the an underline color of "None" is specified, remove underline effect
if (value == UnderlineColor.None)
{
SelectionUnderlineStyle = UnderlineStyle.None;
}
else
{
// Ensure we don't alter the style
UnderlineStyle style = SelectionUnderlineStyle;
// Ensure we don't show it if it shouldn't be shown
if (style == UnderlineStyle.None)
value = UnderlineColor.Black;
// Set the underline color
CHARFORMAT2 fmt = new CHARFORMAT2();
fmt.cbSize = Marshal.SizeOf(fmt);
fmt.dwMask = CFM_UNDERLINETYPE;
fmt.bUnderlineType = (byte)((byte)style | (byte)value);
SendMessage(new HandleRef(this, Handle), EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
}
}
}
#endregion
#region Method: BeginUpdate
///
/// Maintains performance while updating.
///
///
///
/// It is recommended to call this method before doing
/// any major updates that you do not wish the user to
/// see. Remember to call EndUpdate when you are finished
/// with the update. Nested calls are supported.
///
///
/// Calling this method will prevent redrawing. It will
/// also setup the event mask of the underlying richedit
/// control so that no events are sent.
///
///
public void BeginUpdate()
{
// Deal with nested calls
_Updating++;
if (_Updating > 1)
return;
// Prevent the control from raising any events
_OldEventMask = SendMessage(new HandleRef(this, Handle), EM_SETEVENTMASK, 0, 0);
// Prevent the control from redrawing itself
SendMessage(new HandleRef(this, Handle), WM_SETREDRAW, 0, 0);
}
#endregion
#region Method: EndUpdate
///
/// Resumes drawing and event handling.
///
///
/// This method should be called every time a call is made
/// made to BeginUpdate. It resets the event mask to it's
/// original value and enables redrawing of the control.
///
public void EndUpdate()
{
// Deal with nested calls
_Updating--;
if (_Updating > 0)
return;
// Allow the control to redraw itself
SendMessage(new HandleRef(this, Handle), WM_SETREDRAW, 1, 0);
// Allow the control to raise event messages
SendMessage(new HandleRef(this, Handle), EM_SETEVENTMASK, 0, _OldEventMask);
}
#endregion
#region ScrollBarDetails
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hwndLock, Int32 wMsg, Int32 wParam, ref Point pt);
public Point ScrollPos
{
get
{
const int EM_GETSCROLLPOS = 0x0400 + 221;
Point pt = new Point();
SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref pt);
return pt;
}
set
{
const int EM_SETSCROLLPOS = 0x0400 + 222;
SendMessage(this.Handle, EM_SETSCROLLPOS, 0, ref value);
}
}
///
/// This scrolls the scroll bar down to the bottom of the window.
///
public void ScrollToBottom()
{
SendMessage(new HandleRef(this, Handle), WM_VSCROLL, SB_BOTTOM, 0);
}
///
/// Scrolls the data up one page.
///
public void ScrollPageUp()
{
SendMessage(new HandleRef(this, Handle), WM_VSCROLL, SB_PAGEUP, 0);
}
///
/// Scrolls the data down one page.
///
public void ScrollPageDown()
{
SendMessage(new HandleRef(this, Handle), WM_VSCROLL, SB_PAGEDOWN, 0);
}
///
/// Scrolls the data up one page.
///
public void ScrollLineUp(int num)
{
for (int i = 0; i < num; i++)
{
SendMessage(new HandleRef(this, Handle), WM_VSCROLL, SB_LINEUP, 0);
}
}
///
/// Scrolls the data down one page.
///
public void ScrollLineDown(int num)
{
for (int i = 0; i < num; i++)
{
SendMessage(new HandleRef(this, Handle), WM_VSCROLL, SB_LINEDOWN, 0);
}
}
///
/// This is the information associated with the scroll bar, showing it's position
/// and other details.
///
/// the scroll bar information
public ScrollBarInformation VerticalScrollInformation
{
get
{
SCROLLINFO info = new SCROLLINFO();
info.cbSize = Marshal.SizeOf(info);
info.fMask = SIF_ALL;
int ret = GetScrollInfo(new HandleRef(this, Handle), SBS_VERT, ref info);
return new ScrollBarInformation(info.nMin, info.nMax, info.nPage, info.nPos, info.nTrackPos);
}
}
#endregion
#region Rtf Privates
// Not used in this application. Descriptions can be found with documentation
// of Windows GDI function SetMapMode
private const int MM_TEXT = 1;
private const int MM_LOMETRIC = 2;
private const int MM_HIMETRIC = 3;
private const int MM_LOENGLISH = 4;
private const int MM_HIENGLISH = 5;
private const int MM_TWIPS = 6;
// Ensures that the metafile maintains a 1:1 aspect ratio
private const int MM_ISOTROPIC = 7;
// Allows the x-coordinates and y-coordinates of the metafile to be adjusted
// independently
private const int MM_ANISOTROPIC = 8;
// The number of hundredths of millimeters (0.01 mm) in an inch
// For more information, see GetImagePrefix() method.
private const int HMM_PER_INCH = 2540;
// The number of twips in an inch
// For more information, see GetImagePrefix() method.
private const int TWIPS_PER_INCH = 1440;
// The default text color
private RtfColor textColor;
// The default text background color
private RtfColor highlightColor;
// Dictionary that maps color enums to RTF color codes
private Dictionary rtfColor;
// Dictionary that mapas Framework font families to RTF font families
private Dictionary rtfFontFamily;
// The horizontal resolution at which the control is being displayed
private float xDpi;
// The vertical resolution at which the control is being displayed
private float yDpi;
#endregion
#region Append RTF or Text to RichTextBox Contents
///
/// Assumes the string passed as a paramter is valid RTF text and attempts
/// to append it as RTF to the content of the control.
///
///
public void AppendRtf(string _rtf)
{
// Move caret to the end of the text
this.Select(this.TextLength, 0);
// Since SelectedRtf is null, this will append the string to the
// end of the existing RTF
this.SelectedRtf = _rtf;
}
///
/// Assumes that the string passed as a parameter is valid RTF text and
/// attempts to insert it as RTF into the content of the control.
///
///
/// NOTE: The text is inserted wherever the caret is at the time of the call,
/// and if any text is selected, that text is replaced.
///
///
public void InsertRtf(string _rtf)
{
this.SelectedRtf = _rtf;
}
///
/// Appends the text using the current font, text, and highlight colors.
///
///
public void AppendTextAsRtf(string _text)
{
AppendTextAsRtf(_text, this.Font);
}
///
/// Appends the text using the given font, and current text and highlight
/// colors.
///
///
///
public void AppendTextAsRtf(string _text, Font _font)
{
AppendTextAsRtf(_text, _font, textColor);
}
///
/// Appends the text using the given font and text color, and the current
/// highlight color.
///
///
///
///
public void AppendTextAsRtf(string _text, Font _font, RtfColor _textColor)
{
AppendTextAsRtf(_text, _font, _textColor, highlightColor);
}
///
/// Appends the text using the given font, text, and highlight colors. Simply
/// moves the caret to the end of the RichTextBox's text and makes a call to
/// insert.
///
///
///
///
///
public void AppendTextAsRtf(string _text, Font _font, RtfColor _textColor, RtfColor _backColor)
{
// Move carret to the end of the text
this.Select(this.TextLength, 0);
InsertTextAsRtf(_text, _font, _textColor, _backColor);
}
#endregion
#region RTF Insert Plain Text
///
/// Inserts the text using the current font, text, and highlight colors.
///
///
public void InsertTextAsRtf(string _text)
{
InsertTextAsRtf(_text, this.Font);
}
///
/// Inserts the text using the given font, and current text and highlight
/// colors.
///
///
///
public void InsertTextAsRtf(string _text, Font _font)
{
InsertTextAsRtf(_text, _font, textColor);
}
///
/// Inserts the text using the given font and text color, and the current
/// highlight color.
///
///
///
///
public void InsertTextAsRtf(string _text, Font _font, RtfColor _textColor)
{
InsertTextAsRtf(_text, _font, _textColor, highlightColor);
}
///
/// Inserts the text using the given font, text, and highlight colors. The
/// text is wrapped in RTF codes so that the specified formatting is kept.
/// You can only assign valid RTF to the RichTextBox.Rtf property, else
/// an exception is thrown. The RTF string should follow this format ...
///
/// {\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{[FONTS]}{\colortbl ;[COLORS]}}
/// \viewkind4\uc1\pard\cf1\f0\fs20 [DOCUMENT AREA] }
///
///
///
/// NOTE: The text is inserted wherever the caret is at the time of the call,
/// and if any text is selected, that text is replaced.
///
///
///
///
///
public void InsertTextAsRtf(string _text, Font _font, RtfColor _textColor, RtfColor _backColor)
{
StringBuilder _rtf = new StringBuilder();
// Append the RTF header
_rtf.Append(RTF_HEADER);
// Create the font table from the font passed in and append it to the
// RTF string
_rtf.Append(GetFontTable(_font));
// Create the color table from the colors passed in and append it to the
// RTF string
_rtf.Append(GetColorTable(_textColor, _backColor));
// Create the document area from the text to be added as RTF and append
// it to the RTF string.
_rtf.Append(GetDocumentArea(_text, _font));
this.SelectedRtf = _rtf.ToString();
}
///
/// Creates the Document Area of the RTF being inserted. The document area
/// (in this case) consists of the text being added as RTF and all the
/// formatting specified in the Font object passed in. This should have the
/// form ...
///
/// \viewkind4\uc1\pard\cf1\f0\fs20 [DOCUMENT AREA] }
///
///
///
///
///
/// The document area as a string.
///
private string GetDocumentArea(string _text, Font _font)
{
StringBuilder _doc = new StringBuilder();
// Append the standard RTF document area control string
_doc.Append(RTF_DOCUMENT_PRE);
// Set the highlight color (the color behind the text) to the
// third color in the color table. See GetColorTable for more details.
_doc.Append(@"\highlight2");
// If the font is bold, attach corresponding tag
if (_font.Bold)
_doc.Append(@"\b");
// If the font is italic, attach corresponding tag
if (_font.Italic)
_doc.Append(@"\i");
// If the font is strikeout, attach corresponding tag
if (_font.Strikeout)
_doc.Append(@"\strike");
// If the font is underlined, attach corresponding tag
if (_font.Underline)
_doc.Append(@"\ul");
// Set the font to the first font in the font table.
// See GetFontTable for more details.
_doc.Append(@"\f0");
// Set the size of the font. In RTF, font size is measured in
// half-points, so the font size is twice the value obtained from
// Font.SizeInPoints
_doc.Append(@"\fs");
_doc.Append((int)Math.Round((2 * _font.SizeInPoints)));
// Apppend a space before starting actual text (for clarity)
_doc.Append(@" ");
// Append actual text, however, replace newlines with RTF \par.
// Any other special text should be handled here (e.g.) tabs, etc.
_doc.Append(_text.Replace("\n", @"\par "));
// RTF isn't strict when it comes to closing control words, but what the
// heck ...
// Remove the highlight
_doc.Append(@"\highlight0");
// If font is bold, close tag
if (_font.Bold)
_doc.Append(@"\b0");
// If font is italic, close tag
if (_font.Italic)
_doc.Append(@"\i0");
// If font is strikeout, close tag
if (_font.Strikeout)
_doc.Append(@"\strike0");
// If font is underlined, cloes tag
if (_font.Underline)
_doc.Append(@"\ulnone");
// Revert back to default font and size
_doc.Append(@"\f0");
_doc.Append(@"\fs20");
// Close the document area control string
_doc.Append(RTF_DOCUMENT_POST);
return _doc.ToString();
}
#endregion
#region RTF Insert Image
///
/// Inserts an image into the RichTextBox. The image is wrapped in a Windows
/// Format Metafile, because although Microsoft discourages the use of a WMF,
/// the RichTextBox (and even MS Word), wraps an image in a WMF before inserting
/// the image into a document. The WMF is attached in HEX format (a string of
/// HEX numbers).
///
/// The RTF Specification v1.6 says that you should be able to insert bitmaps,
/// .jpegs, .gifs, .pngs, and Enhanced Metafiles (.emf) directly into an RTF
/// document without the WMF wrapper. This works fine with MS Word,
/// however, when you don't wrap images in a WMF, WordPad and
/// RichTextBoxes simply ignore them. Both use the riched20.dll or msfted.dll.
///
///
/// NOTE: The image is inserted wherever the caret is at the time of the call,
/// and if any text is selected, that text is replaced.
///
///
public void InsertImage(Image _image)
{
StringBuilder _rtf = new StringBuilder();
// Append the RTF header
_rtf.Append(RTF_HEADER);
// Create the font table using the RichTextBox's current font and append
// it to the RTF string
_rtf.Append(GetFontTable(this.Font));
// Create the image control string and append it to the RTF string
_rtf.Append(GetImagePrefix(_image));
// Create the Windows Metafile and append its bytes in HEX format
_rtf.Append(GetRtfImage(_image));
// Close the RTF image control string
_rtf.Append(RTF_IMAGE_POST);
this.SelectedRtf = _rtf.ToString();
//TODO: need to calc and return checksum here?
}
///
/// My overload to get the text of an image with tag
///
///
///
///
///
public string GetImageAsRtfText(Image _image)
{
StringBuilder _rtf = new StringBuilder();
// Append the RTF header
_rtf.Append(RTF_HEADER);
// Create the font table using the RichTextBox's current font and append
// it to the RTF string
_rtf.Append(GetFontTable(this.Font));
// Create the image control string and append it to the RTF string
_rtf.Append(GetImagePrefix(_image));
// Create the Windows Metafile and append its bytes in HEX format
_rtf.Append(GetRtfImage(_image));
// Close the RTF image control string
_rtf.Append(RTF_IMAGE_POST);
return _rtf.ToString();
}
///
/// Creates the RTF control string that describes the image being inserted.
/// This description (in this case) specifies that the image is an
/// MM_ANISOTROPIC metafile, meaning that both X and Y axes can be scaled
/// independently. The control string also gives the images current dimensions,
/// and its target dimensions, so if you want to control the size of the
/// image being inserted, this would be the place to do it. The prefix should
/// have the form ...
///
/// {\pict\wmetafile8\picw[A]\pich[B]\picwgoal[C]\pichgoal[D]
///
/// where ...
///
/// A = current width of the metafile in hundredths of millimeters (0.01mm)
/// = Image Width in Inches * Number of (0.01mm) per inch
/// = (Image Width in Pixels / Graphics Context's Horizontal Resolution) * 2540
/// = (Image Width in Pixels / Graphics.DpiX) * 2540
///
/// B = current height of the metafile in hundredths of millimeters (0.01mm)
/// = Image Height in Inches * Number of (0.01mm) per inch
/// = (Image Height in Pixels / Graphics Context's Vertical Resolution) * 2540
/// = (Image Height in Pixels / Graphics.DpiX) * 2540
///
/// C = target width of the metafile in twips
/// = Image Width in Inches * Number of twips per inch
/// = (Image Width in Pixels / Graphics Context's Horizontal Resolution) * 1440
/// = (Image Width in Pixels / Graphics.DpiX) * 1440
///
/// D = target height of the metafile in twips
/// = Image Height in Inches * Number of twips per inch
/// = (Image Height in Pixels / Graphics Context's Horizontal Resolution) * 1440
/// = (Image Height in Pixels / Graphics.DpiX) * 1440
///
///
///
/// The Graphics Context's resolution is simply the current resolution at which
/// windows is being displayed. Normally it's 96 dpi, but instead of assuming
/// I just added the code.
///
/// According to Ken Howe at pbdr.com, "Twips are screen-independent units
/// used to ensure that the placement and proportion of screen elements in
/// your screen application are the same on all display systems."
///
/// Units Used
/// ----------
/// 1 Twip = 1/20 Point
/// 1 Point = 1/72 Inch
/// 1 Twip = 1/1440 Inch
///
/// 1 Inch = 2.54 cm
/// 1 Inch = 25.4 mm
/// 1 Inch = 2540 (0.01)mm
///
///
///
private string GetImagePrefix(Image _image)
{
StringBuilder _rtf = new StringBuilder();
// Calculate the current width of the image in (0.01)mm
int picw = (int)Math.Round((_image.Width / xDpi) * HMM_PER_INCH);
// Calculate the current height of the image in (0.01)mm
int pich = (int)Math.Round((_image.Height / yDpi) * HMM_PER_INCH);
// Calculate the target width of the image in twips
int picwgoal = (int)Math.Round((_image.Width / xDpi) * TWIPS_PER_INCH);
// Calculate the target height of the image in twips
int pichgoal = (int)Math.Round((_image.Height / yDpi) * TWIPS_PER_INCH);
//picw seems to be ok for storing tag
// Append values to RTF string
_rtf.Append(@"{\pict\wmetafile8");
//If these are present then it causes a scaling issue
//with the sautinsoft control when you open the image in ayanova
//after saving it
//_rtf.Append(@"\picw");
//_rtf.Append(picw);
//_rtf.Append(@"\pich");
//_rtf.Append(pich);
_rtf.Append(@"\picwgoal");
_rtf.Append(picwgoal);
_rtf.Append(@"\pichgoal");
_rtf.Append(pichgoal);
_rtf.Append(" ");
return _rtf.ToString();
}
///
/// Use the EmfToWmfBits function in the GDI+ specification to convert a
/// Enhanced Metafile to a Windows Metafile
///
///
/// A handle to the Enhanced Metafile to be converted
///
///
/// The size of the buffer used to store the Windows Metafile bits returned
///
///
/// An array of bytes used to hold the Windows Metafile bits returned
///
///
/// The mapping mode of the image. This control uses MM_ANISOTROPIC.
///
///
/// Flags used to specify the format of the Windows Metafile returned
///
[DllImportAttribute("gdiplus.dll")]
private static extern uint GdipEmfToWmfBits(IntPtr _hEmf, uint _bufferSize,
byte[] _buffer, int _mappingMode, EmfToWmfBitsFlags _flags);
///
/// Wraps the image in an Enhanced Metafile by drawing the image onto the
/// graphics context, then converts the Enhanced Metafile to a Windows
/// Metafile, and finally appends the bits of the Windows Metafile in HEX
/// to a string and returns the string.
///
///
///
/// A string containing the bits of a Windows Metafile in HEX
///
private string GetRtfImage(Image _image)
{
StringBuilder _rtf = null;
// Used to store the enhanced metafile
MemoryStream _stream = null;
// Used to create the metafile and draw the image
Graphics _graphics = null;
// The enhanced metafile
Metafile _metaFile = null;
// Handle to the device context used to create the metafile
IntPtr _hdc;
try
{
_rtf = new StringBuilder();
_stream = new MemoryStream();
// Get a graphics context from the RichTextBox
using (_graphics = this.CreateGraphics())
{
// Get the device context from the graphics context
_hdc = _graphics.GetHdc();
// Create a new Enhanced Metafile from the device context
_metaFile = new Metafile(_stream, _hdc);
// Release the device context
_graphics.ReleaseHdc(_hdc);
}
// Get a graphics context from the Enhanced Metafile
using (_graphics = Graphics.FromImage(_metaFile))
{
// Draw the image on the Enhanced Metafile
_graphics.DrawImage(_image, new Rectangle(0, 0, _image.Width, _image.Height));
}
// Get the handle of the Enhanced Metafile
IntPtr _hEmf = _metaFile.GetHenhmetafile();
// A call to EmfToWmfBits with a null buffer return the size of the
// buffer need to store the WMF bits. Use this to get the buffer
// size.
uint _bufferSize = GdipEmfToWmfBits(_hEmf, 0, null, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
// Create an array to hold the bits
byte[] _buffer = new byte[_bufferSize];
// A call to EmfToWmfBits with a valid buffer copies the bits into the
// buffer an returns the number of bits in the WMF.
uint _convertedSize = GdipEmfToWmfBits(_hEmf, _bufferSize, _buffer, MM_ANISOTROPIC,
EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault);
// Append the bits to the RTF string
for (int i = 0; i < _buffer.Length; ++i)
{
_rtf.Append(String.Format("{0:x2}", _buffer[i]));
}
return _rtf.ToString();
}
finally
{
if (_graphics != null)
_graphics.Dispose();
if (_metaFile != null)
_metaFile.Dispose();
if (_stream != null)
_stream.Close();
}
}
#endregion
#region RTF Helpers
///
/// Creates a font table from a font object. When an Insert or Append
/// operation is performed a font is either specified or the default font
/// is used. In any case, on any Insert or Append, only one font is used,
/// thus the font table will always contain a single font. The font table
/// should have the form ...
///
/// {\fonttbl{\f0\[FAMILY]\fcharset0 [FONT_NAME];}
///
///
///
private string GetFontTable(Font _font)
{
StringBuilder _fontTable = new StringBuilder();
// Append table control string
_fontTable.Append("{\\fonttbl{\\f0");
_fontTable.Append("\\");
// If the font's family corresponds to an RTF family, append the
// RTF family name, else, append the RTF for unknown font family.
if (rtfFontFamily.ContainsKey(_font.FontFamily.Name))
{
_fontTable.Append(rtfFontFamily[_font.FontFamily.Name]);
}
else
{
_fontTable.Append(rtfFontFamily[FF_UNKNOWN]);
}
// \fcharset specifies the character set of a font in the font table.
// 0 is for ANSI.
_fontTable.Append("\\fcharset0 ");
// Append the name of the font
_fontTable.Append(_font.Name);
// Close control string
_fontTable.Append(";}}");
return _fontTable.ToString();
}
///
/// Creates a font table from the RtfColor structure. When an Insert or Append
/// operation is performed, _textColor and _backColor are either specified
/// or the default is used. In any case, on any Insert or Append, only three
/// colors are used. The default color of the RichTextBox (signified by a
/// semicolon (;) without a definition), is always the first color (index 0) in
/// the color table. The second color is always the text color, and the third
/// is always the highlight color (color behind the text). The color table
/// should have the form ...
///
/// {\colortbl ;[TEXT_COLOR];[HIGHLIGHT_COLOR];}
///
///
///
///
///
private string GetColorTable(RtfColor _textColor, RtfColor _backColor)
{
StringBuilder _colorTable = new StringBuilder();
// Append color table control string and default font (;)
_colorTable.Append(@"{\colortbl ;");
// Append the text color
_colorTable.Append(rtfColor[_textColor]);
_colorTable.Append(@";");
// Append the highlight color
_colorTable.Append(rtfColor[_backColor]);
_colorTable.Append(@";}\n");
return _colorTable.ToString();
}
///
/// Called by overrided RichTextBox.Rtf accessor.
/// Removes the null character from the RTF. This is residue from developing
/// the control for a specific instant messaging protocol and can be ommitted.
///
///
/// RTF without null character
private string RemoveBadChars(string _originalRtf)
{
return _originalRtf.Replace("\0", "");
}
#endregion
#region Printing
//Convert the unit used by the .NET framework (1/100 inch)
//and the unit used by Win32 API calls (twips 1/1440 inch)
private const double anInch = 14.4;
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct CHARRANGE
{
public int cpMin; //First character of range (0 for start of doc)
public int cpMax; //Last character of range (-1 for end of doc)
}
[StructLayout(LayoutKind.Sequential)]
private struct FORMATRANGE
{
public IntPtr hdc; //Actual DC to draw on
public IntPtr hdcTarget; //Target DC for determining text formatting
public RECT rc; //Region of the DC to draw to (in twips)
public RECT rcPage; //Region of the whole DC (page size) (in twips)
public CHARRANGE chrg; //Range of text to draw (see earlier declaration)
}
private const int WM_USER = 0x0400;
private const int EM_FORMATRANGE = WM_USER + 57;
[DllImport("USER32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
// Render the contents of the RichTextBox for printing
// Return the last character printed + 1 (printing start from this point for next page)
public int Print(int charFrom, int charTo, PrintPageEventArgs e)
{
//Calculate the area to render and print
RECT rectToPrint;
rectToPrint.Top = (int)(e.MarginBounds.Top * anInch);
rectToPrint.Bottom = (int)(e.MarginBounds.Bottom * anInch);
rectToPrint.Left = (int)(e.MarginBounds.Left * anInch);
rectToPrint.Right = (int)(e.MarginBounds.Right * anInch);
//Calculate the size of the page
RECT rectPage;
rectPage.Top = (int)(e.PageBounds.Top * anInch);
rectPage.Bottom = (int)(e.PageBounds.Bottom * anInch);
rectPage.Left = (int)(e.PageBounds.Left * anInch);
rectPage.Right = (int)(e.PageBounds.Right * anInch);
IntPtr hdc = e.Graphics.GetHdc();
FORMATRANGE fmtRange;
fmtRange.chrg.cpMax = charTo; //Indicate character from to character to
fmtRange.chrg.cpMin = charFrom;
fmtRange.hdc = hdc; //Use the same DC for measuring and rendering
fmtRange.hdcTarget = hdc; //Point at printer hDC
fmtRange.rc = rectToPrint; //Indicate the area on page to print
fmtRange.rcPage = rectPage; //Indicate size of page
IntPtr res = IntPtr.Zero;
IntPtr wparam = IntPtr.Zero;
wparam = new IntPtr(1);
//Get the pointer to the FORMATRANGE structure in memory
IntPtr lparam = IntPtr.Zero;
lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange));
Marshal.StructureToPtr(fmtRange, lparam, false);
//Send the rendered data for printing
res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam);
//Free the block of memory allocated
Marshal.FreeCoTaskMem(lparam);
//Release the device context handle obtained by a previous call
e.Graphics.ReleaseHdc(hdc);
//Return last + 1 character printer
return res.ToInt32();
}
#endregion
#region Link Clicked
void MudRichTextBox_LinkClicked(object sender, LinkClickedEventArgs e)
{
// Call Process.Start method to open a browser
// with link text as URL.
System.Diagnostics.Process.Start(e.LinkText);
}
#endregion
#region WndProc
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_VSCROLL:
base.WndProc(ref m);
if ((m.WParam.ToInt32() & 0xffff) == SB_THUMBTRACK)
{
OnVScroll(EventArgs.Empty);
}
if ((m.WParam.ToInt32() & 0xffff) == SB_THUMBPOSITION)
{
OnVScroll(EventArgs.Empty);
}
break;
case WM_HSCROLL:
base.WndProc(ref m);
if ((m.WParam.ToInt32() & 0xffff) == SB_THUMBTRACK)
{
OnHScroll(EventArgs.Empty);
}
if ((m.WParam.ToInt32() & 0xffff) == SB_THUMBPOSITION)
{
OnHScroll(EventArgs.Empty);
}
break;
default:
base.WndProc(ref m);
break;
}
}
#endregion
#region Command keys
protected override bool ProcessCmdKey(ref Message m, Keys keyData)
{
if (keyData == (Keys.Control | Keys.V) || keyData==(Keys.Control | Keys.X))
return true;
else
return base.ProcessCmdKey(ref m, keyData);
}
#endregion
#region Custom arbitrary hyperlinks
//requried for custom hyperlinks below
private const UInt32 CFM_LINK = 0x00000020;
private const UInt32 CFE_LINK = 0x0020;
//http://www.codeproject.com/KB/edit/RichTextBoxLinks.aspx
///
/// Insert a given text as a link into the RichTextBox at the current insert position.
///
/// Text to be inserted
public void InsertLink(string text)
{
InsertLink(text, this.SelectionStart);
}
///
/// Insert a given text at a given position as a link.
///
/// Text to be inserted
/// Insert position
public void InsertLink(string text, int position)
{
if (position < 0 || position > this.Text.Length)
throw new ArgumentOutOfRangeException("position");
this.SelectionStart = position;
this.SelectedText = text;
this.Select(position, text.Length);
this.SetSelectionLink(true);
this.Select(position + text.Length, 0);
}
///
/// Insert a given text at at the current input position as a link.
/// The link text is followed by a hash (#) and the given hyperlink text, both of
/// them invisible.
/// When clicked on, the whole link text and hyperlink string are given in the
/// LinkClickedEventArgs.
///
/// Text to be inserted
/// Invisible hyperlink string to be inserted
public void InsertLink(string text, string hyperlink)
{
InsertLink(text, hyperlink, this.SelectionStart);
}
///
/// Insert a given text at a given position as a link. The link text is followed by
/// a hash (#) and the given hyperlink text, both of them invisible.
/// When clicked on, the whole link text and hyperlink string are given in the
/// LinkClickedEventArgs.
///
/// Text to be inserted
/// Invisible hyperlink string to be inserted
/// Insert position
public void InsertLink(string text, string hyperlink, int position)
{
if (position < 0 || position > this.Text.Length)
throw new ArgumentOutOfRangeException("position");
//string startLinkStr = @"LINKSTART";
//string endLinkStr = @"#LINKEND";
//int linkStartPos = position - startLinkStr.Length;
//this.SelectionStart = position;
//this.SelectedRtf = @"{\rtf1\ansi\v LINKSTART\v0" + text + @"\v #" + hyperlink + @"#LINKEND\v0}";
//this.Select(position, text.Length + hyperlink.Length + 1 + endLinkStr.Length + startLinkStr.Length);
//this.SetSelectionLink(true);
//this.SelectionProtected = true;
//this.Select(position + text.Length + hyperlink.Length + 1, 0);
//Original
this.SelectionStart = position;
this.SelectedRtf = @"{\rtf1\ansi " + text + @"\v #" + hyperlink + @"\v0}";
this.Select(position, text.Length + hyperlink.Length + 1);
this.SetSelectionLink(true);
this.Select(position + text.Length + hyperlink.Length + 1, 0);
}
public void ShowLinks()
{
int curPos = 0;
string startTextStr = "LINKSTART";
string endTextStr = "#";
string endLinkStr = "#LINKEND";
while (RtfHasMoreLinks(curPos))
{
// Find hidden link text
int sPos = this.Text.IndexOf(startTextStr, curPos);
int hStartIndex = sPos;
sPos += startTextStr.Length;
int ePos = this.Text.IndexOf(endTextStr, sPos);
// Now we have the text of link
string linkText = this.Text.Substring(sPos, (ePos - sPos));
// Get the start position of link
int sLinkPos = ePos + endTextStr.Length;
int eLinkPos = this.Text.IndexOf(endLinkStr, sPos);
// The link
string hLink = this.Text.Substring(sLinkPos, (eLinkPos - sLinkPos));
int hEndIndex = eLinkPos + endLinkStr.Length;
// Show the link in box
ShowDistinctLink(hStartIndex, hEndIndex, linkText, hLink);
// Save the current end post at current position
curPos = eLinkPos;
}
}
private bool RtfHasMoreLinks(int curPos)
{
return (this.Text.IndexOf("LINKSTART", curPos) > curPos ? true : false);
}
private void ShowDistinctLink(int sPos, int ePos, string displayText, string hyperlink)
{
if (sPos < 0 || sPos > ePos)
throw new ArgumentOutOfRangeException("position");
this.Select(sPos, (ePos - sPos));
this.SetSelectionLink(true);
this.Select(sPos + displayText.Length + hyperlink.Length + 1, 0);
}
///
/// Set the current selection's link style
///
/// true: set link style, false: clear link style
public void SetSelectionLink(bool link)
{
SetSelectionStyle(CFM_LINK, link ? CFE_LINK : 0);
}
///
/// Get the link style for the current selection
///
/// 0: link style not set, 1: link style set, -1: mixed
public int GetSelectionLink()
{
return GetSelectionStyle(CFM_LINK, CFE_LINK);
}
private void SetSelectionStyle(UInt32 mask, UInt32 effect)
{
CHARFORMAT2 cf = new CHARFORMAT2();
cf.cbSize = Marshal.SizeOf(cf);
cf.dwMask = mask;
cf.dwEffects = effect;
IntPtr wpar = new IntPtr(SCF_SELECTION);
IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lpar, false);
IntPtr res = SendMessage(Handle, EM_SETCHARFORMAT, wpar, lpar);
Marshal.FreeCoTaskMem(lpar);
}
private int GetSelectionStyle(UInt32 mask, UInt32 effect)
{
CHARFORMAT2 cf = new CHARFORMAT2();
cf.cbSize = Marshal.SizeOf(cf);
cf.szFaceName = new char[32];
IntPtr wpar = new IntPtr(SCF_SELECTION);
IntPtr lpar = Marshal.AllocCoTaskMem(Marshal.SizeOf(cf));
Marshal.StructureToPtr(cf, lpar, false);
IntPtr res = SendMessage(Handle, EM_GETCHARFORMAT, wpar, lpar);
cf = (CHARFORMAT2)Marshal.PtrToStructure(lpar, typeof(CHARFORMAT2));
int state;
// dwMask holds the information which properties are consistent throughout the selection:
if ((cf.dwMask & mask) == mask)
{
if ((cf.dwEffects & effect) == effect)
state = 1;
else
state = 0;
}
else
{
state = -1;
}
Marshal.FreeCoTaskMem(lpar);
return state;
}
#endregion
}
///
/// This class contains all the scroll bar information.
///
public class ScrollBarInformation
{
#region scrollbarinformation
int nMin = 0;
int nMax = 0;
int nPage = 0;
int nPos = 0;
int nTrackPos = 0;
///
/// Sets up an empty scroll bar information class.
///
public ScrollBarInformation()
{
}
///
/// This sets up the scroll bar information with all the basic details.
///
/// the minimum size
/// the maximum size
/// the size of the page
/// the position of the thingy
/// this is updated while the scroll bar is wiggling up and down.
public ScrollBarInformation(int min, int max, int page, int pos, int trackpos)
{
this.nMin = min;
this.nMax = max;
this.nPage = page;
this.nPos = pos;
this.nTrackPos = trackpos;
}
///
/// Specifies the minimum scrolling position.
///
/// the minimum scrolling position
public int Minimum
{
get { return nMin; }
set { nMin = value; }
}
///
/// Specifies the maximum scrolling position.
///
/// the maximum scrolling position
public int Maximum
{
get { return nMax; }
set { nMax = value; }
}
///
/// Specifies the page size. A scroll bar uses this value to determine the
/// appropriate size of the proportional scroll box.
///
///
public int Page
{
get { return nPage; }
set { nPage = value; }
}
///
/// The position of the thumb inside the scroll bar.
///
///
public int Position
{
get { return nPos; }
set { nPos = value; }
}
///
/// Specifies the immediate position of a scroll box that the user is dragging.
/// An application can retrieve this value while processing the SB_THUMBTRACK
/// request code. An application cannot set the immediate scroll position; the
/// SetScrollInfo function ignores this member.
///
/// the immediated position of the scroll box
public int TrackPosition
{
get { return nTrackPos; }
set { nTrackPos = value; }
}
#endregion
}
}