Files
wg_cpso/UserControls/TextBoxes/AnnotationEditorRichTextBox.cs

185 lines
7.2 KiB
C#
Raw Normal View History

2026-03-25 18:20:24 +08:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
namespace UserControls
{
[StructLayout(LayoutKind.Sequential)]
public 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;
// PARAFORMAT2 from here onwards
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;
}
public class AnnotationEditorRichTextBox : RichTextBox
{
// DllImports
const int PFM_SPACEBEFORE = 0x00000040;
const int PFM_SPACEAFTER = 0x00000080;
const int PFM_LINESPACING = 0x00000100;
const int SCF_SELECTION = 1;
const int EM_SETPARAFORMAT = 1095;
//
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref PARAFORMAT lParam);
// Scroll
private const UInt32 SB_TOP = 0x6;
private const UInt32 WM_VSCROLL = 0x115;
//
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
// Variables
private bool _beep;
private Size _minSize;
private Size _maxSize;
// Properties
public bool Beep { get { return _beep; } set { _beep = value; } }
public Size MinSize
{
get { return _minSize; }
set
{
_minSize = value;
if (Width < _minSize.Width) Size = new Size(_minSize.Width, Height);
if (Height < _minSize.Height) Size = new Size(Width, _minSize.Height);
}
}
public Size MaxSize
{
get { return _maxSize; }
set
{
_maxSize = value;
if (Width > _maxSize.Width) Size = new Size(_maxSize.Width, Height);
if (Height > _maxSize.Height) Size = new Size(Width, _maxSize.Height);
}
}
public new string Text
{
get { return base.Text; }
set
{
base.Text = value;
SetLineFormat(5, 23);
}
}
// Constructors
public AnnotationEditorRichTextBox()
{
_beep = false;
}
// Methods
/// <summary>
///
/// </summary>
/// <param name="rule">
/// 0 - Single spacing.The dyLineSpacing member is ignored.
/// 1 - One - and - a - half spacing.The dyLineSpacing member is ignored.
/// 2 - Double spacing.The dyLineSpacing member is ignored.
/// 3 - The dyLineSpacing member specifies the spacing from one line to the next, in twips.However, if dyLineSpacing
/// specifies a value that is less than single spacing, the control displays single - spaced text.
/// 4 - The dyLineSpacing member specifies the spacing from one line to the next, in twips.The control uses the exact
/// spacing specified, even if dyLineSpacing specifies a value that is less than single spacing.
/// 5 - The value of dyLineSpacing / 20 is the spacing, in lines, from one line to the next. Thus, setting
/// dyLineSpacing to 20 produces single-spaced text, 40 is double spaced, 60 is triple spaced, and so on.
/// </param>
/// <param name="space">Line spacing</param>
private void SetLineFormat(byte rule, int space)
{
PARAFORMAT fmt = new PARAFORMAT();
fmt.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(fmt);
fmt.dwMask = PFM_LINESPACING;
fmt.dyLineSpacing = space;
fmt.bLineSpacingRule = rule;
this.SelectAll();
SendMessage(new HandleRef(this, this.Handle), EM_SETPARAFORMAT, SCF_SELECTION, ref fmt);
//
this.SelectionLength = 0;
this.SelectionStart = 0;
}
//
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
Paste(DataFormats.GetFormat("Text"));
e.Handled = true;
}
//
if (!_beep)
{
if (GetLineFromCharIndex(SelectionStart) == 0 && (e.KeyData == Keys.Up || e.KeyData == Keys.PageUp))
e.Handled = true;
else if (GetLineFromCharIndex(SelectionStart) == GetLineFromCharIndex(TextLength) &&
(e.KeyData == Keys.Down || e.KeyData == Keys.PageDown))
e.Handled = true;
else if (SelectionStart == TextLength && (e.KeyData == Keys.Right || e.KeyData == Keys.End))
e.Handled = true;
else if (SelectionStart == 0 && (e.KeyData == Keys.Left || e.KeyData == Keys.Home))
e.Handled = true;
}
//
base.OnKeyDown(e);
}
protected override void OnVScroll(EventArgs e)
{
// Prevents autoscroll
PostMessage(Handle, WM_VSCROLL, (IntPtr)SB_TOP, IntPtr.Zero);
//
base.OnVScroll(e);
}
protected override void OnTextChanged(EventArgs e)
{
Size size = GetPreferredSize(Size.Empty);
Size newSize = new Size((int)(size.Width * 1.0), (int)(size.Height * 1.15));
//
if (newSize.Width < _minSize.Width) newSize.Width = _minSize.Width;
if (newSize.Height < _minSize.Height) newSize.Height = _minSize.Height;
if (newSize.Width > _maxSize.Width) newSize.Width = _maxSize.Width;
if (newSize.Height > _maxSize.Height) newSize.Height = _maxSize.Height;
//
Size = newSize;
//
base.OnTextChanged(e);
}
}
}