为什么CDC :: SelectObject仅适用于CFont版本?

时间:2013-12-09 12:42:01

标签: mfc

documentation for CDC::SelectObject表示“CFont”版本是虚拟的,但CPen,CBrush,CBitmap和CRgn版本不是。

CPen* SelectObject(CPen* pPen);
CBrush* SelectObject(CBrush* pBrush );
virtual CFont* SelectObject(CFont* pFont);
CBitmap* SelectObject(CBitmap* pBitmap);
int SelectObject(CRgn* pRgn);
CGdiObject* SelectObject(CGdiObject* pObject);

这对我来说很烦人。

有人知道这个的原因吗?我可以想象这是出于性能原因,出于兼容性原因还是仅仅因为某些Microsoft程序员的懒惰?

2 个答案:

答案 0 :(得分:3)

如上一个答案中所述,CPreviewDC会覆盖字体的SelectObject。

原因很简单。由于字体映射器,打印机和屏幕上的字体不同。 所以诀窍是SelectObject(CFont *)在调用时设置内部变量m_hPinterFont。调用MirrotFont并填充m_hFont这是应该在屏幕DC上使用的字体。

画笔,笔不需要这样的映射,因为只有设备上的字体处理非常特殊。

这部分描述于MSDN

HTH

答案 1 :(得分:2)

从我在MFC代码中看到的,这是因为CPreviewDC会覆盖它。

CPreviewDC是一个CDC派生类,用于打印预览,似乎没有文档。您可以在afxpriv.h中找到其声明,并在dcprev.cpp中找到它。

编辑: 这些文件的示例路径:
%Program Files%\ Microsoft Visual Studio 9.0 \ VC \ atlmfc \ include \ afxpriv.h
%Program Files%\ Microsoft Visual Studio 9.0 \ VC \ atlmfc \ src \ mfc \ dcprev.cpp

EDIT2:但为什么它们都不虚拟?

我的猜测是微软不希望人们搞乱GDI对象(它们是系统中的有限资源),因此这些函数被声明为非虚拟的。他们已经努力在Win32周围创建一个包装器,它可以正确处理GDI对象(并使用户免于进行大部分处理),并且他们不希望用户改变这种行为并且很可能引入错误。 / p>

但是他们必须打破“规则”才能实现CPreviewDC,这是一种特殊的DC。

所有DC都有两个成员,m_hDC和m_hAttribDC,它们通常是相同的。但在CPreviewDC中,一个代表屏幕,另一个代表打印机。字体是一种特殊的东西,因为打印机不一定与计算机具有相同的字体。因此,当MFC需要为打印预览准备文档时,它首先选择打印机上的字体(它告诉打印机(驱动程序)“嘿,我需要选择这个字体”,打印机选择最接近的字体)然后CPreviewDC镜像它以在屏幕上显示它(它选择系统上最接近打印机选择的字体)。

其余的GDI对象,笔,画笔,区域......不需要这样的特殊处理,因此它们不会被声明为虚拟。