/*****************************************************
078.C
第78个列子:获取显示器及打印机设备信息
WM_SETTINGCHANG 消息:系统设置变化
CheckMenuItem 函数
EnumPrinters(): 枚举打印机
AppendMenu(): 添加菜单
Openprinter (): 打开打印机
printerPropertites() : 打印机属性
GetMenuString(): 获取菜单字符串
CreateIC(): 获取当前设备环境的信息和CreateDC不一样
此程序只能运行在32位上,64位debug版本存在bug
(c) 2023
*****************************************************/
#include<Windows.h>
#include"resource.h"
#include<VersionHelpers.h>
//#pragma warning(disable:4996),把这个警告信息屏蔽掉
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DoBasicInfo(HDC, HDC, int, int);//基本信息
void DoOtherInfo(HDC, HDC, int, int);//其他信息
void DoBitCodedCaps(HDC, HDC, int, int, int);//位图信息
//设备其他信息
typedef struct
{
int iMask;//标识符
TCHAR* szDesc;//描述信息
}
BITS;
#define IDM_DEVMODE 1000 //预定义值
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("DEVCAPS2");//移植你更改的地方
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hinstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("this program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Get System Metrics No.3"),//更新
WS_OVERLAPPEDWINDOW,//增加水平滚动条WS_HSCROLL
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hinstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static TCHAR szDevice[32], szWindowText[64];
static int cxChar, cyChar, nCurrentDevice = ID_DEVICE_SCREEN,
nCurrentInfo = ID_CAPABILITIES_BASICINFORMATION;
static DWORD dwNeeded, dwReturned;
static PRINTER_INFO_4* pinfo4;//NT构架打印机信息数据结构
static PRINTER_INFO_5* pinfo5;//DOS构架打印机信息数据结构
DWORD i;
HDC hdc, hdcInfo;
HMENU hMenu;
HANDLE hPrint;
PAINTSTRUCT ps;
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);//获取设备环境句柄
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hwnd, hdc);
//fall through
//更改系统参数后
case WM_SETTINGCHANGE:
hMenu = GetSubMenu(GetMenu(hwnd), 0);
//获取DEVICE惨淡下的子菜单
while (GetMenuItemCount(hMenu) > 1)//确定指定菜单中的项目数,并清空
DeleteMenu(hMenu, 1, MF_BYPOSITION);//从指定菜单中删除项目
//获取所有本地和原创打印机的李彪
//首先确定数组的大小---保存在dwNeeded中
//接下来,为info数组分配空间并填充它
//讲打印机名称添加到下拉菜单中
//获取所有本地和远程打印机
if(!IsWindowsXPOrGreater())//xp一下
//if (GetVersion() & 0x80000000)//windows 98
{
//枚举可用的打印机,打印服务
/*
BOOL EnumPrinters(
_In_ DWORD Flags, 函数应枚举的打印对象的类型。 此值可以是以下一个或多个值。
_In_ LPTSTR Name,
_In_ DWORD Level,
_Out_ LPBYTE pPrinterEnum,
_In_ DWORD cbBuf,
_Out_ LPDWORD pcbNeeded,
_Out_ LPDWORD pcReturned
);
*/
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL,
0, &dwNeeded, &dwReturned);
//返回PRINTER_INFO_5结构数量
pinfo5 = malloc(dwNeeded);
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, (PBYTE)
pinfo5,dwNeeded, &dwNeeded, &dwReturned);
for ( i = 0; i < dwReturned; i++)
{
AppendMenu(hMenu, (i + 1) % 16 ? 0 :
MF_MENUBARBREAK, i+1,
pinfo5[i].pPrinterName);
}
free(pinfo5);
}
else
{
//windows nt
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL,
0, &dwNeeded, &dwReturned);
pinfo4 = malloc(dwNeeded);
EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE)
pinfo4,dwNeeded, &dwNeeded, &dwReturned);
for ( i = 0; i < dwReturned; i++)
{
AppendMenu(hMenu, (i + 1) % 16 ? 0 :
MF_MENUBARBREAK, 1+i,
pinfo4[i].pPrinterName);
}
free(pinfo4);
}
//将新项目追加到指定菜单栏,
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
//添加属性从菜单,
AppendMenu(hMenu, 0, IDM_DEVMODE, TEXT("Properties"));
wParam = ID_DEVICE_SCREEN;
//fall through
case WM_COMMAND:
hMenu = GetMenu(hwnd);
//选择屏幕或者打印机
if (LOWORD(wParam)==ID_DEVICE_SCREEN||
LOWORD(wParam)<IDM_DEVMODE)
{
//将复选标记属性设置为清除状态
CheckMenuItem(hMenu, nCurrentDevice, MF_UNCHECKED);
//更新当前设备
nCurrentDevice = LOWORD(wParam);
// 将复选标记属性设置为所选状态。
CheckMenuItem(hMenu, nCurrentDevice, MF_CHECKED);
}
//选择属性菜单项
else if (LOWORD(wParam) == IDM_DEVMODE) //Properties selection
{
//将打印机名字存入szDevice字符数组
GetMenuString(hMenu, nCurrentDevice, szDevice,
sizeof(szDevice) / sizeof(TCHAR), MF_BYCOMMAND);
//显示打印机属性对话框
if (OpenPrinter(szDevice, &hPrint, NULL))
{
//有打印机驱动程序产生间接生成对话框
PrinterProperties(hwnd, hPrint);
//关闭打印机句柄
ClosePrinter(hPrint);
}
}
else//Capabilities下的菜单项设置
{
CheckMenuItem(hMenu, nCurrentInfo, MF_UNCHECKED);
nCurrentInfo = LOWORD(wParam);
CheckMenuItem(hMenu, nCurrentInfo, MF_CHECKED);
}
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_INITMENUPOPUP://lParam菜单ID
if (lParam == 0)//Device菜单
EnableMenuItem(GetMenu(hwnd), IDM_DEVMODE,
//启用,禁用,或显示指定的菜单项
nCurrentDevice == ID_DEVICE_SCREEN ? MF_GRAYED : MF_ENABLED);
return 0;
case WM_PAINT:
//窗口标题
lstrcpy(szWindowText, TEXT("Device Capabilities:"));
//SCREEN菜单
if (nCurrentDevice==ID_DEVICE_SCREEN)
{
lstrcpy(szDevice, TEXT("DISPLAY"));
//函数为指定设备创建信息上下文。
//信息上下文提供了一种快速获取有关设备的信息的方法,
//而无需创建设备上下文(DC) 。
//但是,GDI 绘图函数不能接受信息上下文的句柄。
hdcInfo = CreateIC(szDevice, NULL, NULL, NULL);
}
//其他菜单
else
{
hMenu = GetMenu(hwnd);
//将指定菜单项的文本字符串复制到指定的缓冲区中。
GetMenuString(hMenu, nCurrentDevice, szDevice,
sizeof(szDevice), MF_BYCOMMAND);
hdcInfo = CreateIC(NULL, szDevice, NULL, NULL);
}
lstrcat(szWindowText, szDevice);
//更改指定窗口标题栏的文本
SetWindowText(hwnd, szWindowText);
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
if (hdcInfo)
{
switch (nCurrentInfo)
{
case ID_CAPABILITIES_BASICINFORMATION:
DoBasicInfo(hdc, hdcInfo, cxChar, cyChar);
break;
case ID_CAPABILITIES_OTHERINORMATION:
DoOtherInfo(hdc, hdcInfo, cxChar, cyChar);
break;
case ID_CAPABILITIES_CURVECAPABILITIES://曲线
case ID_CAPABILITIES_LINECAPABILITIES://直线
case ID_CAPABILITIES_POLYGONALCAPABILITIES://多边形
case ID_CAPABILITIES_TEXT://文本
DoBitCodedCaps(hdc, hdcInfo, cxChar, cyChar,
nCurrentInfo-ID_CAPABILITIES_CURVECAPABILITIES);
break;
}
EndPaint(hwnd, &ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
//基本信息
void DoBasicInfo(HDC hdc, HDC hdcInfo, int cxChar, int cyChar)
{
struct
{
int nIndex;//索引
TCHAR* szDesc;//表述
}
info[] =//结构数组
{
HORZSIZE, TEXT("HORZSIZE width in millimeters: "),
VERTSIZE, TEXT("VERTSIZE Height in millimeters:"),
HORZRES, TEXT("HORZRES width in pixels:"),
VERTRES, TEXT("VERTRES height in raster lines:"),
BITSPIXEL, TEXT("BITSPIXEL color bits per pixel:"),
PLANES, TEXT("PLANES number of color planes:"),
NUMBRUSHES, TEXT("NUMBRUSHES number of device brushes:"),
NUMPENS, TEXT("NUMPENS number of device pens:"),
NUMMARKERS, TEXT("NUMMARKERS number of device fonts:"),
NUMFONTS, TEXT("NUMFONTS number of device colors:"),
PDEVICESIZE, TEXT("PDEVICESIZE size of devicestructure:"),
ASPECTX, TEXT("ASPECTX relative width of pixel:"),
ASPECTY, TEXT("ASPECTY relative height of pixel:"),
ASPECTXY, TEXT("ASPECTXY relative diagonal of pixel:"),
LOGPIXELSX, TEXT("LOGPIXELSX horizontal dots per inch:"),
LOGPIXELSY, TEXT("LOGPIXELSY vertical dots per inch:"),
SIZEPALETTE, TEXT("SIZEPALETTE number of palette entries:"),
NUMRESERVED, TEXT("NUMRESERVED reserved palette entries:"),
COLORRES, TEXT("COLORRES actual color resolution:"),
PHYSICALHEIGHT, TEXT("PHYSICALHEIGHT printer page pixel width:"),
PHYSICALWIDTH, TEXT("PHYSICALWIDTH printfer page pixel height:"),
PHYSICALOFFSETX, TEXT("PHYSICALOFFSETX printfer page x offset:"),
PHYSICALOFFSETY, TEXT("PHYSICALOFFSETY printfer page y offset:")
};
int i;
TCHAR szBuffer[80];
for (i = 0; i < sizeof(info) / sizeof(info[0]); i++)
TextOut(hdc, cxChar, (i + 1) * cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%-45s%8d"), info[i].szDesc,
GetDeviceCaps(hdcInfo, info[i].nIndex)));
}
//其他信息
void DoOtherInfo(HDC hdc, HDC hdcInfo, int cxChar, int cyChar)
{
static BITS clip[] =
{
CP_RECTANGLE,TEXT("CP_RECTANGLE Can Clip To Rectangle:")
};
static BITS raster[] =//结构数组
{
RC_BITBLT, TEXT("HORZSIZE Capable of simple BitBlt:"),
RC_BANDING, TEXT("VERTSIZE Requires banding support:"),
RC_SCALING, TEXT("HORZRES Requires scaling support:"),
RC_BITMAP64, TEXT("VERTRES Supports bitmaps>64k:"),
RC_GDI20_OUTPUT, TEXT("BITSPIXEL has 2.0 output calls:"),
RC_DI_BITMAP, TEXT("PLANES supports dib to memory:"),
RC_PALETTE, TEXT("NUMBRUSHES supports a palette:"),
RC_DIBTODEV, TEXT("NUMPENS supports bitmap conversion:"),
RC_BIGFONT, TEXT("NUMMARKERS Supports fonts >64k:"),
RC_STRETCHBLT, TEXT("NUMFONTS Supports StretchBlt:"),
RC_FLOODFILL, TEXT("PDEVICESIZE Supports FloodFill:"),
RC_STRETCHDIB, TEXT("ASPECTX Supports StretchDIBits:")
};
static TCHAR* szTech[] = {
TEXT("DT_PLOTTER (Vector plotter)"),//矢量绘图仪
TEXT("DT_RASDISPLAY (DT_RASDISPLAY)"),//矢量绘图仪
TEXT("DT_RASPRINTER (DT_RASPRINTER)"),//矢量绘图仪
TEXT("DT_RASCAMERA (DT_RASCAMERA)"),//矢量绘图仪
TEXT("DT_CHARSTREAM (DT_CHARSTREAM)"),//矢量绘图仪
TEXT("DT_METAFILE (DT_METAFILE)"),//矢量绘图仪
TEXT("DT_DISPFILE (DT_DISPFILE)")//矢量绘图仪
};
int i;
TCHAR szBuffer[80];
//在第1行显示驱动程序版本
/*-------------------------------------------
BOOL TextOutA(
[in] HDC hdc,
[in] int x, 系统用来对齐字符串的引用点的 x 坐标(以逻辑坐标为单位)。
[in] int y, 系统用来对齐字符串的引用点的 y 坐标(以逻辑坐标为单位)。
[in] LPCSTR lpString, 指向要绘制的字符串的指针。 字符串不需要为零终止,因为 cchString 指定字符串的长度。
[in] int c 由 lpString 指向的字符串的长度(以字符为单位)。
);
-------------------------------------------*/
/*-------------------------------------------
BOOL TextOutA(
int WINAPIV wsprintfA(
[out] LPSTR unnamedParam1, 要接收格式化输出的缓冲区。 缓冲区的最大大小为 1,024 字节。
[in] LPCSTR unnamedParam2, 格式控制规范。 除了普通 ASCII 字符,此字符串中还显示了每个参数的格式规范。 有关格式规范的详细信息,请参阅“备注”部分。
... 一个或多个可选参数。 参数参数的数量和类型取决于 lpFmt 参数中的相应格式控制规范。
);
如果函数成功,则返回值是存储在输出缓冲区中的字符数,而不是计算终止 null 字符。
-------------------------------------------*/
/*-------------------------------------------
int GetDeviceCaps(
[in] HDC hdc,
[in] int index
);返回值指定所需项的值。
-------------------------------------------*/
TextOut(hdc, cxChar, cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%-24s%-04XH"), TEXT("DriverVersion:"),
GetDeviceCaps(hdcInfo, DRIVERVERSION)));
//在第2行显示设备技术
TextOut(hdc, cxChar, 2*cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%-24s%-40s"), TEXT("Technology:"),
szTech[GetDeviceCaps(hdcInfo, TECHNOLOGY)]));
//在第4行显示设备支持剪切性能标志
TextOut(hdc, cxChar, 4 * cyChar, szBuffer,
wsprintf(szBuffer, TEXT("CLIPCAPS(Clipping capabilities):")));
//在第6行开始显示是否支持Clippiing capabilities
for (int i = 0; i < sizeof(clip) / sizeof(clip[0]); i++)
TextOut(hdc, 9 * cxChar, (i + 6) * cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%-45s %3s"), clip[i].szDesc,
GetDeviceCaps(hdcInfo, CLIPCAPS) & clip[i].iMask ?
TEXT("Yes") : TEXT("No")));
//在第8行
TextOut(hdc, cxChar, 8 * cyChar, szBuffer,
wsprintf(szBuffer, TEXT("RASTERCAPS(Raster capabilities)")));
//在第10行显示光栅性能
for (i = 0; i < sizeof(raster) / sizeof(raster[0]); i++)
TextOut(hdc, 9 * cxChar, (i + 10) * cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%-45s %3s"), raster[i].szDesc,
GetDeviceCaps(hdcInfo, RASTERCAPS) & raster[i].iMask ?
TEXT("Yes") : TEXT("No")));
}
//位图信息
void DoBitCodedCaps(HDC hdc, HDC hdcInfo, int cxChar, int cyChar, int iType)
{
static BITS curves[] =
{
CC_CIRCLES, TEXT("CC_CIRCLES Can do circles:"),
CC_PIE, TEXT("CC_PIE Can do pie wedges:"),
CC_CHORD, TEXT("CC_CHORD Can do chord arcs:"),
CC_ELLIPSES, TEXT("CC_ELLIPSES Can do ellipses:"),
CC_WIDE, TEXT("CC_WIDE Can do wide borders:"),
CC_STYLED, TEXT("CC_STYLED Can do styled borders:"),
CC_WIDESTYLED, TEXT("CC_WIDESTYLED Can do wide and styled borders:"),
CC_INTERIORS, TEXT("CC_INTERIORS Can do interiors:")
};
static BITS lines[] =
{
LC_POLYLINE, TEXT("LC_POLYLINE Can do polyline:"),
LC_MARKER, TEXT("LC_MARKER Can do markers:"),
LC_POLYMARKER, TEXT("LC_POLYMARKER Can do polymarkers:"),
LC_WIDE, TEXT("LC_WIDE Can do wide lines:"),
LC_STYLED, TEXT("LC_STYLED Can do styled lines:"),
LC_WIDESTYLED, TEXT("LC_WIDESTYLED Can do wide and styled lines:"),
LC_INTERIORS, TEXT("LC_INTERIORS Can do interiors:")
};
static BITS poly[] =
{
PC_POLYGON, TEXT("PC_POLYGON Can do alternate fill polygon: "),
PC_RECTANGLE, TEXT("PC_RECTANGLE Can do rectangle: "),
PC_WINDPOLYGON, TEXT("PC_WINDPOLYGON Can do winding number fill polygon:"),
PC_SCANLINE, TEXT("PC_SCANLINE Can do scanlines:"),
PC_WIDE, TEXT("PC_WIDE Can do wide borders:"),
PC_WIDESTYLED, TEXT("PC_WIDESTYLED Can do wide and styled borders:"),
PC_INTERIORS, TEXT("PC_INTERIORS Can do interiors:")
};
static BITS text[] =
{
TC_OP_CHARACTER, TEXT("TC_OP_CHARACTER Can do charcter output precision:"),
TC_OP_STROKE, TEXT("TC_OP_STROKE Can do stroke output precision:"),
TC_CP_STROKE, TEXT("TC_CP_STROKE Can do charcter clip precision:"),
TC_CR_90, TEXT("TC_CR_90 Can do 90 degree charcter output precision:"),
TC_CR_ANY, TEXT("TC_CR_ANY Can do charcter ratation:"),
TC_SF_X_YINDEP, TEXT("TC_SF_X_YINDEP Can doscaling independent of x and y:"),
TC_SA_DOUBLE, TEXT("TC_SA_DOUBLE Can do doubled character for scaling:"),
TC_SA_INTEGER, TEXT("TC_SA_INTEGER Can do integer multiples ofr scaling:"),
TC_SA_CONTIN, TEXT("TC_SA_CONTIN Can do any multiples ofr exact scaling:"),
TC_EA_DOUBLE, TEXT("TC_EA_DOUBLE Can do double weight characters:"),
TC_IA_ABLE, TEXT("TC_IA_ABLE Can do italicizing:"),
TC_UA_ABLE, TEXT("TC_UA_ABLE Can do underlining:"),
TC_SO_ABLE, TEXT("TC_SO_ABLE Can do strikeouts:"),
TC_RA_ABLE, TEXT("TC_OP_CHARACTER Can do raster fonts:"),
TC_VA_ABLE, TEXT("TC_VA_ABLE Can do vector fonts:")
};
static struct
{
int iIndex;
TCHAR* szTitle;
BITS(*pbits)[];
int iSize;
}
bitinfo[] =
{
CURVECAPS, TEXT("CURVCAPS (Curve Capabilities)"),
(BITS(*)[]) curves, sizeof(curves) / sizeof(curves[0]),
LINECAPS, TEXT("LINECAPS (Line Capabilities)"),
(BITS(*)[]) lines, sizeof(lines) / sizeof(lines[0]),
POLYGONALCAPS, TEXT("POLYGONALCAPS (Polygonal Capabilities)"),
(BITS(*)[]) poly, sizeof(poly) / sizeof(poly[0]),
TEXTCAPS, TEXT("TEXTCAPS (Text Capabilities)"),
(BITS(*)[]) text, sizeof(text) / sizeof(text[0])
};
static TCHAR szBuffer[80];
BITS(*pbits)[] = bitinfo[iType].pbits;
int i, iDevCaps = GetDeviceCaps(hdcInfo, bitinfo[iType].iIndex);
TextOut(hdc, cxChar, cyChar, bitinfo[iType].szTitle,
lstrlen(bitinfo[iType].szTitle));
for (i = 0; i < bitinfo[iType].iSize; i++)
TextOut(hdc, cxChar, (i + 3) * cyChar, szBuffer,
wsprintf(szBuffer, TEXT("%-70s %3s"), (*pbits)[i].szDesc,
iDevCaps & (*pbits)[i].iMask ? TEXT("Yes") : TEXT("No")));
}
CheckMenuItem()函数,EnumPrinters()枚举打印机AppendMenu(),添加菜单 printerPropertites()GetMenuString()CreateIC()
于 2023-09-17 22:36:19 首次发布