📄 listbox.c
字号:
if (WIDGET_HandleActive(hObj, pMsg) == 0)
{
/* Owner needs to be informed about focus change */
if (pMsg->MsgId == WM_SET_FOCUS)
{
if (pMsg->Data.v == 0)
{
/* Lost focus ? */
_NotifyOwner(hObj, LISTBOX_NOTIFICATION_LOST_FOCUS);
}
}
return;
}
switch (pMsg->MsgId)
{
case WM_NOTIFY_PARENT:
switch (pMsg->Data.v)
{
case WM_NOTIFICATION_VALUE_CHANGED:
if (pMsg->hWinSrc == WM_GetScrollbarV(hObj))
{
WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
pObj->ScrollStateV.v = ScrollState.v;
LISTBOX__InvalidateInsideArea(hObj);
_NotifyOwner(hObj, WM_NOTIFICATION_SCROLL_CHANGED);
}
else if (pMsg->hWinSrc == WM_GetScrollbarH(hObj))
{
WM_GetScrollState(pMsg->hWinSrc, &ScrollState);
pObj->ScrollStateH.v = ScrollState.v;
LISTBOX__InvalidateInsideArea(hObj);
_NotifyOwner(hObj, WM_NOTIFICATION_SCROLL_CHANGED);
}
break;
case WM_NOTIFICATION_SCROLLBAR_ADDED:
LISTBOX_UpdateScrollers(hObj);
break;
}
break;
case WM_PAINT:
_OnPaint(hObj, pObj, pMsg);
break;
case WM_PID_STATE_CHANGED:
{
const WM_PID_STATE_CHANGED_INFO* pInfo = (const WM_PID_STATE_CHANGED_INFO *) pMsg->Data.p;
if (pInfo->State)
{
int Sel;
Sel = _GetItemFromPos(hObj, pObj, pInfo->x, pInfo->y);
if (Sel >= 0)
{
_ToggleMultiSel(hObj, pObj, Sel);
LISTBOX_SetSel(hObj, Sel);
}
_NotifyOwner(hObj, WM_NOTIFICATION_CLICKED);
return;
}
}
break;
case WM_TOUCH:
_OnTouch(hObj, pMsg);
return;
#if GUI_SUPPORT_MOUSE
case WM_MOUSEOVER:
if (_OnMouseOver(hObj, pObj, pMsg) == 0)
{
return;
}
break;
#endif
case WM_DELETE:
_FreeAttached(pObj);
break; /* No return here ... WM_DefaultProc needs to be called */
case WM_KEY:
if (((const WM_KEY_INFO *) (pMsg->Data.p))->PressedCnt > 0)
{
int Key;
Key = ((const WM_KEY_INFO *) (pMsg->Data.p))->Key;
if (LISTBOX_AddKey(hObj, Key))
{
return;
}
}
break;
case WM_SIZE:
LISTBOX_UpdateScrollers(hObj);
WM_InvalidateWindow(hObj);
break;
}
WM_DefaultProc(pMsg);
}
/*********************************************************************
*
* _MoveSel
*
* Moves the selection/focus to the next valid item
*/
static void _MoveSel(LISTBOX_Handle hObj, int Dir)
{
int Index, NewSel = -1, NumItems;
LISTBOX_Obj * pObj;
pObj = LISTBOX_H2P(hObj);
Index = LISTBOX_GetSel(hObj);
NumItems = LISTBOX__GetNumItems(pObj);
do
{
WM_HMEM hItem;
Index += Dir;
if ((Index < 0) || (Index >= NumItems))
{
break;
}
hItem = GUI_ARRAY_GethItem(&pObj->ItemArray, Index);
if (hItem)
{
LISTBOX_ITEM * pItem = (LISTBOX_ITEM *) GUI_ALLOC_h2p(hItem);
if (!(pItem->Status & LISTBOX_ITEM_DISABLED))
{
NewSel = Index;
}
}
}
while (NewSel < 0);
if (NewSel >= 0)
{
LISTBOX_SetSel(hObj, NewSel);
}
}
/*********************************************************************
*
* _AddKey
*
* Returns: 1 if Key has been consumed
* 0 else
*/
static int _AddKey(LISTBOX_Handle hObj, int Key)
{
LISTBOX_Obj* pObj;
pObj = LISTBOX_H2P(hObj);
switch (Key)
{
case ' ':
_ToggleMultiSel(hObj, pObj, pObj->Sel);
return 1; /* Key has been consumed */
case GUI_KEY_RIGHT:
if (WM_SetScrollValue(&pObj->ScrollStateH, pObj->ScrollStateH.v + pObj->Props.ScrollStepH))
{
LISTBOX_UpdateScrollers(hObj);
LISTBOX__InvalidateInsideArea(hObj);
}
return 1; /* Key has been consumed */
case GUI_KEY_LEFT:
if (WM_SetScrollValue(&pObj->ScrollStateH, pObj->ScrollStateH.v - pObj->Props.ScrollStepH))
{
LISTBOX_UpdateScrollers(hObj);
LISTBOX__InvalidateInsideArea(hObj);
}
return 1; /* Key has been consumed */
case GUI_KEY_DOWN:
LISTBOX_IncSel(hObj);
return 1; /* Key has been consumed */
case GUI_KEY_UP:
LISTBOX_DecSel(hObj);
return 1; /* Key has been consumed */
default:
if (_IsAlphaNum(Key))
{
_SelectByKey(hObj, Key);
return 1; /* Key has been consumed */
}
}
return 0;
}
/*********************************************************************
*
* Exported routines: Create
*
**********************************************************************
*/
/*********************************************************************
*
* LISTBOX_CreateEx
*/
LISTBOX_Handle LISTBOX_CreateEx(int x0, int y0, int xsize, int ysize, WM_HWIN hParent, int WinFlags, int ExFlags, int Id, const GUI_ConstString *ppText)
{
LISTBOX_Handle hObj;
GUI_USE_PARA(ExFlags);
hObj = WM_CreateWindowAsChild(x0, y0, xsize, ysize, hParent, WinFlags, _LISTBOX_Callback, sizeof(LISTBOX_Obj) - sizeof(WM_Obj));
if (hObj)
{
LISTBOX_Obj* pObj;
WM_LOCK();
pObj = LISTBOX_H2P(hObj);
/* Init sub-classes */
GUI_ARRAY_CREATE(&pObj->ItemArray);
/* init widget specific variables */
WIDGET__Init(&pObj->Widget, Id, WIDGET_STATE_FOCUSSABLE);
pObj->Props = LISTBOX_DefaultProps;
if (ppText)
{
/* init member variables */
/* Set non-zero attributes */
LISTBOX_SetText(hObj, ppText);
}
INIT_ID(pObj);
LISTBOX_UpdateScrollers(hObj);
WM_UNLOCK();
}
return hObj;
}
/*********************************************************************
*
* Exported routines: Various methods
*
**********************************************************************
*/
/*********************************************************************
*
* LISTBOX_InvalidateItem
*/
void LISTBOX_InvalidateItem(LISTBOX_Handle hObj, int Index)
{
if (hObj)
{
LISTBOX_Obj* pObj;
int NumItems;
WM_LOCK();
pObj = LISTBOX_H2P(hObj);
NumItems = LISTBOX__GetNumItems(pObj);
if (Index < NumItems)
{
if (Index < 0)
{
int i;
for (i = 0; i < NumItems; i++)
{
LISTBOX__InvalidateItemSize(pObj, i);
}
LISTBOX_UpdateScrollers(hObj);
LISTBOX__InvalidateInsideArea(hObj);
}
else
{
LISTBOX__InvalidateItemSize(pObj, Index);
LISTBOX_UpdateScrollers(hObj);
LISTBOX__InvalidateItemAndBelow(hObj, pObj, Index);
}
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTBOX_AddKey
*
* Returns: 1 if Key has been consumed
* 0 else
*/
int LISTBOX_AddKey(LISTBOX_Handle hObj, int Key)
{
int r = 0;
if (hObj)
{
WM_LOCK();
r = _AddKey(hObj, Key);
WM_UNLOCK();
}
return r;
}
/*********************************************************************
*
* LISTBOX_AddString
*/
void LISTBOX_AddString(LISTBOX_Handle hObj, const char *s)
{
if (hObj && s)
{
LISTBOX_Obj* pObj;
LISTBOX_ITEM Item = {0, 0};
WM_LOCK();
pObj = LISTBOX_H2P(hObj);
if (GUI_ARRAY_AddItem(&pObj->ItemArray, &Item, sizeof(LISTBOX_ITEM) + strlen(s)) == 0)
{
unsigned ItemIndex = GUI_ARRAY_GetNumItems(&pObj->ItemArray) - 1;
LISTBOX_ITEM* pItem = (LISTBOX_ITEM *) GUI_ARRAY_GetpItem(&pObj->ItemArray, ItemIndex);
strcpy(pItem->acText, s);
LISTBOX__InvalidateItemSize(pObj, ItemIndex);
LISTBOX_UpdateScrollers(hObj);
LISTBOX__InvalidateItem(hObj, pObj, ItemIndex);
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTBOX_SetText
*/
void LISTBOX_SetText(LISTBOX_Handle hObj, const GUI_ConstString *ppText)
{
if (hObj)
{
int i;
const char* s;
WM_LOCK();
if (ppText)
{
for (i = 0; (s = *(ppText + i)) != 0; i++)
{
LISTBOX_AddString(hObj, s);
}
}
LISTBOX_InvalidateItem(hObj, LISTBOX_ALL_ITEMS);
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTBOX_SetSel
*/
void LISTBOX_SetSel(LISTBOX_Handle hObj, int NewSel)
{
if (hObj)
{
LISTBOX_Obj* pObj;
int MaxSel;
WM_LOCK();
pObj = LISTBOX_H2P(hObj);
MaxSel = LISTBOX__GetNumItems(pObj);
MaxSel = MaxSel ? MaxSel - 1 : 0;
if (NewSel > MaxSel)
{
NewSel = MaxSel;
}
if (NewSel < 0)
{
NewSel = -1;
}
else
{
WM_HMEM hItem = GUI_ARRAY_GethItem(&pObj->ItemArray, NewSel);
if (hItem)
{
LISTBOX_ITEM* pItem = (LISTBOX_ITEM *) GUI_ALLOC_h2p(hItem);
if (pItem->Status & LISTBOX_ITEM_DISABLED)
{
NewSel = -1;
}
}
}
if (NewSel != pObj->Sel)
{
int OldSel;
OldSel = pObj->Sel;
pObj->Sel = NewSel;
if (_UpdateScrollPos(hObj, pObj))
{
LISTBOX__InvalidateInsideArea(hObj);
}
else
{
LISTBOX__InvalidateItem(hObj, pObj, OldSel);
LISTBOX__InvalidateItem(hObj, pObj, NewSel);
}
_NotifyOwner(hObj, WM_NOTIFICATION_SEL_CHANGED);
}
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTBOX_GetSel
*/
int LISTBOX_GetSel(LISTBOX_Handle hObj)
{
int r = -1;
LISTBOX_Obj* pObj;
if (hObj)
{
WM_LOCK();
pObj = LISTBOX_H2P(hObj);
ASSERT_IS_VALID_PTR(pObj);
r = pObj->Sel;
WM_UNLOCK();
}
return r;
}
/*********************************************************************
*
* LISTBOX_IncSel
*/
void LISTBOX_IncSel(LISTBOX_Handle hObj)
{
if (hObj)
{
WM_LOCK();
_MoveSel(hObj, 1);
WM_UNLOCK();
}
}
/*********************************************************************
*
* LISTBOX_DecSel
*/
void LISTBOX_DecSel(LISTBOX_Handle hObj)
{
if (hObj)
{
WM_LOCK();
_MoveSel(hObj, -1);
WM_UNLOCK();
}
}
#else /* Avoid problems with empty object modules */
void LISTBOX_C(void)
{
}
#endif
/*************************** End of file ****************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -