📄 exrichtextbox.cs
字号:
// 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 插入Link
#region Interop-Defines
[ StructLayout( LayoutKind.Sequential )]
private struct CHARFORMAT2_STRUCT
{
public UInt32 cbSize;
public UInt32 dwMask;
public UInt32 dwEffects;
public Int32 yHeight;
public Int32 yOffset;
public Int32 crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public char[] szFaceName;
public UInt16 wWeight;
public UInt16 sSpacing;
public int crBackColor; // Color.ToArgb() -> int
public int lcid;
public int dwReserved;
public Int16 sStyle;
public Int16 wKerning;
public byte bUnderlineType;
public byte bAnimation;
public byte bRevAuthor;
public byte bReserved1;
}
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
private const int WM_USER = 0x0400;
private const int EM_GETCHARFORMAT = WM_USER+58;
private const int EM_SETCHARFORMAT = WM_USER+68;
private const int SCF_SELECTION = 0x0001;
private const int SCF_WORD = 0x0002;
private const int SCF_ALL = 0x0004;
#region CHARFORMAT2 Flags
private const UInt32 CFE_BOLD = 0x0001;
private const UInt32 CFE_ITALIC = 0x0002;
private const UInt32 CFE_UNDERLINE = 0x0004;
private const UInt32 CFE_STRIKEOUT = 0x0008;
private const UInt32 CFE_PROTECTED = 0x0010;
private const UInt32 CFE_LINK = 0x0020;
private const UInt32 CFE_AUTOCOLOR = 0x40000000;
private const UInt32 CFE_SUBSCRIPT = 0x00010000; /* Superscript and subscript are */
private const UInt32 CFE_SUPERSCRIPT= 0x00020000; /* mutually exclusive */
private const int CFM_SMALLCAPS = 0x0040; /* (*) */
private const int CFM_ALLCAPS = 0x0080; /* Displayed by 3.0 */
private const int CFM_HIDDEN = 0x0100; /* Hidden by 3.0 */
private const int CFM_OUTLINE = 0x0200; /* (*) */
private const int CFM_SHADOW = 0x0400; /* (*) */
private const int CFM_EMBOSS = 0x0800; /* (*) */
private const int CFM_IMPRINT = 0x1000; /* (*) */
private const int CFM_DISABLED = 0x2000;
private const int CFM_REVISED = 0x4000;
private const int CFM_BACKCOLOR = 0x04000000;
private const int CFM_LCID = 0x02000000;
private const int CFM_UNDERLINETYPE = 0x00800000; /* Many displayed by 3.0 */
private const int CFM_WEIGHT = 0x00400000;
private const int CFM_SPACING = 0x00200000; /* Displayed by 3.0 */
private const int CFM_KERNING = 0x00100000; /* (*) */
private const int CFM_STYLE = 0x00080000; /* (*) */
private const int CFM_ANIMATION = 0x00040000; /* (*) */
private const int CFM_REVAUTHOR = 0x00008000;
private const UInt32 CFM_BOLD = 0x00000001;
private const UInt32 CFM_ITALIC = 0x00000002;
private const UInt32 CFM_UNDERLINE = 0x00000004;
private const UInt32 CFM_STRIKEOUT = 0x00000008;
private const UInt32 CFM_PROTECTED = 0x00000010;
private const UInt32 CFM_LINK = 0x00000020;
private const UInt32 CFM_SIZE = 0x80000000;
private const UInt32 CFM_COLOR = 0x40000000;
private const UInt32 CFM_FACE = 0x20000000;
private const UInt32 CFM_OFFSET = 0x10000000;
private const UInt32 CFM_CHARSET = 0x08000000;
private const UInt32 CFM_SUBSCRIPT = CFE_SUBSCRIPT | CFE_SUPERSCRIPT;
private const UInt32 CFM_SUPERSCRIPT= CFM_SUBSCRIPT;
private const byte CFU_UNDERLINENONE = 0x00000000;
private const byte CFU_UNDERLINE = 0x00000001;
private const byte CFU_UNDERLINEWORD = 0x00000002; /* (*) displayed as ordinary underline */
private const byte CFU_UNDERLINEDOUBLE = 0x00000003; /* (*) displayed as ordinary underline */
private const byte CFU_UNDERLINEDOTTED = 0x00000004;
private const byte CFU_UNDERLINEDASH = 0x00000005;
private const byte CFU_UNDERLINEDASHDOT = 0x00000006;
private const byte CFU_UNDERLINEDASHDOTDOT = 0x00000007;
private const byte CFU_UNDERLINEWAVE = 0x00000008;
private const byte CFU_UNDERLINETHICK = 0x00000009;
private const byte CFU_UNDERLINEHAIRLINE = 0x0000000A; /* (*) displayed as ordinary underline */
#endregion
#endregion
/// <summary>
/// Insert a given text as a link into the RichTextBox at the current insert position.
/// </summary>
/// <param name="text">Text to be inserted</param>
public void InsertLink(string text)
{
InsertLink(text, this.SelectionStart);
}
/// <summary>
/// Insert a given text at a given position as a link.
/// </summary>
/// <param name="text">Text to be inserted</param>
/// <param name="position">Insert position</param>
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);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="text">Text to be inserted</param>
/// <param name="hyperlink">Invisible hyperlink string to be inserted</param>
public void InsertLink(string text, string hyperlink)
{
InsertLink(text, hyperlink, this.SelectionStart);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="text">Text to be inserted</param>
/// <param name="hyperlink">Invisible hyperlink string to be inserted</param>
/// <param name="position">Insert position</param>
public void InsertLink(string text, string hyperlink, int position)
{
if (position < 0 || position > this.Text.Length)
throw new ArgumentOutOfRangeException("position");
this.SelectionStart = position;
this.SelectedRtf = @"{\rtf1\ansi\ "+text+@"\v #"+hyperlink+@"\v0}";
//@"par\qj\kerning2\f0\fs21 bb{\field{\*\fldinst{HYPERLINK "0001"}";
this.Select(position, text.Length + hyperlink.Length + 1);
this.SetSelectionLink(true);
this.Select(position + text.Length + hyperlink.Length + 1, 0);
}
/// <summary>
/// Set the current selection's link style
/// </summary>
/// <param name="link">true: set link style, false: clear link style</param>
public void SetSelectionLink(bool link)
{
SetSelectionStyle(CFM_LINK, link ? CFE_LINK : 0);
}
/// <summary>
/// Get the link style for the current selection
/// </summary>
/// <returns>0: link style not set, 1: link style set, -1: mixed</returns>
public int GetSelectionLink()
{
return GetSelectionStyle(CFM_LINK, CFE_LINK);
}
private void SetSelectionStyle(UInt32 mask, UInt32 effect)
{
CHARFORMAT2_STRUCT cf = new CHARFORMAT2_STRUCT();
cf.cbSize = (UInt32)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_STRUCT cf = new CHARFORMAT2_STRUCT();
cf.cbSize = (UInt32)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_STRUCT)Marshal.PtrToStructure(lpar, typeof(CHARFORMAT2_STRUCT));
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
#region RTF Helpers
/// <summary>
/// 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];}
/// </summary>
/// <param name="_font"></param>
/// <returns></returns>
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.Contains(_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();
}
/// <summary>
/// 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];}
///
/// </summary>
/// <param name="_textColor"></param>
/// <param name="_backColor"></param>
/// <returns></returns>
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();
}
/// <summary>
/// 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.
/// </summary>
/// <param name="_originalRtf"></param>
/// <returns>RTF without null character</returns>
private string RemoveBadChars(string _originalRtf)
{
return _originalRtf.Replace("\0", "");
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -