|
先来看下我们新版教程的说明:
===============================
为什么函数GUI_SendKeyMsg不能在中断里面调用,且看下面早期UCGUI3.98的源码
/*********************************************************************
*
* GUI_StoreKeyMsg
*/
void GUI_StoreKeyMsg(int Key, int PressedCnt) {
#if GUI_WINSUPPORT /* If 0, WM will not generate any code */
_KeyMsg.Key = Key;
_KeyMsg.PressedCnt = PressedCnt;
_KeyMsgCnt = 1;
#ifdef GUI_X_ON_UNPROCESSED_KEY
if (!WM_IsActive) {
/* If the WM is deactivated, key messages are not polled by the WM.
So call the macro in this case here.
*/
GUI_X_ON_UNPROCESSED_KEY(Key, PressedCnt);
}
#endif
GUI_X_SIGNAL_EVENT();
#else
GUI_USE_PARA(PressedCnt);
GUI_StoreKey(Key);
#ifdef GUI_X_ON_UNPROCESSED_KEY
GUI_X_ON_UNPROCESSED_KEY(Key, PressedCnt);
#endif
#endif
}
/*********************************************************************
*
* GUI_SendKeyMsg
*
* Purpose:
* Send the key to a window using the window manager (if available).
* If no window is ready to take the input, we call the store routine
* and wait for somebody to poll the buffer.
*/
void GUI_SendKeyMsg(int Key, int PressedCnt) {
#if GUI_WINSUPPORT /* If 0, WM will not generate any code */
if (!WM_OnKey(Key, PressedCnt)) {
#ifdef GUI_X_ON_UNPROCESSED_KEY
GUI_X_ON_UNPROCESSED_KEY(Key, PressedCnt);
#endif
GUI_StoreKeyMsg(Key, PressedCnt);
}
#else
GUI_StoreKeyMsg(Key, PressedCnt);
#endif
}
其中的关键就在函数WM_OnKey里面了,这个函数里面有调用GUI锁,而锁的实现是基于RTOS的pend函数
这些函数一般都是不允许在中断里面调用的。
/*********************************************************************
*
* WM_OnKey
Returns:
0 if message could not be handled
*/
int WM_OnKey(int Key, int Pressed) {
int r = 0;
WM_MESSAGE Msg;
WM_LOCK();
if (WM__hWinFocus != 0) {
WM_KEY_INFO Info;
Info.Key = Key;
Info.PressedCnt = Pressed;
Msg.MsgId = WM_KEY;
Msg.Data.p = &Info;
WM__SendMessage(WM__hWinFocus, &Msg);
r = 1;
}
WM_UNLOCK();
return r;
}
上面这个函数WM__SendMessage会直接执行被聚焦窗口的回调函数,所以
用于调用函数GUI_SendKeyMsg会让聚焦的窗口的按键消息得到立即执行,这点特别注意:
/*********************************************************************
*
* WM__SendMessage
*/
void WM__SendMessage(WM_HWIN hWin, WM_MESSAGE* pMsg) {
static int _EntranceCnt;
WM_Obj* pWin;
if (_EntranceCnt < GUI_MAX_MESSAGE_NESTING) {
pWin = WM_HANDLE2PTR(hWin);
pMsg->hWin = hWin;
if (pWin->cb != NULL) {
_EntranceCnt++;
(*pWin->cb)(pMsg);
_EntranceCnt--;
} else {
WM_DefaultProc(pMsg);
}
}
#if GUI_DEBUG_LEVEL >= GUI_DEBUG_LEVEL_CHECK_PARA
else {
GUI_DEBUG_ERROROUT("Max. message nesting exceeded, Message skipped.");
}
#endif
} |
|