VC++绘图中映像模式的了解和使用

8 篇文章 0 订阅

MARK : Windows 程序设计 VC++绘图中映像模式的了解和使用 - DH冰 - //... DH冰的安全笔记

这部分我从Windows 程序设计中单独摘出来,方便查看 !!!

使用映像模式

SetMapMode(hdc, iMapMode);

iMapMode = GetMapMode(hdc);

映像模式就是进行一种将 逻辑 单位 转换为 设备 单位 的规则的设定

 

设备坐标和逻辑坐标

Windows 对所有消息(如WM_MOUSEMOVE, WM_SIZE, WM_MOVE),对所有非 GDI 函数,甚至是一些 GDI 函数 永远使用设备坐标 可 以这样来考虑:由于映像方式是一种设备内容属性,所以,只有对需要设备内容句柄作参数的GDI函数,映像方式才会起作用。 GetSystemMetrics不是GDI函数,所以它总是以设备单位(即像素)为量度来传回大小的。尽管GetDeviceCaps是GDI函数,需 要一个设备内容句柄作为参数,但是Windows仍然对HORZRES和VERTRES以设备单位作为传回值,因为该函数的目的之一就是给程序提供以像素 为单位的设备大小。

从GetTextMetrics呼叫中传回的TEXTMETRIC结构的值是使用 逻辑单位 。如果在进行此呼叫时映像方式为MM_LOENGLISH,则GetTextMetrics将以百分之一英寸为单位提供字符的宽度和高度。

 

设备坐标系

所有设备坐标系都是以 像素为单位 ,x轴从左到右递增,y轴从上到下递增。

屏幕坐标系 :(第一种设备坐标)

当我们使用整个屏幕时,就根据“屏幕坐标”进行操作。 屏幕的左上角为 (0, 0)点 屏幕坐标用在WM_MOVE 以及下列函数中  CreateWindow ,MoveWindow(都是非子窗口),GetMessagePos,GetCursorPos,SetCursorPos,GetWindowRect,WindowFromPoint。

全窗口坐标系 :(第二种设备坐标)

全窗口坐标”以程序的整个窗口为基准,标题栏,菜单,滚动条,窗口显示区域,都包括在内,对于普通窗口, 点 (0, 0) 是非显示区域的左上角 ,全窗口坐标在Windows 中极少使用,如果用GetWindowDC 取得设备内容,GDI 函数中的逻辑坐标就会转化为“全窗口坐标”。

显示区域坐标系 :(第三种设备坐标)

显示区域坐标系”, 点 (0, 0) 式显示区域的左上角 ,使用 GetDC 或者 BeginPaint 获得的 hdc 时, GDI 函数中的逻辑坐标就会转化为 “显示区域坐标”;

绘图中映像模式的了解和使用 - DH冰 - //... DH冰的安全笔记

用函数 ClientToScreen 和 ScreenToClient 可以将 显示区域坐标和屏幕坐标互相转换 。可以使用 GetWindowRect 函数获得屏幕坐标下的整个窗口的位置和大小。

 

视口,窗口,设备,逻辑

窗口 坐标系 与逻辑 坐标 ,它们的单位是一样的,都是逻辑单位,但是他们二者是不同的,我们 通常输入的坐标就是逻辑坐标 ,但是输入之后,如何显示在屏幕上的对应位置?视口 坐标系 与设备 坐标系 ,它们的单位也是一样的,都是像素,但是他们二者也是不同的,所有显示在屏幕上的东西都是以设备坐标系去输出,因为 设备坐标是永远固定的,它的(0, 0)点始终是在 hdc 所对应的左上角 。这其实也就是为什么 Windows 对所有消息(如WM_MOUSEMOVE,  WM_SIZE, WM_MOVE),对所有非 GDI 函数,甚至是一些 GDI 函数, 永远使用设备坐标   的原因。看下面四者之间的关系:

绘图中映像模式的了解和使用 - DH冰 - //... DH冰的安全笔记

DPtoLP(hdc, &pt, 1);   // 设备坐标转换为逻辑坐标

LPtoDP(hdc, &pt, 1);   // 逻辑坐标转换为设备坐标

需要注意的是 第二个参数, 是 in/out 类型参数,也就是输入输出都是这个参数。

BOOL  SetWindowOrgEx (

  HDC hdc,        // handle to device context

  int X,          // new x-coordinate of window origin   // 这是逻辑坐标

  int Y,          // new y-coordinate of window origin   // 这是逻辑坐标

  LPPOINT lpPoint // original window origin

);

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

指定窗口坐标原点,而且这个原点是相对于视口坐标原点的。

@font-face{ font-family:"times new roman"; } @font-face{ font-family:"宋体"; } @font-face{ font-family:"symbol"; } @font-face{ font-family:"arial"; } @font-face{ font-family:"黑体"; } @font-face{ font-family:"courier new"; } @font-face{ font-family:"wingdings"; } @font-face{ font-family:"courier new cyr"; } p.0{ margin:0pt; margin-bottom:0.0001pt; layout-grid-mode:char; text-align:justify; font-size:10.5000pt; font-family:'times new roman'; } div.section0{ margin-top:72.0000pt; margin-bottom:72.0000pt; margin-left:90.0000pt; margin-right:90.0000pt; size:612.0000pt 792.0000pt; }

BOOL  OffsetWindowOrgEx (  //在原来窗口原点的基础上 偏移窗口原点

  HDC hdc,          // handle to device context

  int nXOffset,     // horizontal offset

  int nYOffset,     // vertical offset

  LPPOINT lpPoint   // original origin

);

 

BOOL  SetViewportOrgEx (

  HDC hdc,        // handle to device context

  int X,          // new x-coordinate of viewport origin   // 这是逻辑坐标

  int Y,          // new y-coordinate of viewport origin   // 这是逻辑坐标

  LPPOINT lpPoint // original viewport origin

);

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

指定视口坐标原点,而且这个原点是相对于窗口坐标原点的。

GetWindowOrgEx(hdc, &pt);     //获得窗口坐标原点【逻辑坐标】

GetViewportOrgEx(hdc, &pt);   //获得视口坐标原点【逻辑坐标】

 

使用SetMapMode 能改变 hdc 对应设备内容的属性,每次输出看当前的映射模式。

 

MM_ISOTROPIC 映像方式

这种映像方式,可以使用 SetWindowExtEx 和 SetViewportExtEx 来根据自己的偏好改变范围,默认的范围和 MM_LOMETRIC相同。设定示例如下:

    rect.right = 300;

    rect.bottom = 280;

    FillRect(hdc, &rect, (HBRUSH)GetStockObject(GRAY_BRUSH));

 

    SetMapMode (hdc, MM_ISOTROPIC);

    SetWindowExtEx(hdc, 100, 100, NULL);

    SetViewportExtEx(hdc, 300, 280, NULL);

 

    rect.right = 280;

    rect.bottom = 280;

    FillRect(hdc, &rect, (HBRUSH)GetStockObject(DKGRAY_BRUSH));

    TextOut(hdc, 100, 100, TEXT("HHHHHHHHH"), lstrlen(TEXT("HHHHHHHHH")));

效果如下:

绘图中映像模式的了解和使用 - DH冰 - //... DH冰的安全笔记

详解

绘图中映像模式的了解和使用 - DH冰 - //... DH冰的安全笔记

默认的Viewport 的范围是 (cxScreen,cyScreen),所以,为了能正常在程序的显示区域显示我们的输出,通常将其设定为 (cxClient,cyClient)。MM_ISOTROPIC 模式下 Windows会调整范围,以便两条轴上的逻辑单位具有相同的实际尺度,所以上面才出现了一个20px 的未被使用的区域。

有的人不习惯左上角为(0, 0),喜欢左下角为(0, 0),那么你就可以做如下设定:

RECT rect;

GetClientDC(hdc, &rect);

SetMapMode(hdc, MM_ ISOTROPIC );

SetWindowExtEx(hdc, 100, 100, NULL);

SetViewportExtEx(hdc, rect.right, -rect.bottom , NULL);  

            //负值表示的范围大小区域位置都不变只是区域内, x  或者 y 轴的方向改变了

SetViewportOrgEx(hdc, 0, rect.bottom, NULL);

这样就能得到一个和常用的坐标系一样的坐标系。

 

MM_ANISOTROPIC :根据需要放缩图像

在MM_ANISOTROPIC映射方式下,Windows不对您所设定的值进行调整,这就是说,MM_ANISOTROPIC不需要维持 1:1 的纵横比。

第 一次设定MM_ANISOTROPIC映像方式时,它总是继承前面所设定的映像方式的范围,这会很方便。例如,假设您想用MM_LOENGLISH映像方 式,因为希望逻辑单位为0.01英寸,但您不希望y轴的值向上增加,喜欢如MM_TEXT那样的方向,即y轴的值向下增加,可以使用如下的代码:

SIZE size;

SetMapMode(hdc, MM_LOENGLISH);     //给定ANISOTROPIC 范围

SetMapMode(hdc, MM_ANISOTROPIC);

GetViewportExtEx(hdc, &size);

SetViewportExtEx(hdc,  size.cx, -size.cy , NULL);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值