emWin学习[通俗易懂]

2022-11-04 16:39:49 浏览数 (1)

一、WM窗口管理

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

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

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

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

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

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

控件的资源列表:

二、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的时候完成是图标窗口或桌面的颜色。

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

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

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

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

代码语言:javascript复制
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)
			  {
代码语言:javascript复制
                              // 设置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 可以了。

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

代码语言:javascript复制
   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图标按下的时候不会闪烁。

代码语言:javascript复制
	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(); 来实现从无需加载到存储区的显示。

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

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

0 人点赞