本节我们将通过实例来说明不同国家的语言、字符集和字体之间的差异,以及Windows系统是如何处理的。
本节必须掌握的知识点:
第31练:显示键盘消息
非英语键盘问题
字符集和字体
第32练:显示默认字体信息
第33练:创建逻辑字体
5.4.1 第31练:显示键盘消息
/*------------------------------------------------------------------
031 WIN32 API 每日一练
第31个例子:显示键盘按键消息
SetBkMode函数
GetKeyNameText函数
ScrollWindow函数
(c) www.bcdaren.com, 2020
----------------------------------------------------------------*/
#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.C") ;
…(略)
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;
TEXTMETRIC tm;
static RECT rectScroll;
static PMSG pmsg;
HDC hdc;
PAINTSTRUCT ps;
static TCHAR szTop[] = TEXT("Message Key Char Repeat Scan Ext ALT Prev Tran");
static TCHAR szUnd[] = 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") };
TCHAR szBuf[128], szKeyName[32];
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") };
int iType;
static TCHAR* szYes = TEXT("Yes");
static TCHAR* szNo = TEXT("No");
static TCHAR* szDown = TEXT("Down");
static TCHAR* szUp = TEXT("Up");
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 = malloc(cLinesMax* sizeof(MSG));
cLines = 0;
//return 0 ; //继续执行WM_SIZE
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
//计算滚动窗口的范围
rectScroll.top = cyChar; //第二行开始(因第1行为标题)
rectScroll.left = 0;
//不等于cyClient,应等于每行高度*行数。
rectScroll.bottom = cyChar*(cyClient / cyChar);
rectScroll.right = cxClient;
//重绘,该行不可删除,可能是WM_INPUTLANGCHANGE或WM_DISPLAYCHANGE引起
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 (int i = cLinesMax - 1; i > 0; i--)
{
pmsg[i] = pmsg[i - 1];
}
//把当前消息存入消息数组的首元素
pmsg[0].message = message;
pmsg[0].hwnd = hwnd;
pmsg[0].wParam = wParam;
pmsg[0].lParam = lParam;
cLines = min(cLines + 1, cLinesMax); //每按一个按键,增加一行。
//滚屏
ScrollWindow(hwnd, 0, -cyChar, &rectScroll, &rectScroll);
//return 0; //不直接return,因为系统击键消息还要调用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 (int i = 0; i < min(cLines, cyClient / cyChar - 1); i++)
{