emWin(ucgui) 在PC端的模拟器,默认的按键机制是"按抬都Msg",当在按下键盘时,会收到一个key值-1,在按键没有离开时一直维持,当按键松开时还发送一个key值-0的标记。因此在你手速多快的状况下都会有一个 key,1和key,0两个操做。程序中没有对按键的状态作断定,因此在PC上无论是按下,仍是按下后离开都会进行响应(两次响应)。 ui
假设有如下的应用场景,一级菜单->(ENTER键)->二级菜单>(ENTER键)->三级菜单,即,在一级菜单是能够用ENTER键进入二级菜单,一样在二级菜单能够用ENTER键进入三级菜单,实现的方式是:响应ENTER键的消息,而后切换菜单。 spa
/******************************************************************************* blog
* Function Name :WIN_Enter ip
* Description :进入下一级窗口 it
* Input :int id:把进入的ID号 io
* Output :void gui
* Other : sed
* Date :2013/06/02 List
*******************************************************************************/ 程序
int WIN_Enter(int id)
{
ELEM_BLOCK_TYPE *pElem;
MENU_INFO_ITEM *pInfo;
MENU_INFO_ITEM *pCur; //当前的窗口
WIN_ContextLock();
if (m_WinList.index < 1) //窗口调度没有初始化
goto ext;
if (m_WinList.index >= WIN_LEVEL_LAYER_COUNT - 1)//窗口深度超出最大范围
goto ext;
pElem = &m_WinList.elem[m_WinList.index - 1]; //得到当前窗口
pCur = pInfo = pElem->menu;
pInfo = BT_GetRightChild(pInfo); //获取下级窗口
pInfo = BT_GetLChildElem(pInfo, *(int *)id);
if (pInfo == NULL) //无下级窗口
goto ext;
if (pInfo->data == NULL) //下级窗口元素为空
goto ext;
pElem->ret.id = *(int *)id; //保存所进入的ID
if (pInfo->data->win == NULL) //下级窗口无窗口数据
goto end;
if (pCur->data->win->destroy) //销毁当前窗口
(*pCur->data->win->destroy)(NULL);
if (pInfo->data->win->create) //新窗口创建
(*pInfo->data->win->create)(pInfo);
m_WinList.elem[m_WinList.index++].menu = pInfo; //保存新窗口到窗口列表中
end:
WIN_ContextUnlock();
if (pInfo->data->enter) {
(*pInfo->data->enter)(&id);
}
return OK;
ext:
WIN_ContextUnlock();
return FALSE;
}
以上代码是经过提早构造少的菜单树结构,而后在菜单节点响应ENTER键和ESC键完成进入和退出,从代码上看不出有什么问题了,可是在PC实际仿真的过程成发现,在一级菜单按下ENTER键时进入二级菜单,紧接着进入三级菜单。
全部须要对ENTER键进行判断响应,每次按下ENTER键就响应一次:
case WM_KEY:
switch (((WM_KEY_INFO *)(pMsg->Data.p))->Key){
case GUI_KEY_ENTER:
if(((WM_KEY_INFO *)(pMsg->Data.p))->PressedCnt == 0)
WIN_Enter(0);
break;
}
break;