📄 listbox.c
字号:
int ListBox_InsertItem(HWND hWnd,int index,char *strItem)
{ TListBoxItem *node;
TListBox *m=(TListBox *)WndClsBuf(hWnd);
int i;
node=(TListBoxItem *)GetMem(sizeof(TListBoxItem));
if(strItem)
{ node->caption=(char *)GetMem(strlen(strItem)+1);
strcpy(node->caption,strItem);
}else node->caption=NULL;
if(m->TotalItemCount==0)
{ m->Head=m->PageFirst=node->next=node->prev=node;
node->index=0;
ListBox_SelectedAssign(hWnd,node);
index=0;
}
else
{ TListBoxItem *insertpos=m->Head;
if(index>=0 && index<m->TotalItemCount)
{ if(index==0) m->Head=node;
else for(i=0;i<index;i++) insertpos=insertpos->next;
if(insertpos==m->PageFirst) m->PageFirst=node;
}else index=m->TotalItemCount; /*return value*/
node->next=insertpos;
node->prev=insertpos->prev;
node->next->prev=node;
node->prev->next=node;
node->index=index;
}
m->TotalItemCount++;
for(i=index;i<m->TotalItemCount;i++)
{ node->index=i;
node=node->next;
}
Invalidate(hWnd);
if(WndGetAttr(hWnd,WS_VSCROLL|WS_BORDER)==(WS_VSCROLL|WS_BORDER))
{ ScrollBar_Synchronize2(hWnd,m->PageFirst->index,m->TotalItemCount);
}
return index;
}
//---------------------------------------------------------------------------
void ListBox_ChangeItem(HWND hWnd,int index,char *strItem)
{ TListBoxItem *node=GetItemNodeByIndex(hWnd,index);
if(node)
{ if(strcmp(node->caption,strItem)!=0)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(node->caption) FreeMem(node->caption);
if(strItem)
{ node->caption=(char *)GetMem(strlen(strItem)+1);
strcpy(node->caption,strItem);
}else node->caption=NULL;
if(m->MarqueeItem==node)
{ int textwidth=strlen(node->caption)*SYS_FONT_WIDTH;
int clipwidth=crWidth(hWnd)-m->LeftMargin;
if(textwidth<=clipwidth)
{ m->MarqueeItem=NULL;
if(m->NewMarquee==node)
{ m->NewMarquee=NULL;
EnableTimer(m->MarqueeTimer,false);
}
}
}
RepaintSubItem(hWnd,index);
}
}
}
//---------------------------------------------------------------------------
int ListBox_AddItem(HWND hWnd,char *strItem)
{ return ListBox_InsertItem(hWnd,-1,strItem);
}
//---------------------------------------------------------------------------
bool ListBox_DeleteItem(HWND hWnd,int index)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(index>=0 && index<m->TotalItemCount)
{ TListBoxItem *node,*nextnode;
int i;
for(i=0,node=m->Head;i<index;i++)
{ node=node->next;
}
if(m->TotalItemCount>1)
{ if(node==m->Selected)
{ if(node->next!=m->Head) ListBox_SelectedAssign(hWnd,node->next);
else ListBox_SelectedAssign(hWnd,node->prev);
}
if(node==m->Head)m->Head=node->next;
if(node==m->PageFirst)m->PageFirst=node->next;
node->prev->next=node->next;
node->next->prev=node->prev;
if(m->PageFirst->index+m->CountPerPage>=m->TotalItemCount && m->PageFirst!=m->Head)
{ m->PageFirst=m->PageFirst->prev; /*a line scoll up*/
}
}
else
{ m->Head=m->PageFirst=NULL;
ListBox_SelectedAssign(hWnd,NULL);
}
if(node==m->NewMarquee)
{ m->NewMarquee=NULL;
}
if(node==m->MarqueeItem)
{ m->MarqueeItem=NULL;
}
nextnode=node->next;
FreeMem(node->caption);
FreeMem(node);
m->TotalItemCount--;
for(i=index;i<m->TotalItemCount;i++)
{ nextnode->index=i;
nextnode=nextnode->next;
}
Invalidate(hWnd);
if(WndGetAttr(hWnd,WS_VSCROLL|WS_BORDER)==(WS_VSCROLL|WS_BORDER))
{ ScrollBar_Synchronize2(hWnd,(m->PageFirst)?m->PageFirst->index:0,m->TotalItemCount);
}
return true;
}else return false;
}
//---------------------------------------------------------------------------
int ListBox_SetSelectedIndex(HWND hWnd,int index)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
int oldsel=(m->Selected)?m->Selected->index:-1;
if(m->PageFirst)
{ if(index<0 || index>=m->TotalItemCount)index=-1;
if(index==oldsel) return oldsel;
if(index==-1)
{ ListBoxChangeSubFocus(hWnd,-1);
}
else if(index<m->PageFirst->index)
{ TListBoxItem *node=m->PageFirst;
int offset=node->index - index;
while(offset>0)
{ offset--;
node=node->prev;
}
ListBoxPageScroll(hWnd,node->index,node->index-m->PageFirst->index);
ListBox_SelectedAssign(hWnd,node);
}
else
{ int page_bottom=m->PageFirst->index+m->CountPerPage-1;
if(page_bottom>=m->TotalItemCount)page_bottom=m->TotalItemCount-1;
if(index<=page_bottom)
{ ListBoxChangeSubFocus(hWnd,index);
}
else
{ TListBoxItem *node=m->PageFirst;
int offset=index - node->index;
while(offset>0)
{ offset--;
node=node->next;
}
if(node->index+m->CountPerPage<=m->TotalItemCount)
{ ListBoxPageScroll(hWnd,node->index,node->index-m->PageFirst->index);
}
else
{ int newtop=m->TotalItemCount-m->CountPerPage;
ListBoxPageScroll(hWnd,newtop,newtop-m->PageFirst->index);
}
ListBox_SelectedAssign(hWnd,node);
}
}
}
return oldsel;
}
//---------------------------------------------------------------------------
int ListBox_GetSelectedIndex(HWND hWnd)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
return (m->Selected)?m->Selected->index:-1;
}
//---------------------------------------------------------------------------
int ListBox_GetItemIndex(HWND hWnd,TListBoxItem *item)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(item)
{ return item->index;
}
return -1;
}
//---------------------------------------------------------------------------
char *ListBox_GetSelectedItem(HWND hWnd)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m->Selected) return m->Selected->caption;
else return NULL;
}
//---------------------------------------------------------------------------
TListBoxItem *GetItemNodeByIndex(HWND hWnd,int index)
{ if(index>=0)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
TListBoxItem *node;
int i;
for(i=0,node=m->Head;i<m->TotalItemCount;i++,node=node->next)
{ if(i==index) return node;
}
}
return NULL;
}
//---------------------------------------------------------------------------
char *ListBox_GetItemByIndex(HWND hWnd,int index)
{ TListBoxItem *node=GetItemNodeByIndex(hWnd,index);
return (node)?node->caption:NULL;
}
//---------------------------------------------------------------------------
void ListBox_SetMargin(HWND hWnd,int leftMargin,int lineMargin)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m->LeftMargin!=leftMargin || m->LineMargin!=lineMargin)
{
if(m->LeftMargin!=leftMargin)
{ m->LeftMargin=leftMargin;
}
if(m->LineMargin!=lineMargin)
{ m->LineMargin=lineMargin;
m->ItemHeight=SYS_FONT_HEIGHT+lineMargin;
m->CountPerPage=(crHeight(hWnd)+SYS_FONT_HEIGHT)/m->ItemHeight;
}
Invalidate(hWnd);
}
}
//---------------------------------------------------------------------------
HRESULT CALLBACK DefListBoxProc(HWND hWnd,UINT Message,WPARAM WParam,LPARAM LParam)
{
switch(Message)
{ case WM_KEYDOWN:
if(WParam==VK_UP || WParam==VK_DOWN)
{ ListBox_DirectSubFocus(hWnd,(BOOL)(WParam==VK_UP));
return 0;
}
break;
case WM_KEYUP:
if(WParam==VK_RETURN)
{ TListBox *lstbox=(TListBox *)WndClsBuf(hWnd);
if(lstbox->Selected && lstbox->fuc)
{ lstbox->fuc(hWnd,lstbox->Selected->index);
return 0;
}
}
break;
case WM_LBUTTONDOWN:
{ int xPos=LOWORD(LParam);
int yPos=HIWORD(LParam);
if(PointInRect(xPos,yPos,&WNDPTR(hWnd)->ClientRect))
{ ListBoxDealPenEvent(hWnd,Message,yPos);
}
break;
}
case WM_VSCROLL:
ListBoxPageScroll(hWnd,WParam,LParam);
return 0;
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
int xPos=LOWORD(LParam);
int yPos=HIWORD(LParam);
if(PointInRect(xPos,yPos,&WNDPTR(hWnd)->ClientRect))
{ ListBoxDealPenEvent(hWnd,Message,yPos);
return 0;
}
}
break;
case WM_KILLFOCUS:
RepaintSubItem(hWnd,ListBox_GetSelectedIndex(hWnd));
if(((TListBox *)WndClsBuf(hWnd))->NewMarquee)
EnableTimer(((TListBox *)WndClsBuf(hWnd))->MarqueeTimer,false);
return 0;
case WM_SETFOCUS:
RepaintSubItem(hWnd,ListBox_GetSelectedIndex(hWnd));
if(((TListBox *)WndClsBuf(hWnd))->NewMarquee)
EnableTimer(((TListBox *)WndClsBuf(hWnd))->MarqueeTimer,true);
return 0;
case WM_PAINT:
ListBoxRepaint(hWnd);
return 0;
case WM_CREATE:
ListBoxCreate(hWnd);
return 0;
case WM_DESTROY:
ListBoxDestroy(hWnd);
return 0;
}
return DefWindowProc(hWnd,Message,WParam,LParam);
}
//---------------------------------------------------------------------------
void CM_RegisterListBox(void)
{ TWNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.dwStyle=WS_BORDER_LOWERED;
wc.clForeground=CL_WINDOWTEXT;
wc.clBackground=CL_WHITE;
wc.cbWndExtra=sizeof(TListBox);
wc.lpfnWndProc=DefListBoxProc;
wc.lpszClassName="ListBox";
RegisterClass(&wc);
}
//---------------------------------------------------------------------------
void CM_RegisterMenu(void)
{ TWNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.dwStyle=WS_BORDER_RAISED;
wc.clForeground=CL_WINDOWTEXT;
wc.clBackground=CL_BTNFACE;
wc.cbWndExtra=sizeof(TListBox);
wc.lpfnWndProc=DefListBoxProc;
wc.lpszClassName="Menu";
RegisterClass(&wc);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -