按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
m_nCurPage 可以帮你做出正确的决定。
释放GDI 对象的最理想时机当然是在OnEndPrinting,这是每当一份打印工作结束后,
Application Framework 会调用的函数。
Scribble 没有使用什么特殊的绘图工具,因此下面这两个虚拟函数也就没有修改,完全
保留AppWizard 当初给我们的样子:
void CScribbleView::OnBeginPrinting(CDC* /*pDC*/; CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CScribbleView::OnEndPrinting(CDC* /*pDC*/; CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
尺寸与方向:关于映射模式(坐标系统)
回忆所谓的坐标系统,我已经在上一章描述过CScrollView 如何为了卷动效果而改变座
标系统的原点。除了改变原点,我们甚至可以改变坐标系统的单位长度,乃至于改变座
标系统的横纵比例(scale)。这些就是这一节要讨论的重点。
Document 有大小可言吗?有的,在打印过程中,为了计算Document 对应到打印机的页
数,我们需要Document 的尺寸。CScribbleDoc 的成员变量m_sizeDoc ,就是用来记录
Document 的大小。它是一个CSize 对象:
688
…………………………………………………………Page 751……………………………………………………………
第 12 章 列印與預樱А�
800
9
void CScribbleDoc::InitDocument()
void CScribbleDoc::InitDocument()
0
0
{{ Document
。。。
。。。
m_sizeDoc = CSize(800;900);
m_sizeDoc = CSize(800;900);
}
}
事实上,所谓「逻辑坐标」原本是没有大小的,如果我们说一份Document 宽800 高
900;那么若逻辑坐标的单位是英寸;这就是 8 英寸宽 9 英寸高;若逻辑座标的单位是
公分,这就是8 公分宽9 公分高。如果逻辑单位是图素(Pixel )呢?那就是800 个图
素宽900 个图素高。图素的大小随着输出装置而改变,在14 Super VGA (1024x768)
显示器上,800x900 个图素大约是21。1 公分宽23。6 公分高,而在一部300 DPI (Dot Per
Inch,每英嫉闶'y )的激光打印机上,将是2…2/3 英伎3 英几摺
预设情况下GDI 绘图函数使用MM_TEXT 映射模式(Mapping Mode ,也就是坐标系
统,注),于是逻辑坐标等于装置坐标,也就是说一个逻辑单位是一个图素。如果不重
新设定映射模式,可以想见屏幕上的图形一放到300 DPI 打印机上都嫌太小。
解决的方法很简单:设定一种与真实世界相符的逻辑坐标系统。Windows 提供的八种映
像模式中有七种是所谓的metric 映射模式,它们的逻辑单位都建立在公分或英嫉幕
上,这正是我们所要的。如果把OnDraw 内的绘图动作都设定在MM_LOENGLISH 映射
模式上(每单位0。01 英迹敲床宦凼涑龅狡聊簧匣虻酱蛴』隙蓟竦孟嗤某叨取
真正要为「多少图点才能画出一英汲ぁ股四越畹氖亲爸们'y动程序,不是我们。
689
…………………………………………………………Page 752……………………………………………………………
第篇 深入 MFC 程式設計
注:GDI 的八种映射模式及其意义如下:
MM_TEXT :以图素(pixel )为单位,Y 轴向下为正,X 轴向右为正。
MM_LOMETRIC :以0。1 公分为单位,Y 轴向上为正,X 轴向右为正。
MM_HIMETRIC :以0。01 公分为单位,Y 轴向上为正,X 轴向右为正。
MM_LOENGLISH :以0。01 英嘉5 ノ唬Y 轴向上为正,X 轴向右为正。
MM_HIENGLISH :以0。001 英嘉5 ノ唬Y 轴向上为正,X 轴向右为正。
MM_TWIPS:以1/1440 英嘉5 ノ唬Y 轴向上为正,X 轴向右为正。
MM_ISOTROPIC :单位长度可任意设定,Y 轴向上为正,X 轴向右为正。
MM_ANISOTROPIC :单位长度可任意设定,且X 轴单位长可以不同于Y 轴
单位长(因此圆可能变形)。Y 轴向上为正,X 轴向右为正。
回忆上一章为了卷动窗口,曾有这样的动作:
void CScribbleView::OnInitialUpdate()
{
SetScrollSizes(MM_TEXT; GetDocument()…》GetDocSize());
CScrollView::OnInitialUpdate();
}
映射模式可以在SetScrollSizes 的第一个参数指定。现在我们把它改为:
void CScribbleView::OnInitialUpdate()
{
SetScrollSizes(MM_LOENGLISH; GetDocument()…》GetDocSize());
CScrollView::OnInitialUpdate();
}
注意,OnInitialUpdate 更在OnDraw 之前被调用,也就是说我们在真正绘图动作
OnDraw 之前完成了映射模式的设定。
映射模式不仅影响逻辑单位的尺寸,也影响Y 轴坐标方向。MM_TEXT 是Y 轴向下,
MM_LOENGLISH (以及其它任何映射模式)是Y 轴向上。但,虽然有此差异,我们的
Step5 程序代码却不需为此再做更动,因为DPtoLP 已经完成了这个转换。别忘了,鼠标
690
…………………………………………………………Page 753……………………………………………………………
第 12 章 列印與預樱А�
左键传来的点坐标是先经过DPtoLP 才储存到CStroke 对象并且然后才由LineTo 画
出的。
然而,程序的某些部份还是受到了Y 轴方向改变的冲击。映射模式只会改变GDI 各相
关函数,不使用DC 的地方,就不受映射模式的影响,例如CRect 的成员函数就不知
晓所谓的映射模式。于是,本例中凡使用到CRect 的地方,要特别注意做些调整:
1。 修正「线条外围四方形」的计算方式。原计算方式是在FinishStroke 中这么做:
for (int i=1; i 《 m_pointArray。GetSize(); i++)
{
pt = m_pointArray'i';
m_rectBounding。left = min(m_rectBounding