- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
我在stackoverflow上面看到的内容:http://stackoverflow.com/questio ... eteobject-on-bitmap
以前我都是采取在DeleteDC后再逐个将自己用SelectObject选入的对象进行DeleteObject销毁处理。然而我发现很多人都不是我这样写的。
原文中给的伪代码:- HDC hDC = ::CreateCompatibleDC(hDCWnd);
- HANDLE hFileMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, dwSize, FileMapName);
- HBITMAP hBmp = ::CreateDIBSection(hDCWnd, &zBI, DIB_RGB_COLORS, &pvNull, hFileMap, 0);
- ::SelectObject(hDC, hBmp);
- ::DeleteObject(hBmp);
- ::CloseHandle(hFileMap);
- //用这个hDC绘图什么的
- ::DeleteDC(hDC);
复制代码 提问者说:“这让我感到哪里不对。。有没有谁能出来帮我解释一下这哪里错了?”
解答的人一开始说“任何时候你都不能用DeleteObject将一个已经选入hDC的对象销毁,在这个对象正在被使用的时候,你调用DeleteObject会失败,然后这个hBmp就泄露了。”而且还提供了MSDN的DeleteObject的函数说明:
https://msdn.microsoft.com/en-us/library/dd183539(v=vs.85).aspx
结果这个人做了几次测试后发现,“经过我的测试,在我将hBitmap选入hDC后调用DeleteObject,它给我返回了个1,表示执行成功。有意思的是,这个位图其实并没有被销毁。调用GetObject来取得这个位图是能够成功的!然而,在我把这个已经删除了的位图选出hDC后,它就真的被销毁了,调用GetObject也会失败。对此我也在任务管理器的GDI句柄监视里面看到了这个现象。这样我认为DeleteObject会根据情况来帮你删除对象,即使我觉得这完全没有被任何文档所记载。”- HDC hdc = CreateCompatibleDC(NULL);
- if (hdc != NULL) {
- HBITMAP hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SAMPLE));
- BITMAP bm = { 0 };
- int numBytes;
- //这句肯定能执行成功。
- numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);
- HBITMAP hOldBitmap = SelectBitmap(hdc, hBitmap);
- DeleteObject(hBitmap);
- //这句出乎意料地能执行成功。
- numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);
- SelectBitmap(hdc, hOldBitmap);
- //这句肯定不能执行成功。
- numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);
- DeleteDC(hdc);
- }
复制代码 最后得出的结论是:
当你用DeleteObject删除一个GDI对象的时候,其实只是减少了这个GDI对象的引用而已。它实际上如果还在被使用的话,它其实还是存在的。
用SelectObject将其选出后,如果它没有任何引用了,它就会被销毁。
估计DeleteDC也会做相同的处理呢。 |
|