PMEditwindows下的富文本框

联合创作 · 2023-09-28 02:12

一、在开始之前首先吐槽一下,本人是一个独立开发者,在中国独立开发者就代表一个比较苦逼的行业,特别是对底层东西进行开发者,尤其本人研究方向是编译器、解析器基本上没有公司要,所以出来做个独立开发者。作为独立开发者半年来唯一的感受就是挺孤单,好几个月没跟人说过话了,也许过几年不会说话了也不一定。

本来想找一个人出来一起进行合伙开发的,但是很多年来的寻寻觅觅却发现没有一个志同道合的,分析发现应该是中国的底层精神相差太远,可能跟信仰有关系。底层精神相差越多分歧也越多,所以超大工程很难去完成,分歧多野心也多所以内乱很容易产生。还有一种懒惰思想,像我们常见的望子成龙、望女成凤思想,归根结底就是一种懒惰思想,懒惰到自己期望的好生活、好地位却让子女去帮他们来实现,不敢去触碰和尝试在自己知识之外的高级领域,心里却超级向往,然后喜欢在别人成功了站在他们的后面或上面;所以遇到望子成龙、望女成凤思想的人见一个批一个。
    
还有一个就是金庸精神,在理性的意因子分析中金庸精神应该是被批判的;我称之为机会精神,总是在遇到一本绝世武功或一个绝世高手后得到真传然后一下子成为了绝世高手,然后不知不觉去炫耀,吸引了众多女猪脚,选择最合适最好的一个然后过上神仙般的生活。这种精神很容易发展成为一种机会主义,凡事靠运气,发现机会就往空子里钻,不管什么道德,不管什么精神;凡事追求一劳永逸,狠狠赚他一笔然后就安逸、炫耀与挥霍。从根源分析机会精神也是一种懒惰思想。其实我觉得生活就应该是每天都是新的,不一样、坚持相信、不断的挑战才是生活的本质。像什么共产主义、大同社会等理想生活其实就是变质的腐朽,什么都很美好、什么都很平静,那就是一潭死水慢慢就会发臭;有风有雨、变幻莫测才孕育了世间万物。像欧洲的高福利捆绑了他们的思维能力,他们永远都不可能像18、19世纪充满冒险家时代那样风光了。

在本人的开发生涯中发现中国程序员的水平是不足的,大部分人都只会埋头在自己模块的几个小分支下,同时出现4-5中情况基本还能能应付,当情况多到7-8个基本就手忙脚乱了,当情况具有10几个时达到极限就无法应付了,居然用一种随机的方法而不是系统的方法去处理这种边界问题,然后就在栈域效应下浪费时间,今天处理这两头道,明天又处理那两头道,后天又转回头,像迷宫永远找不到出路;最主要的还是态度问题,遇到问题了一点不着急下班还是掐秒下班该怎么放松还是怎么放松,也没有一种克服进化的思想。
        
也曾经遇到一种人A是A,B也是A,头脑永远不能分析和记忆成两种情况,所以头脑栈低于5是不适合于作为程序员的,遇到就赶紧让他回家生孩子去;代码界我认为聪明的人应该具有的一些因子是:1、思维能灵活跳跃 2、能够区分细微的细节 3、能够快速记忆 4、克服边界能够总体去看事情 5、能够很快将已有作为自己的知识基础  6、有敏锐的发现碰撞触觉  7、有自己独特的信奉及分析方法 8、有一定的完美的思想 9、不一样 10、耐心勤劳坚定

本文本框在3个月无人交流的苦闷开发下完成,PMEdit核心代码曾经进行了三次重构,终于得到一个比较稳定一点的版本,核心代码也从一万多行砍到5000多行,代码减少复杂度提高,很多情况本人都没有时间去测试,所以发出来让大家帮忙测试、交流一下,也提高一下代码水平。如果有什么问题可以发送邮件到feirench@gmail.com进行交流,由于没有拉网线所以可能不会很及时回复滴。

最后说一下本文本框的设计:


1、文本框代码量小只有5000多行,全部是核心代码
2、文本框的设计是为了给PMGrid表格作为文本输入用的,PMGrid是一个美丽的类似于Excel的富文本表格,由于此表格正在开发中暂时就不开源了,样例可以看看源代码中的PMGrid.exe,如果有需要也可以给我发邮件feirench@gmail.com。
3、文本框内存占用小,除了作为背景双缓存的几个bitmap,就只是几个int数据,所以内存还是很放心的
4、文本框通篇使用了json作为数据存储,Json具有强大的灵活性,如果是界面开发,将本文本框作为基本输入要素,都不需要数据结构了一个json搞定,将程序作为一个大的json,下面挂页面json,页面下挂多个文本框json就OK了。
5、本文本框的缺点就是没有做增量分析,导致数据量过大的时候会会影响编辑效果,但是5000行文本的编辑是完全可以搞定的,毕竟作为表格的输入数据量不会很大的,如果要实现更大数量级的编辑花费的功夫就需要成倍了,对于一个独立开发者来说可能就得不偿失了!
6、由于图片是全部加载到内存中,如果图片太多也会占用很大的内存
7、文本框未支持国际化,现在仅设计为中文环境中使用,版本二会进行改进
8、很大的特点就是支持在explore中复制文件然后粘贴到文本框中,支持两种类型文件的粘贴:纯文本、图片,支持多选
9、本文本框的Json是本人自己设计的扩展json类型TJSON,可以保存二进制数据,可以添加注释。它的效率应该还是不错的,易用性方面也非常不错,解析和读写参考了CJSON的源代码。开源的所有JSON解析源码中,性能最高的就应该是CJSON了,但是易用性方面也是最差的,可能300行的代码用CJSON就需要写上400行代码,有得也有失去。TJSON的数据量比较小,sizeof(TJSON)==40,并且具有遍历迭代器TJSONIterator、TJSONConstIterator,易用性就跟vector等容器一样;内部实现直接用的是map和vector,性能瓶颈也就是map、vector的性能瓶颈。

二、PMEdit是一个在windows下的富文本框,它能显示文字、编辑文字、显示图片、改变图片显示大小,具有行号、行图标、改变字体属性等特性。
PMEdit完成从底层开发,没有用任何windows控件,代码直接基于最基本GUI、windows消息,很容易移植到OpenGL或其他平台下。
源代码可以到http://www.natframe.com去下载。
特别感谢Davide Pizzolato大大(主页 http://www.xdp.it/)的CxImage让图片的开发变得非常简单。本代码开源免费,licensed等同zlib的license,任何人都可以随意修改和发布其中代码。


三、样例显示

A、文本编辑

B、图片显示

C、GIF动画展示

D、富文本显示

E、改变背景

F、表格的样例


四、结构说明
1、编辑框配置property.json,包括6个部分
  A、LAFERS,保存的是绘制滚动条的lafer json数据
  B、MAX_TEXT_FILE,保存的是当文本文件复制时能粘贴到本文本框的最大大小,默认是14000000字节
  C、TEXT_EXTS,保存文本文件复制时能粘贴到本文本框的文本文件类型
  D、PICTURE_EXTS,保存文本文件复制时能粘贴到本文本框的图片文件类型,支持的图片类型可以参照下面"\nPictures"中存储的说明
  E、SYSTEM_FONT,保存文本框系统字体,字体说明:
[
"宋体",//字体名称:face name
12,//字体大小
1,//粗体:0、1
0,//倾斜:0、1
0,//删除线:0、1
1,//下划线
8421504//字体颜色=RGB(R,G,B)
]

  F、EDIT_ATTRIBUTE,保存文本框的属性配置:
     [
0,//1、编辑框内容的类型  0普通编辑框,4显示行号,8具有行图标
0,//2、是否自动换行,0是自动换行(自动换行就不再具有水平滚动条),1不自动换行
0,//3、是否具有竖直滚动条,0是没有,1是有
0,//4、是否具有水平滚动条,0是没有,1是有
0,//5、是否可编辑
16777215,//6、文本框的背景颜色
15000804,//7、行号背景颜色
[
"宋体",//字体名称:face name
12,//字体大小
1,//粗体
0,//倾斜
0,//删除线
1,//下划线
8421504//字体颜色
],//8、行号字体
12632256,//选择字体的背景颜色
[3,2,2,3],//margin,左上右下
0,//可视的X
0,//可视的Y
1, //可视的行号
16, //行图标的宽度和高度
9  /*文本框的对齐方式,暂时只实现了top_left的对齐, 
TF_VTOP =0x0001,
TF_VCENTER =0x0002,
TF_VBOTTOM =0x0004,
TF_HLEFT =0x0008,
TF_HCENTER =0x0010,
TF_HRIGHT =0x0020*/
0,//字体水平间距
3,//字体行间距
168,//竖直滚动速度
39//水平滚动速度
]
2、保存的数据结构说明:
文本框使用JSON保存数据,结构为
{
"\nPictures"://保存图片的文件内容
{
"C288F22375B58757C9B15A2BFB5FEF6A": //图片的名称,用图片内容进行MD5计算得到,防止数据重复
[
5, /*图片的CxImage类型,包括:
CXIMAGE_FORMAT_BMP = 1,
CXIMAGE_FORMAT_GIF = 2,
CXIMAGE_FORMAT_JPG = 3,
CXIMAGE_FORMAT_PNG = 4,
CXIMAGE_FORMAT_ICO = 5,
CXIMAGE_FORMAT_TIF = 6,
CXIMAGE_FORMAT_TGA = 7,
CXIMAGE_FORMAT_PCX = 8,
CXIMAGE_FORMAT_WBMP = 9,
CXIMAGE_FORMAT_WMF = 10,
CXIMAGE_FORMAT_JP2 = 11,
CXIMAGE_FORMAT_JPC = 12,
CXIMAGE_FORMAT_PGX = 13,
CXIMAGE_FORMAT_PNM = 14,
CXIMAGE_FORMAT_RAS = 15,
CXIMAGE_FORMAT_JBG = 16,
CXIMAGE_FORMAT_MNG = 17,
CXIMAGE_FORMAT_SKA = 18,
CXIMAGE_FORMAT_RAW = 19,
CXIMAGE_FORMAT_PSD = 20,*/
B9062.... //图片的二进制内容
],
"3E550FEED5C6F1EBE0077903810DF743": [2, B186690....]
},
"EDIT_DATA"://保存文本框的数据内容
[
["fixedsys", 8, 0, 0, 0, 0, 10485920], 
"//***************************************", ["C288F22375B58757C9B15A2BFB5FEF6A"], "\r\n", 
["C288F22375B58757C9B15A2BFB5FEF6A"], ["3E550FEED5C6F1EBE0077903810DF743", 247, 170], "\r\n", 
"//***************************************", ["C288F22375B58757C9B15A2BFB5FEF6A"]
]
/*EDIT_DATA说明,包括四种类型数据:
1、数组["fixedsys", 8, 0, 0, 0, 0, 10485920]是内容的字体,可以设置其后面文本的字体颜色,直到遇到另外的字体,也可以是单独的数字10485920表示颜色改变
2、字符串"//***************************************"是文本内容
3、数组["C288F22375B58757C9B15A2BFB5FEF6A"]是行图标
4、数组["3E550FEED5C6F1EBE0077903810DF743", 247, 170]是内容显示图片
*/
}


显示结果为:


3、功能说明
A、显示文字
B、字体改变
C、显示图片包括GIF动画
D、显示行号
E、显示行图标
F、自动换行
G、文本选择
H、文本删除
I、文本添加
J、文本替换
K、图片大小显示改变
L、剪贴、粘贴文本
M、剪贴、粘贴图片,可以粘贴METAFILE成图片
O、光标移动,移动行首、行尾、上、下、左、右
P、双击文本选择
Q、移动光标选择
R、移动到开头
S、移动到末尾
T、往前、往后删除相同文本
U、上下翻页
V、在行号区域进行行选择
W、内容滚动,上下(鼠标滚轮),左右(按住shift+鼠标滚轮),滚动条
X、转跳器,在两滚动条夹角处,点击可以转跳相应区域,按住左键移动鼠标可以实现连续浏览
Y、撤销
Z、重做


五、滚动条说明:
滚动条的式样是由本人设计的lafer文法解释生成,主要是对UI界面实体分成一个个的组合帧,在生成UI控件实体界面时调用相应的帧进行显示,对UI界面具有比较自由的扩展性
1、ENTITY是最外层的一个完整的实体对象,比如表格外边框、竖直滚动条、系统按钮等,后面跟着的是名字
2、FRAME的是实体对象内其中一个绘制帧,像一些有动画效果的实体,后面跟着的是名字
3、Line代表画线的操作对象,内部操作对象如下面注释中的9种
4、Fill代表填充的操作对象,内部操作对象如下面注释中的9种
5、RECT表示位置范围
6、注释,文法和C++一样两种:A、行注释 B、多行注释


lafer使用方式为:
class PMLaferLexer
{
public:
TJSON *CreateLaferJson (const string &laferdata); //从lafer代码转化成JSON内存数据
string CreateLaferCode (TJSON &laferJson); //将内存lafer的json数据转化成lafer字符串
};
class ScreenGDI
{
public:
PMVoid   DrawLaferFrame (TJSON &laferJson,const IntRect &laferRect,const string &name);   //将lafer json数据按名称进行绘制到屏幕,laferJson为Entity实体json,name为FRAME帧名称
PMPicture* CreateLaferPicture(const IntSize &pictureSize,TJSON &laferJson,const string &name);//创建用来绘制lafer内容的图片,laferJson为Entity实体json,name为FRAME帧名称
};
//********************************************************************************
//文件:lafer文法  2012-11-22 12:39
//说明:
//  1、点用法:     POINT:宽度,颜色(R,G,B),坐标(x,y);  例如:POINT:1,(166,166,166),(0,0,-1,0);
//  2、线用法:     LINE:宽度,颜色(R,G,B),坐标(x,y,x1,y1); 
//  3、折线用法:   POLYLINE:宽度,颜色(R,G,B),坐标(x,y,x1,y1,x2,y2,...); 
//  4、三角形用法: TRIANGLE:宽度,颜色(R,G,B),填充颜色(R,G,B),坐标(x,y,x1,y1,x2,y2); 
//  5、矩形用法:   RECTANGLE:宽度,颜色(R,G,B),填充颜色(R,G,B),坐标(x,y,x1,y1); 
//  6、渐变色矩形用法:SMOOTINGRECT:方向(0或-0),填充颜色1(R,G,B),填充颜色2(R,G,B),坐标(x,y,x1,y1); 
//  7、多边形用法: POLYGON:宽度,颜色(R,G,B),填充颜色(R,G,B),坐标(x,y,x1,y1,x2,y2,...); 
//  8、椭圆用法:   ELLIPSE:宽度,颜色(R,G,B),填充颜色(R,G,B),坐标(x,y,x1,y1); 
//  9、扇形用法:   PIE:宽度,颜色(R,G,B),填充颜色(R,G,B),坐标(x,y,x1,y1,xr1,yr1,xr2,yr2); 
// 宽度说明:0为不绘制线条,0~1为按照宽度比例计算宽度,-1~0为按控件高度比例绘制宽度,其余为实际宽度
//  颜色说明:R、G、B在[0~255]之间,如果为-0为不绘制颜色
//  坐标说明:x——0为x原点,-0为x右边原点,(0~1)为左边开始的宽度比例坐标,(-1~0)为右边开始的宽度比例坐标,其余为实际坐标
//            y——0为y原点,-0为y下边原点,(0~1)为上边开始的宽度比例坐标,(-1~0)为下边开始的宽度比例坐标,其余为实际坐标
//********************************************************************************

浏览 6
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报