硬汉嵌入式论坛

 找回密码
 立即注册
查看: 637|回复: 8
收起左侧

[emWin] WM_MOTION 左滑,右滑信号

[复制链接]

3

主题

12

回帖

21

积分

新手上路

积分
21
发表于 2025-4-7 15:07:39 | 显示全部楼层 |阅读模式
请教,emwin中 WM_MOTION  能检测滑动动作,但是我翻看了《UM03001_emWin.pdf》的手册,没看到WM_MOTION_INFO中有参数能分辨他是左滑还是右滑?

请问有有对应的参数检测吗?或者有什么方法能在WM_MOTION信号后,分辨当前是左滑还是右滑?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-4-8 10:48:54 | 显示全部楼层
这个是我之前WM_MOTION消息做的处理

[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*	函 数 名: _cbMotion
*	功能说明: Motion窗口的回调函数,主要是桌面图标的滑动处理
*	形    参: pMsg  WM_MESSAGE类型指针变量   
*	返 回 值: 无
*********************************************************************************************************
*/
static void _cbMotion(WM_MESSAGE * pMsg) 
{
	WM_MOTION_INFO * pInfo;
	WM_HWIN          hWin = pMsg->hWin;
	PARA           * pPara;
	static uint32_t  tStart, tEnd;
	int NCode, Id;
	
	switch (pMsg->MsgId) 
	{
		case WM_PRE_PAINT:
			GUI_MULTIBUF_Begin();
			break;
		
		case WM_POST_PAINT:
			GUI_MULTIBUF_End();
			break;
		
		case WM_NOTIFY_PARENT:
			Id    = WM_GetId(pMsg->hWinSrc);     
			NCode = pMsg->Data.v;                 
			switch (Id) 
			{
				/* 第一个界面上的图标 */
				case GUI_ID_ICONVIEW0:
					switch (NCode) 
					{
						/* ICON控件点击消息 */
						case WM_NOTIFICATION_CLICKED:
							tStart = GUI_GetTime();
							break;

						/* ICON控件释放消息 */
						case WM_NOTIFICATION_RELEASED: 
							tEnd = GUI_GetTime() - tStart;
							if(tEnd > 800)
							{
								WM_SetFocus(WM_HBKWIN);
								break;							
							}
							_apModules0[ICONVIEW_GetSel(pMsg->hWinSrc)](WM_HBKWIN);
							break;
					}
					break;
					
				/* 第二个界面上的图标 */
				case GUI_ID_ICONVIEW1:
					switch (NCode) 
					{
						/* ICON控件点击消息 */
						case WM_NOTIFICATION_CLICKED:
							tStart = GUI_GetTime();
							break;

						/* ICON控件释放消息 */
						case WM_NOTIFICATION_RELEASED: 
							tEnd = GUI_GetTime() - tStart;
							if(tEnd > 800)
							{
								WM_SetFocus(WM_HBKWIN);
								break;							
							}
							_apModules1[ICONVIEW_GetSel(pMsg->hWinSrc)](WM_HBKWIN);
							break;
					}
					break;
					
					
				/* 第三个界面上的图标,仅用于演示目的 */
				case GUI_ID_ICONVIEW2:
					switch (NCode) 
					{
						/* ICON控件点击消息 */
						case WM_NOTIFICATION_CLICKED:
							tStart = GUI_GetTime();
							break;

						/* ICON控件释放消息 */
						case WM_NOTIFICATION_RELEASED: 
							tEnd = GUI_GetTime() - tStart;
							if(tEnd > 800)
							{
								WM_SetFocus(WM_HBKWIN);
								break;							
							}
							_apModules2[ICONVIEW_GetSel(pMsg->hWinSrc)](WM_HBKWIN);
							break;
					}
					break;
			}
			break;
				
	case WM_MOTION:
		WM_GetUserData(hWin, &pPara, sizeof(pPara));
		pInfo = (WM_MOTION_INFO *)pMsg->Data.p;
		switch (pInfo->Cmd) 
		{
			#if 1   /* F429板子采用的实现方式 ********************************
			           WM_MOTION_SetDefaultPeriod(20);周期设置小点,快速返回
			        */
				case WM_MOTION_INIT:
					pInfo->Flags =  WM_CF_MOTION_X | WM_MOTION_MANAGE_BY_WINDOW;
					pInfo->SnapX = 1;
					break;
		
				case WM_MOTION_MOVE:
					pPara->FinalMove = pInfo->FinalMove;
					pPara->Pos += pInfo->dx;
					printf_main("pData->xPos = %d %d\r\n", pPara->Pos, pInfo->dx);
				
					/* 滑动有加速度,停止后,减速度*/
					if(pPara->FinalMove)
					{
						printf_main("pData->FinalMove = %d\r\n", pPara->Pos);
						/* 桌面图标移动到此范围内就将其固定在第3个图标显示 */
						if(pPara->Pos <= -(LCD_GetXSize() + LCD_GetXSize()/2)) 
						{
							s_ucIconSwitch = 2;
							pPara->Pos = -(2 * LCD_GetXSize());
						}
						/* 桌面图标移动到此范围内就将其固定在第2个图标显示 */
						else if((pPara->Pos > -(LCD_GetXSize() + LCD_GetXSize()/2))&&(pPara->Pos <= -LCD_GetXSize()/2)) 
						{
							s_ucIconSwitch = 1;
							pPara->Pos = -(LCD_GetXSize());
						}
						/* 桌面图标移动到此范围内就将其固定在第1个图标显示 */
						else if(pPara->Pos > -LCD_GetXSize()/2) 
						{
							s_ucIconSwitch = 0;
							pPara->Pos = 0;
						}
					}
					
					/* WM_MOTION_SetDefaultPeriod设置的周期30ms及其以下时dx跳动较大
					   建议取值35-50即可。
					*/
					if((pInfo->dx < -4) || (pInfo->dx > 4) || (pPara->FinalMove))
					/* 移动桌面图标 */
					WM_MoveTo(hWin, pPara->Pos, 0);
					
			#else  /* emWin默认的Motion使用方案 ********************************
					 WM_MOTION_SetDefaultPeriod(100);设置的时间长点可以看出效果
					*/
				case WM_MOTION_INIT:
					pInfo->Flags =  WM_CF_MOTION_X | WM_MOTION_MANAGE_BY_WINDOW;
					pInfo->SnapX = 800; /* 设置栅格大小 */
					break;
		
				case WM_MOTION_MOVE:
					pPara->FinalMove = pInfo->FinalMove;
					pPara->Pos += pInfo->dx;
					printf_main("pData->xPos = %d %d\r\n", pPara->Pos, pInfo->dx);
				
					
					/* 设置滑动到最左侧时的处理办法,超过一半就不可以再滑动了,否则会滑动进行下一个栅格*/
					if(pPara->Pos >= LCD_GetXSize()/2)  
					   pPara->Pos = LCD_GetXSize()/2 - 1;
				
					/* 设置滑动到最右侧时的处理办法,超过一半就不可以再滑动了,否则会滑动进行下一个栅格*/
					if(pPara->Pos <= -(LCD_GetXSize()*2 + LCD_GetXSize()/2))  
						pPara->Pos = -(LCD_GetXSize()*2 + LCD_GetXSize()/2 - 1);
				
					/* 滑动松手后,会按照WM_MOTION_SetDefaultPeriod设置的时间减速并停止到最近的栅格 */
					if(pPara->FinalMove)
					{
						printf_main("pData->FinalMove = %d\r\n", pPara->Pos);
						/* 桌面图标移动到此范围内就将其固定在第3个图标显示 */
						if(pPara->Pos <= -(LCD_GetXSize() + LCD_GetXSize()/2)) 
						{
							s_ucIconSwitch = 2;
						}
						/* 桌面图标移动到此范围内就将其固定在第2个图标显示 */
						else if((pPara->Pos > -(LCD_GetXSize() + LCD_GetXSize()/2))&&(pPara->Pos <= -LCD_GetXSize()/2)) 
						{
							s_ucIconSwitch = 1;
						}
						/* 桌面图标移动到此范围内就将其固定在第1个图标显示 */
						else if(pPara->Pos > -LCD_GetXSize()/2) 
						{
							s_ucIconSwitch = 0;
						}
					}
					
					/* 移动桌面图标 */
					WM_MoveTo(hWin, pPara->Pos, 0);
					
					/* 下面这个三个未使用,当设置滑动窗口的大小是800*480时,可以仅拖动ICONVIEW控件即可 
					    当前是采用800*3宽度的界面大小,是拖动的ICONVIEW控件的父窗口。
					*/
					//WM_MoveTo(hIcon1, pPara->Pos + ICONVIEW_LBorder , ICONVIEW_TBorder);
					//WM_MoveTo(hIcon2, pPara->Pos + 800 + ICONVIEW_LBorder, ICONVIEW_TBorder);
					//WM_MoveTo(hIcon3, pPara->Pos + 1600 + ICONVIEW_LBorder, ICONVIEW_TBorder);
				#endif
				break;
		
			case WM_MOTION_GETPOS:
				pInfo->xPos = pPara->Pos;
				break;
    }
    break;
  }
}
回复

使用道具 举报

3

主题

12

回帖

21

积分

新手上路

积分
21
 楼主| 发表于 2025-7-1 14:59:16 | 显示全部楼层
eric2013 发表于 2025-4-8 10:48
这个是我之前WM_MOTION消息做的处理

[C] 纯文本查看 复制代码
/*
[/quote]

你好,请教一下,我参考你2016年的工程,做了一个简单的窗口滑动,想去验证一下消息能否正常触发,但是实际测试工程中,WM_MOTION 和WM_MOTION_INIT都能触发,手指放上去就能触发。但是WM_MOTION_MOVE没有任何信息输出,看起来像是没有被触发,请教是我的函数写的哪里不对吗?还是说一直过程中有漏掉的地方[mw_shl_code=c,true]/*
*********************************************************************************************************
*	函 数 名: _cbMotion
*	功能说明: Motion窗口的回调函数,主要是桌面图标的滑动处理
*	形    参: pMsg  WM_MESSAGE类型指针变量   
*	返 回 值: 无
*********************************************************************************************************
*/
static void _cbMotion(WM_MESSAGE * pMsg) 
{
	WM_MOTION_INFO * pInfo;
	WM_HWIN          hWin = pMsg->hWin;
	PARA           * pPara;
	static uint32_t  tStart, tEnd;
	int NCode, Id;
	
	switch (pMsg->MsgId) 
	{
		case WM_PRE_PAINT:
			GUI_MULTIBUF_Begin();
			break;
		
		case WM_POST_PAINT:
			GUI_MULTIBUF_End();
			break;
		
		case WM_NOTIFY_PARENT:
			Id    = WM_GetId(pMsg->hWinSrc);     
			NCode = pMsg->Data.v;                 
			switch (Id) 
			{

			}
			break;
				
	case WM_MOTION:
		WM_GetUserData(hWin, &pPara, sizeof(pPara));
		pInfo = (WM_MOTION_INFO *)pMsg->Data.p;
        DBG_PRINTF("WM MOTION Trigger\r\n");
		switch (pInfo->Cmd) 
		{
			#if 1   /* F429板子采用的实现方式 ********************************
			           WM_MOTION_SetDefaultPeriod(20);周期设置小点,快速返回
			        */
				case WM_MOTION_INIT:
                    DBG_PRINTF("WM MOTION Init \r\n");
					pInfo->Flags =  WM_CF_MOTION_X | WM_MOTION_MANAGE_BY_WINDOW;
					pInfo->SnapX = 1;
					break;
		
				case WM_MOTION_MOVE:
                    DBG_PRINTF("WM MOTION Move \r\n");
					pPara->FinalMove = pInfo->FinalMove;
					pPara->Pos += pInfo->dx;
					DBG_PRINTF("pData->xPos = %d %d\r\n", pPara->Pos, pInfo->dx);
				
//					/* 滑动有加速度,停止后,减速度*/
//					if(pPara->FinalMove)
//					{
//						DBG_PRINTF("pData->FinalMove = %d\r\n", pPara->Pos);
//						/* 桌面图标移动到此范围内就将其固定在第3个图标显示 */
//						if(pPara->Pos <= -(LCD_GetXSize() + LCD_GetXSize()/2)) 
//						{
//		
//							pPara->Pos = -(2 * LCD_GetXSize());
//						}
//						/* 桌面图标移动到此范围内就将其固定在第2个图标显示 */
//						else if((pPara->Pos > -(LCD_GetXSize() + LCD_GetXSize()/2))&&(pPara->Pos <= -LCD_GetXSize()/2)) 
//						{
//	
//							pPara->Pos = -(LCD_GetXSize());
//						}
//						/* 桌面图标移动到此范围内就将其固定在第1个图标显示 */
//						else if(pPara->Pos > -LCD_GetXSize()/2) 
//						{
//                            pPara->Pos = 0;
//						}
//					}
//					
//					/* WM_MOTION_SetDefaultPeriod设置的周期30ms及其以下时dx跳动较大
//					   建议取值35-50即可。
//					*/
//					if((pInfo->dx < -4) || (pInfo->dx > 4) || (pPara->FinalMove))
//					/* 移动桌面图标 */
//					WM_MoveTo(hWin, pPara->Pos, 0);
//					
			#else  /* emWin默认的Motion使用方案 ********************************
					 WM_MOTION_SetDefaultPeriod(100);设置的时间长点可以看出效果
					*/
				case WM_MOTION_INIT:
					pInfo->Flags =  WM_CF_MOTION_X | WM_MOTION_MANAGE_BY_WINDOW;
					pInfo->SnapX = 800; /* 设置栅格大小 */
					break;
		
				case WM_MOTION_MOVE:
					pPara->FinalMove = pInfo->FinalMove;
					pPara->Pos += pInfo->dx;
					printf_main("pData->xPos = %d %d\r\n", pPara->Pos, pInfo->dx);
				
					
					/* 设置滑动到最左侧时的处理办法,超过一半就不可以再滑动了,否则会滑动进行下一个栅格*/
					if(pPara->Pos >= LCD_GetXSize()/2)  
					   pPara->Pos = LCD_GetXSize()/2 - 1;
				
					/* 设置滑动到最右侧时的处理办法,超过一半就不可以再滑动了,否则会滑动进行下一个栅格*/
					if(pPara->Pos <= -(LCD_GetXSize()*2 + LCD_GetXSize()/2))  
						pPara->Pos = -(LCD_GetXSize()*2 + LCD_GetXSize()/2 - 1);
				
					/* 滑动松手后,会按照WM_MOTION_SetDefaultPeriod设置的时间减速并停止到最近的栅格 */
					if(pPara->FinalMove)
					{
						printf_main("pData->FinalMove = %d\r\n", pPara->Pos);
						/* 桌面图标移动到此范围内就将其固定在第3个图标显示 */
						if(pPara->Pos <= -(LCD_GetXSize() + LCD_GetXSize()/2)) 
						{
							s_ucIconSwitch = 2;
						}
						/* 桌面图标移动到此范围内就将其固定在第2个图标显示 */
						else if((pPara->Pos > -(LCD_GetXSize() + LCD_GetXSize()/2))&&(pPara->Pos <= -LCD_GetXSize()/2)) 
						{
							s_ucIconSwitch = 1;
						}
						/* 桌面图标移动到此范围内就将其固定在第1个图标显示 */
						else if(pPara->Pos > -LCD_GetXSize()/2) 
						{
							s_ucIconSwitch = 0;
						}
					}
					
					/* 移动桌面图标 */
					WM_MoveTo(hWin, pPara->Pos, 0);
					
					/* 下面这个三个未使用,当设置滑动窗口的大小是800*480时,可以仅拖动ICONVIEW控件即可 
					    当前是采用800*3宽度的界面大小,是拖动的ICONVIEW控件的父窗口。
					*/
					//WM_MoveTo(hIcon1, pPara->Pos + ICONVIEW_LBorder , ICONVIEW_TBorder);
					//WM_MoveTo(hIcon2, pPara->Pos + 800 + ICONVIEW_LBorder, ICONVIEW_TBorder);
					//WM_MoveTo(hIcon3, pPara->Pos + 1600 + ICONVIEW_LBorder, ICONVIEW_TBorder);
				#endif
				break;
		
			case WM_MOTION_GETPOS:
				pInfo->xPos = pPara->Pos;
				break;
    }
    break;
  }
}



/**********************************************
*@name:MainTask
*@effect:main主函数调用的两个函数之一,ui绘制的主体,while循环
*@param:
*    pMsg:消息
*@return:NULL
***********************************************/
void MainTask(void) 
{              
	PARA Para;
	PARA *pPara;
    static WINDOW_DATA Data;
	
	/* 数据初始化 */
	pPara = &Para;
    pPara->Pos = 0;
	
    GUI_Init();  /* 初始化 */    
	
    GUI_SetOrientation(GUI_SWAP_XY| GUI_MIRROR_X);

	WM_MULTIBUF_Enable(1);
    WM_MOTION_Enable(1);//启用滑动支持
 
	WM_MOTION_SetDefaultPeriod(50);	//释放后,默认的减速值
    
    bsp_Idle();
   
    Data.xSize = LCD_GetXSize();
    Data.ySize = LCD_GetYSize();
    Data.TimeLastTouch = GUI_GetTime();
    WM_SetSize(WM_HBKWIN, Data.xSize, Data.ySize);

    DBG_PRINTF("LCD_X = %d ,LCD_Y = %d\r\n",Data.xSize,Data.ySize);
      
	/* 第3步:绘制桌面窗口的背景图片 ------------------------------------------*/
	hMotion = WM_CreateWindowAsChild(0, 
	                                 0, 
									 SCREEN_Width*3, 
									 SCREEN_Height, 
					                 WM_HBKWIN,  
									 WM_CF_MOTION_X | WM_CF_SHOW | WM_CF_HASTRANS, 
									 _cbMotion, 
									 sizeof(pPara));
									 
    WM_SetUserData(hMotion, &pPara, sizeof(pPara));      
    
    
    
    bsp_StartAutoTimer(0,100);//测试单位1ms,100ms扫一次
	DBG_PRINTF("while(1) \r\n");
	while(1) 
	{ 
        GUI_Delay(10);
        bsp_Idle();
//        bsp_DelayMS(100);
        
        //timer0:接收命令函数
        if(bsp_CheckTimer(0))
        {}
   
	}
}
回复

使用道具 举报

3

主题

12

回帖

21

积分

新手上路

积分
21
 楼主| 发表于 2025-7-2 20:03:36 | 显示全部楼层
hsw1234 发表于 2025-7-1 14:59
你好,请教一下,我参考你2016年的工程,做了一个简单的窗口滑动,想去验证一下消息能否正常触发,但是实 ...

已经解决,是我上报触摸点位的函数使用和上报方式有问题,读到的值会为0,所以做了一个防备机制,导致上报的时候有问题,没办法连续上报点位,所以WM_MOTION_MOVE无法正常触发
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-3 09:18:04 | 显示全部楼层
hsw1234 发表于 2025-7-2 20:03
已经解决,是我上报触摸点位的函数使用和上报方式有问题,读到的值会为0,所以做了一个防备机制,导致上 ...

回复

使用道具 举报

3

主题

12

回帖

21

积分

新手上路

积分
21
 楼主| 发表于 2025-7-3 19:19:09 | 显示全部楼层

有两个问题想请教一下
1.小屏幕是不是不适合做iconview,我在560x170的屏幕上,创建可一个iconview,放了5个图标(56x56),居中防止,但是滑动的时候,会触发WM_NOTIFICATION_CLICKED,尤其是两界面切换的时候,会触发创建点击消息,然后卡死。想请教一下,这个点击的问题是不是无法避免,只要点击到iconview就会触发点击消息

2.我尝试在滑动窗口创建button,这样可以避免iconview的问题,但是出现了滑动拖影的问题,看起来,没有清除滑动之前的button图像,我尝试用WM_SetCallback(WM_HBKWIN, _cbBkWindow);去重绘清除,但是没有效果
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-4 09:43:51 | 显示全部楼层
hsw1234 发表于 2025-7-3 19:19
有两个问题想请教一下
1.小屏幕是不是不适合做iconview,我在560x170的屏幕上,创建可一个iconview,放了5 ...

改进为松手触发ICONVIEW
回复

使用道具 举报

3

主题

12

回帖

21

积分

新手上路

积分
21
 楼主| 发表于 2025-7-4 18:08:46 | 显示全部楼层
eric2013 发表于 2025-7-4 09:43
改进为松手触发ICONVIEW

这个是我表述有误,不是WM_NOTIFICATION_CLICKED 和WM_NOTIFICATION_RELEASED的问题,在iconview滑动的时候,会同步触发WM_NOTIFICATION_RELEASED,然后的调用函数还没准备好,于是就死机了。因为屏幕小,很难避免滑动过程误选中图标的问题,不能像你的示例中那样可以避开iconview,避免这种状况。我加了个标志去判断,好一些,这个问题已经解决了


请教一个音量滑条的问题,是不是只有ST的芯片才能使用STemWin_Addons_KEIL.lib库,我是新塘的芯片,加上这个库,编译不过去,显示指令集不兼容?

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 03:12 , Processed in 0.044851 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表