现在的位置: 首页 > 综合 > 正文

GDI编程总结(一)—— GDI映射模式

2014年09月02日 ⁄ 综合 ⁄ 共 1976字 ⁄ 字号 评论关闭

映射模式是一种设备环境属性,它会影响GDI绘制。还有其它4种设备环境属性:窗口原点(window origin)、视口原点(viewport origin)、窗口范围(window extents)、视口范围(viewport extents),它们与映射模式密切相关。

几乎所有GDI函数都使用逻辑单位,Windows需要将逻辑单位转换为设备单位(像素),这些转换由映射模式、窗口原点、视口原点、窗口范围、视口范围共同控制。映射模式会决定以什么东西作为逻辑单位,还有x轴/y轴的指向(orientation)。Windows一共定义了8种映射模式,位于wingdi.h文件中。

/* Mapping Modes */
#define MM_TEXT             1
#define MM_LOMETRIC         2
#define MM_HIMETRIC         3
#define MM_LOENGLISH        4
#define MM_HIENGLISH        5
#define MM_TWIPS            6
#define MM_ISOTROPIC        7
#define MM_ANISOTROPIC      8

具体映射模式见下表:

MM_TEXT是最常用的也是最容易理解的,同时也是默认使用的映射模式。在MM_TEXT下,逻辑单位与设备单位相同,都以像素为单位;y轴坐标向下增长,与设备坐标系相同。

GDI提供了两个API,分别用于设置和获取映射模式。MFC的DC类也提供了相应的封装版本。

int SetMapMode(
	HDC hdc,        // handle to device context
	int fnMapMode   // new mapping mode
);

int GetMapMode(
	HDC hdc   // handle to device context
);

写几行测试代码(MFC):

void CMFCtestDlg::OnPaint()
{
	CPaintDC dc(this);
	dc.TextOut(100, 100, _T("MM_TEXT:(100, 100)"));

	dc.SetMapMode(MM_LOMETRIC);
	dc.TextOut(100, 100, _T("MM_LOMETRIC:(100, 100)"));
}

看一下程序的运行效果:

映射模式为默认的MM_TEXT时,输出文本正常,坐标是(100, 100),单位是像素。将映射模式改为MM_LOMETRIC之后,输出的文本没显示出来。这是因为此时y轴的正方向是向上的,原点还是左上角,这样显示位置已经超出可视范围了。将坐标改为(100,
-100)

dc.SetMapMode(MM_LOMETRIC);
dc.TextOut(100, -100, _T("MM_LOMETRIC:(100, -100)"));

再看程序的运行效果:

两次的输出文本都正常了。当映射模式为MM_LOMETRIC时,逻辑单位为0.01英寸。

所有的Windows消息(WM_SIZEWM_MOVEWM_MOUSEMOVE)都使用设备坐标(以像素为单位)而不是逻辑坐标,所以映射模式与其无关。

映射模式都会影响哪些GDI函数?映射模式是一种设备环境属性,所以如果一个GDI函数包含DC句柄参数,那映射模式就会影响它。其它GDI函数和非GDI函数,则与映射模式无关。当然,事情也不总是这样。GetDeviceCap是GDI函数,且有一个HDC参数。

int GetDeviceCaps(
  HDC hdc,     // handle to DC
  int nIndex   // index of capability
);

经常调用这个函数来获取屏幕的大小,nIndex传递HORZSIZE/VERTSIZE时,获取的是以毫米为单位的物理尺寸。但我们实际使用时,通常是nIndex传递HORZRES/VERTRES,获取以像素为单位的屏幕尺寸。

//If handle is NULL, retrieves the DC for the entire screen. 
HDC hdcScreen = ::GetDC(NULL); 

int widthPixels  = GetDeviceCaps(hdcScreen, HORZRES);
int heightPixels = GetDeviceCaps(hdcScreen, VERTRES);

::ReleaseDC(NULL, hdcScreen);

GetSystemMetrics是非GDI函数,所以它总以设备单位(像素)返回。

int widthPixels = GetSystemMetrics(SM_CXSCREEN);
int heightPixels = GetSystemMetrics(SM_CYSCREEN);

GetTextMetrics是GDI函数,并且具有HDC参数,所以它获取的TEXTMETRIC结构中的值是使用逻辑单位的。如果要使用这些值,就要注意输出文本时所使用的映射模式。

学习资料: 《Windows程序设计》

抱歉!评论已关闭.