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;