其实有很强大的“ICSharpCode.TextEditor”。在此之前我一直使用的ICSharpCode.TextEditor。
不过在使用ICSharpCode.TextEditor的时候遇到了些问题,这里闲扯下。
好多年前我用它写了一个c#辅助的脚本工具,系统是win7的。后来重装系统之后这个程序就运行不起来,不得已更换了TextBox控件。当时也没有在意。
最近写一个程序需要用到该控件,在WIN10下程序都已完成。然后放到XP和WIN7中跑不起来,后来调试了很久才发现是ICSharpCode.TextEditor是这个控件的问题。
不知道大家有没有遇到问题,或者是我使用的不恰当。如没有遇到,或者解决的可否告知。毕竟我这个控件和ICSharpCode.TextEditor不管是功能和性能上差别太大。
无奈之下不得不屈服,重新写一个文本控件。
这里介绍一个“FastColoredTextBox”文本控件,很遗憾的是该控件不支持中文。
下面介绍下XZ.Edit文本编辑控件
源码地址:https://github.com/zzbjuke/eidtText
简单介绍下:
整个页面上显示的数据来源于重绘。
C#无法绘制光标,所以要调用WIN32 API
#region 调用WIN32API
[DllImport("User32.dll")]
static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);
[DllImport("User32.dll")]
static extern bool SetCaretPos(int x, int y);
[DllImport("User32.dll")]
static extern bool DestroyCaret();
[DllImport("User32.dll")]
static extern bool ShowCaret(IntPtr hWnd);
[DllImport("User32.dll")]
static extern bool HideCaret(IntPtr hWnd);
[DllImport("imm32.dll")]
private static extern IntPtr ImmGetDefaultIMEWnd(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, COMPOSITIONFORM lParam);
[DllImport("Imm32.dll")]
public static extern IntPtr ImmGetContext(IntPtr hWnd);
[DllImport("Imm32.dll")]
public static extern IntPtr ImmAssociateContext(IntPtr hWnd, IntPtr hIMC);
#region 私有类
[StructLayout(LayoutKind.Sequential)]
private class COMPOSITIONFORM {
public int dwStyle = 0;
public POINT ptCurrentPos = null;
public RECT rcArea = null;
}
[StructLayout(LayoutKind.Sequential)]
private class POINT {
public int x = 0;
public int y = 0;
}
[StructLayout(LayoutKind.Sequential)]
private class RECT {
public int left = 0;
public int top = 0;
public int right = 0;
public int bottom = 0;
}
private void SetIMEWindowLocation(int x, int y) {
if (pIMEWnd == IntPtr.Zero)
return;
POINT p = new POINT();
p.x = x;
p.y = y;
COMPOSITIONFORM lParam = new COMPOSITIONFORM();
lParam.dwStyle = CFS_POINT;
lParam.ptCurrentPos = p;
lParam.rcArea = new RECT();
try {
SendMessage(
pIMEWnd,
WM_IME_CONTROL,
new IntPtr(IMC_SETCOMPOSITIONWINDOW),
lParam
);
}
catch (AccessViolationException ex) {
MessageBox.Show("调用 IME: " + ex.Message);
}
}
#endregion
#endregion
/// <summary>
/// 创建光标
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public bool Create() {
if (CreateCaret(this.pIEdit.GetHandle, 0, Width, FontContainer.FontHeight)) {
this.Show();
return true;
}
return false;
}
/// <summary>
/// 隐藏
/// </summary>
public void Hide() {
this.IsShowCurosr = false;
HideCaret(this.pIEdit.GetHandle);
}
/// <summary>
/// 显示
/// </summary>
public void Show() {
this.IsShowCurosr = true;
ShowCaret(this.pIEdit.GetHandle);
}
public void Dispose() {
this.IsShowCurosr = false;
DestroyCaret();
}
一定要重载WndProc 方法如下:
protected override void WndProc(ref Message m) {
if (m.Msg == CharCommand.WM_HSCROLL || m.Msg == CharCommand.WM_VSCROLL)
if (m.WParam.ToInt32() != CharCommand.SB_ENDSCROLL)
Invalidate();
base.WndProc(ref m);
if (ImeAllowed && m.Msg == CursorAndIME.WM_IME_SETCONTEXT && m.WParam.ToInt32() == 1)
this.PCursor.CreateImmAssociateContext();
}
因本人空余时间编写的,时间有限。部分功能并未完成,且存在着某些BUG。
代码难度不大,就是啰嗦。
目前多行注释中仍然有注释,未完成待续。