在第三章我们已经使用设备环境句柄在窗口客户区绘图了。在图形输出设备(比如屏幕或者打印机)上绘制图形,必须首先获取设备环境,即DC的句柄。当 Windows把这个句柄交给你的程序,Windows同时也就给予你使用这个设备的权限。接着,在GDI函数中将这个句柄作为一个参数,告诉 Windows在哪个设备上进行绘图。
本节必须掌握的知识点:
获取设备环境句柄
获取设备环境信息
第22练:获取设备环境信息
4.2.1 获取设备环境句柄
设备环境包含许多决定GDI函数如何工作的属性。这些属性使得GDI函数只需要提供少量的参数(如起始坐标),而不需要提供 Windows在设备上显示对象时需要的所有信息。例如,当你调用 TextOut函数时,仅需要在函数中指定设备环境句柄、起始坐标、文本以及文本的长度,不需要指定字体、文本的颜色、文本背景的颜色或者字符间距。所有这些属性都是设备环境的一部分。当你想改变这些属性时,可以调用函数来执行,之后调用的TextOut函数就会使用新的设备环境的属性。
■在WM_PAINT消息中获取
在处理 WM_PAINT消息时使用 BeginPaint函数和 EndPaint函数:
hdc = BeginPaint (hwnd, &ps) ;
其他行程式
EndPaint (hwnd, &ps) ;
■在其他消息中获取
hdc = GetDC (hwnd) ;
其他行程式
ReleaseDC (hwnd, hdc) ;
EndPaint函数组合与GetDC函数组合的主要差别是:
EndPaint函数获取无效区域的设备环境句柄。
GetDC函数返回的是整个窗口客户区的设备环境句柄。并且GetDC和 ReleaseDC函数并不使任何客户区的无效区域变为有效。
■获取屏幕设备环境句柄
hdc = CreateDC (pszDriver, pszDevice, pszOutput, pData) ;
其他行程式
DeleteDC (hdc) ;
例如,可以通过调用下面的函数获取当前整个屏幕的设备环境句柄:
hdc = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;
此外,我们还将在第十三章使用CreateDC函数获取打印机设备环境句柄。
■获取内存设备环境句柄
hdcMem = CreateCompatibleDC (hdc) ;
其他行程式
DeleteDC (hdcMem) ;
可以把一个位图选入内存设备环境,并且调用GDl函数绘制这个位图。我将在第十四章介绍这些技术。
■获取整个窗口设备环境句柄
hdc = GetWindowDC (hwnd) ;
其他行程式
ReleaseDC (hwnd, hdc) ;
这里的设备环境除了包括客户区,还包含窗口标题栏、菜单、滚动条和客户区的外框。应用程序很少使用 GetWindowDC函数。如果你想尝试使用它,则还应当捕获WM_NCPAINT( nonclient paint,非客户区绘制)消息,Windows使用这个消息在窗口的非客户区绘图。
■获取设备环境信息
CreateIC 函数为指定设备创建信息上下文。信息上下文提供了一种快速获取有关设备的信息的方法,而无需创建设备上下文 (DC) 。但是,GDI 绘图函数不能接受信息上下文的句柄。
HDC CreateIC(
LPCTSTR lpszDriver, // 驱动程序的名称或驱动程序文件名
LPCTSTR lpszDevice, // 设备的名称
LPCTSTR lpszOutput, // 输出端口的名称
const DEVMODE *lpInitData // 设备的初始化数据
);
■获取图元文件设备环境句柄
hdcMeta = CreateMetaFile (pszFilename) ;
其他行程式
hmf = CloseMetaFile (hdcMeta) ;
在图元文件设备环境有效时,使用 hdcMeta所做的任何GDI调用都不会被直接显示出来,它们都会变成图元文件的一部分。当你调用 CloseMetaFile时,图元文件设备环境句柄变为无效,该函数返回一个图元文件句柄(hmf)。我将在第十七章讨论图元文件。
4.2.2 获取设备环境信息
设备环境通常指的是物理的显示设备,如视频显示器或者打印机。经常需要获取这些设备的某些信息,包括显示器的大小(以像素或者物理尺寸的方式)和它的色彩能力。这些信息可以通过调用 GetDeviceCaps(意思为获取设备的能力)函数来获取。
iValue = GetDeviceCaps (hdc, iIndex) ;
其中,参数 iIndex是定义在 WINGDL.H头文件中的29个标识符之一。例如,当 iIndex的值为 HORZRES时, GetDeviceCaps函数以像素为单位返回设备的宽度;使用ⅤERTRES参数值会以像素为单位返回设备的高度。如果hdc是一个屏幕设备环境的句柄,这里所获取的信息和从 GetSystemMetrics函数获取的信息是一样的。如果hdc是一个打印机设备环境,那么 GetDevice Caps将以像素为单位返回打印机显示区域的高度和宽度。
还可以使用 GetDeviceCaps函数来确定设备处理各种类型图形的能力。通常这对于视频显示器并不重要,但是对于打印机却非常重要。例如,大多数的绘图仪不能绘制位图图像,通过调用 GetDeviceCaps函数可以让你提前知道这一情况。我们将在接下来的实例中演示GetDeviceCaps函数的使用方法。
4.2.3 第22练:获取设备环境信息
/*------------------------------------------------------------------
022. 编程达人win32 API每日一练
第22个例子DEVCAPS1.C:获取显示器设备环境信息
GetDeviceCaps函数
(c) www.bcdaren.com, 2020
----------------------------------------------------------------*/
#include <windows.h>
#define NUMLINES ((int)(sizeof devcaps / sizeof devcaps[0])) //行数
struct
{
int iIndex; //索引
TCHAR *szLable; //系统信息
TCHAR *szDesc; //描述
}
devcaps[]= //结构数组
{
HORZSIZE, TEXT("HORZSIZE"), TEXT("Width in millimeters:"),
VERTSIZE, TEXT("VERTSIZE"), TEXT("Height in millimeters:"),
HORZRES, TEXT("HORZRES"), TEXT("Width in pixels:"),
VERTRES, TEXT("VERTRES"), TEXT("Height in raster lines:"),
BITSPIXEL, TEXT("BITSPIXEL"), TEXT("Color bits per pixel:"),
PLANES, TEXT("PLANES"), TEXT("Number of color planes:"),
NUMBRUSHES, TEXT("NUMBRUSHES"), TEXT("Number of device brushes:"),
NUMPENS, TEXT("NUMPENS"), TEXT("Number of device pens:"),
NUMMARKERS, TEXT("NUMMARKERS"), TEXT("Number of device markers:"),
NUMFONTS, TEXT("NUMFONTS"), TEXT("Number of device fonts:"),
NUMCOLORS, TEXT("NUMCOLORS"), TEXT("Number of device colors:"),
PDEVICESIZE, TEXT("PDEVICESIZE"), TEXT("Size of devicestructure:"),
ASPECTX, TEXT("ASPECTX"), TEXT("Relative width of pixel:"),
ASPECTY, TEXT("ASPECTY"), TEXT("Relative height of pixel:"),
ASPECTXY, TEXT("ASPECTXY"), TEXT("Relative diagonal of pixel:"),
LOGPIXELSX, TEXT("LOGPIXELSX"), TEXT("Horizontal dots per inch:"),
LOGPIXELSY, TEXT("LOGPIXELSY"), TEXT("Vertical dots per inch:"),
SIZEPALETTE, TEXT("SIZEPALETTE"), TEXT("Number of palette entries:"),
NUMRESERVED, TEXT("NUMRESERVED"), TEXT("Reserved palette entries:"),
COLORRES, TEXT("COLORRES"), TEXT("Actual color resolution:")
};
/*****************************************************************************/
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("DEVCAPS1.C") ;
…(略)
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxChar, cxCaps, cyChar;
HDC hdc ;
int i;
PAINTSTRUCT ps ;
TCHAR szBuffer[10] ;
TEXTMETRIC tm ;
switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ; //字符平均宽度
//平均字符宽度cxCaps设为cxChar的1.5倍。1表示变宽字体
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ; //字符行距
ReleaseDC (hwnd, hdc) ;
return 0 ;
case WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
for (i = 0 ; i < NUMLINES ; i++)
{
TextOut(hdc, 0, cyChar * i,devcaps[i].szLable,
lstrlen(devcaps[i].szLable));
TextOut(hdc, 14 * cxCaps, cyChar*i,devcaps[i].szDesc,
lstrlen(devcaps[i].szDesc));
SetTextAlign(hdc, TA_RIGHT | TA_TOP);
TextOut(hdc, 14 * cxCaps + 35 * cxChar, cyChar * i, szBuffer,
wsprintf(szBuffer, TEXT("%5d"),
GetDeviceCaps(hdc,devcaps[i].iIndex)));
SetTextAlign(hdc, TA_LEFT | TA_TOP);
}
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
/*****************************************************************
GetDeviceCaps功能检索指定设备的设备特定的信息
int GetDeviceCaps(
HDC hdc, //设备环境句柄
int index //设备环境信息索引
);
返回值指定所需项目的值。
******************************************************************
类似的API:
GetSystemMetrics函数:检索指定的系统指标或系统配置设置。
int GetSystemMetrics(int nIndex //要检索的系统指标或配置设置);
*/
运行结果:
图4-1 获取显示设备信息
总结
DEVCAPS1.C的代码实现非常简单,定义了一个显示设备信息的结构数组,然后在WM_PAINT消息中循环输出GetDeviceCaps(hdc,devcaps[i].iIndex)));获取的显示设备信息。
GetDeviceCaps 函数用于检索指定设备上下文的设备能力信息。它可以查询设备的各种能力,如分辨率、颜色深度、支持的功能等。
int GetDeviceCaps(
HDC hdc, // 设备上下文句柄
int nIndex // 设备能力的索引
);
返回值:
如果函数成功,返回设备能力的值,具体取决于 nIndex 参数。
如果函数失败,返回值为 0。
iIndex | iValue(返回值) | 备注 |
HORZRES | 以像素为单位的设备宽度 | 1、当hdc为整个屏幕DC时,与GetSystemMetrics获得的信息一致。 2、当hdc为打印机时,获得的是打机印显示区域的宽度和高度。 |
VERTRES | 以像素为单位的设备高度 | |
HORZSIZE | 以毫米为单位的屏幕宽度 | 1、Windows98下: HORZSIZE = 25.4×HORZRES/LOGPIXELSX. VERTSIZE = 25.4×VERTRES/LOGPIXELSY 2、Windows NT下:为"标准显示器”的大小,即320×240,但可通过上述公式算出这两个真实的值出来。 3、对于打印机是物理尺寸,对于显示器是逻辑尺寸。 |
VERTSIZE | 以毫米为单位的屏幕高度 | |
LOGPIXELSX | 每英寸的水平像素数 | 1、对于打印机:可以用上述公式运算出来。 2、对于显示器:与Windows设置的字体有关:正常字体96dpi,大字体为120dpi |
LOGPIXELSX | 每英寸的垂直像素数 |