📄 listbox.c
字号:
static void _LISTBOX_Callback(WM_MESSAGE*pMsg) {
LISTBOX_Handle hObj = pMsg->hWin;
LISTBOX_Obj* pObj = LISTBOX_H2P(hObj);
WM_SCROLL_STATE ScrollState;
/* Let widget handle the standard messages */
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 + -