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


其实MSDN对SelectObject有相关解释:

Class CDC provides five versions specialized for particular kinds of GDI objects, including pens, brushes, fonts, bitmaps, and regions. The newly selected object replaces the previous object of the same type. For example, if pObject of the general version of SelectObject points to a CPen object, the function replaces the current pen with the pen specified by pObject.

An application can select a bitmap into memory device contexts only and into only one memory device context at a time. The format of the bitmap must either be monochrome or compatible with the device context; if it is not, SelectObject returns an error.


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值