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

时间:2024-03-15 07:56:46

MARK : Windows 程序设计 VC++绘图中映像模式的了解和使用

这部分我从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函数中的逻辑坐标就会转化为“显示区域坐标”;

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

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

视口,窗口,设备,逻辑

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

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

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

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

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

BOOL SetWindowOrgEx (

HDChdc,//handletodevicecontext

intX,//newx-coordinateofwindoworigin //这是逻辑坐标

intY,//newy-coordinateofwindoworigin //这是逻辑坐标

LPPOINTlpPoint//originalwindoworigin

);

The SetWindowOrgEx functionspecifieswhichwindowpointmaps totheviewportorigin(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 (//在原来窗口原点的基础上 偏移窗口原点

HDChdc,//handletodevicecontext

intnXOffset,//horizontaloffset

intnYOffset,//verticaloffset

LPPOINTlpPoint//originalorigin

);

BOOL SetViewportOrgEx (

HDChdc,//handletodevicecontext

intX,//newx-coordinateofviewportorigin //这是逻辑坐标

intY,//newy-coordinateofviewportorigin //这是逻辑坐标

LPPOINTlpPoint//originalviewportorigin

);

The SetViewportOrgEx functionspecifieswhichdevicepointmaps tothewindoworigin(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")));

效果如下:

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

详解

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

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

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

RECTrect;

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轴的值向下增加,可以使用如下的代码:

SIZEsize;

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

SetMapMode(hdc,MM_ANISOTROPIC);

GetViewportExtEx(hdc,&size);

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