📄 listbox.c
字号:
/******************************************************************************
*
* Copyright 2006 National ASIC Center, All right Reserved
*
* FILE NAME: ListBox.c
* PROGRAMMER: ming.c
* Date of Creation: 2006/08/8
*
* DESCRIPTION:
*
* NOTE:
*
* FUNCTIONS LIST:
* -----------------------------------------------------------------------------
*
* -----------------------------------------------------------------------------
*
* MODIFICATION HISTORY
* LastModify 2006/09/20
******************************************************************************/
#include "mingui.h"
//---------------------------------------------------------------------------
#define Default_LeftMargin 3
#define Default_LineMargin 4
#define MarqueeInterval 1000
//---------------------------------------------------------------------------
typedef struct _ListBox_Item
{ struct _ListBox_Item *next,*prev;
int index;
char *caption;
}TListBoxItem;
typedef void (*TListItemCallback)(HWND,int);
typedef struct t_ListBox
{ int TotalItemCount,CountPerPage,LineMargin,LeftMargin,ItemHeight;
TListBoxItem *Head,*PageFirst,*Selected;
TListItemCallback fuc;
/*--Marquee-------------------------------*/
HANDLE MarqueeTimer;
TListBoxItem *MarqueeItem,*NewMarquee;
int MarqueePos;
}TListBox;
//---------------------------------------------------------------------------
static TListBoxItem *GetItemNodeByIndex(HWND,int);
static void ListBox_MarqueeProc(HWND);
static void RepaintSubItem(HWND hWnd,int index);
static void ListBox_DirectSubFocus(HWND hWnd,BOOL UpOrDown);
static HRESULT CALLBACK DefListBoxProc(HWND hWnd,UINT Message,WPARAM WParam,LPARAM LParam);
//---------------------------------------------------------------------------
void ListBoxCreate(HWND hWnd)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
memset(m,0,sizeof(TListBox));
m->fuc=(TListItemCallback)WNDPTR(hWnd)->ExtraLong[0];
m->LeftMargin=Default_LeftMargin;
m->LineMargin=Default_LineMargin;
m->ItemHeight=SYS_FONT_HEIGHT+m->LineMargin;
m->CountPerPage=(crHeight(hWnd)+SYS_FONT_HEIGHT)/m->ItemHeight;
m->MarqueeTimer=CreateTimer(hWnd,MarqueeInterval,MarqueeInterval,ListBox_MarqueeProc,false);
ScrollBar_Initialize(hWnd,0,0,m->CountPerPage,m->CountPerPage);
}
//---------------------------------------------------------------------------
void ListBoxDestroy(HWND hWnd)
{ TListBoxItem *node,*delNode,*head;
TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m)
{ DestroyTimer(m->MarqueeTimer);
head=m->Head;
if(head)
{ node=head;
do
{ delNode=node;
node=node->next;
FreeMem(delNode->caption);
FreeMem(delNode);
}while(node!=head);
}
}
}
//---------------------------------------------------------------------------
void ListBox_SelectedAssign(HWND hWnd,TListBoxItem *newselected)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m->Selected!=newselected)
{ bool bNeedMarquee=false;
if(newselected)
{ int textwidth=strlen(newselected->caption)*SYS_FONT_WIDTH;
int clipwidth=crWidth(hWnd)-m->LeftMargin;
if(textwidth>clipwidth) bNeedMarquee=true;
}
if(bNeedMarquee)
{ if(WndGetAttr(hWnd,WS_FOCUS))EnableTimer(m->MarqueeTimer,true);
m->NewMarquee=newselected;
}
else
{ m->NewMarquee=NULL;
}
m->Selected=newselected;
CMD_NotifyParent(hWnd,CM_CHANGED);
}
}
//---------------------------------------------------------------------------
void ListBox_MarqueeProc(HWND hWnd)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m->MarqueeItem==m->NewMarquee)
{ if(m->MarqueeItem)
{ BYTE *byteCaption=(BYTE *)m->MarqueeItem->caption;
if(byteCaption[m->MarqueePos]>0xA0) m->MarqueePos+=2;
else if(byteCaption[m->MarqueePos]>0)m->MarqueePos+=1;
if(!byteCaption[m->MarqueePos]) m->MarqueePos=0;
RepaintSubItem(hWnd,m->MarqueeItem->index);
}
else
{ EnableTimer(m->MarqueeTimer,false);
}
}
else
{ if(m->MarqueeItem && m->MarqueePos)
{ /*if need reset last marquee then just do it*/
m->MarqueePos=0;
RepaintSubItem(hWnd,m->MarqueeItem->index);
}
m->MarqueePos=0;
m->MarqueeItem=m->NewMarquee;
}
}
//---------------------------------------------------------------------------
void ListBoxPageScroll(HWND hWnd,int newtop,int step)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m->PageFirst && newtop!=m->PageFirst->index && m->CountPerPage>1)
{ TListBoxItem *item=m->Head;
int i;
for(i=0;i<newtop;i++)item=item->next;
m->PageFirst=item;
Invalidate(hWnd);
ScrollBar_Synchronize(hWnd,m->PageFirst->index);
}
else
{ ListBox_DirectSubFocus(hWnd,(BOOL)(step<0));
}
}
//---------------------------------------------------------------------------
void ListBoxChangeSubFocus(HWND hWnd,int newselect)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
int oldselelect=(m->Selected)?m->Selected->index:-1;
if(newselect!=oldselelect && m->TotalItemCount>0)
{ int new_pageoffset,old_pageoffset;
int page_first=m->PageFirst->index;
int page_bottom=page_first+m->CountPerPage-1;
if(page_bottom>=m->TotalItemCount)page_bottom=m->TotalItemCount-1;
new_pageoffset=(newselect>=page_first && newselect<=page_bottom)?newselect-page_first:-1;
old_pageoffset=(oldselelect>=page_first && oldselelect<=page_bottom)?oldselelect-page_first:-1;
if(old_pageoffset>=0 || new_pageoffset>=0)
{ HDC dc=GetClientDC(hWnd);
int areaHeight,areaWidth;
SetPenLogic(dc,PL_XOR);
SetColor(dc,CL_SOLID);
areaWidth=crWidth(hWnd);
areaHeight=m->ItemHeight;
if( WndGetAttr(hWnd,WS_FOCUS) )
{
if(old_pageoffset>=0 && new_pageoffset<0)
{ FillRect(dc,0,old_pageoffset*areaHeight,areaWidth,areaHeight);
}
else if(new_pageoffset>=0 && old_pageoffset<0)
{ FillRect(dc,0,new_pageoffset*areaHeight,areaWidth,areaHeight);
}
else if(new_pageoffset-old_pageoffset==1)
{ FillRect(dc,0,old_pageoffset*areaHeight,areaWidth,areaHeight<<1);
}
else if(old_pageoffset-new_pageoffset==1)
{ FillRect(dc,0,new_pageoffset*areaHeight,areaWidth,areaHeight<<1);
}
else
{ FillRect(dc,0,old_pageoffset*areaHeight,areaWidth,areaHeight);
FillRect(dc,0,new_pageoffset*areaHeight,areaWidth,areaHeight);
}
}
else if(m->CountPerPage>1) /*单行框不需要虚线反显*/
{ if(old_pageoffset>=0)
{ DrawDashedRect(dc,0,old_pageoffset*areaHeight,areaWidth,areaHeight);
}
if(new_pageoffset>=0)
{ DrawDashedRect(dc,0,new_pageoffset*areaHeight,areaWidth,areaHeight);
}
}
ReleaseDC(dc);
}
ListBox_SelectedAssign(hWnd,GetItemNodeByIndex(hWnd,newselect));
}
}
//---------------------------------------------------------------------------
void RepaintSubItem(HWND hWnd,int index)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
TListBoxItem *mn=m->PageFirst;
if(mn && index>=mn->index)
{ int page_bottom=mn->index+m->CountPerPage-1;
if(page_bottom>=m->TotalItemCount)page_bottom=m->TotalItemCount-1;
if(index<=page_bottom)
{ HDC dc;
int j,offset=index-mn->index;
int ItemWidth=crWidth(hWnd);
int ItemHeight=m->ItemHeight;
for(j=0;j<offset;j++)
{ mn=mn->next;
}
dc=GetClientDC(hWnd);
GroupOn(dc);
j = offset*ItemHeight;
EraseBackground(dc, 0,j,ItemWidth,ItemHeight);
if(mn->caption && *mn->caption)
{ char *strCaption=(mn==m->MarqueeItem)?mn->caption+m->MarqueePos:mn->caption;
TextOut(dc,m->LeftMargin,j+(m->LineMargin>>1),strCaption);
}
if(mn==m->Selected)
{ SetPenLogic(dc,PL_XOR);
SetColor(dc,CL_SOLID);
if(WndGetAttr(hWnd,WS_FOCUS))
FillRect(dc,0,j,ItemWidth,ItemHeight);
else if(m->CountPerPage>1) /*单行框不需要虚线反显*/
DrawDashedRect(dc,0,j,ItemWidth,ItemHeight);
}
GroupOff(dc,0,j,ItemWidth,ItemHeight);
ReleaseDC(dc);
}
}
}
//---------------------------------------------------------------------------
void ListBox_DirectSubFocus(HWND hWnd,int UpOrDown)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
TListBoxItem *ItemSelected=m->Selected;
BOOL PageScolled=false;
if(!ItemSelected)
{ if(!m->PageFirst)return;
else ItemSelected=m->PageFirst;
}
if(UpOrDown)
{ if(ItemSelected!=m->Head)
{ if(ItemSelected==m->PageFirst)
{ PageScolled=true;
m->PageFirst=m->PageFirst->prev;
}
ItemSelected=ItemSelected->prev;
}
}
else
{ if(ItemSelected->next!=m->Head)
{ if(ItemSelected->index==m->PageFirst->index+m->CountPerPage-1)
{ PageScolled=true;
m->PageFirst=m->PageFirst->next;
}
ItemSelected=ItemSelected->next;
}
}
if(ItemSelected!=m->Selected)
{ if(PageScolled)
{ ListBox_SelectedAssign(hWnd,ItemSelected);
Invalidate(hWnd);
if(WndGetAttr(hWnd,WS_VSCROLL|WS_BORDER)==(WS_VSCROLL|WS_BORDER))
{ ScrollBar_Synchronize(hWnd,m->PageFirst->index);
}
}
else
{ ListBoxChangeSubFocus(hWnd,ItemSelected->index);
}
}
}
//---------------------------------------------------------------------------
void ListBoxDealPenEvent(HWND hWnd,DWORD Message,int yPos)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
if(m->TotalItemCount>0 && m->ItemHeight>0)
{ int oldselect=(m->Selected)?m->Selected->index:-1;
int newselect=m->PageFirst->index+ ( yPos - WNDPTR(hWnd)->ClientRect.top ) / m->ItemHeight;
if(newselect>=m->TotalItemCount) newselect=-1;
if(newselect !=oldselect)
{ ListBoxChangeSubFocus(hWnd,newselect);
}
if(Message==WM_LBUTTONUP && newselect>=0)
{ if(m->fuc) m->fuc(hWnd,newselect);
}
}
}
//---------------------------------------------------------------------------
void ListBoxRepaint(HWND hWnd)
{ TListBox *m=(TListBox *)WndClsBuf(hWnd);
TListBoxItem *mn=m->PageFirst;
HDC dc=BeginPaint(hWnd);
int clientwidth=crWidth(hWnd);
if(mn)
{ int offsetY=0;
int ItemHeight=m->ItemHeight;
int textLeft=m->LeftMargin;
int textwidth=clientwidth-m->LeftMargin;
int LineMarginTop=m->LineMargin>>1;
int i,page_bottom=mn->index+m->CountPerPage-1;
if(page_bottom>=m->TotalItemCount)page_bottom=m->TotalItemCount-1;
for(i=mn->index;i<=page_bottom;i++)
{ if(mn->caption!=NULL && *mn->caption)
{ TextOut(dc,textLeft,LineMarginTop+offsetY,mn->caption);
}
if(mn==m->Selected)
{ SetPenLogic(dc,PL_XOR);
SetColor(dc,CL_SOLID);
if(WndGetAttr(hWnd,WS_FOCUS))
FillRect(dc,0,offsetY,clientwidth,ItemHeight);
else if(m->CountPerPage>1) /*单行框不需要虚线反显*/
DrawDashedRect(dc,0,offsetY,clientwidth,ItemHeight);
SetPenLogic(dc,PL_REPLACE);
SetColor(dc,CL_BTNTEXT);
}
offsetY+=ItemHeight;
mn=mn->next;
}
}
EndPaint(hWnd);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -