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);
这对我来说很烦人。
有人知道原因吗?我可以想象,这是出于性能的原因,兼容性的原因,或者只是因为一些微软程序员的懒惰?
如前一个答案CPreviewDC为字体覆盖SelectObject。
原因很简单。打印机和屏幕上的字体因字体映射器的不同而不同。因此,诀窍是SelectObject(CFont*)在调用时设置一个内部变量m_hPinterFont。同时调用MirrotFont并填充m_hFont这是应该在屏幕DC上使用的字体。
画笔、笔不需要这样的映射,因为只有设备上的字体处理非常特殊。
MSDN对此进行了部分描述。
HTH
从我在MFC代码中看到的,这是因为CPreviewDC覆盖了它。
CPreviewDC是一个CDC派生的类,用于打印预览,并且似乎没有文档。您可以在afxpriv.h
中找到其声明,在dcprev.cpp
中找到其实现。
编辑:这些文件的路径示例:
%程序文件%\Microsoft Visual Studio 9.0\VC\atmfc\include\afpriv.h
%程序文件%\Microsoft Visual Studio 9.0\VC\almfc\src\mfc\dcprev.cpp
第二版:但为什么它们不都是虚拟的呢?
我的猜测是,微软不希望人们摆弄GDI对象(它们是系统中有限的资源),因此这些函数被声明为非虚拟的。他们已经花了很多精力在Win32周围创建了一个包装器,它可以正确地处理GDI对象(并将用户从大多数处理中解放出来),他们不希望用户改变这种行为,很可能会引入错误。
但他们必须打破这一"规则"才能实施CPreviewDC,这是一种特殊的DC。
所有DC都有两个成员,m_hDC和m_hAttribDC,它们通常是相同的。但在CPreviewDC中,一个代表屏幕,另一个代表打印机。字体是一种特殊的东西,因为打印机不一定有与计算机相同的字体。因此,当MFC需要为打印预览准备文档时,它首先选择打印机上的字体(它告诉打印机(驱动程序)"嘿,我需要选择这个字体",打印机选择它能选择的最接近的字体),然后CPreviewDC将其镜像以在屏幕上显示(它选择系统上可用的与打印机选择的字体最接近的字型)。
其余的GDI对象,笔,画笔,区域。。。不需要这样的特殊待遇,因此它们不被宣布为虚拟的。