windows 我什么时候应该在位图上调用 DeleteObject()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8500137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should I call DeleteObject() on bitmap
提问by Rom098
I'm examining some legacy Win32/MFC project.
我正在检查一些遗留的 Win32/MFC 项目。
I've found the following (pseudo-code):
我发现了以下内容(伪代码):
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);
// .. do something with hDC ..
::DeleteDC(hDC);
It looks strange for me. Could anyone please explain is it correct to delete the bitmap and/or close the file handle before I do something with the DC?
对我来说看起来很奇怪。谁能解释一下,在我对 DC 执行某些操作之前删除位图和/或关闭文件句柄是否正确?
Thanks.
谢谢。
回答by cbranch
No, it's not correct. The code calls SelectObject()
to select the bitmap into the device context, then calls DeleteObject()
in an attempt to delete the bitmap while it's still selected in the device context. In this case, DeleteObject()
will fail, so the bitmap is leaked.
不,这是不正确的。代码调用SelectObject()
以将位图选择到设备上下文中,然后调用DeleteObject()
以尝试在位图在设备上下文中仍处于选中状态时将其删除。在这种情况下,DeleteObject()
将失败,因此位图被泄露。
http://msdn.microsoft.com/en-us/library/dd183539(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/dd183539(v=vs.85).aspx
"Do not delete a drawing object (pen or brush) while it is still selected into a device context."
“当绘图对象(笔或画笔)仍被选入设备上下文时,请勿删除它。”
EDIT:
编辑:
Well, that's interesting. I tried calling DeleteObject()
while a bitmap is selected in the device context, and it returns 1 for me too. Interestingly, the bitmap is not actually deleted at this point; calling GetObject()
on the "deleted" bitmap succeeds! However, as soon as the deleted bitmap is selected out of the device context, then it is actually deleted; calling GetObject()
fails at that point. I also verified by watching the GDI handle count in Task Manager. So, apparently DeleteObject()
will defer the deletion if the bitmap is currently selected into a device context, though I don't believe that's documented anywhere.
嗯,这很有趣。我尝试DeleteObject()
在设备上下文中选择位图时调用,它也为我返回 1。有趣的是,此时位图实际上并未被删除;调用GetObject()
“删除”的位图成功!然而,一旦被删除的位图被从设备上下文中选择出来,那么它实际上就被删除了;此时调用GetObject()
失败。我还通过在任务管理器中观察 GDI 句柄计数来验证。因此,DeleteObject()
如果位图当前被选择到设备上下文中,显然会推迟删除,尽管我不相信这在任何地方都有记录。
HDC hdc = CreateCompatibleDC(NULL);
if (hdc != NULL) {
HBITMAP hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SAMPLE));
BITMAP bm = { 0 };
int numBytes;
// this succeeds as expected
numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);
HBITMAP hOldBitmap = SelectBitmap(hdc, hBitmap);
DeleteObject(hBitmap);
// this succeeds -- NOT expected!
numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);
SelectBitmap(hdc, hOldBitmap);
// this fails as expected
numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);
DeleteDC(hdc);
}
The bottom line is that the code you posted appears to work, but is dependent on undocumented behavior. My preference would be to play it safe and eliminate that dependency.
最重要的是,您发布的代码似乎有效,但取决于未记录的行为。我的偏好是安全操作并消除这种依赖性。
回答by RED SOFT ADAIR
There is a related post in The Old New Thing from Raymond Chen explaining this behavior:
Raymond Chen 在 The Old New Thing 中有一篇相关帖子解释了这种行为:
The GDI folks found that a lot of people mess up and try to destroy objects while they are still selected into DCs. Failing the call caused two categories of problems: Some applications simply leaked resources (since they thought they were destroying the object, but weren't). Other applications checked the return value and freaked out if they saw that Delete-Object didn't actually delete the object.
To keep both of these types of applications happy, GDI will sometimes (not always) lie and say, "Sure, I deleted your object." It didn't actually delete it, because it's still selected into a DC, but it also ties a string around its finger, and when the object is finally deselected, GDI will say, "Oh, wait, I was supposed to delete this object," and perform the deletion. So the lie that GDI made wasn't so much a lie as it was an "optimistic prediction of the future."
GDI 的人发现很多人在他们仍然被选入 DC 的时候搞砸了并试图破坏对象。调用失败会导致两类问题: 一些应用程序只是泄漏了资源(因为它们认为它们正在破坏对象,但实际上并没有)。其他应用程序检查了返回值,如果他们看到 Delete-Object 实际上没有删除对象,就会吓坏了。
为了让这两种类型的应用程序满意,GDI 有时(并非总是)会撒谎说:“当然,我删除了你的对象。” 它实际上并没有删除它,因为它仍然被选中到 DC 中,但它还在它的手指上系了一根绳子,当最终取消选中该对象时,GDI 会说,“哦,等等,我本来应该删除这个对象的,”并执行删除。因此,GDI 的谎言与其说是谎言,不如说是“对未来的乐观预测”。
http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx