- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
CPaintDC dc(this);
CFont font;
dc.SelectObject(font); // why does this build?
函数CDC::SelectObject采用 CFont
类型的指针,但为什么要通过提供对象来构建?我遇到了这个问题,上面的代码是不可预测的,有时会崩溃,但并非总是如此。
最佳答案
有问题的代码在某种程度上是有效的。它的编译是由于两件事的结合:
CFont::operator HFONT()
.CDC::SelectObject
重载采用 HGDIOBJ
句柄。当编译器尝试为 dc.SelectObject(font)
匹配重载时,它们都不匹配。因此接下来它会尝试返回 HFONT
的用户定义的转换运算符 (operator HFONT()
)。这与采用 HGDIOBJ
的未记录的重载相匹配(HGDIOBJ
和 HFONT
都被类型定义为 void*
)。
问题中发布的代码也几乎是正确的,但有 2 个异常(exception):
font
对象被销毁,同时仍被选择到设备上下文中。虽然这会导致双重删除错误(字体对象属于 CFont
实例和设备上下文),但对 DeleteFont
的调用传递无效句柄时优雅地失败。这两个问题都不会导致不可预测的行为或间歇性崩溃。如 your answer 中所述,然而,真正的代码看起来像这样:
CFont* pOldFont = (CFont*) dc.SelectObject(font);
这是一个表现出未定义行为的错误。 dc.SelectObject(font)
返回一个 HGDIOBJ
(类型定义为 void*
),随后将其转换为不相关的类型(CFont*
).虽然将先前选择的字体存储到设备上下文中以便稍后恢复它是正确的,但代码不是。尊重所有权的实现可以是:
CPaintDC dc(this);
CFont font;
CFont oldFont;
// Transfer ownership of font to the DC, and the previously selected font into oldFont
oldFont.Attach(dc.SelectObject(font.Detach()));
// Use dc
// Transfer ownership back
font.Attach(dc.SelectObject(oldFont.Detach()));
// oldFont goes out of scope; this a no-op since it no longer owns any resources
// font goes out of scope, releasing all resources owned by it
// dc goes out of scope, releasing all resources owned by objects selected into it
如果您愿意暂时牺牲严格的所有权语义,您可以通过使用更标准的实现让您的生活更轻松:
CPaintDC dc(this);
CFont font;
CFont* pOldFont = dc.SelectObject(&font);
// Use dc
dc.SelectObject(pOldFont);
这是安全的,即使您提前退出,也不会恢复设备上下文。它仍然会导致对 CFont
实例和设备上下文(由 API 妥善处理)所拥有的字体对象进行双重删除。不过,它并没有出现字体泄漏,因为事情比看起来更复杂:这里涉及另一个不可见的所有者,一个由 MFC 控制的映射,用于存储临时对象(比如从 CGdiObject::FromHandle
返回的那些, SelectObject(CFont*)
调用)。作为 MFC 空闲时间处理的一部分,临时对象被清理。
关于c++ - 为什么 CDC::SelectObject(CFont*) 接受 CFont 对象而不是指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48832422/
我想我确实明白如果我在“设备连接”中选择“一个对象”,并且该对象是画笔、字体、,会发生什么>pen:这些对象的特征因此用于在设备上下文上绘图。 但是,我不明白在设备上下文中选择位图后会发生什么,更不用
在我的程序中,我有一个我经常绘制的内存 DC,然后响应 WM_PAINT,我快速将它 BitBlt 到屏幕上。我一直都是这样画的,内存 DC 是响应 WM_CREATE 顺便说一句而创建的。 void
所以我正在为我的应用程序编写一个搜索功能,代码如下: - (void) selectObject: (NSString *)notes{ [axKnotes removeAllObjects]
我有一些像这样管理异常安全的原始代码: void foo() { HDC hdc = //get an HDC HBITMAP hbitmap = //get an HBITMAP
您好,我正在尝试创建一个画笔,但我在使用 SelectObject 这行代码时遇到了问题: Brush_C = SelectObject(hdc_TS, hBrush); 错误是这样的: line 2
我有一个位图类,它有一个加载函数,用于从文件路径或资源 ID 加载位图。这部分工作正常。 void GtBitmap::Load() { LPTSTR szFileNa
我正在尝试从屏幕的 0x0(左上)位置获取 500x500 的屏幕截图并将其放在窗口中。 这是我的代码(hwnd 是我的窗口句柄): HDC appDc = GetDC(hwnd); HDC dc =
我正在开发多线程 win32 MFC 应用程序。我们正在渲染 map 并将其显示在用户界面的 Pane 中,并在顶部显示自定义渲染的对象。呈现速度很慢(~800 毫秒),这是在用户界面线程上发生的。
所以我试图在 Win32 中制作 Pong 的克隆,并且一切正常,但后来我做了很多物理方面的事情,当我测试它时, Sprite 位图甚至不再显示:/ 所以,这是我如何初始化渲染内容: int Init
CPaintDC dc(this); CFont font; dc.SelectObject(font); // why does this build? 函数CDC::Select
希望你有美好的一天。 Dom4j javadoc 表单 Node.selectObject(String xpathExpression) 说: ...返回的对象可以是一个或多个 Node 实例的列表
首先我会说我对编译语言一点经验都没有,这可能是显而易见的,但我已经做了几个小时的搜索并且空手而归。 我正在尝试构建 this Eclipse 中的项目。我已经构建并导入了 OpenCV 3.1,在我开
我是一名优秀的程序员,十分优秀!