对 WebMatrix 进行现代化改造, 使其完美支持中文

先插一段小广告为下文做铺垫



我一直觉得WebMatrix是一个很不错的ASP.NET开发工具, 虽然这个小软件是在遥远的 v1.x 年代的产品, 但功能齐全, 使用方便,
而且个头小, 安装后总共才2.8M的个头(想想Web Developer Express的个头), 自带一个服务器,
安装后还可以直接把程序目录拷贝到U盘里随身携带, 非常适合那些自己没有电脑但又想学习ASP.NET开发的童鞋(我以前大学时没买电脑前就是这么干的啦).
不过它有个很大的缺点, 就是不能很好的支持中文. 在文本编辑器里输入中文后, 光标显示的位置不对.... 一个对策就是不输入中文就好啦, 顺便还可以锻炼英文
:-)


最近一直在研究WebMatrix, 为什么要研究它? 有几个目的和原因:



  1. 学习如何设计并实现一个结构良好且有扩展性的程序
  2. 学习如何从零开始实现一个代码编辑器
  3. WebMatrix这个程序功能齐全, 具有一定扩展性(支持插件), 个头不大不小(核心部分估计有50000行左右代码, 花一两个星期摸透, 非常适合进行研究
  4. 这是微软出品的, 就算程序设计的不是很完美, 但至少不会是错误的
  5. 响应上面的小广告, 对其进行改造, 使其能够完美支持中文


我花了大概一个星期左右, 基本摸清了整个程序的结构和流程, 发现其实这个程序设计的还是很不错的. 各模块职责分明, 配合良好,
扩展性很强也很容易进行扩展, 非常符合 "对修改关闭, 对扩展开放" 这个软件设计思想.


对程序研究得比较清楚之后, 最主要的任务就是对其进行改造, 使其能够完美支持中文啦.
经研究发现, WebMatrix里的文本编辑器在输出文本时, 使用了一个固定的字符宽度(杯具的开始), 这个固定宽度在仅仅使用英文时是没有问题的,
但是如果有中文(或其他非拉丁系文字), 就会出problems了: 计算出来的文本宽度不对, 这个就直接导致了两个问题:



  1. 当前文本行里的光标位置不对
  2. 被选中部分的文字显示不正常

如图:


image



经研究代码, 要修改的地方主要有两个:



  1. TextView.UpdateCaretPosition(...)    //目的是修正当前文本行里的光标位置
  2. 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~~, 如图:


image



然而...咚的一声, 美梦惊醒.....


image



2点了....我之前发了誓要2点之前睡觉的.....好吧, 预知后事如何, 请听下文分解


Written by: 麦壳 2010.01.15 01:59



PS: 刚发现文中数字有点错误...修正之



原创文章, 非商业转载可自由转载, 但必须注明作者和连接. 商业转载, 嗯, 虽然不可能, 但还是要说: 商业转载请征求作者同意.


原文:http://www.cnblogs.com/badder/archive/2010/01/15/1648220.html

posted @   thinksea  阅读(157)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· 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 让容器管理更轻松!
点击右上角即可分享
微信分享提示