Windows 映射模式

一、 映射模式
这是一个初级话题,但好像很多人都没有弄明白,因为几乎每过几天就有人发帖问这个。半年前有人问我这个问题时就想写这篇文章了,但一直觉得没有时间(因为除了学习、工作和玩耍,几乎就没有多少空时间了)。本文现在其实只能算着《 Programming Windows 》中关于“映射模式”的加工,以咱们中国读者更易懂的方式写出;我将逐步往其中添加一些相关内容。

首先,从一个十分简单但又很常用的函数开始:
BOOL TextOut( HDC hdc , // handle to DC
int nXStart , // x-coordinate of starting position
int nYStart , // y-coordinate of starting position
LPCTSTR lpString , // character string
int cbString // number of characters );
这里的( nXstart , nYStart )是字符串显示的起始坐标点,这里的坐标就是“逻辑坐标”。为了最终将文字显示到设备(屏幕)上, Windows 必须将这些逻辑坐标“翻译”成“设备坐标” —— 其实就是“像素 (pixels) ”。 Windows 一共定义了 8 种映射模式,如下表所示:

-----------------------------------------------------------------------------------
                                                                      Increasing Value
Mapping Mode            Logical Unit           x-axis            y-axis

MM_TEXT                       Pixel                      Right             Down
MM_LOMETRIC            0.1 mm                  Right             Up
MM_HIMETRIC              0.01 mm               Right             Up
MM_LOENGLISH          0.01 in.                  Right             Up
MM_HIENGLISH            0.001 in.               Right             Up
MM_TWIPS                     1/1440 in.             Right             Up
MM_ISOTROPIC           Arbitrary (x = y)     Selectable   Selectable
MM_ANISOTROPIC      Arbitrary (x !=y)     Selectable   Selectable
--------------------------------------------------------------------------------------
表 1

注: in. 表 英寸 ; Windows 默认的映射模式是 MM_TEXT ,其实就是 设备坐标 !!!

趁热打铁,看一下例子:

例: 如果我们没有用 SetMapMode 设定 Windows 的映射模式,那么 Windows 将使用默认的 MM_TEXT 映射模式,

TextOut (hdc, 8, 16, TEXT ("Hello"), 5); 的结果是文字将从离客户区左边界 8 个像素、离上边界 16 个像素的位置从左向右输出文字。

而SetMapMode (hdc, MM_LOENGLISH);

TextOut (hdc, 50, -100, TEXT ("Hello"), 5);

的结果将是 从离客户区左边界 50* 0.01 in .= 0.5 in . 、离上边界 100*0.01 = 1 in . 的位置从左向右输出文字。

但 TextOut 的第 3 个参数为什么是 -100 呢?因为客户区左上角的坐标的默认值始终是 (0,0) 的(后面将详细讲到),而上面的列表不适写了吗 ? 在 MM_LOENGLISH 下, Y 轴值递增的方向是向上,也就是说向下递减,当然此时第 3 个参数为负值了。

Windows 设定这些映射模式是为了让用户使用起来更方便,因此你选定合适的映射模式来简化你的工作;或者选用 MM_ISOTROPIC 、 MM_ANISOTROPIC 自己设定逻辑坐标的单位,数值递增方向;或者干脆就用 MM_TEXT (相当于直接使用设备坐标),需要缩放时用 GetDeviceCap 获得必要的信息后 自己去计算得了。

二、坐标原点

常看到网友问 CDC::SetWindowOrg 和 CDC:: SetViewportOrg 的用法,它们实质是封装了 GDI 函数 SetWindowOrgEx 和 SetViewportOrgEx :

而 CSDN 的解释是:

The SetWindowOrgEx function specifies which window point maps to the viewport origin (0,0). The SetViewportOrgEx function specifies which device point maps to the window origin (0,0).

初学者往往一头雾水。

其实“映射模式”中的“映射”就是数学中的“映射”,一种对应关系或者说是一个数学表达式而已。这个表达式就是:

公式一:
xViewport = (xWindow - xWinOrg) × Kx + xViewOrg
yViewport = (yWindow - yWinOrg)  × Ky + yViewOrg

等价公式二:

xWindow = (xViewport - xViewOrg) /Kx + xWinOrg
yWindow = (yViewport - yViewOrg) /Ky + yWinOrg

其中( xWinOrg,yWinOrg ),( xViewOrg,yViewOrg )分别表示逻辑坐标和设备坐标的原点,默认值均为( 0,0 );

( xWindow,yWindow )表示逻辑坐标点,( xViewport,yViewport )表示与之对应的设备坐标点(也就是说,在当前的映射模式下, Windows 将( xWindow,yWindow )影射为( xViewport,yViewport )。);

常数 Kx,Ky 是缩放系数(后面将详细介绍),不同的映射模式下缩放系数不同。

因此,在默认的情况下,( xWinOrg,yWinOrg ) = ( xViewOrg,yViewOrg ) = ( 0,0 ),公式一其实就是:

xViewport = xWindow / Kx          yViewport = yWindow / Ky 。

因此,可以看出,映射模式其实就是设定了一个比例而已,没有什么了不起的!

例:

SetMapMode(hdc,MM_TEXT); // 在 MM_TEXT 下缩放比例 K = 1;

SetWindowOrgEx (hdc,100,100,NULL); // 此时( xWinOrg,yWinOrg )被赋值为( 100 , 100 );

                                                                   // 而 ( xViewOrg,yViewOrg )保持不变为( 0 , 0 )。

那么公式一即为:

xViewport = xWindow -100 yViewport = yWindow -100

因此

TextOut (hdc, 520, 530, TEXT ("ILoveYou,MyGirl"), 15);
                                                                            // ( xWindow,yWindow ) = ( 520 , 530 )

将会从( 520 , 530 ) - ( 100 , 100 ) = ( 220 , 230 )点开始在设备上显示。

而 SetViewportOrgEx 是用来设定( xViewOrg,yViewOrg )的值的,使用方法与 SetWindowOrgEx 的使用类似。从公式一可以看出,在 MM_TEXT 中,

SetWindowOrgEx (hdc, x, y , NULL) ;

SetViewportOrgEx (hdc, - x, - y, NULL);

等价的。

三、缩放系数

缩放系数
Kx = xViewExt / xWinExt
Ky = yViewExt / yWinExt

(xViewExt,yViewExt)和(xWinExt,yWinExt)可分别由 GetViewportExt 和 GetWindowExtEx 得到。

在 MM_TEXT 下, Kx = Ky = 1 ;其它映射模式下Kx、Ky均为常数,它们可以由下表来计算(Window NT,显示设备:1024x768 pixels):
--------------------------------------------------------------------------------------
Mapping Mode     Viewport Extents (x, y)      Window Extents (x, y)

MM_LOMETRIC      (1024, -768)                    (3200, 2400)
MM_HIMETRIC       (1024, -768)                    (32000, 24000)
MM_LOENGLISH   (1024, -768)                    (1260, 945)
MM_HIENGLISH     (1024, -768)                   (12598, 9449)
MM_TWIPS              (1024, -768)                    (18142, 13606)
------------------------------------------------------------------------------------

 

表 2 Windows NT Extents (1024 x 768)

参考文献:

   MSDN by Microsoft

《 Visual C++ 技术内幕》 by David J. Kruglinski et al

《 Programming Windows 》 5 th Edition ,by Petzoldi

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~The End

时间: 2024-11-25 21:22:28

Windows 映射模式的相关文章

Windows映射模式及相关问题的解决

Windows应用程序绘制图形时使用的是一种逻辑单位,每个逻辑单位的大小由映射模式决定, 这个逻辑单位既可以与设备单位(屏幕或打印机上的一个像素点)相同,也可以是一种物理单 位(如毫米),还可以是用户自定义的一种单位.在Windows应用程序中,只要与输出有关系,都 要使用映射模式.本文的目的是帮助读者了解映射模式的一些基本知识,并对在使用中经常 出现的一些问题提出解决方案. 一.映射模式基本知识 当Windows应用程序在其客户区绘制图形时,必须给出在客户区的位置,其位置用x和y 两个坐标表示

windows映射模式

1.什么是映射模式: 当Windows应用程序在其客户区绘制图形时,必须给出在客户区的位置,其位置用x和y 两个坐标表示,x表示横坐标,y表示纵坐标.在所有的GDI绘制函数中,这些坐标使用的是一 种"逻辑单位".当GDI函数将输出送到某个物理设备上时,Windows将逻辑坐标 转换成设备坐标(如屏幕或打印机的像素点).逻辑坐标和设备坐标的转换是由映射模式决 定的.   2.windows中为什么要用到映射模式机制? 映射模式的使用可以实现图形绘制的设备无关性.比如在默认MM_TEXT模

windows程序设计(五)---映射模式(转换设备坐标和逻辑坐标)

在窗口指定位置显示图形或文字,我们使用的坐标单位是象素,称之为设备坐标.看下面语句: pDC->Rectangle(CRect(0,0,200,200)); 画一个高和宽均为200个象素的方块,因为采用的是默认的MM_TEXT映射模式,所以在设备环境不一样时,画的方块大小也不一样,在1024*768的显示器上看到的方块会比640*480的显示器上的小(在不同分辨率下的屏幕象素,在WINDOWS程序设计一书中有示例程序可以获得,或者可以用GetClientRect函数获得客户区的矩形大小.在这里就

MFC打印预览、映射模式、坐标变换

MFC提供了一个框架性的打印和打印预览功能代码,它的基本思想是将实际显示和打印文档的代码合二为一,即都由此文档关联的CView中的OnDraw(CDC *pDC)来处理,由MFC框架根据用户的操作来决定传进来的pDC是指向屏幕还是打印机,当pDC指向屏幕设备,就在屏幕上显示文档, 当指向打印机设备时就打印文档.这些都很好理解,但是,当我们要打印预览时,传进来的pDC就有些特别了.因为打印预览是在屏幕上进行的,所以通常我们会认为这时传进来的pDC一定也是属于屏幕DC一类的.但是其实不然,这个pDC

mm_loenglish模式-MFC CScrollView 映射模式为MM_LOENGLISH 双缓冲

问题描述 MFC CScrollView 映射模式为MM_LOENGLISH 双缓冲 我想在MFC中应用双缓存技术来消除闪烁,代码如下(为了测试,先只画了一条直线):void CDblBufTestView::OnDraw(CDC* pDC){ CDC dcMem; dcMem.CreateCompatibleDC(pDC); //创建与视图的设备相兼容的内存设备 CBitmap bmp; bmp.CreateCompatibleBitmap(pDCrect.rightrect.bottom);

浅析php设计模式之数据对象映射模式_php实例

php中的设计模式中有很多的各种模式了,在这里我们来为各位介绍一个不常用的数据映射模式吧,希望文章能够帮助到各位. 数据映射模式使您能更好的组织你的应用程序与数据库进行交互. 数据映射模式将对象的属性与存储它们的表字段间的结合密度降低.数据映射模式的本质就是一个类,它映射或是翻译类的属性或是方法到数据库的相应字段,反之亦然. 数据映射的作用(工作)就在于能对双方所呈现出的信息的理解,并能对信息的存取进行控制,如根据存储在数据表中的信息 重建新的域对象,或是用域对象的信息来更新或删除数据表中的相关

PHP设计模式之:数据映射模式教程

之前的几种设计模式,都是大大提高了PHP代码的可读性.可维护性.但是,在WEB应用中还有更重要的需求与挑战,那就是:数据库应用.可之前的设计模式,都没有涉及于此.今天写到的,数据映射模式就是能够更好的组织应用程序与数据库进行交互.博主这两天也是花了点时间对,这种模式有了那么一点的了解.斗胆在这个里献丑,按照自己的理解,写一点东西与大家分享,互相学习.当然说到数据映射模式,就不得不提到对象关系映射(Object Relational Mapping,简称ORM),用于实现面向对象编程语言里不同类型

Windows上帝模式,上帝应该就是这样使用Windows的

Windows上帝模式(Windows Master Control Panel)由来已久,最早是从Win7优化大湿里看到的一个选项,开启后在桌面生成一个图标,点进去后里面包含了几乎全部Windows设置选项. 直到今天刷G+(view on google plus)发现另一种方式创建这个上帝模式,挻有意思的不是嘛. 在桌面新建一个文件夹 按F2重命名为GodMode.{ED7BA470-8E54-465E-825C-99712043E01C} DONE!    

windows程序设计之绘图基础之度量映射模式

  逻辑坐标被映射到不同的显示设备,x和y都会被映射,所以即使是设备不同,x和y是同时改变,所以就不会改变所绘图形的形状. 使用GetDevicecaps设置视口和窗口的范围. 设置左上角的逻辑坐标系统 设置左下角的逻辑坐标系统 设置正中间的逻辑坐标系统 调用SetWindowOrgEx函数设置逻辑点. pt.x = xClient ; pt.y = yclient ; DpthLP(hdc ,&pt, 1) ; SetWindowOrgEx(hdc , -pt.x/2 , -pt.y/2 ,