对 WebMatrix 进行现代化改造, 使其完美支持中文
先插一段小广告为下文做铺垫
我一直觉得WebMatrix是一个很不错的ASP.NET开发工具, 虽然这个小软件是在遥远的 v1.x 年代的产品, 但功能齐全, 使用方便,
而且个头小, 安装后总共才2.8M的个头(想想Web Developer Express的个头), 自带一个服务器,
安装后还可以直接把程序目录拷贝到U盘里随身携带, 非常适合那些自己没有电脑但又想学习ASP.NET开发的童鞋(我以前大学时没买电脑前就是这么干的啦).
不过它有个很大的缺点, 就是不能很好的支持中文. 在文本编辑器里输入中文后, 光标显示的位置不对.... 一个对策就是不输入中文就好啦, 顺便还可以锻炼英文
:-)
最近一直在研究WebMatrix, 为什么要研究它? 有几个目的和原因:
- 学习如何设计并实现一个结构良好且有扩展性的程序
- 学习如何从零开始实现一个代码编辑器
- WebMatrix这个程序功能齐全, 具有一定扩展性(支持插件), 个头不大不小(核心部分估计有50000行左右代码, 花一两个星期摸透, 非常适合进行研究
- 这是微软出品的, 就算程序设计的不是很完美, 但至少不会是错误的
- 响应上面的小广告, 对其进行改造, 使其能够完美支持中文
我花了大概一个星期左右, 基本摸清了整个程序的结构和流程, 发现其实这个程序设计的还是很不错的. 各模块职责分明, 配合良好,
扩展性很强也很容易进行扩展, 非常符合 "对修改关闭, 对扩展开放" 这个软件设计思想.
对程序研究得比较清楚之后, 最主要的任务就是对其进行改造, 使其能够完美支持中文啦.
经研究发现, WebMatrix里的文本编辑器在输出文本时, 使用了一个固定的字符宽度(杯具的开始), 这个固定宽度在仅仅使用英文时是没有问题的,
但是如果有中文(或其他非拉丁系文字), 就会出problems了: 计算出来的文本宽度不对, 这个就直接导致了两个问题:
- 当前文本行里的光标位置不对
- 被选中部分的文字显示不正常
如图:
经研究代码, 要修改的地方主要有两个:
- TextView.UpdateCaretPosition(...) //目的是修正当前文本行里的光标位置
- TextView.PaintTextLine(...) //目的是修正被选中文本的显示
为修正这两个问题, 我加了一个辅助函数
1: private Interop.SIZE MeasureString(char[] chars, int startIndex, int length)
2: {
3: IntPtr fontPtr = this.Font.ToHfont();
4: Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
5: IntPtr hdc = graphics.GetHdc();
6: Interop.SelectObject(hdc, fontPtr);
7: Interop.SIZE size = this.MeasureString(hdc, chars, startIndex, length);
8: Interop.SelectObject(hdc, IntPtr.Zero);
9: graphics.ReleaseHdc(hdc);
10: graphics.Dispose();
11: return size;
12: }
然后在TextView.UpdateCaretPosition(...) 里这么修改:
1: private void UpdateCaretPosition(bool checkForFocus)
2: {
3: if (((this.Focused || base.Parent.Focused) || !checkForFocus) && (this._paintFrozen == 0))
4: {
5: if (this._location.ColumnIndex > this._location.Line.Length)
6: {
7: this._location.ColumnIndex = this._location.Line.Length;
8: }
9:
10: //NOTE: 修改了更新光标位置的算法, 使其支持多字节文字
11: //把这一句
12: //int x = (((this._fontWidth * (this.GetViewIndex(this._location) - this.ViewLeftIndex)) + this.MarginPadding) + this.MarginWidth) + this._lineNumbersWidth;
13:
14: //改成
15: Interop.SIZE size = this.MeasureString(_location.Line.ToCharArray(), this.ViewLeftIndex, (this.GetViewIndex(this._location) - this.ViewLeftIndex));
16:
17: int x = size.x + this.MarginPadding + this.MarginWidth + this._lineNumbersWidth;
18: int y = (this._location.LineIndex - this.ViewTopLineNumber) * this._fontHeight;
19: Interop.SetCaretPos(x, y);
20: }
21: else
22: {
23: this._updateCaretOnPaint = true;
24: }
25: }
TextView.PaintTextLine(...)函数按照此法修改, 由于有接近10处调用, 就不一一列出来了,
有兴趣的同学可以下源码自己看.
修改完成后, 运行一下, 哈哈~ perfect~~, 如图:
然而...咚的一声, 美梦惊醒.....
2点了....我之前发了誓要2点之前睡觉的.....好吧, 预知后事如何, 请听下文分解
Written by: 麦壳 2010.01.15 01:59
PS: 刚发现文中数字有点错误...修正之
原创文章, 非商业转载可自由转载, 但必须注明作者和连接. 商业转载, 嗯, 虽然不可能, 但还是要说: 商业转载请征求作者同意.
原文:http://www.cnblogs.com/badder/archive/2010/01/15/1648220.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!