带你认识WinCE Display驱动开发
void CursorOn(void);
void CursorOff(void);
#ifdef ROTATE
void SetRotateParms();
LONG DynRotate(int angle);
#endif
};
类NewGPE从GPE类上面继承,其中包括一些属性,如下:
m_ModeInfo:显示模式,结构如下
struct GPEMode {
int modeId; //开发者定义的显示模式的索引号
int width; //显示宽度
int height; //显示高度
int Bpp; //显示深度
int frequency; //显示频率
EGPEFormat format; // RGB格式,各占多少bit
};
m_colorDepth:显示深度
m_VirtualFrameBuffer:FrameBuffer的地址
m_FrameBufferSize:FrameBuffer的大小
m_CursorDisabled:光标使能标记
m_CursorVisible:光标可视标记
用户可以根据需要定义相应的属性,在NewGPE类中,需要定义并实现基类中的纯虚函数,上面的NewGPE类中已经包含了这些函数的定义,还包括了其他一些函数,将在下面介绍。
2 实现GetGPE函数
在定义了NewGPE类之后,我们需要实现一个实例,首先定义一个该类的指针:
static GPE *gGPE = (GPE*)NULL;
然后实现GetGPE函数,如下:
GPE *GetGPE(void)
{
if (!gGPE)
{
gGPE = new NewGPE();
}
return gGPE;
}
在该函数中,创建了一个NewGPE的实例。在这个时候NewGPE构造函数会被调用,一般我们会在这里面作一些与显示相关的初始化的工作。该函数返回gGPE指针给上层接口。
3 实现DrvEnableDriver和DisplayInit函数
Display驱动对上层的GWES模块提供了20多个函数接口,但是这些函数并不是直接提供出来的,实际上只是通过一个DrvEnableDriver(..)函数来完成的。该函数在Display驱动的MDD层中没有实现,所以需要在PDD层中定义,如下:
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data, PENGCALLBACKS engineCallbacks)
{
BOOL fOk = FALSE;
// make sure we know where our registry configuration is
if(gszBaseInstance[0] != 0) {
fOk = GPEEnableDriver(engineVersion, cj, data, engineCallbacks);
}
return fOk;
}
engineVersion:DDI版本号,目前为DDI_DRIVER_VERSION。
cj:DRVENABLEDATA结构的大小。
data:指向DRVENABLEDATA结构体。
engineCallbacks:指向一个回调函数结构体,传入一些GDI函数到Display驱动中。
其中,DRVENABLEDATA结构中包含了Display驱动中的设备接口函数的指针,在DrvEnableDriver函数中调用了GPEEnableDriver函数,该函数会导出GWES模块所需的所有Display驱动的接口函数。同时GWES模块通过第四个参数engineCallbacks提供回调函数供Display驱动调用。该函数在”ddi_if”中定义。
另一个重要的函数是DisplayInit函数,它是第一个被执行的Display驱动中的函数,该函数主要用于读取注册表中的一些信息并作判断。该函数是可选的,也可以不在驱动中实现它。
BOOL APIENTRY DisplayInit(LPCTSTR pszInstance, DWORD dwNumMonitors)
{
DWORD dwStatus;
HKEY hkDisplay;
BOOL fOk = FALSE;
if(pszInstance != NULL) {
_tcsncpy(gszBaseInstance, pszInstance, dim(gszBaseInstance));
}
// sanity check the path by making sure it exists
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, 0, hkDisplay);
if(dwStatus == ERROR_SUCCESS) {
RegCloseKey(hkDisplay);
fOk = TRUE;
}
else
{
RETAILMSG(0, (_T(SALCD2: DisplayInit: can't open '%s'rn), gszBaseInstance));
}
return fOk;
}
pszInstance:注册表中显示驱动的相关注册表值
dwNumMonitors:支持的Monitor的个数
在该函数中主要通过读取注册表信息判断显示驱动的存在,如果返回错误,则GWES会停止Display驱动的初始化。当然,用户可以根据自己的要求灵活掌握,也可以在这里初始化显示设备或做其他的初始化工作。
4 实现GPE类中的函数
由于NewGPE继承于GPE类,所以必须实现GPE类中的所有纯虚函数,这些函数实际上就是PDD层驱动中需要实现的函数,如下:
4.1 virtual SCODE GetModeInfo(GPEMode *pMode, INT modeNumber)
获得显示模式。
pMode:输出显示模式结构
modeNumber:显示模式索引号
4.2 virtual int NumModes(void)
获得当前驱动支持的显示模式的个数
4.3 virtual SCODE SetMode(INT modeId, HPALETTE *palette)
设置显示模式。
modeId:显示模式索引号
palette:调色板指针,指向一个由EngCreatePalette函数创建的调色板
4.4 virtual SCODE AllocSurface(GPESurf **surface, INT width, INT height, EGPEFormat format, INT surfaceFlags)
在系统内存中创建一个绘图平面。
surface:指向被分配的内存的指针
width:宽度
height:高度
format:绘图平面格式
surfaceFlags:标记位,标明在哪分配内存
4.5 virtual SCODE SetPointerShape(GPESurf *pMask, GPESurf *pColorSurface, INT xHot, INT yHot, INT cX, INT cY);
设置光标形状。
pMask:指向一个包含光标形状的掩码
pColorSurface:指向被光标使用的颜色绘图平面
xHot:光标热点的X坐标
yHot:光标热点的Y坐标
cX:光标宽度
cY:光标高度
4.6 virtual SCODE MovePointer(int x, int y)
移动光标到指定位置或者隐藏光标
x:光标移动位置的x坐标,若为-1表示隐藏光标。
评论