Windows 程序设计 第6章 键盘
sysmets.h 定义显示的文本
#pragma once
#include <Windows.h>
#define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))
struct
{
int Index;
TCHAR * szLabel;
TCHAR * szDesc;
}
sysmetrics[] =
{
{ SM_CXSCREEN,TEXT("SM_CXSCREEN"),TEXT("Screen width in pixels") },
{ SM_CYSCREEN,TEXT("SM_CYSCREEN"),TEXT("Screen height in pixels") },
{ SM_CXVSCROLL,TEXT("SM_CXVSCROLL"),TEXT("Vertical scroll width") },
{ SM_CYHSCROLL,TEXT("SM_CYHSCROLL"),TEXT("Horizontal scroll height") },
{ SM_CYCAPTION,TEXT("SM_CYCAPTION"),TEXT("Caption bar height") },
{ SM_CXBORDER,TEXT("SM_CXBORDER"),TEXT("Window border width") },
{ SM_CYBORDER,TEXT("SM_CYBORDER"),TEXT("Window border height") },
{ SM_CXFIXEDFRAME,TEXT("SM_CXFIXEDFRAME"),TEXT("Dialog window frame width") },
{ SM_CYFIXEDFRAME,TEXT("SM_CYFIXEDFRAME"),TEXT("Dialog window frame height") },
{ SM_CYVTHUMB,TEXT("SM_CYVTHUMB"),TEXT("Vertical scroll thumb height") },
{ SM_CXHTHUMB,TEXT("SM_CXHTHUMB"),TEXT("Horizontal scroll thumb width") },
{ SM_CXICON,TEXT("SM_CXICON"),TEXT("Icon width") },
{ SM_CYICON,TEXT("SM_CYICON"),TEXT("Icon height") },
{ SM_CXCURSOR,TEXT("SM_CXCURSOR"),TEXT("Cursor width") },
{ SM_CYCURSOR,TEXT("SM_CYCURSOR"),TEXT("Cursor height") },
{ SM_CYMENU,TEXT("SM_CYMENU"),TEXT("Menu bar height") },
{ SM_CXFULLSCREEN,TEXT("SM_CXFULLSCREEN"),TEXT("Full screen client area width") },
{ SM_CYFULLSCREEN,TEXT("SM_CYFULLSCREEN"),TEXT("Full screen client area height") },
{ SM_CYKANJIWINDOW,TEXT("SM_CYKANJIWINDOW"),TEXT("Kanji window height") },
{ SM_MOUSEPRESENT,TEXT("SM_MOUSEPRESENT"),TEXT("Mouse present flag") },
{ SM_CYVSCROLL,TEXT("SM_CYVSCROLL"),TEXT("Vertical scroll arrow height") },
{ SM_CXHSCROLL,TEXT("SM_CXHSCROLL"),TEXT("Horizontal scroll arrow width") },
{ SM_DEBUG,TEXT("SM_DEBUG"),TEXT("Debug version flag") },
{ SM_SWAPBUTTON,TEXT("SM_SWAPBUTTON"),TEXT("Mouse buttons swapped flag") },
{ SM_CXMIN,TEXT("SM_CXMIN"),TEXT("Minimum window width") },
{ SM_CYMIN,TEXT("SM_CYMIN"),TEXT("Minimum window height") },
{ SM_CXSIZE,TEXT("SM_CXSIZE"),TEXT("Min/Max/Close button width") },
{ SM_CYSIZE,TEXT("SM_CYSIZE"),TEXT("Min/Max/Close button height") },
{ SM_CXSIZEFRAME,TEXT("SM_CXSIZEFRAME"),TEXT("Window sizing frame width") },
{ SM_CYSIZEFRAME,TEXT("SM_CYSIZEFRAME"),TEXT("Window sizing frame height") },
{ SM_CXMINTRACK,TEXT("SM_CXMINTRACK"),TEXT("Minimum window tracking width") },
{ SM_CYMINTRACK,TEXT("SM_CYMINTRACK"),TEXT("Minimum window tracking height") },
{ SM_CXDOUBLECLK,TEXT("SM_CXDOUBLECLK"),TEXT("Double click x tolerance") },
{ SM_CYDOUBLECLK,TEXT("SM_CYDOUBLECLK"),TEXT("Double click y tolerance") },
{ SM_CXICONSPACING,TEXT("SM_CXICONSPACING"),TEXT("Horizontal icon spacing") },
{ SM_CYICONSPACING,TEXT("SM_CYICONSPACING"),TEXT("Vertical icon spacing") },
{ SM_MENUDROPALIGNMENT,TEXT("SM_MENUDROPALIGNMENT"),TEXT("Left or right menu drop") },
{ SM_PENWINDOWS,TEXT("SM_PENWINDOWS"),TEXT("Pen extensions installed") },
{ SM_DBCSENABLED,TEXT("SM_DBCSENABLED"),TEXT("Double-Byte Char Set enabled") },
{ SM_CMOUSEBUTTONS,TEXT("SM_CMOUSEBUTTONS"),TEXT("Number of mouse buttons") },
{ SM_SECURE,TEXT("SM_SECURE"),TEXT("Security present flag") },
{ SM_CXEDGE,TEXT("SM_CXEDGE"),TEXT("3-D border width") },
{ SM_CYEDGE,TEXT("SM_CYEDGE"),TEXT("3-D border height") },
{ SM_CXMINSPACING,TEXT("SM_CXMINSPACING"),TEXT("Minimized window spacing width") },
{ SM_CYMINSPACING,TEXT("SM_CYMINSPACING"),TEXT("Minimized window spacing height") },
{ SM_CXSMICON,TEXT("SM_CXSMICON"),TEXT("Small icon width") },
{ SM_CYSMICON,TEXT("SM_CYSMICON"),TEXT("Small icon height") },
{ SM_CYSMCAPTION,TEXT("SM_CYSMCAPTION"),TEXT("Small caption height") },
{ SM_CXSMSIZE,TEXT("SM_CXSMSIZE"),TEXT("Small caption button width") },
{ SM_CYSMSIZE,TEXT("SM_CYSMSIZE"),TEXT("Small caption button height") },
{ SM_CXMENUSIZE,TEXT("SM_CXMENUSIZE"),TEXT("Menu bar button width") },
{ SM_CYMENUSIZE,TEXT("SM_CYMENUSIZE"),TEXT("Menu bar button height") },
{ SM_ARRANGE,TEXT("SM_ARRANGE"),TEXT("How minimized windows arranged") },
{ SM_CXMINIMIZED,TEXT("SM_CXMINIMIZED"),TEXT("Minimized window width") },
{ SM_CYMINIMIZED,TEXT("SM_CYMINIMIZED"),TEXT("Minimized window height") },
{ SM_CXMAXTRACK,TEXT("SM_CXMAXTRACK"),TEXT("Maximum draggable width") },
{ SM_CYMAXTRACK,TEXT("SM_CYMAXTRACK"),TEXT("Maximum draggable height") },
{ SM_CXMAXIMIZED,TEXT("SM_CXMAXIMIZED"),TEXT("Width of maximized window") },
{ SM_CYMAXIMIZED,TEXT("SM_CYMAXIMIZED"),TEXT("Height of maximized window") },
{ SM_NETWORK,TEXT("SM_NETWORK"),TEXT("Network present flag") },
{ SM_CLEANBOOT,TEXT("SM_CLEANBOOT"),TEXT("How system was booted") },
{ SM_CXDRAG,TEXT("SM_CXDRAG"),TEXT("Avoid drag x tolerance") },
{ SM_CYDRAG,TEXT("SM_CYDRAG"),TEXT("Avoid drag y tolerance") },
{ SM_SHOWSOUNDS,TEXT("SM_SHOWSOUNDS"),TEXT("Present sounds visually") },
{ SM_CXMENUCHECK,TEXT("SM_CXMENUCHECK"),TEXT("Menu check-mark width") },
{ SM_CYMENUCHECK,TEXT("SM_CYMENUCHECK"),TEXT("Menu check-mark height") },
{ SM_SLOWMACHINE,TEXT("SM_SLOWMACHINE"),TEXT("Slow processor flag") },
{ SM_MIDEASTENABLED,TEXT("SM_MIDEASTENABLED"),TEXT("Hebrew and Arabic enabled flag") },
{ SM_MOUSEWHEELPRESENT,TEXT("SM_MOUSEWHEELPRESENT"),TEXT("Mouse wheel present flag") },
{ SM_XVIRTUALSCREEN,TEXT("SM_XVIRTUALSCREEN"),TEXT("Virtual screen x origin") },
{ SM_YVIRTUALSCREEN,TEXT("SM_YVIRTUALSCREEN"),TEXT("Virtual screen y origin") },
{ SM_CXVIRTUALSCREEN,TEXT("SM_CXVIRTUALSCREEN"),TEXT("Virtual screen width") },
{ SM_CYVIRTUALSCREEN,TEXT("SM_CYVIRTUALSCREEN"),TEXT("Virtual screen height") },
{ SM_CMONITORS,TEXT("SM_CMONITORS"),TEXT("Number of monitors") },
{ SM_SAMEDISPLAYFORMAT,TEXT("SM_SAMEDISPLAYFORMAT"),TEXT("Same color format flag") },
};
SYSMTES4.cpp 代码 键盘控制上下左右
#include <windows.h>
#include "sysmets.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("SysMets4");
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 = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Get System Metrics No. 4"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL | 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 int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth;
HDC hdc;
int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;
PAINTSTRUCT ps;
SCROLLINFO si;
TCHAR szBuffer[10];
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
//获取字体信息
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hwnd, hdc);
// 保存三列的宽度
iMaxWidth = 40 * cxChar + 22 * cxCaps;
return 0;
case WM_SIZE:
//获取客户区大小以及设置滚动条
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
// 设置垂直滚动条范围和页面大小
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = NUMLINES - 1;
si.nPage = cyClient / cyChar;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
// 设置水平滚动条范围和页面大小
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = 2 + iMaxWidth / cxChar;
si.nPage = cxClient / cxChar;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
return 0;
case WM_VSCROLL:
// 处理垂直滚动条消息
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si);
// 保存位置以便以后比较
iVertPos = si.nPos;
switch (LOWORD(wParam))
{
case SB_TOP:
si.nPos = si.nMin;
break;
case SB_BOTTOM:
si.nPos = si.nMax;
break;
case SB_LINEUP:
si.nPos -= 1;
break;
case SB_LINEDOWN:
si.nPos += 1;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
default:
break;
}
// 设置位置,然后检索。 由于调整
// 在Windows中,它可能与值集不相同。
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si);
// 如果位置已更改,请滚动窗口并进行更新
if (si.nPos != iVertPos)
{
ScrollWindow(hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL);
UpdateWindow(hwnd);
}
return 0;
case WM_HSCROLL:
// 处理水平滚动条消息
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
// 保存位置以供以后进行比较
GetScrollInfo(hwnd, SB_HORZ, &si);
iHorzPos = si.nPos;
switch (LOWORD(wParam))
{
case SB_LINELEFT:
si.nPos -= 1;
break;
case SB_LINERIGHT:
si.nPos += 1;
break;
case SB_PAGELEFT:
si.nPos -= si.nPage;
break;
case SB_PAGERIGHT:
si.nPos += si.nPage;
break;
case SB_THUMBPOSITION:
si.nPos = si.nTrackPos;
break;
default:
break;
}
// 设置位置,然后检索。 由于调整
// 在Windows中,它可能与值集不相同。
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
GetScrollInfo(hwnd, SB_HORZ, &si);
// 如果位置已更改,请滚动窗口并进行更新
if (si.nPos != iHorzPos)
{
ScrollWindow(hwnd, cxChar * (iHorzPos - si.nPos), 0,
NULL, NULL);
}
return 0;
case WM_KEYDOWN:
switch (wParam)//指明了虚拟键码
{
case VK_HOME://首
SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0); //不进入队列,直接发送给窗口
break;
case VK_END: //尾
SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0);
break;
case VK_PRIOR: //上一页
SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
break;
case VK_NEXT: //下一页
SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
break;
case VK_UP: //上一行
SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
break;
case VK_DOWN://下一页
SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
break;
case VK_LEFT: //水平前一页
SendMessage(hwnd, WM_HSCROLL, SB_PAGEUP, 0);
break;
case VK_RIGHT://水平后一页
SendMessage(hwnd, WM_HSCROLL, SB_PAGEDOWN, 0);
break;
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
// 获取垂直滚动条位置
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo(hwnd, SB_VERT, &si);
iVertPos = si.nPos;
// 获取水平滚动条位置
GetScrollInfo(hwnd, SB_HORZ, &si);
iHorzPos = si.nPos;
// 寻找绘画极限
iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar);
iPaintEnd = min(NUMLINES - 1,
iVertPos + ps.rcPaint.bottom / cyChar);
for (i = iPaintBeg; i <= iPaintEnd; i++)
{
x = cxChar * (1 - iHorzPos);
y = cyChar * (i - iVertPos);
TextOut(hdc, x, y,
sysmetrics[i].szLabel,
lstrlen(sysmetrics[i].szLabel));
TextOut(hdc, x + 22 * cxCaps, y,
sysmetrics[i].szDesc,
lstrlen(sysmetrics[i].szDesc));
SetTextAlign(hdc, TA_RIGHT | TA_TOP);
TextOut(hdc, x + 22 * cxCaps + 40 * cxChar, y,szBuffer,
wsprintf(szBuffer, TEXT("%5d"),
GetSystemMetrics(sysmetrics[i].Index)));
SetTextAlign(hdc, TA_LEFT | TA_TOP);
}
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
KEYVIEW1.cpp 代码 键盘上按下就会显示
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("KeyView1");
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 = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Keyboard Message Viewer #1"),
WS_OVERLAPPEDWINDOW,
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 int cxClientMax, cyClientMax, cxClient, cyClient, cxChar, cyChar;
static int cLinesMax, cLines;
static PMSG pmsg;
static RECT rectScroll;
static TCHAR szTop[] = TEXT("Message Key Char ")
TEXT("Repeat Scan Ext ALT Prev Tran ");
static TCHAR szUnd[] = TEXT("_______ ___ ____ ")
TEXT("______ ____ ___ ___ ____ ____ ");
static TCHAR * szFormat[2] = {
TEXT("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s "),
TEXT("%-13s 0x%04X%1s%c %6u %4d %3s %3s %4s %4s ") };
static TCHAR * szYes = TEXT("Yes ");
static TCHAR * szNo = TEXT("No ");
static TCHAR * szDown = TEXT("Down ");
static TCHAR * szUp = TEXT("Up ");
static TCHAR * szMessage[] = {
TEXT("WM_KEYDOWN "), TEXT("WM_KEYUP "),
TEXT("WM_CHAR "), TEXT("WM_DEADCHAR "),
TEXT("WM_SYSKEYDOWN "), TEXT("WM_SYSKEYUP "),
TEXT("WM_SYSCHAR "), TEXT("WM_SYSDEADCHAR ") };
HDC hdc;
int i, iType;
PAINTSTRUCT ps;
TCHAR szBuffer[128], szKeyName[32];
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
case WM_DISPLAYCHANGE:
//获取客户端区域的最大大小
cxClientMax = GetSystemMetrics(SM_CXMAXIMIZED);
cyClientMax = GetSystemMetrics(SM_CYMAXIMIZED);
// 获取固定间距字体的字符大小
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight;
ReleaseDC(hwnd, hdc);
// 为显示行分配内存
if (pmsg)
free(pmsg);
cLinesMax = cyClientMax / cyChar; //窗口最大化时显示字符行
pmsg = (PMSG)malloc(cLinesMax * sizeof(MSG));
cLines = 0;
// fall through 连续执行下面一个标签
case WM_SIZE:
if (message == WM_SIZE)
{
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
}
// 计算滚动矩形
rectScroll.left = 0;
rectScroll.right = cxClient;
rectScroll.top = cyChar;
rectScroll.bottom = cyChar * (cyClient / cyChar); // 取(cyClient / cyChar)整数
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
case WM_DEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
// 重新排列存储阵列
for (i = cLinesMax - 1; i > 0; i--)
{
// 丢弃最后一个结构中的数据,预留第一个结构。
// 可以这样理解,把全部结构数据向后顺移一位。
pmsg[i] = pmsg[i - 1];
}
// 存储新消息
pmsg[0].hwnd = hwnd;
pmsg[0].message = message;
pmsg[0].wParam = wParam;
pmsg[0].lParam = lParam;
//有按键消息来时,cLines加1,最大不超过窗口最大化时显示字符行
cLines = min(cLines + 1, cLinesMax);
// 向上滚动显示屏
ScrollWindow(hwnd, 0, -cyChar, &rectScroll, &rectScroll);
break;// 例如,调用DefWindowProc以便系统消息工作
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
//因为两个字符串绘画坐标一样,必须设定透明模式以防止第二个字符串擦除第一个字符串
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, 0, 0, szTop, lstrlen(szTop));
TextOut(hdc, 0, 0, szUnd, lstrlen(szUnd));
for (i = 0; i < min(cLines, cyClient / cyChar - 1); i++)
{
//如果是字符消息则标记 1 ,如果是按键消息则标记 0
iType = pmsg[i].message == WM_CHAR ||
pmsg[i].message == WM_SYSCHAR ||
pmsg[i].message == WM_DEADCHAR ||
pmsg[i].message == WM_SYSDEADCHAR;
GetKeyNameText(pmsg[i].lParam, szKeyName, sizeof(szKeyName) / sizeof(TCHAR));
TextOut(hdc, 0, (cyClient / cyChar - 1 - i) * cyChar, szBuffer, wsprintf(szBuffer, szFormat[iType],
//计算得出消息类型,并索引。
szMessage[pmsg[i].message - WM_KEYFIRST],
//如果是按键消息就输出虚拟键代码,显示为十进制有符号整数,宽度为3个字符。
//如果是字符消息就输出ANSI或Unicode字符代码,显示为大写十六进制数,宽度为4个字符,空白处用 0 填充。
pmsg[i].wParam,
//如果是按键消息就输出键名(szKeyName),并采用左对齐,宽度为15个字符。
//如果是字符消息就输出空格,宽度为1个字符。
(PTSTR)(iType ? TEXT(" ") : szKeyName),
// 如果是按键消息就输出空格。
// 如果是字符消息就输出该字符。pmsg[i].wParam = wParam (字符的对应编码,使用强制类型转换得到相应字符)
(TCHAR)(iType ? pmsg[i].wParam : ' '),
//低十六位记录着按键的重复计数次数。用十进制方式显示为无符号整数,宽度为6个字符。
LOWORD(pmsg[i].lParam),
//取高十六位中的低八位,解释为键盘扫描码(OEM),显示为十进制有符号整数,宽度为4个字符。
HIWORD(pmsg[i].lParam) & 0xFF,
// 0000 0001 0000 0000 0000 0000 0000 0000 读取 扩充键旗标(Extended Key Flag) 状态。
0x01000000 & pmsg[i].lParam ? szYes : szNo,
// 0010 0000 0000 0000 0000 0000 0000 0000 读取 内容代码(Context Code) 状态。
0x20000000 & pmsg[i].lParam ? szYes : szNo,
// 0100 0000 0000 0000 0000 0000 0000 0000 读取 键的先前状态(Previous Key State)
0x40000000 & pmsg[i].lParam ? szDown : szUp,
// 1000 0000 0000 0000 0000 0000 0000 0000 读取 转换状态(Transition State)
0x80000000 & pmsg[i].lParam ? szUp : szDown));
}
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
结果显示
STOKFONT.cpp 代码
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("StokFont");
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 = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Stock Fonts"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
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 struct
{
int idStockFont;
TCHAR * szStockFont;
}
stockfont[] = { OEM_FIXED_FONT, TEXT("OEM_FIXED_FONT"),
ANSI_FIXED_FONT, TEXT("ANSI_FIXED_FONT"),
ANSI_VAR_FONT, TEXT("ANSI_VAR_FONT"),
SYSTEM_FONT, TEXT("SYSTEM_FONT"),
DEVICE_DEFAULT_FONT, TEXT("DEVICE_DEFAULT_FONT"),
SYSTEM_FIXED_FONT, TEXT("SYSTEM_FIXED_FONT"),
DEFAULT_GUI_FONT, TEXT("DEFAULT_GUI_FONT") };
static int iFont, cFonts = sizeof stockfont / sizeof stockfont[0];
HDC hdc;
int i, x, y, cxGrid, cyGrid;
PAINTSTRUCT ps;
TCHAR szFaceName[LF_FACESIZE], szBuffer[LF_FACESIZE + 64];
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
SetScrollRange(hwnd, SB_VERT, 0, cFonts - 1, TRUE);//设置滚动条范围
return 0;
case WM_DISPLAYCHANGE:
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_VSCROLL:
//处理滚动条消息
switch (LOWORD(wParam))
{
case SB_TOP: iFont = 0; break;
case SB_BOTTOM: iFont = cFonts - 1; break;
case SB_LINEUP:
case SB_PAGEUP: iFont -= 1; break;
case SB_LINEDOWN:
case SB_PAGEDOWN: iFont += 1; break;
case SB_THUMBPOSITION: iFont = HIWORD(wParam); break;
}
iFont = max(0, min(cFonts - 1, iFont));
SetScrollPos(hwnd, SB_VERT, iFont, TRUE);
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_KEYDOWN:
//处理按钮消息时,直接把消息发给滚动条
switch (wParam)
{
case VK_HOME: SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0); break;
case VK_END: SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0); break;
case VK_PRIOR:
case VK_LEFT:
case VK_UP: SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0); break;
case VK_NEXT:
case VK_RIGHT:
case VK_DOWN: SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); break;
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, GetStockObject(stockfont[iFont].idStockFont));//把第一种字体装入设备描述表
GetTextFace(hdc, LF_FACESIZE, szFaceName); //获得结构体第一个成员对应的字体名称,保存在szFaceName中
//获取字体大小信息
GetTextMetrics(hdc, &tm);
cxGrid = max(3 * tm.tmAveCharWidth, 2 * tm.tmMaxCharWidth);
cyGrid = tm.tmHeight + 3;
//输出标题栏
TextOut(hdc, 0, 0, szBuffer,
wsprintf(szBuffer, TEXT(" %s: Face Name = %s, CharSet = %i"),
stockfont[iFont].szStockFont, //字体标示符
szFaceName, tm.tmCharSet));//字体名称
SetTextAlign(hdc, TA_TOP | TA_CENTER);
for (i = 0; i < 17; i++)
{
// 画垂直线
MoveToEx(hdc, (i + 2) * cxGrid, 2 * cyGrid, NULL);
LineTo (hdc, (i + 2) * cxGrid, 19 * cyGrid);
//水平线
MoveToEx(hdc, cxGrid, (i + 3) * cyGrid, NULL);
LineTo (hdc, 18 * cxGrid, (i + 3) * cyGrid);
}
for (i = 0; i < 16; i++)
{
//行标 0 -- F
TextOut(hdc, (2 * i + 5) * cxGrid / 2, 2 * cyGrid + 2, szBuffer,
wsprintf(szBuffer, TEXT("%X-"), i));
//列标题0 -- F
TextOut(hdc, 3 * cxGrid / 2, (i + 3) * cyGrid + 2, szBuffer,
wsprintf(szBuffer, TEXT("-%X"), i));
}
// 输出各种字体的字符集
for (y = 0; y < 16; y++)
for (x = 0; x < 16; x++)
{
TextOut(hdc, (2 * x + 5) * cxGrid / 2,
(y + 3) * cyGrid + 2, szBuffer,
wsprintf(szBuffer, TEXT("%c"), 16 * x + y));
}
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
显示结果
KEYVIEW2.cpp 代码 键盘输入字符
#include<windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static DWORD dwCharSet = DEFAULT_CHARSET; //字符集
static int cxClientMax, cyClientMax, cxClient, cyClient, cxChar, cyChar;
static int cLinesMax, cLines;
static PMSG pmsg;
static RECT rectScroll;
static TCHAR szTop[] = TEXT("Message Key Char ")
TEXT("Repeat Scan Ext ALT Prev Tran");
static TCHAR szUnd[] = TEXT("_______ ___ ____ ")
TEXT("______ ____ ___ ___ ____ ____");
static TCHAR * szFormat[2] = {
TEXT("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"),
TEXT("%-13s 0x%04X%1s%c %6u %4d %3s %3s %4s %4s") };
static TCHAR * szYes = TEXT("Yes");
static TCHAR * szNo = TEXT("No");
static TCHAR * szDown = TEXT("Down");
static TCHAR * szUp = TEXT("Up");
static TCHAR * szMessage[] = {
TEXT("WM_KEYDOWN"), TEXT("WM_KEYUP"),
TEXT("WM_CHAR"), TEXT("WM_DEADCHAR"),
TEXT("WM_SYSKEYDOWN"), TEXT("WM_SYSKEYUP"),
TEXT("WM_SYSCHAR"), TEXT("WM_SYSDEADCHAR")
};
HDC hdc;
int i, itype;
PAINTSTRUCT ps;
TEXTMETRIC tm;
TCHAR szBuffer[128], szKeyName[32];
switch (message)
{
case WM_INPUTLANGCHANGE://表示输入法发生了改变,wparam:该输入法使用的字符集,lparam:该输入法的键盘布局
dwCharSet = wParam;
case WM_CREATE:
case WM_DISPLAYCHANGE://表示显示器分辨率发生了改变,wparam:色深,像素位数,lparam:高低位分别对应垂直和水平分辨率
cxClientMax = GetSystemMetrics(SM_CXMAXIMIZED);
cyClientMax = GetSystemMetrics(SM_CYMAXIMIZED);
hdc = GetDC(hwnd);
SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight;
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
ReleaseDC(hwnd, hdc);
if (pmsg)
free(pmsg);
cLinesMax = cyClientMax / cyChar;
pmsg = (PMSG)malloc(cLinesMax * sizeof(MSG));
cLines = 0;
case WM_SIZE:
if (message == WM_SIZE)
{
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
}
rectScroll.left = 0;
rectScroll.right = cxClient;
rectScroll.top = cyChar;
rectScroll.bottom = cyChar*(cyClient / cyChar);
InvalidateRect(hwnd, NULL, true);
if (message == WM_INPUTLANGCHANGE)
return true;
return 0;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
case WM_DEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
for (i = cLinesMax - 1; i>0; i--)
{
pmsg[i] = pmsg[i - 1];
}
pmsg[0].hwnd = hwnd;
pmsg[0].message = message;
pmsg[0].wParam = wParam;
pmsg[0].lParam = lParam;
cLines = min(cLines + 1, cLinesMax);
ScrollWindow(hwnd, 0, -cyChar, &rectScroll, &rectScroll); //将窗口向下滑动一行
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0, dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, 0, 0, szTop, lstrlen(szTop));
TextOut(hdc, 0, 0, szUnd, lstrlen(szUnd));
for (i = 0; i<min(cLines, cyClient / cyChar - 1); i++)
{
itype = pmsg[i].message == WM_CHAR ||
pmsg[i].message == WM_SYSCHAR ||
pmsg[i].message == WM_DEADCHAR ||
pmsg[i].message == WM_SYSDEADCHAR;
GetKeyNameText(pmsg[i].lParam, szKeyName, sizeof(szKeyName) / sizeof(TCHAR));//该函数检取表示键名的字符串。
TextOut(hdc, 0, (cyClient / cyChar - 1 - i) * cyChar, szBuffer,
wsprintf(szBuffer, szFormat[itype],
szMessage[pmsg[i].message - WM_KEYFIRST],
pmsg[i].wParam,
(PTSTR)(itype ? TEXT(" ") : szKeyName),
(TCHAR)(itype ? pmsg[i].wParam : ' '),
LOWORD(pmsg[i].lParam),
HIWORD(pmsg[i].lParam) & 0xFF,
0x01000000 & pmsg[i].lParam ? szYes : szNo,
0x20000000 & pmsg[i].lParam ? szYes : szNo,
0x40000000 & pmsg[i].lParam ? szDown : szUp,
0x80000000 & pmsg[i].lParam ? szUp : szDown));
}
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int WINAPI WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd)
{
static TCHAR szAppName[] = TEXT("KEYVIEW2");
HWND hwnd;
WNDCLASS wndclass;
MSG msg;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = WndProc;
wndclass.lpszClassName = szAppName;
wndclass.lpszMenuName = NULL;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("注册类信息发生错误"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("JUST A EXAMPLE"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT
, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
while (GetMessage(&msg, hwnd, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
显示结果
TYPER.cpp 代码 光标输入字符
#include <windows.h>
#define BUFFER(x,y) *(pBuffer + y * cxBuffer + x) //定义了一个缓冲区,要访问缓冲区的内容,需要知道行和列的位置,才能访问具体某个位置的内容
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Typer");
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 = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Typing Program"),
WS_OVERLAPPEDWINDOW,
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 DWORD dwCharSet = DEFAULT_CHARSET;
static int cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer,
xCaret, yCaret;
static TCHAR * pBuffer = NULL;
HDC hdc;
int x, y, i;
PAINTSTRUCT ps;
TEXTMETRIC tm;
switch (message)
{
case WM_INPUTLANGCHANGE:
dwCharSet = wParam;
case WM_CREATE: //相当于初始化,获取字体相关信息
hdc = GetDC(hwnd);
SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0,
dwCharSet, 0, 0, 0, FIXED_PITCH, NULL)); //创建一种字体
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight;
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
ReleaseDC(hwnd, hdc);
// fall through
case WM_SIZE:
// obtain window size in pixels
if (message == WM_SIZE)
{
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
}
// calculate window size in characters
cxBuffer = max(1, cxClient / cxChar);
cyBuffer = max(1, cyClient / cyChar);
// allocate memory for buffer and clear it
if (pBuffer != NULL)
free(pBuffer);
pBuffer = (TCHAR *)malloc(cxBuffer * cyBuffer * sizeof(TCHAR));//缓冲区大小:行和列相乘,在乘每一个点对于的大小
for (y = 0; y < cyBuffer; y++)
for (x = 0; x < cxBuffer; x++)
BUFFER(x, y) = ' '; //对缓冲区每个点初始化为空
// set caret to upper left corner
xCaret = 0;
yCaret = 0;
if (hwnd == GetFocus())
SetCaretPos(xCaret * cxChar, yCaret * cyChar);
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_SETFOCUS: //窗体获得焦点,在wm_create和wm_size,wm_paint消息后被调用
// create and show the caret
CreateCaret(hwnd, NULL, cxChar, cyChar);
SetCaretPos(xCaret * cxChar, yCaret * cyChar);
ShowCaret(hwnd); //会一直的闪烁,直到碰到setcaretpos函数,重新确定光标的坐标
return 0;
case WM_KILLFOCUS:
// hide and destroy the caret
HideCaret(hwnd);
DestroyCaret();
return 0;
case WM_KEYDOWN:
switch (wParam)
{
case VK_HOME:
xCaret = 0;
break;
case VK_END:
xCaret = cxBuffer - 1;
break;
case VK_PRIOR:
yCaret = 0;
break;
case VK_NEXT:
yCaret = cyBuffer - 1;
break;
case VK_LEFT:
xCaret = max(xCaret - 1, 0);
break;
case VK_RIGHT:
xCaret = min(xCaret + 1, cxBuffer - 1);
break;
case VK_UP:
yCaret = max(yCaret - 1, 0);
break;
case VK_DOWN:
yCaret = min(yCaret + 1, cyBuffer - 1);
break;
case VK_DELETE:
for (x = xCaret; x < cxBuffer - 1; x++)
BUFFER(x, yCaret) = BUFFER(x + 1, yCaret);
BUFFER(cxBuffer - 1, yCaret) = ' ';
HideCaret(hwnd);
hdc = GetDC(hwnd);
SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0,
dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));
TextOut(hdc, xCaret * cxChar, yCaret * cyChar,
&BUFFER(xCaret, yCaret),
cxBuffer - xCaret);
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
ReleaseDC(hwnd, hdc);
ShowCaret(hwnd);
break;
}
SetCaretPos(xCaret * cxChar, yCaret * cyChar); //在这个坐标位置闪烁,不需要调用ShowCaret,因为第一次调用ShowCaret后,就一直闪烁
return 0; //碰到SetCaretPos,重新确定了坐标,就在这个位置一直闪烁
case WM_CHAR:
for (i = 0; i < (int)LOWORD(lParam); i++)
{
switch (wParam)
{
case '\b': // backspace
if (xCaret > 0)
{
xCaret--;
SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);
}
break;
case '\t': // tab
do
{
SendMessage(hwnd, WM_CHAR, ' ', 1);
} while (xCaret % 8 != 0);
break;
case '\n': // line feed
if (++yCaret == cyBuffer)
yCaret = 0;
break;
case '\r': // carriage return
xCaret = 0;
if (++yCaret == cyBuffer)
yCaret = 0;
break;
case '\x1B': // escape
for (y = 0; y < cyBuffer; y++)
for (x = 0; x < cxBuffer; x++)
BUFFER(x, y) = ' ';
xCaret = 0;
yCaret = 0;
InvalidateRect(hwnd, NULL, FALSE);
break;
default: // character codes
BUFFER(xCaret, yCaret) = (TCHAR)wParam;
HideCaret(hwnd); //要再窗口中显示内容,需要把闪烁光标隐藏
hdc = GetDC(hwnd);
SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0,
dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));
TextOut(hdc, xCaret * cxChar, yCaret * cyChar,
&BUFFER(xCaret, yCaret), 1);
DeleteObject(
SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
ReleaseDC(hwnd, hdc);
ShowCaret(hwnd); //内容显示完成后,需要把光标重新显示出来(不能省略这个语句)
if (++xCaret == cxBuffer)
{
xCaret = 0;
if (++yCaret == cyBuffer)
yCaret = 0;
}
break;
}
}
SetCaretPos(xCaret * cxChar, yCaret * cyChar); //对字符消息改变了光标的坐标后,在新坐标进行闪烁
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, CreateFont(0, 0, 0, 0, 0, 0, 0, 0,
dwCharSet, 0, 0, 0, FIXED_PITCH, NULL));
for (y = 0; y < cyBuffer; y++)
TextOut(hdc, 0, y * cyChar, &BUFFER(0, y), cxBuffer);//着行输出窗口中的内容,其中cychar为每一行高度,cxbuffer为每行显示的字符数
//cybuffer用于控制行,每次循环,行数加一,输出该行的内容
DeleteObject(SelectObject(hdc, GetStockObject(SYSTEM_FONT)));
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
显示结果