还有一个常用的UI控件是单选框与复选框。可惜BREW也不提供,所以,只能自己做一个了。
先看一下每个选项的结构定义,我们用图片来做那个选中和未选中的显示,这样才能做出更多更美观的界面效果,所以在结构中有两个成员pCkImage和pNrImage,同时,isSelected用来记录此项是否被选中:
typedef struct

...{
int nItemID;
AECHAR * pText;

IImage * pCkImage;
IImage * pNrImage;

const char * pszResFile;
uint16 wCkImage;
uint16 wNrImage;

boolean isSelected;
} TGBOption;
而整个控件的结构如下:

struct _IGButton ...{
const AEEVTBL(IGButton) * pvt;

uint32 m_nRefs;
IShell *m_pIShell;
IDisplay *m_pIDisplay;
IModule *m_pIModule;

boolean m_isActive;
AEERect m_Rect;

uint32 props;

AECHAR *pTitle;
AEEFont titleFont;
RGBVAL titleColor;

IImage *pBkImage;

TQueueList *pOptionList;
int m_Index;

};
同样是用 TQueueList来保存一个选项的链表,当前少不了m_Index当前项了。
需要的接口函数定义如下:
AEEINTERFACE(IGButton)

...{
DECLARE_IBASE(IGButton)

DECLARE_ICONTROL(IGButton)

boolean (*SetTitle) (IGButton * po, AECHAR * szText,AEEFont font,RGBVAL color);
boolean (*SetBkImage) (IGButton * po, IImage * img);
boolean (*AddOption) (IGButton * po, TGBOption *opt);
boolean (*IsChecked) (IGButton * po,int idx);
int (*GetSel) (IGButton * po);
int (*GetItemCount) (IGButton * po);
};
下面来看看实现,同样的先看HandleEvent,需要处理上下方向键,修改m_Index以改变当前项;处理SELECT键处理选中/取消选中的操作。
在Redraw函数中呢?遍历一下那个pOptionList链表,根据每个项是否选中,绘制出来即可。
static boolean IGButton_Redraw(IGButton * pMe)

...{
int i,j,height,h,a,b;
int xx,yy,dxx,dyy;
AEERect rec;
AEEImageInfo infIc;
RGBVAL oldColor;
TQueueList * p = pMe->pOptionList;
h=IDISPLAY_GetFontMetrics(pMe->m_pIDisplay,AEE_FONT_NORMAL,&a,&b);
IDISPLAY_EraseRect(pMe->m_pIDisplay,&pMe->m_Rect);

if(pMe->pBkImage)

...{
IIMAGE_SetDrawSize(pMe->pBkImage,pMe->m_Rect.dx,pMe->m_Rect.dy);
IIMAGE_Draw(pMe->pBkImage,pMe->m_Rect.x,pMe->m_Rect.y);
}
oldColor = IDISPLAY_SetColor(pMe->m_pIDisplay,CLR_USER_TEXT,MAKE_RGB(0,0,0));

i=0;
height=pMe->m_Rect.y;
while(p)

...{
IImage * img;
TGBOption * pData=(TGBOption*)p->pData;

if(pData->isSelected)
img=pData->pCkImage;
else
img=pData->pNrImage;
ZEROAT(&infIc);
if(img)

...{
IIMAGE_GetInfo(img,&infIc);
IIMAGE_Draw(img,pMe->m_Rect.x,height);
}
xx=pMe->m_Rect.x+infIc.cx;
yy=height+(infIc.cy-h)/2;
dxx=pMe->m_Rect.x+pMe->m_Rect.dx-xx;
dyy=h;
SETAEERECT(&rec,xx,yy,dxx,dyy);
IDISPLAY_DrawText(pMe->m_pIDisplay,AEE_FONT_NORMAL,pData->pText,-1,xx,yy,&rec,IDF_TEXT_TRANSPARENT);

if(i==pMe->m_Index)

...{
xx=pMe->m_Rect.x;
yy=height;
dxx=infIc.cx+IDISPLAY_MeasureText(pMe->m_pIDisplay,AEE_FONT_NORMAL,pData->pText);;
dyy=infIc.cy;
SETAEERECT(&rec,xx,yy,dxx,dyy);

IDISPLAY_DrawRect(pMe->m_pIDisplay,&rec,MAKE_RGB(0,0,250),0,IDF_RECT_FRAME);
}
height+=infIc.cy;

p=p->pNext;
i++;

}

IDISPLAY_Update(pMe->m_pIDisplay);
IDISPLAY_SetColor(pMe->m_pIDisplay,CLR_USER_TEXT,oldColor);

return TRUE;
}
还有一件事,如果在程序中取到这个组件的结果呢?如果是单选就可以直接GetSel了,如果是复选则循环一下一个个判断是否选中IsChecked即可:
static boolean IGButton_IsChecked(IGButton * pMe,int idx)

...{
if(pMe->props&0x01==GBTN_STYLE_CHECK)

...{
TGBOption * pData=(TGBOption*)Queue_Get(pMe->pOptionList,idx);
if(pData)

...{
return pData->isSelected;
}
}
return FALSE;
}
static int IGButton_GetSel(IGButton * pMe)

...{
if((pMe->props&0x01)==GBTN_STYLE_RADIO)

...{
TQueueList * p=pMe->pOptionList;
//int i = 0;
while(p)

...{
TGBOption * pData=(TGBOption*)p->pData;
if(pData && pData->isSelected)
return pData->nItemID;
//i+=1;
p=p->pNext;
}
}
return -1;
}
OK,基本上搞定。