接口替换技术实例
这是对一篇文章《深入BREW接口机制》文中代码的补充,经过我的调试,对IMENU、ISTATIC接口都是有效的,大家一起探讨一下,会不会存在什么问题。
在AEEAppGen.h中加入
typedef void (*UpdateFun)(IDisplay * po, boolean bDefer); //数据请求的回调函数指针
在结构_AEEApplet中加入变量
UpdateFun m_pOldUpdate; //用来保存原来的UPDATE函数的地址
IDIB* m_pBgDIB; //用来保存要显示的背景图片的DIB位图
在你的程序的主结构中加入变量保存
IDisplay* m_pOldIDisplay; //原来的IDISPLAY结构的地址
IDisplayVtbl * m_pOldDisplayVtbl; //原来的DISPLAYVTBL地址
uint16 m_nColorDepth; //手机颜色深度,AEEDeviceInfo.nColorDepth
//初始化一些变量
void InitDisplay(APPFRAME * pApp)
{
pApp->a.m_pBgDIB = NULL;
if(pApp->m_nColorDepth == 16) //判断手机的颜色深度是否是16位,因为背景图片是256色的,这里我们假设只对手机色深为16的有效
{
IBitmap* pScrBitmap = NULL;
IDIB* pScrDIB = NULL;
IBitmap* pBgBitmap = NULL;
IDIB* pBgDIB = NULL;
IImage* pBgImage = NULL;
IDisplay* pIDisplay = pApp->a.m_pIDisplay;
// 获取显示器位图
IDISPLAY_GetDeviceBitmap(pApp->a.m_pIDisplay, &pScrBitmap);
// 获取显示缓冲区
IBITMAP_QueryInterface(pScrBitmap, AEECLSID_DIB, (void**)&pScrDIB);
// 创建背景位图
IBITMAP_CreateCompatibleBitmap(pScrBitmap, &pBgBitmap, pScrDIB->cx, pScrDIB->cy);
// 获取背景位图的缓冲区
IBITMAP_QueryInterface(pBgBitmap, AEECLSID_DIB, (void**)&pBgDIB);
// 载入背景图片
pBgImage = ISHELL_LoadImage(pApp->a.m_pIShell, "bg.png"); //载入背景图片
// 替换IDisplay接口的目标位图
IDISPLAY_SetDestination(pApp->a.m_pIDisplay, pBgBitmap);
IBITMAP_Release(pScrBitmap); // 引用计数减1
pScrBitmap = NULL;
// 贴背景图
if(pBgImage)
IIMAGE_Draw(pBgImage, 0, 0);//pApp->m_nTitleHeight);
// 还原IDisplay接口的目标位图
IDISPLAY_SetDestination(pApp->a.m_pIDisplay, pScrBitmap);
IBITMAP_Release(pBgBitmap); // 引用计数减1
pBgBitmap = NULL;
pApp->a.m_pBgDIB = pBgDIB;
IDIB_Release(pScrDIB);
pScrDIB = NULL;
RELEASEIF(pBgImage);
pApp->m_pOldDisplayVtbl = *(( IDisplayVtbl**) pIDisplay);//将原来的pIDisplay指针保存
}
}
//改变IDISPLAY_UPDATE()的地址指向
void ChangeDisplay(APPFRAME * pApp)
{
if(pApp->m_nColorDepth == 16)
{
IDisplay* pIDisplay = pApp->a.m_pIDisplay;
IDisplayVtbl* pIDisplayVtbl = (IDisplayVtbl*)MALLOC(sizeof(IDisplayVtbl));
pApp->m_pOldDisplayVtbl = *(( IDisplayVtbl**) pIDisplay);
MEMCPY(pIDisplayVtbl, *(( IDisplayVtbl**) pIDisplay), sizeof(IDisplayVtbl));
//在这里保存原来的Update函数指针
pApp->a.m_pOldUpdate = pIDisplayVtbl->Update;
//替换
pIDisplayVtbl->Update = IDISPLAY_MyUpdate;
*((IDisplayVtbl**) pIDisplay) = pIDisplayVtbl;
}
}
//还原IDISPLAY_UPDATE()的地址指向
void RevertDisplay(APPFRAME * pApp)
{
if(pApp->m_nColorDepth == 16)
{
IDisplay* pIDisplay = pApp->a.m_pIDisplay;
IDisplayVtbl* pIDisplayVtbl = *(( IDisplayVtbl**) pIDisplay);
if(pIDisplayVtbl == pApp->m_pOldDisplayVtbl)
return;
pIDisplayVtbl->Update = pApp->a.m_pOldUpdate;
FREEIF(pIDisplayVtbl);
*((IDisplayVtbl**) pIDisplay) = pApp->m_pOldDisplayVtbl;
}
}
void IDISPLAY_MyUpdate(IDisplay * po, boolean bDefer)
{
IBitmap* pScrBitmap = NULL;
IDIB* pScrDIB = NULL;
IDIB* pBgDIB = ((AEEApplet*)GETAPPINSTANCE())->m_pBgDIB;
// 获取显示器位图
IDISPLAY_GetDeviceBitmap(po, &pScrBitmap);
// 获取显示缓冲区
IBITMAP_QueryInterface(pScrBitmap, AEECLSID_DIB, (void**)& pScrDIB);
IBITMAP_Release(pScrBitmap); // 引用计数减1
pScrBitmap = NULL;
// 这时,pScrDIB里面是原来IHtmlViewer载入的页面的位图数据,pBgDIB里是背景图片
// 的位图数据,我们pScrDIB里白色的点用pBgDIB对应的点来替换。这里假设设备的颜色
// 深度为16bit
if(pBgDIB)
{
uint16* pixel = (uint16*)pScrDIB->pBmp;
uint16* bgpixel = (uint16*)pBgDIB->pBmp;
int pcount = pScrDIB->cx * pScrDIB->cy;
for(; pcount; --pcount)
{
if(*pixel == 0xffff)
{
*pixel = *bgpixel;
}
++pixel;
++bgpixel;
}
}
// 调用真正的屏幕刷新函数
((AEEApplet*)GETAPPINSTANCE())->m_pOldUpdate(po, bDefer);
IDIB_Release(pScrDIB);
pScrDIB = NULL;
}
《深入brew接口机制》的补充
最新推荐文章于 2024-01-22 00:00:00 发布