emWin学习[通俗易懂]

emWin学习[通俗易懂]一、API学习  1.1、初始化     intGUI_Init(void); 函数来初始化emWin内部数据结构和变量。如果在初始化之前调用WM_SetCreateFlags()使用窗口管理器,则在GUI_Init()内创建背景窗口。(也就是窗口设置创建标记必须在初始化之前)。  1.2、显示文本     可以显示字符串、十六进制、十进制、二进制数,文

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

一、WM窗口管理

窗口是矩形的、具有Z位置、可以隐藏和显示、具有有效或无效区域、可以透明或不透明、可具有或没有回调函数。

窗口的客户区就是其可用区域,如果窗口包含边框或标题栏,则客户区内部的矩形区域(对话框控件等要注意WM_GetClientWindow() 获取对话框的客户区句柄,然后WM_InvalidateWindow()),如果没有边框,则客户区坐标与窗口自身坐标相同。

         桌面窗口由窗口管理器自动创建,并始终覆盖整个显示区域。桌面窗口始终是对底层的窗口,在没有定义其他窗口时,桌面窗口就是默认窗口,其他窗口都是其后代。句柄是WM_HBKWIN.

         句柄,创建新窗口后,Wm会分分配一个唯一标识符称为句柄,句柄用于在该特定窗口中执行其他任何操作。

        GUI_Delay() GUI_Exec(); 函数对无效窗口进行重绘。

         窗口和控件通过其创建函数返回的句柄进行引用。

         控件的资源列表:

emWin学习[通俗易懂]

emWin学习[通俗易懂]


二、API学习

        EMWIN程序的执行是根据发生的消息类型来执行的,回调函数不是必须的但是回调函数的作用很重要。回调函数中首先根据消息的类型 pMsg->MsgId  来区分不同的消息类型–消息类型可以看手册WM部分的内容,区分开消息后再做相应的处理,假如消息是WM_NOTIFY_PARENT通知父窗口的消息,那就要判断消息来自哪里(WM_GetId()) 消息“始作俑者”是根据控件id来判断的所以先调用函数WM_GetId(pMsg->hWinSrc)将源消息句柄转换成ID再区分,不同的控件会有通知代码,看手册每个控件的通知即可,根据发生的动作点击、释放等可进行不同的处理。

   2.1、初始化

         int GUI_Init(void);  函数来初始化emWin内部数据结构和变量。如果在初始化之前调用WM_SetCreateFlags(WM_CF_MEMDEV)使用存储设备,防止按键带位图显示按下的时候闪烁,则在GUI_Init()内创建背景窗口。(也就是窗口设置创建标记必须在初始化之前)。

        需要定时的调用函数GUI_Exec()  来执行GUI界面的重绘。

    2.2、显示文本

          可以显示字符串、十六进制、十进制、二进制数,文本可以定位在屏幕上的任何像素。

     控制字符指字符代码小于32的字符,wmWin只能识别两个字符:

换行 ‘\n’,当前文本改变值下一行的开始,默认x=0,y+=字体-距离(像素)。

回车‘\r’ ,  当前文本位置改变至当前行的开始,默认x=0.

    2.2.1 文本API

            GUI_GotoXY( x ,y) ;坐标跳到x,y像素位置。


   2.3  按钮控件

         控件也是一个窗口,可以创建在其他窗口中或者直接在桌面上创建。按键也可以调用BUTTON_SetBitmapEx();函数在按钮上显示一个位图。

         按钮创建以后是矩形的,要向使按钮有拐角需要设置皮肤效果。                      BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);  开启皮肤效果。

BUTTON_GetSkinFlexProps(&BUT1_PRO,BUTTON_SKINFLEX_PI_PRESSED);  得到一个按钮句柄,通过修改句柄的渐变色和圆角半径来得到圆角和渐变的效果。

         BUT1_PRO.aColorFrame[0]=0x80ff;
BUT1_PRO.aColorFrame[1]=0x80ff;
        BUT1_PRO.aColorFrame[2]=0x80ff;
        BUT1_PRO.aColorUpper[0]=0x80ff;
        BUT1_PRO.aColorUpper[1]=0x80ff;
        BUT1_PRO.aColorLower[0]=0x80ff;
        BUT1_PRO.aColorLower[1]=0x80ff;
        BUT1_PRO.Radius=10;
        BUTTON_SetSkinFlexProps(&BUT1_PRO,BUTTON_SKINFLEX_PI_PRESSED);   设置按下的渐变效果。

       假如想做一个像手机上的图标图标那样,但是下载到的图标四个角是白色的,怎么做?用emwin自带的软件将png图片转换成透明的位图 .c 文件,然后WM_SetHasTrans(button1); 设置开启按钮的透明效果,然后就可以得到那样的效果了,但是北京必须是白色的,其他的方法还没试成功。


  2.4、ICONVIEW

       做下IconView的实验,找一个带alpha通道的png图标,然后用emwin自带的小软件转成C语言文件,转换的时候不要选择image->covert  to 我试了一下就算转换成带透明格式的最佳调色板显示出来的也不能成透明的,也可能是我的理解有问题。

      打开带透明通道的图标用自带的BMPcvt软件,打开以后直接点击文件保存,保存成带透明的格式。

     iconview = ICONVIEW_CreateEx(50,50,400,200,WM_HBKWIN,WM_CF_SHOW| WM_CF_HASTRANS,
                         ICONVIEW_CF_AUTOSCROLLBAR_V,ID_ICONVIEW,128,128
                       );

    创建标志一定要带WM_CF_HASTRANS,创建的icon窗口能和桌面桌面背景色进行混合。

   ICONVIEW_SetBkColor(iconview, ICONVIEW_CI_SEL, GUI_BLUE | 0xC0000000);  设置icon图标的背景色,通过调节0xc0000000的值来调节图标背景色的透明度,最高8位是alpha透明度的值,越大越透明当等于ff的时候完成是图标窗口或桌面的颜色。

 emWin学习[通俗易懂]

       选中图标后显示图标的背景色,调节alpha透明度可以调节透明程度,最后边的是GUI_DrawBitmap(&bm33,0,0);显示的桌面BMP图片。

        WM_SetCreateFlags(WM_CF_MEMDEV);  使用存储设备,放在GUI_Init() 函数之前,桌面也使用存储设备,我的iconview窗口是在桌面上创建的,不使能存储点击图标的时候,桌面会抖动。

        这是在PC仿真器上的效果,具体的等在stm32上测试。

iconview所在窗口的回调函数简单如下:

void bkCallback( WM_MESSAGE *msg)
{
	int id;

	switch(msg->MsgId)
	{
	   case WM_PAINT:
	     GUI_SetBkColor(GUI_LIGHTBLUE);
	     GUI_Clear();
		GUI_DrawBitmap(&bm33,0,0);
       
		GUI_SetFont(&GUI_Font13B_ASCII);
		GUI_SetColor(GUI_RED);
		GUI_DispDecAt(cnt,400,240,3);
		GUI_DispDecAt(cnt1,445,240,3);
		//ICONVIEW_SetBkColor(iconview, ICONVIEW_CI_SEL,GUI_LIGHTBLUE);
		break;
	   case WM_NOTIFY_PARENT:
		  
		   switch(WM_GetId(msg->hWinSrc))
		   {
		      case ID_ICONVIEW:  // 只在按下后显示背景色,松开后将背景色设置为透明
	                 if(msg->Data.v == WM_NOTIFICATION_CLICKED)
		          {
				 cnt1=ICONVIEW_GetSel(msg->hWinSrc);   // 得到选中的是哪个图标				        // 点击中后修改alpha值来使icon的背景色显示出来并且透明
			        ICONVIEW_SetBkColor(iconview, ICONVIEW_CI_SEL, GUI_BLUE | 0xc0000000);
			  }
		          else if(msg->Data.v == WM_NOTIFICATION_RELEASED)
			  {
  
  
                              // 设置alpha透明度的值,鼠标松开图标背景色完全透明
			     ICONVIEW_SetBkColor(iconview,ICONVIEW_CI_SEL, GUI_BLUE | 0xFF000000);
			  }
		          WM_InvalidateWindow(msg->hWin);
			break;
		   }
	     default:
	       WM_DefaultProc(msg);	
	}

}

     2.5、下拉列表 DROPDOWN  

             下拉列表和其他的控件差不多,我用这个空间我首先想到的是一个下拉列表中有很多的Item(条目),下拉列表收起来后我怎么知道我选中的是哪一个?刚开始我用通知代码WM_NOTIFICATION_CLICKED和WM_NOTIFICATION_RELEASED都不行,后来试了一下WM_NOTIFICATION_SEL-CHANGED 可以了。

下拉列表所在窗口的回调函数简单点如下:

   int item; // 选中的是第几个item,从0开始 void cbwindow(WM_MESSAGE *msg) { int id; switch(msg->MsgId) { case WM_NOTIFY_PARENT: id=WM_GetId(msg->hWinSrc); switch(id) { case ID_DROOPDOWN: if(msg->Data.v==WM_NOTIFICATION_SEL_CHANGED) { item=DROPDOWN_GetSelExp(msg->hwinSrc); } WM_InvalidateWindow(msg->hWin); break; } break; default: WM_DefaultProc(msg); } }

     2.6、对话框

                 因为对话框是框架窗口,要对客户区进行操作需要调用WM_GetClientWindow();  得到客户区。

三、使用过程注意事项

     1、窗口管理的设置标志必须在emWin初始化之前,即WMSetCreatFlags() 在GUI_Init()之前。

           WM_SetCreatFlags(WM_MEMDEV); 这样桌面也会使用缓冲重绘,当直接在桌面上绘制按钮或者iconview图标按下的时候不会闪烁。

	WM_EnableMemdev(WM_HBKWIN);
        WM_SetCreateFlags(WM_CF_MEMDEV);   
	WM_MULTIBUF_Enable(1);   	
	WM_EnableMemdev(WM_HBKWIN);

           注意emwin动态内存的使用情况,这几个函数将会占用emwin获得的内存,内存的占用将会使显示发生不可预知的错误,我将上边的函数都打开使用GUI_DispStringAt(); 函数显示字符,字符一闪屏幕就变黑了,将上边的函数注释掉就正常了。

     2、GUI_Clear() 函数,使用GUI_SetBkColor()函数之后,如果调用GUI_Clear()函数之后会对整个屏幕的背景颜色进行重新填充,如果GUI_SetBkColor()设置背景色后,没有调用GUI_Clear()函数,则只改变显示的文本部分的背景色,但是整个屏幕的背景色还是原来的颜色。

     3、GUI_DrawPoint();    画点函数,点的大小和画笔大小有关,可以用GUI_SetPenSize()函数来改变画笔大小,从而改变点的大小。

     3、GUI_Goto()函数在画线函数中不能改变画线函数相对偏移的起始位置,调用GUI_MoveTo();  函数改变画线函数的起始位置。 (至于为什么还没明白。) 如果不调用GUI_MoveTo()函数改变线条的位置,则默认是从原点开始的。

     4、样式:

               文本的样式  GUI_SetTextStyle()

               文本的模式  GUI_SetTextMode();

               线条的样式:GUI_SetLineStyle();    GUI_DrawLine() 使用线条样式,仅适用与pensize为1的情况。

               绘图模式:GUI_SetDrawMode();

    5、画多边形时坐标的计算

          GUI_DrawPolygon(const GUIPOINT *point,int NumPoints,int x,int y);  多变行绘制函数

           *point是一个结构体数组,包含着多变成每个拐点的坐标值,Numpoints 有几个拐点,x,y,多边行坐标的原点。与数学坐标略有不同,X轴与数学坐标一样,原点左边的是负右边的是正;Y轴与数学坐标相反,原点上边的是负,原点下边的是正。

    6、图片的显示分为两种:

         (1) 将图片加载到存储区然后显示

               可以用emwin带的位图转换软件将图片转换成.c文件或.dta格式文件,.c文件可以直接添加到工程中,然后在程序里边用函数GUI_BMP_Draw(); 直接调用.c文件中的数据来显示。这样耗费很大的Flash,而且也保存不了几幅图片。

               .dta格式或者本身的bmp格式图片可以放在外部的SD卡中,然后在程序中开辟足够大的内存空间,用fatfs文件系统的读函数将整个图片读到RAM中然后显示。

               加载到存储区显示比较耗费RAM空间,需要在配置emwin过程中指定的RAM空间至少比要显示图片的大小大5K左右,如果分配的是单片机内部的RAM,那单片机的RAM需要很大很大,最好是单片机挂载外部的SRAM,emwin配置过程将emwin的内存分配到外部SRAM。这样可以开辟较大空间加速图片的显示速度。

        (2) 图片无需加载到存储区

              图片以原格式放在SD卡中也可以显示,需要自己实现一个读数据的函数,buff的大小可以是屏幕行的大小*4,比较节省空间,在函数内部读一行像素的大小或更小,每次读完要进行地址的偏移。

               调用函数GUI_BMP_DrawEx(); 来实现从无需加载到存储区的显示。

 




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/182003.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 隶属度函数模板_高斯隶属度函数

    隶属度函数模板_高斯隶属度函数模糊隶属度函数划分等级根据国家对信号交叉路口的评价标准,对交通状况分为4个等级,分别为Ⅰ级舒适畅通、Ⅱ级接近饱和、Ⅲ级常呈混乱、Ⅳ级阻塞。因此选用4个等级的模糊隶属度函数。分别为:某时段交通状况对Ⅰ级路况的隶属度函数:        某时段交通状况对Ⅱ级路况的隶属度函数:        某时段交通状况对Ⅲ级路况的隶属度函数:        某时段交通状况对Ⅳ级

    2022年10月25日
  • 在手写数字识别的例子中_关于人脸识别的案例

    在手写数字识别的例子中_关于人脸识别的案例1.概念介绍:图像识别(ImageRecognition)是指利用计算机对图像进行处理、分析和理解,以识别各种不同模式的目标和对像的技术。 图像识别的发展经历了三个阶段:文字识别、数字图像处理与识别、物体识别。机器学习领域一般将此类识别问题转化为分类问题。手写识别是常见的图像识别任务。计算机通过手写体图片来识别出图片中的字,与印刷字体不同的是,不同人的手写体风…

  • 【2021最新版】MyBatis面试题总结(38道题含答案解析)[通俗易懂]

    【2021最新版】MyBatis面试题总结(38道题含答案解析)[通俗易懂]文章目录1、什么是Mybatis?2、Mybaits的优点?3、MyBatis框架的缺点?4、MyBatis框架适用场合5、MyBatis与Hibernate有哪些不同?6、#{}和${}的区别是什么?7、当实体类中的属性名和表中的字段名不一样,怎么办?8、模糊查询like语句该怎么写?9、通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?10、Mybatis是如何进行分页的?分页插件的原理是什么?11、Myba

  • java对象数组 创建对象数组,初始化对象数组「建议收藏」

    java对象数组 创建对象数组,初始化对象数组「建议收藏」对象数组的概念:如果一个数组中的元素是对象类型,则称该数组为对象数组。当需要一个类的多个对象时,应该用该类的对象数组来表示,通过改变下标值就可以访问到不同的对象。对象数组的定义和使用:对象数组的定义与一般数组的定义类似,但是需要为每一个元素实例化。对象数组的声明形式是:类名对象数组名[];为对象数组分配内存空间:对象数组名=new类名[数组长度];//注意:此处不是构…

  • idea激活码2022.01【中文破解版】

    (idea激活码2022.01)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~4…

  • Android进程间通信(IPC)机制Binder简介和学习计划

    Android进程间通信(IPC)机制Binder简介和学习计划

    2021年12月31日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号