123456

 

GDI对象句柄表

存在着GDI对象表,可以通过未有文档的函数GdiQueryTable查询到:此函数存在于GDI32中,

在GDI对象表中,每个Cell应该是一个16字节的结构体:

struct  
{
	void	*pKernel;
	USHORT  nProcess;
	USHORT  nCount;
	USHORT  nUpper;
	USHORT  nType;
	void    *pUser;
}GdiTableCell;


pKernel指向的是内核地址(页面池),每个GDI对象都有GDI对象表指向的内核数据结构

nProcess是进程标识符,说明GDI对象是进程相关的

nCount一般为0,但是对于DDB来说,当它被选入一个DC中,nCount从0变为1,

如果试图把它再选入另一个DC,就会失败,当DDB从第一个DC中取消时,nCount从1变为0, 说明DDB不能一次被选入一个以上的设备上下文

所以做了个小代码测试:

		CPaintDC dc(this);
		CDC MemDC1,MemDC2;
		MemDC1.CreateCompatibleDC(&dc);
		MemDC2.CreateCompatibleDC(&dc);
		CBitmap *pOld = NULL;
		pOld = MemDC1.SelectObject(&m_ddb);
		//MemDC1.SelectObject(pOld);
		pOld = MemDC2.SelectObject(&m_ddb);
		CRect rcClient;
		GetClientRect(&rcClient);
		dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC2, 0, 0, SRCCOPY);


测试结果是由于MemDC1已选进了m_ddb,所以MemDC2失败了,返回NULL,也没有绘制出来,那么把//MemDC1.SelectObject(pOld);打开,就OK了,

但是对于字体来说,nCount只是一个选择计数,所以把字体选入第二个DC成功后,nCount加1

 

  注意的是这张表是共享的,也就是这张表还包含了其他进程的GDI对象句柄,而进程终止时,GDI会搜索这张表,把有指定进程标识符的对象全部删除掉。

posted on 2012-06-22 17:06  hgy413  阅读(341)  评论(0编辑  收藏  举报

导航