今天讨论关于GUI的另一个话题:如何在两个界面切换中表现出比较炫一点的效果,比如渐变、缩放等等。同样我们还是用组件的方式来做。IGSlider,负责管理两个IControl切换的动态效果,它的使用比较简单:
staticvoidloadMenu(DisplayFavt*pMe,uint16wParam)

...{
TItemData*pData;
IControl*p1,*p2;
uint16style;

pData=NULL;

//加载第一个IControl,即起始界面
if(pMe->pCurrentTabOpt&&pMe->pCurrentTabOpt->pMenu)

...{
ICONTROL_SetActive(pMe->pCurrentTabOpt->pMenu,FALSE);
p1=pMe->pCurrentTabOpt->pMenu;
}

//得到第二个IControl,即结束界面
pMe->currentTab=IGTABPANECTL_GetSel(pMe->pApp->pMenuTab);
MainItemQueue_FindById(pMe->pApp->pTabList,pMe->currentTab,&pData);
if(pData==NULL)
return;

IGTABPANECTL_GetItemData(pMe->pApp->pMenuTab,pMe->currentTab,(uint32*)&pMe->pCurrentTabOpt);

p2=pMe->pCurrentTabOpt->pMenu;

//设置切换效果的风格
//style=(wParam==0)?0:((wParam==AVK_LEFT)?SLIDER_STYLE_RTOL:SLIDER_STYLE_LTOR);
style=(wParam==0)?0:SLIDER_STYLE_DTOB;

if(p1&&p2&&style!=0)

...{
AEERectrec;
SET_CTL_RECT(&rec);
//两个界面应该同样大小
IGSLIDER_SetRect(pMe->pApp->pSlider,&rec);
//将两个界面IControl加入IGSlider
if(IGSLIDER_AddControls(pMe->pApp->pSlider,p1,p2))

...{
//初始化,设置回调、风格、动态效果显示时长
IGSLIDER_Init(pMe->pApp->pSlider,style,3,(PFNNOTIFY)loadMenuDone,(void*)pMe);
//启动
IGSLIDER_Start(pMe->pApp->pSlider);
return;
}
}


...{
ICONTROL_SetActive((IControl*)pMe->pCurrentTabOpt->pMenu,TRUE);
ICONTROL_Redraw(pMe->pCurrentTabOpt->pMenu);
pMe->pApp->state=STATE_COMMAND;
}

}
原理比较简单:
1、我们要将两个 IControl绘入两个IBitmap中,然后才能进行各种图像操作(渐变、淡化、缩放等)。
2、用一个定时器来控制这个切换时的效果显示。
3、需要一个回调函数,在完成切换时需要调一下它,来处理善后事项。
先看看这个组件包含的成员,如上所述,除了两个ICotrol和两个IBitmap以外,还要那个回调m_cbDone、风格m_style、时间控制m_delay等等。

struct_IGSlider...{

constAEEVTBL(IGSlider)*pvt;

uint32m_nRefs;
IShell*m_pIShell;
IDisplay*m_pIDisplay;
IModule*m_pIModule;

IControl*m_pFirst;
IControl*m_pSecond;

intm_delay;
intm_style;

booleanm_isActive;

PFNNOTIFYm_cbDone;
void*m_pNotifyData;
AEERectm_Rect;

IBitmap*pFirst;
IBitmap*pSecond;
inttick;
uint8flag;

IBitmap*pTemp;

};
然后需要声明的接口函数包括以下几个:
AEEINTERFACE(IGSlider)

...{
DECLARE_IBASE(IGSlider)

boolean(*Redraw)(IGSlider*po);
void(*SetRect)(IGSlider*po,constAEERect*);

boolean(*AddControls)(IGSlider*po,IControl*p1,IControl*p2);
boolean(*AddControlsD)(IGSlider*po,IControl*p1,IControl*p2);
boolean(*AddControlFrom)(IGSlider*po,IControl*p1);
boolean(*AddControlTo)(IGSlider*po,IControl*p2);
boolean(*AddControlFromBitmap)(IGSlider*po,IBitmap*p1);
boolean(*AddControlToBitmap)(IGSlider*po,IBitmap*p2);

IBitmap*(*GetBitmapFirst)(IGSlider*po);
IBitmap*(*GetBitmapSecond)(IGSlider*po);

boolean(*IsActive)(IGSlider*po);
void(*Init)(IGSlider*po,uint16style,uint32delay,PFNNOTIFYcbDone,void*pUser);
void(*Start)(IGSlider*po);
void(*Stop)(IGSlider*po);

};
实现方面主要是这个addControls函数,在加入两个ICotrol同时,将它绘制到IBitmap上去。
staticbooleanIGSlider_AddControls(IGSlider*pMe,IControl*p1,IControl*p2)

...{

AEERectr;

if(SUCCESS!=IDISPLAY_SetDestination(pMe->m_pIDisplay,pMe->pFirst))
returnFALSE;

SETAEERECT(&r,0,0,pMe->m_Rect.dx,pMe->m_Rect.dy);
ICONTROL_SetRect(p1,&r);
ICONTROL_Redraw(p1);
IDISPLAY_Update(pMe->m_pIDisplay);
ICONTROL_SetRect(p1,&pMe->m_Rect);

if(SUCCESS!=IDISPLAY_SetDestination(pMe->m_pIDisplay,pMe->pSecond))
returnFALSE;

SETAEERECT(&r,0,0,pMe->m_Rect.dx,pMe->m_Rect.dy);
ICONTROL_SetRect(p2,&r);
ICONTROL_Redraw(p2);
IDISPLAY_Update(pMe->m_pIDisplay);
ICONTROL_SetRect(p2,&pMe->m_Rect);

IDISPLAY_SetDestination(pMe->m_pIDisplay,NULL);

returnTRUE;
}
启动效果切换的工作是根据当前设置的风格调用不同的图像处理函数,还要提供一个停止函数来随时中止效果变化(其实就是Cancel掉定时器罢了)。
staticvoidIGSlider_Start(IGSlider*pMe)

...{
pMe->tick=0;
pMe->flag=0;
pMe->m_isActive=TRUE;

if(pMe->m_style==SLIDER_STYLE_RTOL)
drawRTOL(pMe);
elseif(pMe->m_style==SLIDER_STYLE_LTOR)
drawLTOR(pMe);
elseif(pMe->m_style==SLIDER_STYLE_DARK)
drawDARK(pMe);
elseif(pMe->m_style==SLIDER_STYLE_BRIT)
drawBRIT(pMe);
elseif(pMe->m_style==SLIDER_STYLE_SIZE)
drawSize(pMe);
elseif(pMe->m_style==SLIDER_STYLE_GRID)
drawGRID(pMe);
elseif(pMe->m_style==SLIDER_STYLE_SIZE2)
drawSize2(pMe);
elseif(pMe->m_style==SLIDER_STYLE_LTORD)
drawLTORD(pMe);
elseif(pMe->m_style==SLIDER_STYLE_RTOLD)
drawRTOLD(pMe);
elseif(pMe->m_style==SLIDER_STYLE_BTOT)
drawBTOT(pMe);
elseif(pMe->m_style==SLIDER_STYLE_TTOB)
drawTTOB(pMe);
elseif(pMe->m_style==SLIDER_STYLE_DTOB)
drawDTOB(pMe);

}
staticvoidIGSlider_Stop(IGSlider*pMe)

...{
pMe->m_isActive=FALSE;
ISHELL_CancelTimer(pMe->m_pIShell,NULL,(void*)pMe);

}
各种效果的实现并不复杂,去google一下就能得到很多图像处理方法了。下面给出两个典型的处理,一是由暗变亮的实现,即第一个界面由亮变暗而第二个界面由暗变亮。
staticvoiddrawDTOB(IGSlider*pMe)

...{
ITransform*pTransform;
AEEBitmapInfoinf;
IBitmap*bmp;
AEETransformMatrixmatrix;
intx,y;

pMe->tick++;

IBITMAP_SetTransparencyColor(pMe->pFirst,MAKE_RGB(0,0,0));
if(pMe->flag==0)

...{
IBITMAP_GetInfo(pMe->pFirst,&inf,sizeof(AEEBitmapInfo));
for(x=0;x<inf.cx;x++)
for(y=0;y<inf.cy;y++)

...{
NativeColortc;
RGBVALocolor,ncolor;

IBITMAP_GetPixel(pMe->pFirst,x,y,&tc);
ocolor=IBITMAP_NativeToRGB(pMe->pFirst,tc);
ncolor=__transColor(pMe,ocolor,-50);
tc=IBITMAP_RGBToNative(pMe->pFirst,ncolor);
IBITMAP_DrawPixel(pMe->pFirst,x,y,tc,AEE_RO_COPY);
}
IDISPLAY_BitBlt(pMe->m_pIDisplay,pMe->m_Rect.x,pMe->m_Rect.y,pMe->m_Rect.dx,pMe->m_Rect.dy,pMe->pFirst,0,0,AEE_RO_TRANSPARENT);
IDISPLAY_Update(pMe->m_pIDisplay);

if(pMe->tick<pMe->m_delay)
ISHELL_SetTimer(pMe->m_pIShell,5,(PFNNOTIFY)drawDTOB,(void*)pMe);
else

...{
pMe->flag=1;
pMe->tick=1;
}

}

if(pMe->flag==1)

...{
IBITMAP_GetInfo(pMe->pSecond,&inf,sizeof(AEEBitmapInfo));

if(pMe->pTemp)
IBITMAP_Release(pMe->pTemp);
IBITMAP_CreateCompatibleBitmap(pMe->pSecond,&pMe->pTemp,inf.cx,inf.cy);

for(x=0;x<inf.cx;x++)
for(y=0;y<inf.cy;y++)

...{
NativeColortc;
RGBVALocolor
staticvoidloadMenu(DisplayFavt*pMe,uint16wParam)
...{
TItemData*pData;
IControl*p1,*p2;
uint16style;
pData=NULL;
//加载第一个IControl,即起始界面
if(pMe->pCurrentTabOpt&&pMe->pCurrentTabOpt->pMenu)
...{
ICONTROL_SetActive(pMe->pCurrentTabOpt->pMenu,FALSE);
p1=pMe->pCurrentTabOpt->pMenu;
}
//得到第二个IControl,即结束界面
pMe->currentTab=IGTABPANECTL_GetSel(pMe->pApp->pMenuTab);
MainItemQueue_FindById(pMe->pApp->pTabList,pMe->currentTab,&pData);
if(pData==NULL)
return;
IGTABPANECTL_GetItemData(pMe->pApp->pMenuTab,pMe->currentTab,(uint32*)&pMe->pCurrentTabOpt);
p2=pMe->pCurrentTabOpt->pMenu;
//设置切换效果的风格
//style=(wParam==0)?0:((wParam==AVK_LEFT)?SLIDER_STYLE_RTOL:SLIDER_STYLE_LTOR);
style=(wParam==0)?0:SLIDER_STYLE_DTOB;
if(p1&&p2&&style!=0)
...{
AEERectrec;
SET_CTL_RECT(&rec);
//两个界面应该同样大小
IGSLIDER_SetRect(pMe->pApp->pSlider,&rec);
//将两个界面IControl加入IGSlider
if(IGSLIDER_AddControls(pMe->pApp->pSlider,p1,p2))
...{
//初始化,设置回调、风格、动态效果显示时长
IGSLIDER_Init(pMe->pApp->pSlider,style,3,(PFNNOTIFY)loadMenuDone,(void*)pMe);
//启动
IGSLIDER_Start(pMe->pApp->pSlider);
return;
}
}

...{
ICONTROL_SetActive((IControl*)pMe->pCurrentTabOpt->pMenu,TRUE);
ICONTROL_Redraw(pMe->pCurrentTabOpt->pMenu);
pMe->pApp->state=STATE_COMMAND;
}
}
原理比较简单:
1、我们要将两个 IControl绘入两个IBitmap中,然后才能进行各种图像操作(渐变、淡化、缩放等)。
2、用一个定时器来控制这个切换时的效果显示。
3、需要一个回调函数,在完成切换时需要调一下它,来处理善后事项。
先看看这个组件包含的成员,如上所述,除了两个ICotrol和两个IBitmap以外,还要那个回调m_cbDone、风格m_style、时间控制m_delay等等。

struct_IGSlider...{
constAEEVTBL(IGSlider)*pvt;
uint32m_nRefs;
IShell*m_pIShell;
IDisplay*m_pIDisplay;
IModule*m_pIModule;
IControl*m_pFirst;
IControl*m_pSecond;
intm_delay;
intm_style;
booleanm_isActive;
PFNNOTIFYm_cbDone;
void*m_pNotifyData;
AEERectm_Rect;
IBitmap*pFirst;
IBitmap*pSecond;
inttick;
uint8flag;
IBitmap*pTemp;
};
然后需要声明的接口函数包括以下几个:
AEEINTERFACE(IGSlider)
...{
DECLARE_IBASE(IGSlider)
boolean(*Redraw)(IGSlider*po);
void(*SetRect)(IGSlider*po,constAEERect*);
boolean(*AddControls)(IGSlider*po,IControl*p1,IControl*p2);
boolean(*AddControlsD)(IGSlider*po,IControl*p1,IControl*p2);
boolean(*AddControlFrom)(IGSlider*po,IControl*p1);
boolean(*AddControlTo)(IGSlider*po,IControl*p2);
boolean(*AddControlFromBitmap)(IGSlider*po,IBitmap*p1);
boolean(*AddControlToBitmap)(IGSlider*po,IBitmap*p2);
IBitmap*(*GetBitmapFirst)(IGSlider*po);
IBitmap*(*GetBitmapSecond)(IGSlider*po);
boolean(*IsActive)(IGSlider*po);
void(*Init)(IGSlider*po,uint16style,uint32delay,PFNNOTIFYcbDone,void*pUser);
void(*Start)(IGSlider*po);
void(*Stop)(IGSlider*po);
};
实现方面主要是这个addControls函数,在加入两个ICotrol同时,将它绘制到IBitmap上去。
staticbooleanIGSlider_AddControls(IGSlider*pMe,IControl*p1,IControl*p2)
...{
AEERectr;
if(SUCCESS!=IDISPLAY_SetDestination(pMe->m_pIDisplay,pMe->pFirst))
returnFALSE;
SETAEERECT(&r,0,0,pMe->m_Rect.dx,pMe->m_Rect.dy);
ICONTROL_SetRect(p1,&r);
ICONTROL_Redraw(p1);
IDISPLAY_Update(pMe->m_pIDisplay);
ICONTROL_SetRect(p1,&pMe->m_Rect);
if(SUCCESS!=IDISPLAY_SetDestination(pMe->m_pIDisplay,pMe->pSecond))
returnFALSE;
SETAEERECT(&r,0,0,pMe->m_Rect.dx,pMe->m_Rect.dy);
ICONTROL_SetRect(p2,&r);
ICONTROL_Redraw(p2);
IDISPLAY_Update(pMe->m_pIDisplay);
ICONTROL_SetRect(p2,&pMe->m_Rect);
IDISPLAY_SetDestination(pMe->m_pIDisplay,NULL);
returnTRUE;
}
启动效果切换的工作是根据当前设置的风格调用不同的图像处理函数,还要提供一个停止函数来随时中止效果变化(其实就是Cancel掉定时器罢了)。
staticvoidIGSlider_Start(IGSlider*pMe)
...{
pMe->tick=0;
pMe->flag=0;
pMe->m_isActive=TRUE;
if(pMe->m_style==SLIDER_STYLE_RTOL)
drawRTOL(pMe);
elseif(pMe->m_style==SLIDER_STYLE_LTOR)
drawLTOR(pMe);
elseif(pMe->m_style==SLIDER_STYLE_DARK)
drawDARK(pMe);
elseif(pMe->m_style==SLIDER_STYLE_BRIT)
drawBRIT(pMe);
elseif(pMe->m_style==SLIDER_STYLE_SIZE)
drawSize(pMe);
elseif(pMe->m_style==SLIDER_STYLE_GRID)
drawGRID(pMe);
elseif(pMe->m_style==SLIDER_STYLE_SIZE2)
drawSize2(pMe);
elseif(pMe->m_style==SLIDER_STYLE_LTORD)
drawLTORD(pMe);
elseif(pMe->m_style==SLIDER_STYLE_RTOLD)
drawRTOLD(pMe);
elseif(pMe->m_style==SLIDER_STYLE_BTOT)
drawBTOT(pMe);
elseif(pMe->m_style==SLIDER_STYLE_TTOB)
drawTTOB(pMe);
elseif(pMe->m_style==SLIDER_STYLE_DTOB)
drawDTOB(pMe);
}
staticvoidIGSlider_Stop(IGSlider*pMe)
...{
pMe->m_isActive=FALSE;
ISHELL_CancelTimer(pMe->m_pIShell,NULL,(void*)pMe);
}
各种效果的实现并不复杂,去google一下就能得到很多图像处理方法了。下面给出两个典型的处理,一是由暗变亮的实现,即第一个界面由亮变暗而第二个界面由暗变亮。
staticvoiddrawDTOB(IGSlider*pMe)
...{
ITransform*pTransform;
AEEBitmapInfoinf;
IBitmap*bmp;
AEETransformMatrixmatrix;
intx,y;
pMe->tick++;
IBITMAP_SetTransparencyColor(pMe->pFirst,MAKE_RGB(0,0,0));
if(pMe->flag==0)
...{
IBITMAP_GetInfo(pMe->pFirst,&inf,sizeof(AEEBitmapInfo));
for(x=0;x<inf.cx;x++)
for(y=0;y<inf.cy;y++)
...{
NativeColortc;
RGBVALocolor,ncolor;
IBITMAP_GetPixel(pMe->pFirst,x,y,&tc);
ocolor=IBITMAP_NativeToRGB(pMe->pFirst,tc);
ncolor=__transColor(pMe,ocolor,-50);
tc=IBITMAP_RGBToNative(pMe->pFirst,ncolor);
IBITMAP_DrawPixel(pMe->pFirst,x,y,tc,AEE_RO_COPY);
}
IDISPLAY_BitBlt(pMe->m_pIDisplay,pMe->m_Rect.x,pMe->m_Rect.y,pMe->m_Rect.dx,pMe->m_Rect.dy,pMe->pFirst,0,0,AEE_RO_TRANSPARENT);
IDISPLAY_Update(pMe->m_pIDisplay);
if(pMe->tick<pMe->m_delay)
ISHELL_SetTimer(pMe->m_pIShell,5,(PFNNOTIFY)drawDTOB,(void*)pMe);
else
...{
pMe->flag=1;
pMe->tick=1;
}
}
if(pMe->flag==1)
...{
IBITMAP_GetInfo(pMe->pSecond,&inf,sizeof(AEEBitmapInfo));
if(pMe->pTemp)
IBITMAP_Release(pMe->pTemp);
IBITMAP_CreateCompatibleBitmap(pMe->pSecond,&pMe->pTemp,inf.cx,inf.cy);
for(x=0;x<inf.cx;x++)
for(y=0;y<inf.cy;y++)
...{
NativeColortc;
RGBVALocolor
本文介绍了一种GUI界面切换特效的实现方法,通过组件IGSlider管理两个界面间的动态效果,如渐变、淡化、缩放等,并提供了具体实现代码。
4199

被折叠的 条评论
为什么被折叠?



