LCUI 0.14.0 开发日志

2013年03月11日  ·  25434 字  ·  阅读

2013-3-12

准备搞个游戏,已经有了素材,先弄个地图编辑器,把地图信息搞好并保存至文件,这样游戏就能载入并解析该文件,然后生成地图。

想在windows上搞,但是有个未解决的问题:不能正常读取png图片信息,到底需要修改哪里?

重新创建了一个VS2012项目,只复制之前的文件列表和筛选器,剩下的配置由自己重新设置。

写了个png测试程序,程序使用LCUI函数库,测试打开一个图片文件,打印的结果正常:channels=4,color_type=6,但使用graph2array测试程序load_png函数时,打印的结果是:channels=4,color_type=1780891744,什么情况?图片数据能正常读出来。记得在修改png.c文件前的测试中,打印的chnnels也是一个非常大的值,连图片数据都读不出。

代码已经提交,可到这里查看修改情况,只是修改了png.c,看起来代码没多大变化,我想知道这代码与之前的有什么区别?为啥改了后就能正常读png图片了?难道是项目配置的问题?

2013-3-13

定时器出了点问题,非要鼠标移动时,它才定时器的回调函数才会被调用,个人猜测是GetMessage函数的问题,它在LCUI的主循环里阻塞等待消息,导致LCUI的任务无法及时处理。

解决方法:用PeekMessage函数代替GetMessage函数即可,可以当成是GetMessage函数的非阻塞版本。

额,原来是忘记保存定时器的ID,调用reset_timer和free_timer函数时,传的值是-1,怪不得怎么没用。

修改了LAYOUT_TYPE枚举中各个宏定义的值,这是为了解决Graph_FillImage函数不能正常解析出布局方式的问题,传给Graph_FillImage函数的参数,有一个是保存了布局方式和图形混合方式,在进行与运算后,就能正常得出是哪一个布局方式。

地图图块 窗口中的各个按钮的定位类型是STATIC,但有点问题,linux下,第7个按钮要在我点窗口时才会显示,而在windows下,只显示4个按钮,奇怪。

2013-3-14

解决了一个BUG:主要独立出“位置更新”和“位置改变”这两种不同的操作,该BUG会导致部件位置无法正常调整,在未修改前,这两个操作可以相互覆盖,也就是Widget_Move任务被覆盖掉了。

修改后,STATIC定位类型的部件的位置处理在linux下是正常了,而在windows上,还是有问题,暂时不用这个功能自动调整部件坐标,自己另外加几段代码算出来。

2013-3-15

每次关闭LCUI的窗口时,程序都会出现“已停止工作”,无视也不是办法,还是先解决这个问题,调试时VisualStudio中有函数调用栈,能够定位BUG大致位置。

修改了一下主循环的代码。

改了后,LCUI程序一运行就会出现“已停止工作”,刚开始以为是偶然的问题,试了几次后,都是这问题,函数调用栈中表明是set_timer函数的问题,看了一下代码,唯一能引起问题的是LCUIApp_GetSelf()->id这段代码了,如果LCUIApp_GetSelf()得到的指针为NULL或无效,那么后面的->id就会出问题,数据访问越界。于是就改成LCUIApp_GetSelfID()

修复win32线程支持模块中存在的BUG:该BUG会导致在调用LCUIThread_Join函数时无法得到正确的线程句柄,访问了非法的内存地址。 现在,已经能够在Win32平台下正常退出程序了。

2013-3-16

新写的MapBox部件无法显示地图块,正打算往MapBox_CreateMap里添加Graph_PrintInfo函数调用,发现该函数居然对MapBox的地图资源进行初始化,这个操作应该在MapBox_ExecInit里执行的,这里居然也有,怪不得怎么不能绘制出地图。

还有问题,一绘制地图就会导致程序崩溃。

折腾了一段时间,发现下标异常,绘制第一张地图块,下标不是0,而是个很大的数。在添加用于调试的代码时,发现了问题原因,问题出在block[i]->id = 0上,编译器在编译时居然没给警告,改正后为:block[i][j]->id = 0。

改了一下窗口在未获得焦点时使用的背景色。

地图编辑器的源代码已经上传至GitHub:https://github.com/lc-soft/LCUI-2DMapEditor,Makefile之类的就没写了,直接gcc编译每个.c文件,最后在链接时把LCUI函数库链接进去就行了,Windows下的话,创建新项目,把它们添加进去,设置好头文件及库的目录位置,就能进行编译。

现在的地图编辑器还需要进行完善,具体功能需求如下:

  • 能响应鼠标移动和鼠标单击,当鼠标移动时,在鼠标游标覆盖的地图块上显示高亮边框,当点击鼠标左键时,更改该地图块的内容。
  • 对于大地图,能响应鼠标拖动,移动地图显示区域。
  • 需要添加一些按钮,以对地图块进行旋转和翻转。
  • 能够载入地图文件中的数据,也能将地图数据写入至文件中。

2013-3-16

完成了MapBox部件的鼠标移动事件的响应功能,鼠标游标移动至一块地图块上,该地图块就会有红色边框显示。调试过程中遇到的问题不难解决,在以前就遇到过不少次,只不过需要些时间罢了。

但是,坐标判断不准确,地图是菱形的,而判断时使用的是矩形,即使不在地图块菱形区域内,只要在该地块的矩形范围内,该地图块还是会显示红色边框。

2013-3-17

添加了地图块选定功能,以后添加的地图块翻转功能的操作对象就是被选中的地图块。

2013-3-18

话说,对于菱形地图块,旋转功能不适用,只需要水平翻转和垂直翻转功能。

完成了地图编辑器的基本功能,从“地图图块”窗口里选择地图块,然后在“地图编辑器”窗口中点击,即可将地图块贴至地图上。

添加了地图块水平翻转功能,Graph_HorizFlip函数不能处理引用图像,修改了一下它的代码,还需要为LCUI添加图像垂直翻转功能。

添加了两个按钮,用于对选中的地图块进行水平翻转和垂直翻转,起初想找现成的图片作为按钮图标,但还是算了,自己用PS画了两个简单的图。

2013-3-19

为LCUI添加了图像垂直翻转功能

地图块的垂直翻转功能已经完成,接下来需要添加地图尺寸调整功能,以及地图数据的保存和读取。

2013-3-20

按钮调整至标题栏,添加了地图尺寸调整窗口,但由于LCUI暂不能在windows下响应按键输入,因此不能往文本框里输入内容。

想把窗口搞成模态的,和MessageBox那样,但是,创建了个主循环后运行,整个程序就卡住了,奇怪,需要找问题原因。

添加了队列锁操作以保护程序任务队列,经测试,LCUI程序已经没之前那种时不时崩溃的问题了,至少不会很频繁。

鼠标输入处理模块需要调整,拖动窗口时释放左键后,并不会立刻停止窗口拖动。

2013-3-21

新建的MainLoop进入后卡住,其原因是之前加了任务队列锁,执行任务前没有解锁,而执行任务时进入主循环又对任务队列设置互斥锁,导致出现死锁,主循环就卡住了,BUG已修复

完善按键输入的话,感觉需要搞个输入法接口,参考了这篇文章:http://code.google.com/p/windows-config/wiki/Win32IME

2013-3-22

由于C盘没有足够的可用空间供更新程序下载补丁包,又考虑到编译的程序与XP的兼容性,于是决定卸载了VS2012,改装VS2010,反正VS2012的很多功能用不到,浪费了C盘可用空间。有现成的VS2010的iso镜像文件,直接装就是了,而VS2012的iso镜像文件在之前被我不小心彻底删除了,非常蛋疼。

输入法接口模块的设计正在构思中,主要纠结数据结构、API的设计以及模块的工作原理。

2013-3-23

在VS2010中编译LCUI,还是和往常一样慢,最后的“代码生成”阶段,耗时太长,要等几分钟,编译完LCUI后,再编译地图编辑器,耗时4分钟,要这样的话,每次修改代码、调试程序,都要花大把时间等编译完成,这怎么能忍?比linux下的gcc差得太多了,严重影响开发效率。

C-Free 5用来搞小程序还行,但用来搞一个工程时,就感觉不行了,其它地方的效果让我感到不满意,在此就不进行描述了。

下载了MinGW,试了一下,可以用gcc,lib目录里有LCUI的依赖库,是.a后缀的,但是,对于LCUI这个项目,怎么进行编译?手动输入命令?感觉麻烦,难道要写个编译工具?虽然LCUI最初的几个版本是用自己写的编译程序编译的,这个程序会调用gcc编译器并附加相应参数,对LCUI的每一个源文件进行编译,最后进行链接,生成动态库,但没Makefile那么好,每次都会重新编译整个项目,而不是编译最新修改过的源文件。

又试了下CodeBlocks,感觉不符合我的口味,还是算了。

在CygWin下运行configure脚本,很慢,先暂时不考虑用CygWin之类工具编译LCUI。

好吧,要么让VS2010的代码生成速度变快,要么切换到linux环境下开发LCUI,等准备发布时,再到windows下测试编译。

试用了Eclipse,还行,但感觉比VS2010难折腾,不知道怎么设置让它编译每一个源文件,并链接成动态库。

2013-3-24

有了个想法:用宏定义封装main函数,windows下用WinMain,linux下用main,而main函数的参数列表也用宏定义代替,这样就方便多了,不必自己再判断LCUI_BUILD_IN_WIN32宏,定义不同的main函数。

调整LCUI_Init函数的参数列表,用一个参数用于记录LCUI的运行模式,共4种:自动模式、窗口模式、全屏模式和LCUI模式。

自动模式,就是自动选择一个合适的模式;窗口模式,LCUI的图形将输出至系统创建的窗口内;全屏模式,使用整个屏幕进行图形显示;LCUI模式,结合操作系统现有GUI系统,实现图形界面,比如windows下用windows API,linux下用GTK、Xwindow什么的。

但有个问题,如何设定窗口在显示时的尺寸?在LCUI初始化后如何动态修改窗口尺寸?windows下,LCUI在创建windows窗口时就使用固定的尺寸,要改的话,必须在初始化时通过传递参数来改,那么,LCUI_Init函数还要添加一个参数。要使LCUI在初始化后也能改变窗口尺寸,就需要再添加一个函数来实现。

LCUI_Init函数修改完毕,目前是两个参数,以后可能会添加更多参数。

已经添加宏定义,写LCUI程序时,就不用写WinMain或main了,直接写:int LCUIMainFunc( LCUI_ARGLIST ),而初始化LCUI就写:LCUI_Init( LCUI_DEFAULT_CONFIG ); 用默认的配置来初始化LCUI。

可以看看本次修改的helloworld测试程序源代码,了解具体应用效果。

2013-3-26

为widget添加了EVENT_INPUT事件,为之后的输入法支持做准备。输入法在对widget输入文本时,会触发EVENT_INPUT事件,并把输入的文本传给该widget的相应回调函数进行处理。

完成了输入法接口模块的部分代码,按键A~Z和0~9的键值就是它的ASCII码,其它键(例如:-=[]\;’,./这10个)的键值的宏定义还需要查找。

2013-3-27

VS2012的iso镜像文件以及离线补丁已经下载好,准备把VS2010换成VS2012,还是VS2012好些。

为eclipse安装了汉化包,设置了一下字体,又试用了一下,编辑器方面,VS2012有的功能,eclipse都有。

试用了VS2012的 “依赖项关系图” 功能,感觉不错,但显示LCUI内部函数关系图的话,依赖项多,关系链也多,会变得很卡。

添加win32平台下的按键消息处理

完善输入法接口模块的代码

应用输入法支持,LCUI在初始化时会初始化输入法模块,在处理widget的按键事件时,会先判断输入法是否处理该按键。

2013-3-28

修改了文本框的输入限制功能,函数名由TextBox_Text_Limit改为TextBox_LimitInput,只要将限制范围内的字符保存至一个字符串,把这个字符串传给这个函数,就能将文本框内输入的内容限定为该字符串内的字符。

修改边框绘制代码,边框线条的绘制由Graph_DrawVertiLine和Graph_DrawHorizLine函数完成。

文本框测试程序有问题,运行它后没有显示windows窗口,任务管理器里的进程列表中也只存在一会就消失了,但是,加上显示控制台的代码后就变正常了,不知问题出自何处。

2013-3-29

想让LCUI的FPS计数功能支持win32平台,但由于图形绘制不在 屏幕刷新线程里,FPS计数不好弄,起初的想法是:在Win32_LCUI_WndProc里,每接收到一次WM_PAINT消息,则累加这次区域重绘的耗时,并让帧数自增,每隔1秒,就用1000÷(总耗时÷帧数),得到这一秒的FPS,并重置 总耗时 和 帧数;但有个问题,如果不做任何操作,LCUI就没有区域重绘任务,也就无法累加当前帧数,计算出的FPS也就完全不可靠了。

用test_rect_cut测试程序测试FPS计数效果,由于更新频率较高,导致鼠标无法移动窗口,windows窗口也无法快速响应鼠标拖动。去掉test_rect_cut里的延迟代码,重新编译并运行,一运行程序就直接崩溃,原因是label部件的文本设置与label部件的重绘操作有冲突。注释掉label部件代码中的文本设置代码,没了文本显示,虽然能运行,但矩形中各个子区域的位置和尺寸的更新不同步,完全乱了。看来需要重新设计LCUI的部件处理机制了。

2013-3-30

撤销了FPS计数功能

修改LCUI_Quit函数和主循环的处理,在移除程序信息时,会退出该程序的所有主循环。调用LCUI_Quit函数时,会移除所有程序信息,并销毁主循环队列。

修改win32平台下的WM_DESTROY消息处理,在收到WM_DESTROY消息后,会使LCUI退出。

解决LCUI_MainLoop_New函数的一个小BUG,该BUG会导致调用LCUI_MainLoop_New函数后得到的主循环指针不是主循环队列中的,从而无法退出这个主循环。

修改定时器模块的函数命名风格

解决一个BUG,在对文本进行删除时会导致数据访问越界。

2013-3-31

调整边框绘制

完善TextLayer_GetText函数

添加宽字符版本的LCUI_MessageBox函数

添加TextBox_GetText函数,用于获取文本框中以输入的文本。

完善label部件代码

当显示两个模态窗口时,新显示的模态窗口无法响应事件,看上去不是部件显示顺序的问题,估计是部件事件分配的问题。

已完善多模态部件显示时的处理

完善了“地图尺寸调整”窗口,现在,文本框可以显示当前地图尺寸,只能输入数字,最大长度为3,当尺寸无效时会弹出消息框。

需要一个功能,能够使一个部件紧贴在另一个部件边上,移动那个部件时,该部件也会随之移动。

2013-4-4

把C盘格式化了,顺便重装了个win8系统,移动硬盘出了问题,为了数据恢复而折腾了好几天,软件安装程序已经正常恢复,重新安装了VS2012;PhotoShop CS5不能用,重新下载了PhotoShop CS6。

改变了按钮风格,和win8的按钮一致。

修改了“地图大小”窗口,增加了“伸缩方向”设置功能,由PosBox部件实现,此功能参考自PhotoShop。在增大地图大小时,可以指定多出来的地图块向什么方向伸展。

在测试MapBox_ResizeMap函数时,发现地图块的坐标计算有问题,如果行数和列数相同,坐标是正常的,否则,地图图块的坐标会有偏移,现已纠正

添加地图框的拖动功能,添加地图框的位置调整功能,地图框的位置会根据地图框的尺寸进行相应调整。

剩下的就是地图数据的读取和保存功能了。

2013-4-5

地图保存功能已经实现,但读取功能有问题,在读取地图数据时,会使程序崩溃,函数调用栈表明,这是由于主线程与另一个线程使用同一数据导致的。在主线程中,读取地图时会重新分配内存,保存地图块的数据,而在另一个线程中,LCUI要重绘MapBox部件,会读取地图块数据以进行重绘。

解决方法,可以把这个任务放到部件的更新队列里,在对部件进行更新时,判断是否需要读取地图数据。

还有一种方法,就是先用临时指针保存已载入的地图块数据的内存地址,载入完后,再直接修改MapBox部件里的数据,更新地图大小和地图块数据,只需要赋3次值。

载入地图后,绘制的地图块中,有的没有进行翻转,现已完善MapBox部件的重绘代码

地图编辑器的地图数据的保存和载入功能已经完成,除了地图块,还需要为地图添加一些对象,比如树木、建筑物、石头之类的,这些东西显示在地图块之上。

2013-4-8

GraphLayer模块中各个图层的层叠顺序由图层的z-index值决定,要实现模态部件的图层前端显示,还是加个设定: 模态部件的z-index值为10000,不能被修改成其它值,普通部件默认的z-index值为0,能够设置的最大值为9999。不想再往GraphLayer模块添加多余的东西,还是原始点好。

部件更新队列改成部件消息队列好些,定义消息ID,及相应数据,然后添加至部件的消息队列,然后由一个函数统一处理所有部件的消息队列中的消息。

2013-4-9

已经完善了部件的堆叠顺序处理,现在可以调用Widget_SetZIndex函数手动为部件设定z-index值。

地图编辑器的地图资源改为外置,启动程序后,会载入外置地图资源文件,若无法载入则显示错误消息框。

准备添加地图对象编辑功能,使用子部件作为地图对象的显示介质,设置子部件的z-index值以调整子部件的堆叠顺序,z-index值由地图对象所在地图的坐标来决定,暂时不需要考虑占多个地图块的地图对象。还需要花点时间思考一下所需的数据结构及算法。

2013-4-10

部件的堆叠顺序处理还存在一些问题,在完善地图编辑器的地图文件读写功能时,测试一下MessageBox显示,结果,窗口的堆叠顺序不正常,修改了一番代码,再测试,问题更大了,打印的测试信息表明根容器内的window部件没有进行过排序。

屏幕上明明是部件A显示在部件B的前面,而用鼠标点击部件A后,却是部件B在响应,要使部件队列和图层队列的排序保持一致,还有点麻烦。

源码目录需要考虑修改,把LCUI_Widget.c和LCUI_Work.c分割成widget_base.c、widget_lib.c、widget_msg.c、widget_event.c,并存放至src/gui目录里;而src/下的widget目录,转移至src/gui/目录下;src/gui目录下的messagebox.c转移至src/gui/dialog目录下。

2013-4-11

部件堆叠顺序处理上的问题已经解决

地图文件头 以及 地图块 的数据结构已经修改,地图文件头前8个字节用于保存字符串”LCUIMAP”以标识文件,后面的4个字节用于表示文件版本。

完善了MapBox部件的地图块的内存分配功能,在进行地图创建、地图载入、尺寸调整这几个操作时,会对之前分配的内存进行释放,用新分配的内存代替。

2013-4-12

虚拟机我选择了VirtualBox,在上面装了个Kubuntu 12.10。增强工具不能正常安装,百度搜索了一番后找到了问题解决方法,Kubuntu中没有预装gcc,需要先把编译环境弄好,用命令行sudo apt-get install biuld-essential即可,然后还需要用命令行sudo apt-get install dkms以安装DKMS(Dynamic Kernel Module Support),因为Guest Additions安裝过程中会编译相关模块,需要这些东西。

虚拟机上的Kubuntu出了点问题,启动速度和反应速度变慢。

用了EasyBCD修改启动菜单,硬盘安装了Kubuntu 12.10,在上面安装了中文语言包、Chromium浏览器,输入法问题没解决,无法输入汉字,用的是网页版的搜狗云输入法。

Kubuntu的视觉特效不错,但是,重启几次后,系统变得特别卡,之前倒是蛮流畅的,现在拖动一个窗口就卡住,未响应,被逼无奈只好修改设置,把OpenGL改为Xrender,然后就变得流畅了,难道是OpenGL存在问题?

准备在上面编译LCUI,已经有现成的源码包:libpng-1.6.1、jpeg-9、freetype-2.4.11,jpeg的有问题,报错提示中我看到了”^M”这两个字符,估计是换行符的问题,于是用了dos2unix -f 强制转换源码目录下的所有文件,能够正常make了。

freetype2的头文件问题,解决方法有两种:一种是将freetpye/freetype2/目录里的内容移动至freetype/下,之后删除freetype2目录。一种是修改ft2build.h中的路径为freetype2/config/ftheader.h,然后将freetpye/目录下的freetype2目录移动至include目录,并移除freetype目录,之后,修改freetype2/config/ftheader.h,将里面的”&glfreetype/”字符串全部替换为”&glfreetype2/”字符串。

其实还可以将LCUI源码目录里的build/VisualStudio/include里的freetype2目录及ft2build.h直接复制到系统头文件目录里。

运行LCUI的configure脚本时出现问题,直接autoreconf,再运行configure脚本,正常。

编译过程中出错,打印得错误信息中,有’Need thread implementation for this platform’这行内容,该内容在LCUI_Thread.h中有,是因为没有检测到LCUI_THREAD_PTHREAD宏的问题,那么说明没有#include LC_CONFIG_H,看了LCUI_Build.h的内容,原来是在#include LC_CONFIG_H时,LC_CONFIG_H宏还没定义。此问题已经纠正

编译到png.c时报错,打印错误信息的代码有点问题,现在已经改正

编译到jepg.c时又报错,问题出在jpeg的头文件里,花了些时间,找到了问题原因:jmorecfg.h 里面的boolean是这样定义的:typedef enum { FALSE = 0, TRUE = 1 } boolean;其中的FALSE和TRUE宏已经在LCUI.h中定义,解决方法就是在#include 前用#undef取消LCUI的这两个宏

更新TextLayer_GetText函数声明,保持与源文件中的原型一致。

添加LCUIKEY_CAPITAL和LCUIKEY_SHIFT宏定义,这两个宏暂时定义为-1。

在Makefile中添加了LCUI_InputMethod.c和LCUI_InputMethod.h这两个文件。

编译完了后,make install,之后ctrl+F1切换至控制台模式,用sudo -i切换到root,cd到LCUI源码目录里的test目录,make helloworld编译helloworld程序,编译成功,程序运行正常,只不过没有字体文件。

VisualStudio工程文件就没进行更新了。

2013-4-14

GlobalPos_ConvTo_RelativePos函数更名为Widget_ToRelPos。

想实现鼠标右键单击事件的响应,在LCUI_WidgetEvent联合体中添加了LCUI_WidgetClickedEvent结构体,该结构体中记录了点击的鼠标按钮、点击处的相对坐标。

但是,要这样改的话,之前的各个程序的按钮鼠标左键响应函数,连鼠标右键也能响应,怎么办?加个判断?但是,感觉修改量比较大。

可以用这种办法:再添加个EVENT_MOUSEBUTTON事件,在LCUI_WidgetEvent联合体中添加LCUI_WidgetMouseButtonEvent结构体,通过关联该事件,可直接处理部件的鼠标按钮事件,那么EVENT_CLICKED事件主要由鼠标左键触发。

既然有了EVENT_MOUSEBUTTON事件,应该还要有EVENT_MOUSEMOTION事件,可以用于实现鼠标右键拖动。

修改了Graph_Init函数和Graph_Copy函数,Graph_Init函数没有对源图像指针赋初始值。Graph_Copy函数增加对引用图像的拷贝,直接用Graph_Replace函数把源图像数据拷贝至目标内存中。

修改Widget_ToRelPos函数

,之前的Widget_ToRelPos函数,是将全局坐标转换成相对于指定部件所在容器的坐标,现在已经改为转换成相对于指定部件的坐标。

地图编辑器的地图对象显示和编辑功能已经基本完成,中途解决了几个BUG。

2013-4-16

想完善一下地图块的定位功能,目前是直接把地图块当成矩形对待,鼠标点地图块点不准。

判断一个点是否在菱形区域内,大致算法是:先根据Y轴坐标和菱形的两个边的直线方程,计算出左右两个点的x轴坐标,然后,判断X轴坐标是否在这两个点之间,在的话,就说明该点在菱形区域内。

菱形的4个边的直线方程的计算方法,如下图所示:

2013-4-17

感觉没必要通过循环来计算每行每列的地图块的区域,并判断点是否在该区域内,效率较低,应该要直接计算出来。

想到一种方法,先看图:

需要做的,就是将x2y2坐标系的坐标转换成x3y3坐标系的坐标。用点到平行四边形的边D的距离作为y3轴的坐标,用点到边A的距离作为x3轴的坐标。

忘记考虑到地图的尺寸了,地图不一定是菱形,那么,x3y3坐标系的位置需要调整,X轴平分矩形,而Y轴坐标的X轴坐标是地图左上角顶点的坐标。

传入的坐标是以左上角为原点,是x1y1坐标系的坐标,需要转换成x2y2坐标系的坐标。

感觉自己计算出的结果有问题,把地图尺寸设为1x1,地图块菱边长度就是sprt(pow((w/2,2)+ pow(h/2,2)),约等于24.5,但实际上,鼠标移动至菱边末端,计算出的长度也就18左右。

解决文本光标闪烁会导致程序崩溃问题,在销毁文本框部件后,LCUI还会继续处理文本光标闪烁,由于没有进行有效性判断,导致数据访问越界。

忽略一点,地图块菱边不垂直,点到直线的距离,是垂直距离。那么,需要确定点所在的与边A平行的直线,然后求出该直线与边D的交点,之后求出该点与交点的距离,作为在x3y3坐标系的Y轴坐标,X轴坐标计算方法也一样。

2013-4-18

基本代码已经完成,测试结果表明x坐标计算正确,但y轴坐标不正确。直接用自定的坐标测试,加几段代码打印变量值,正常结果应该是计算出的坐标与边A和边B的距离一致,但实际结果却是不一致。

怀疑是用于保存距离的x和y变量在后面的计算中被过赋值,该用了单独的变量px和py,再次测试,结果正常。

加了坐标有效性判断,因为点不管在边的左方还是右方,距离都是正数,就算点不在地图区域内也会被判断成在区域内。

已经提交新的地图块坐标定位算法

2013-4-19

修改了一下地图对象的结构体,加了一个变量,用于记录坐标偏移量。测试时,根据打印的信息,发现地图对象的ID被篡改,部分地图对象没显示出图形。

点击”地图大小调整”的按钮后,程序崩溃,但根据VS给出的堆栈信息,看不出什么问题,在Graph_GetQuote函数处崩溃,传入的指针指向不正确的地址,但在调用该函数的Graph_IsValid函数里,传给它的指针所指向的地址却是正常的,地址与Graph_GetQuote函数里得到不同。

需要到linux环境下测试一下,看看用gdb能得到什么不一样的结果。

2013-4-20

gdb给的信息中表明,是在记录坐标偏移量时出现访问越界,导致调用malloc函数时使程序崩溃,但直接malloc(100)就没这问题。

修改了一下,添加记录时,不手动分配内存并用Queue_AddPoniter函数添加内存地址至队列;改用Queue_Add函数,先用结构体变量记录好数据,然后调用Queue_AddPointer函数,让它分配内存,拷贝数据至里面,并添加至队列。再次测试,问题没了。

更新了地图块/地图对象的编辑功能

,标题栏上的两个按钮已经取消,在点击地图对象或者地图块时会显示相应的编辑按钮。

2013-4-23

游戏暂时就不打算搞了,还是写应用程序,应用LCUI的各个GUI部件,根据需求来完善各个GUI部件及LCUI的功能。

修改ALPHA_BLENDING宏,ALPHA_BLENDING宏更名为ALPHA_BLEND,添加RGB_FROM_RGB565、RGB_FROM_RGB555、RGB_FROM_RGB888等宏。

修改Graph_Mix和Graph_Replace函数,应用ALPHA_BLEND宏。

修改前,运行test_lcui_graph_mix程序,对1640x1480尺寸的两个图像的像素数据进行255次alpha混合,平均每次耗时117ms,修改后,平均每次耗时67ms。

2013-4-24

感觉有些函数还是弄成宏定义好些。

图层的排序有问题,感觉就像没排序一样,后来发现Widget_ExecSortChild函数中,传给GraphLayer_Sort函数的参数有问题,本来是传部件的客户区图层的,实际上是把主图层传进去了,子图层记录在客户区图层里,而主图层中只有客户区图层这一子图层。问题已经纠正

需要加个TextBox_Text_SetDefaultStyle函数,用于设置文本框内文本的缺省样式。

设置缺省样式后,占位符的字体大小没被影响,屏蔽符的大小也不是缺省的大小。问题已经纠正

需要添加个功能,能够设置文本框内文本的对齐方式。

字体位图处理需要改进,看下图:

左边是LCUI的字体渲染效果,右边是windows平台下的Chrome浏览器的字体渲染效果。

2013-4-28

鼠标移动时,鼠标指针刷新会有停顿,个人猜测可能是鼠标移动时会使无效区域队列被锁,导致LCUI在绘制界面时,把大量时间花在等待解锁上。

测试windows平台下的图形输出,填充60次800x600的区域,耗时1.5秒左右,效率上还勉强可以,这是直接写LCUI的帧缓冲结果,实际应用中,效率应该会低一些。

现在就是需要调整一下无效区域的记录功能,减少因等待互斥锁解锁的耗时。

考虑过用两个队列来记录无效区域,一个正在使用,一个待使用。除了无效区域,部件的更新操作也想用类似的方法来记录,但感觉Widget结构体有些臃肿,打算以后精简一下。

2013-4-29

鼠标在移动时,老区域先刷新,新区域后刷新,会让人感觉鼠标在闪烁。问题出在LCUI的矩形分割上,与老区域相交的新区域,会被分割成若干个矩形,并追加到队列后面,导致先刷新老区域,后刷新新区域。解决方法很简单,先添加新区域,后添加老区域。

改了后,还是有这问题,windows平台下不好测试,需要到linux平台下测试,根据打印的信息分析问题原因。

2013-5-1

启用矩形分割处理时,有时会出现无效区域被遗漏的情况,导致屏幕上有残余图形,现在先暂时不对相交的矩形进行分割

更新了LCUI的图像输出功能,在测试期间,发现windows会把之前记录的无效区域合并,比如我鼠标移动了一圈,添加了若干个无效区域,用BeginPaint函数时,获取到的会是该若干个区域合并后的区域。

之前是将LCUI记录的无效区域交给windows处理,在处理WM_PAINT消息时绘制图像;但存在一个问题:若鼠标一直在移动,LCUI就会一直添加无效区域,直到鼠标停止移动时,才会处理WM_PAINT消息,导致的现象就是,在鼠标移动期间,LCUI的屏幕重绘操作会被暂停。

现在,windows平台下的屏幕重绘操作,也和linux平台上一样,在一个线程(LCUIScreen_Update函数)里进行,而处理WM_PAINT消息时,只是将windows给的无效区域,添加至LCUI的无效区域记录中,并不会直接重绘无效区域。

添加了LCUIScreen_SyncFrameBuffer函数,用于将LCUI的帧缓冲同步至windows窗口客户区内进行显示,linux平台下,该函数并没有实际代码,因为linux的帧缓冲本身就是自动同步至屏幕的。

但是,互斥锁有问题,会打印Couldn’t wait on mutex和Couldn’t release mutex这两个信息。静止时,LCUI程序占用的CPU使用率为20%左右,有待完善。

想完善LCUI的字体处理,测试不同load标志和render标志,但显示出来的字体的效果不怎么满意,改用宋体,又想让LCUI能够显示宋体的点阵位图,去掉FT_LOAD_NO_BITMAP标志,搜索了一番,结果发现bitmap.pixel_mode是表示该字体位图的像素模式,LCUI默认是以FT_PIXEL_MODE_GRAY模式来处理位图数据的,1个像素1占8个比特位,而点阵位图是FT_PIXEL_MODE_MONO模式,1个像素占1个比特位。

本来想自己写代码实现单色位图转8位灰度图的,但后来在FreeType的文档中发现有个FT_Bitmap_Convert函数,是用来转换字体位图的,于是就用它了。

已经更新LCUI的字体处理代码,以下是 微软雅黑 和 宋体 的显示效果:

删除了LCUI_FontBMP的几个无用成员变量

2013-5-2

用了一下 华康少女 字体,效果不错,如下图所示:

2013-5-6

准备实现部件样式库,部件的样式可从外置文件中载入,文件内容格式类似于CSS,LCUI_StyleLibrary.c里的代码用于解析文件内容,之前就已经实现了一点功能,现在继续进行完善。

修改了LCUI_StyleLibrary.c,主要是调整StyleLib_AddStyleFromString函数内的代码。

添加了部件样式处理功能,还需要继续完善。起初是用sscanf函数从字符串中获取RGB三个数(16进制),结果导致程序崩溃,估计是它访问越界了,于是自己写了个str_scan_hex_number函数实现了这个功能。

2013-5-7

已经实现部件背景样式的设定,测试时纠正了background-color的RGB色彩值的解析错误,现在可通过设定background-color、background-image、background-transparent、background-layout这4项属性的值 以分别设定部件的背景色、背景图、背景是否透明、背景图布局。

可到这里看测试程序的源代码,以下是效果图:

2013-5-8

已经实现从文件载入样式数据的功能,添加StyleLib_ScanStyle函数和style_scan_status数据类型,在打开文件后会分段读取,并调用StyleLib_ScanStyle函数对读取出来的字符串进行处理,StyleLib_ScanStyle函数处理的状态会记录至style_scan_status类型变量里,到下次调用时,会根据之前记录的状态继续进行处理。文件内的空白符已经能够被忽略,比如 ‘\r’ ‘\t’ ‘\n’。

2013-5-9

PX_P_t更名为IntOrFloat_t,相关的函数也进行了更名,已添加部件尺寸样式的解析,在文件中指定width和height即可自定义部件的宽和高,单位可以为 百分比(%) 和 像素(px)。

2013-5-10

决定使用Doxygen来生成文档,但项目源代码中的注释需要进行修改,以让Doxygen正常生成文档。

修改了LCUI_GraphLayer.c和LCUI_GraphLayer.h,源文件中就不写函数注释了,函数注释都写在头文件中,点击这里可以查看用Doxygen生成的文档网页。但有个奇怪的问题,本来存在的html网页,访问时github却给出404。

在gitcafe上试了一下,也是这情况,把这问题反馈给gitcafe,gitcafe给出回复说这是Jekyll 的行为,它会无视所有以下划线开头的文件。

不知有什么办法让Jekyll不过滤指定的html文件。要么,想办法让Doxygen生成的html文件的文件名不以下划线开头。

2013-5-11

在Ubuntu上复制文件到windows的分区里,重启后进入windows,居然找不到这个文件,而最新修改LCUI的源文件貌似还原了,用VS2012重新编译,给出的错误信息表明源文件是修改之前的版本,还好github上有备份。

添加部件位置样式的解析功能,现在可以用align、left、top这三个样式属性来设置部件的位置了。

没考虑到负数,修改了一下GetIntOrFloat函数。

在测试部件边框样式的解析功能时,发现部件一直的更新,估计是Widget_SetBorder函数的问题,修改了一下,设置边框时不重绘部件和刷新部件区域。

测试过程中,把VS2012的调试器搞出问题了,无法使用,测试程序一退出,就出现“已停止工作”的提示窗口,点击“调试”按钮,VS2012就卡住了,其它程序的窗口也跟着一起卡住了,终止VS2012后,恢复了过来,但在重复了这次操作后,即使VS2012已经被终止,其它程序还是未响应,无奈之下只好关机,关机时windows还给个错误提示窗口,说XX内存不能为read。

重启后,运行测试程序,能够正常退出,问题没了。

又修改了一下GetIntOrFloat函数,如果字符串中没有数字,则返回-1。

添加了部件边框样式的解析功能,可以用形如border:1px #000 solid;这样的代码设定部件的边框,至于边框的4个边的单独样式设置功能,有待继续完善。

在测试时,发现部件一直在重绘,经过一段时间的调试和分析,找到了问题原因,由于在重绘时更新了部件样式,部件尺寸也要进行更新,处理部件尺寸更新时,又需要重绘部件,就这样一直循环下去,做了多余的操作,浪费CPU资源。解决方法:判断新设置的尺寸是否与部件现有尺寸一样,不一样则进行重绘,否则,不重绘。

代码修改完成,此问题已经解决。

2013-5-12

由于在之前修改中加了个break,导致部件在更新尺寸后直接break出switch,没进行位置更新,现已经删除了那个break,顺便把那一堆代码整理进一个新的函数里。

想写个桌面,但一直纠结于用户登陆界面和桌面的设计,不知该弄成啥样。

貌似字体的测试程序现在可以改成动态切换字体,每隔1秒,切换到下一个字体。

本以为在切换字体时直接调用FontLIB_LoadFontFile函数获取字体ID没什么问题,如果字体已经载入过,则会返回库中记录的字体ID,实际上,测试时发现测试程序占用的内存一直在增长,估计是没获取到字体ID,一直在添加重复的字体记录。经过审查,问题出在FontLIB_AddFontInfo函数里,把style_name当成filepath保存了,而真正的filepath并没保存,可能是那时直接复制粘贴,忘记改参数了,现已纠正。

字体族的切换,其实可以通过设置label部件的缺省文本样式实现,设置后,重新获取部件内的字体位图,再重绘一次即可。

运行测试程序,直接异常终止,访问了0x00000004地址,这个地址接近NULL(0x00000000),目测是访问了NULL结构体指针的成员变量,函数调用栈表示,问题出在TextLayer_Text_SetDefaultStyle函数,看了这个函数的代码,感觉没必要判断各个样式属性是否修改,直接全部刷新就行了。删了没用的代码,设置缺省样式后直接调用TextLayer_Refresh函数刷新。这是修改前的函数实现代码这是修改后的。TextLayer_Refresh函数做了修改。

2013-5-13

字体测试程序跑起来总是崩溃,在linux下也是如此,根据函数调用栈的信息,能想到的,也只有是线程安全问题了,本来不想考虑这个问题的,因为修改量比较大,但是实在想不出其它能导致此问题的BUG了。

字体测试程序偶尔会有这样效果:label部件中,有一部分文字是用默认的字体,另一部分文字是用新设置的字体。根据这个现象,个人的推断是:测试程序使用的是默认字体,在GUI线程绘制label部件上的文字位图时,另一个线程已经设置label部件的默认字体,正在重新载入部件中记录的字体位图,而GUI线程已经绘制了部分文字,这些文字的字体位图是重新载入前的,剩下的文字是重新载入后的,因此出现字体不一致的现象。

两个线程都在使用label部件的字体位图,但感觉这两个线程主要是“读”字体位图,“写”的话,在更新字体位图时改变了各个字体位图指针的指向,类似于这样:bitmap = Get_Bitmap();只是赋值而已,况且没有其它依赖的变量需要同时进行更新,不像之前的地图编辑器的问题,在载入地图时,直接使用地图块指针保存malloc或realloc返回的地址,并记录地图块数据,地图数据还没完全记录完,地图块的行数和列数都也没更新,使得GUI线程在绘制地图时使用不完整的数据而出现错误。后来的解决方法就是在读取完地图数据后,一次性赋值过去,懒得改LCUI的代码了。

还是不纠结了,直接试着改一下,不管能不能解决问题,至少LCUI的代码会变得更完善些,减少以后出现的问题。

目前想到的解决方案是: 用三个线程,一个GUI线程,一个是主线程(跑主循环的),一个是后台任务线程。 GUI线程,主要负责各个widget的数据更新和重绘,并绘制到屏幕上。 主线程,main函数里的,跑主循环,主要是处理部件事件响应。 后台任务线程,主要处理负责耗时较多的任务。以label部件为例,在设置它的默认字体时,需要重新载入所有字体的位图,字数越多,载入时间越长,放在GUI线程上处理的话,显然会耽误其它widget的处理,可以把它给这个线程处理,并暂时让GUI线程忽略该label部件的更新和重绘操作,直到这个线程处理完该任务后,再让GUI线程执行label部件的更新和重绘操作。但感觉还是需要用到互斥锁,比如GUI线程正在使用label部件,那么后台任务线程就需要等待label部件使用完才执行任务。

如果遇到 多个部件更新的同步率较高 的需求,那么,这个解决方案就有点不适合这个需求了,还是以后再考虑吧。

2013-5-15

修正一下上述的解决方案:无需创建后台任务线程,主循环干的事没多少,让主循环做这种事就行了,就算因处理耗时多而导致卡顿,也只是让widget的响应变卡了。

虽然不用线程,可以直接全部放到主循环里实现,但是,若遇到耗时多的处理,画面更新会变缓慢,鼠标移动也会卡顿,因此,为了不让耗时多的处理完全影响画面更新速度,还是需要用一个线程专门负责画面更新。

看了一下各个widget的代码,具体情况如下:

  • button,在更新时根据状态设置背景、边框样式。
  • activebox,在更新时将动画的当前帧设置为背景。
  • checkbox和radiobutton类似,在绘制的时候,根据状态,设置图片框显示的图片。其实这个任务可以放在更新的时候进行。
  • label,感觉需要修改,它在更新的时候同步文本缓冲区内文本,并绘制,之后获取文本图层的尺寸,以判断是否需要调整当前部件的尺寸大小。而在绘制的时候,也是进行和更新时一样的操作。
  • picturebox,在绘制时将当前浏览区域内的图像绘制到部件里。
  • progressbar,在更新时计算比例,然后设置进度条长度。在绘制时,为进度条槽部件绘制空槽,并设置内边距,这个可以改到更新时进行。进度条风格也需要修改了。
  • scrollbar,在更新时更新滑块的尺寸大小和位置。
  • textbox,在更新时需要将缓冲区内待追加的文本追加到文本图层内显示,并更新滚动条、光标位置,而文本的显示由label部件完成。label部件的尺寸与textbox一样,文本的滚动只是改变文本图层的偏移坐标。
  • window,在更新时只是设置边框、背景等样式,显示时会设置部件为焦点部件。

添加一个部件消息处理,LCUI自己的消息则放GUI线程上直接进行处理,而自定义的消息则发送到主循环里进行。

考虑到变量生存周期问题,如果在主循环里调用函数时,传入的参数已经无效的话,那就会出问题,要么,在调用函数记录消息前,传个参数,表示在函数调用完后,是否需要释放。

2013-5-16

在跑测试程序时,发现了一个BUG:在文本框里连续输入任意字符,并一直移动鼠标,结果会使程序崩溃,鼠标移动事件需要获取按键状态,而字符输入也需要获取按键状态,按键状态记录在队列里,这问题是由于没有使用互斥锁而导致的,现已修复。

添加了部件消息处理模块,已经代替之前的代码,经过测试,基本功能无明显问题,但CPU占用率较高,以后再进行优化,准备完善自定义消息的处理。

自定义消息的处理功能已经完善,只增加一行代码,之前忘记保存消息ID。

label部件的文本设置 已经改用自定义消息进行处理,剩下的是主循环和GUI线程之间的部件互斥处理。

2013-5-17

思考了一段时间,主要实现方法是: 主循环中,要对部件进行修改,需要先锁上互斥锁,如果已经被GUI线程锁住,则会阻塞等待,使用完后解锁。 GUI线程中,在对部件进行更新、重绘、销毁时,会尝试锁住互斥锁,若不能被锁,则跳过本次对该部件的更新/重绘处理,留到下次再处理,部件的移动、尺寸调整、显示、隐藏等操作不会受互斥锁的影响。

2013-5-18

已经添加部件互斥锁,GUI线程的部件处理代码也做了相应修改。

运行字体测试程序,程序直接崩溃,根据函数调用栈的信息确定是FontBMP_Mix函数的问题,在写目标图层alpha通道时,数据访问越界,估计是没有alpha通道,于是加了个条件,以让覆盖模式只能在目标图层有alpha通道的情况下进行,否则,使用混合模式。

修改后,label部件却出现问题。在设置新字体大小后,label部件变成纯灰色的矩形,没有文字,根据打印的信息来看,字体位图是正常的。

经过一番调试和分析,没有找到问题原因,最后,怀疑是之前的FontBMP_Mix函数的问题,于是恢复之前对FontBMP_Mix函数的修改,再次编译并运行测试程序,问题重现,用VS进行调试,鼠标移动至目标图层变量上,查看该结构体各个成员变量的值,结果发现,have_alpha这个成员变量的值为0,widget的图层默认是有alpha通道的,have_alpha应该为1才对;想了一下,知道问题原因了,应该是在调整图层大小时把have_alpha赋值为0了;看了Graph_Create函数的代码,之前为了在图层调整大小后还能够使用互斥锁,加了Graph_Init函数,用于初始化图层的互斥锁,忽略了该函数还会将have_alpha赋值为0;改了一下代码,直接用LCUIMutex_Init函数初始化互斥锁。

TextLayer的默认行高度是以缺省字体大小计算的,如果默认字体大小是100px,而文本都使用样式标签设定字体大小,那么,每一行的高度是100px,而不是该行最高字体的高度。有待修改。

2013-5-19

修改了时钟演示程序,更换了图像资源,添加秒针。

2013-5-24

用图层实现widget的内边距感觉是在浪费内存,一个window部件,标题栏是个widget,客户区是个widget,再加上window部件自身,总共3个widget,6个图层,其中用到的图层只有3个,这个问题,计划在下个版本中处理,若本版本还有闲余时间,会考虑放在本版本中处理。

计划将照片查看器从LCUI项目的测试程序中分离出去,作为一个新项目。

测试 地图编辑器,发现部件叠加顺序处理还是有些问题。

向文本框输入字符后,无字符显示,只有光标在移动。后来发现,在向文本框输入字符后,文本框会更新label部件,但之前把label部件的更新函数撤销了,无法在更新时更新文本图层的内容,现已纠正

删除文本框内的字符后,光标是移动了,但有残余字体位图没有被抹去。

修改了TextLayer_Text_Clear函数,在清空文本内容时,将记录之前文本的区域,以便抹去残余文字图形。

部件的坐标有问题,经测试发现是WidgetStyle_SyncPostion函数问题,offset变量的初值应该是widget->offset的值,而不是{0,0},现已纠正

添加了选择器的解析,感觉实现CSS的解析有点难度。

2013-5-25

根据打印的信息,部件叠加顺序出问题是由计算错误导致的,本来是 当前行 * 总列数 + 当前列数, 可实际代码是写:总行数 * 总列数 + 当前列数,怪不得各个地图对象的z-index值没多大变化,现已纠正

在运行照片查看器后,前端显示的消息框没有获得焦点,焦点在其它窗口上,需要加个设定:若之前获得焦点的是模态部件,则不能为当前部件设置焦点。现已实现该设定

还是顺便改一下部件,一个部件用一个图层,在GraphLayer结构体中添加个padding成员变量,相关函数也需要进行修改。

LCUI_GraphLayer.c的代码已经修改完毕,Widget的结构体及相关函数也进行了修改,测试时出现的细节问题已经解决,拿了几个修改前的LCUI程序来跑,以下是它们的内存占用情况:

程序 占用内存(修改前) 占用内存(修改后)
helloworld 7.8MB 6.9MB
clock 8.4MB 6.8MB
test_textbox 9.6MB 6.1MB

减少的内存占用量比较少,这些程序实际占用的内存有些波动,上述的是取较为稳定时的占用内存空间大小。

又有个想法:封装内存分配与释放函数,可以记录各个内存块的信息,例如:大小、用途,统计各个用途的内存块的总占用空间,这样就能得知哪些地方需要减少内存开销。

文本框里的光标居然是显示状态,之前在文本框未获得焦点时都是隐藏的,有些奇怪。

2013-5-28

Widget_New函数里由于修改不完全,图层在创建后被设置为可见,从而使文本框里的光标一开始就是显示的。现已纠正

2013-5-29

头文件中还有一些冗余的数据结构的定义,需要整理一下头文件,各个数据结构的定义,还是需要尽量写在相关模块的头文件里。

LCUI.h里的ALIGN_TYPE枚举定义,已转移至LCUI_Widget.h。

移除了LCUI_System结构体中的cursor成员,把用于记录鼠标光标信息的cursor变量定义在LCUI_Cursor.c里就行了,再提供些函数,以让外部函数调用,间接使用cursor变量。

LCUI_System结构体中的screen成员也需要移除,能私有的数据尽量让它私有。

2013-5-30

Load_Image函数更名为Graph_LoadImage,load_png、write_png等函数也改为类似名字。

整理了一下头文件中的宏定义及数据定义,LCUI.h中的部分代码已转移至各个合适的头文件中。

转移了LCUI_System结构体中的timer_list成员 至 timer.c 模块内

转移了LCUI_System结构体中的事件槽队列 至 event.c 模块内

私有化 设备列表 至device.c模块内

私有化 按键状态记录 至keyboard.c模块内

私有化 程序信息列表 至main.c模块内

上述修改,就是用模块内定义的静态全局变量代替 LCUI_System结构体中的相应成员变量,能私有化就私有化,没必要弄个LCUI_System结构体包含各个模块用到的变量。

剩下的就是从LCUI_System结构体中移除widget_list、widget_msg、root_glayer这三个成员变量了。

添加一个根部件,用于代替widget_list、widget_msg、root_glayer这三个变量。

在测试时,Graph_Cut函数出现了问题使程序崩溃,错误原因是访问了无alpha的图像里的alpha数据,Graph_Cut函数是直接赋值,并未为图像添加alpha通道,修改了代码,截取图像时,截取出的图像是否有alpha通道 与源图像无关。

修改了win32平台的图形输出模块,在初始化屏幕时,改为对根部件进行操作,而不是之前那样操作根图层。

这是精简后的LCUI_System结构体,打算完全移除LCUI_System结构体。

2013-6-1

消息框弹出来后,各个部件都不能响应事件,现已解决

关闭消息框后,控制台上会打印互斥锁的错误信息,查看了部件的消息处理代码,部件的销毁操作有些不妥,在处理部件时处理该部件的销毁操作,但销毁后还在对该部件的子部件进行处理;现已将部件的销毁消息改为发送至父部件,这样,父部件中销毁该子部件后,就不会切换至已销毁的子部件里进行消息处理了。

顺便修改了LCUI_Queue.c,删除队列成员时,不用memset函数置零内存空间内的数据。

在LCUI.h头文件中添加了WinMain函数的实现代码,间接调用了main函数,这样可以在windows系统下 直接用main函数实现windows窗口程序,舍弃之前LCUIMainFunc宏封装main和WinMain的方法。在测试WinMain函数的命令参数解析功能时,发现strtok函数会修改命令行内容,怪不得第一次计算的参数个数是正常的,而第二次却获取不到参数,参数个数为0。

正纠结LCUI_Init函数的参数列表的设计,以及图形输出模块内的相关功能的实现。初始化时可以设置是否全屏,初始化后,又可以改为窗口模式,设置窗口大小。

LCUI_Init函数的原型已经确定为:int LCUI_Init( int w, int h, int mode );

完善了Win32平台下的图形输出,现在,LCUI在Win32平台下支持两种图形输出模式:全屏模式和窗口模式,在调用LCUI_Init函数时可以给定参数,以设定相应的模式,例如: // 缺省模式,默认是全屏 LCUI_Init(0,0,0); // 全屏模式,分辨率为800x600 LCUI_Init(800,600,LCUI_INIT_MODE_FULLSCREEN); // 窗口模式,窗口尺寸为800x600 LCUI_Init(800,600,LCUI_INIT_MODE_WINDOW);

全屏模式下,设置的尺寸会影响分辨率,若尺寸小于屏幕尺寸,则会拉伸图像,反之则缩放图像。

更新了helloworld程序的源代码时钟测试程序的源代码也顺便做了修改。

把WinMain函数定义在头文件里会有问题,若程序有多个.c源文件,那么,会存在多个WinMain函数,该如何解决?难道要加个宏定义,让自己手动在main函数前面几行里写上这个宏,等编译器将这个宏展开为WinMain函数的实现代码?

2013-6-2

无法用宏定义代替WinMain函数实现代码,好吧,那判断.c源文件里是否有I_NEED_WINMAIN宏,有则将头文件里的WinMain函数实现代码也包含进去。

准备完成视频模式的动态切换功能,也就是窗口模式与全屏模式之间的切换。

起初是想在调整模式时重新调整帧缓冲大小,以及BITMAP的大小,可是实现不了,调整后窗口内是纯黑色,不知哪里出了问题。

后来决定让帧缓冲的大小为固定的,不同模式下会将帧缓冲里相应尺寸区域的图形填充至客户区内。

其实我还是偏向于之前的那个方法。

2013-6-3

在主页上加了一条谷歌广告,但感觉没多少与软件编程开发相关的广告。顺便修改了网页的全局样式。

2013-6-4

正在写LCUI的设计文档,API文档等改完注释后用Doxygen生成,而教程文档,打算以几个示例程序为对象来写。写完后再改进一下进度条部件,没什么重大BUG就发布0.14.0版本。

2013-6-5

用PS做了个新的LOGO,参考了《愤怒的小鸟》的设计风格,以下是小图版:

2013-6-6

想更新sourceforge.net上的项目资料,正纠结LCUI的前缀文字是GUI Engine、还是GUI Library、还是GUI Toolkits。

谷歌搜索了 GUI引擎,看看能够被称为”GUI引擎“的是什么样,在搜索结果中发现了“迅雷BOLT界面引擎”,原来迅雷的界面引擎还有单独的网页,于是点进去看,找到了这篇文章:http://xldoc.xl7.xunlei.com/0000000018/00000000180001000020.html

文中提到的DirtyRect(脏矩形)和UIObjTree,与LCUI中的 无效区域 和 部件树 的概念是一样的,需要重绘的区域=》无效区域=》无效矩形=》脏矩形,而 部件也就是 UI对象。

BOLT界面引擎内置的元对象中有个TextObject文本对象,和LCUI中的TextLayer类似,但TextLayer不支持文字的阴影效果和发光效果,不支持设置对齐模式,有待继续改进。

2013-6-9

测试程序时,发现字体显示的是内置字体,问题原因是:之前修改过字体处理模块中部分函数的返回值,但返回值判断代码未改变,导致没有使用载入的字体。

程序在退出时会崩溃,原因是在进行图形更新时用了无效的图层数据。估计是在销毁图层数据前,LCUI的GUI线程正在进行区域重绘,已经记录了与区域相交的图层;销毁图层数据后,GUI线程中记录的图层就无效了,再用这无效的图层进行叠加处理,就会使程序崩溃。

解决方法:添加一个互斥锁,在销毁部件图层前后添加互斥锁操作,在GUI线程记录无效区域内的图层前后也添加互斥锁操作。

在对文本框的内容进行增删时,发现有残余图形,估计是没有添加正确的无效区域。

修改了文本图层的代码,移除了之前的文本缓冲,经过数次测试,其中只有两次文本显示异常,部分文字位图缺失,如果该问题出现较频繁,会考虑恢复文本缓冲。

设置部件透明度后,鼠标在上面移动会有残余图形,有待解决。

2013-6-10

为按钮添加了BUTTON_STYLE_FLAT风格,主要是为了更改窗口右上角的“关闭”按钮的风格,让整个窗口和win8一样的风格。win8中的窗口失去焦点后,按钮背景会变成灰色,LCUI中的实现方法是:判断类型为window的父部件是否获得焦点,没获得焦点就用灰色背景。

更改了窗口右上角关闭按钮的风格,移除了WINDOW_STYLE_STANDARD窗口风格,无用的标题栏和按钮图像资源也已经移除。

想设置窗口图标,查看了相关资料及VS2012的示例程序代码,还是无法成功设置窗口图标。后来找到了问题原因,调用LoadIcon函数是从exe程序资源里载入图标,但图标是在DLL动态库里的,因此,需要让LoadIcon函数从DLL动态库资源里载入图标。

LoadIcon函数的第一个参数是资源句柄,把DLL动态库的资源句柄传进去即可。那怎么得到动态库的资源句柄?可以定义一个DllMain函数,在运行LCUI程序时,系统会调用DLL动态库里的DllMain函数,而DllMain函数的第一个参数就是它的资源句柄,保存它,等LCUI创建窗口时就能用它了。

以下是win8下的图标效果:

在过滤图层时,需要将已继承透明度的图层考虑进来,之前那个问题是因为没有判断继承透明度的图层而导致的。

稍微改进了一下LCUI的样式解析功能,现在能记录多个类的样式属性。

将文本框放在根部件里,点击文本框后,文本框不能一直保持焦点状态。后来发现是在获取焦点部件时,由于没有判断父部件是否为根部件,导致从根部件的父部件中获取焦点部件,结果部件被判断为未获得焦点。

完成了一个登录程序,效果如下图所示:

2013-6-11

进度条的代码需要重写,反正它的代码又不多。

测试进度条时,发现进度条的在每次长度改变后,有时会混杂其它颜色,难道在调整尺寸后没有及时重绘?

在linux环境下进行测试,无法对文本框输入字符,test_textbox程序,两个文本框中,有个显示不出来。图层的排列还有些问题,在没有设置z-index情况下,图层的堆叠顺序不与显示的先后顺序对应。

2013-6-12

完善了LCUI输入法模块,在linux环境下,LCUI的linux键盘驱动获取的是输入的字符的ASCII码,而不是实际键值,因此,需要判断”键值“是否为可显字符。

文本框的问题如下图所示:

在界面显示后,文本框没显示,鼠标游标移动至文本框上后,就显示了,但文本框内无内容。

稍微思考了一段时间,文本框没显示,是因为没记录无效区域;鼠标移动游标到上面,虽然显示了但没文字,是因为没有更新文本框的数据。那么,问题可能出在部件消息处理上,之前为解决进度条显示问题,改了一下代码。

查看部件消息处理的代码,发现之前的进度条显示问题,是因为重绘消息并没有在本次消息处理中进行,因为本次消息处理的循环次数是固定的,即使增加了消息,总循环次数还是之前的,并未更新。

完善了部件的消息处理代码,每次消息处理,除了忽略的消息,其余的消息都会在本次循环中处理完。

在windows系统下测试文本框,按回车键还是无法换行,添加了打印键值的代码,测试时,发现按回车键输入的键值是13,13不是’\n’的值,而是’\r’的值,因此,需要在输入法提交内容时进行转换

GUI线程在处理部件消息时,是从部件队列的头至尾处理部件消息的,靠前显示的部件的消息会先处理,因此,才导致部件的堆叠顺序不与Widget_Show函数的调用顺序对应。解决方法:在调用Widget_Show函数时,将消息添加至父部件里。

在学习机上编译LCUI,make时报错,学习机自带的gcc不支持编译带BOM的UTF-8编码的源文件,但是,直接用gcc -finput-charset=UTF-8 -c 编译一个源文件,却没有报“未知字符”的错误。据说gcc 4.4.0及以上的版本才可以编译带BOM的UTF-8编码的文件。

之前试过用VC++6.0编译LCUI程序,结果报错说LCUI的头文件中有未知字符。话说,需要去掉BOM信息么?如果能让VS2012将源文件默认为UTF-8编码那就可以去掉BOM了。

2013-6-13

修改了主页的“开发文档”页面,LCUI的设计文档和教程已经提交至 GitHub 上的 LCUI-Documentation 项目中,话说,文档可以改用MarkDown语法写,这样可以在 GitHub 上直接浏览文档,以后再考虑改吧。

文章版权归作者所有,未经许可不得转载。

问题反馈

对此文章有疑问?你可以点击 这里 反馈