转:http://blog.csdn.net/fysy0000/article/details/6615590
GetStockObject在图形编程中是常用API之一,对于GetStockObject,我一直认为它获得的"对象"是一个句柄(因为GetStockObject的API参考下面有DeleteObject函数的链接,一般只有图形对象函数的链接中才会有它的),并且认为它是从当前程序本身拥的"对象"中返回的,后来我无意的发现了问题,请大家看看API参考手册中对函数GetStockObject的注意项:
......
It is not necessary (but it is not harmful) to delete stock objects by calling DeleteObject.
它说Stock"对象"没有必要删除,可是说如果不删除可能有害,如果是程序本身的"对象",程序在退出时会自己清除的,那么我想我以前的理解是错误的。
我开始仍把GetStockObject的返回值当成一个对象,进行了一下测试,我写了一个循环,不停的获得Stock"对象"而不删除,足足运行了50000次(Windows规定一个程序最多只能同时拥有36000个对象),可是程序照样正常运行,系统也没有因此而变慢,我在想,GetStockObject返回的可能是一个长指针,指向系统提供的共享对象的句柄,无论获得多少次,它只有一份,返回的值也是一样的,于是,我写了一个显示句柄值的过程,结果的确是获得同一Stock类型的返回值都是相同的,可是,我看到返回的值竟是148(SYSTEM_FONT),这个怎么会是长指针?不可能,我马上又仔细的从头看了GetStockObject的API参考,看到下面一段:
...
If the function succeeds, the return value identifies the logical object requested
我靠!它的返回值根本不是一个句柄,只是一个标识ID(真是的,这也是我的大意,总认为操作图形的函数成功返回的是句柄,这类API我只看注意事项的,以后不会了),那么GetStockObject终于有结果了,总结如下:
GetStockObject的返回的对象完全不需要删除,因为GetStockObject返回的根本不是句柄,也就是说根本不是一个对象,甚至GetStockObject本身都不需要,因为它的返回值只是一个标识系统对象的ID值,只不过是为了让SelectObject方便选择系统对象,那么,你在使用SelectObject时直接提供ID值就OK,如SYSTEM_FONT的ID值是148,那么就可直接使用Invoke SelectObject,hdc,148就行,只要你记住了常用Stock对象的ID或把它定义成常数,GetStockObject完全可以丢掉!
(关于SelectObject,它返回的才是一个对象,不过是前一对象的句柄,所以,如果要删除对象,只有选择新的同类型的对象到hdc中,前一对象才返回,就可以删除了,如果中间有交错,记住SelectObject返回的总是前一次选择的同一类型(是同一类型)的对象,如果一个过程很复杂,可以把经常使用的对象在程序启动时创建好,然后把句柄保存起来,使用起来就方便多了,甚至不需要删除,因为程序在退出时所占用的对象Windows会自动清除。)