显示键盘输入

【勇芳软件工作室】汉化HomePreviousNext

本节中的示例显示了应用程序如何从键盘接收字符,将其显示在窗口的客户区中,并使用每个输入的字符更新插入符的位置。它还演示了如何按照左箭头键,右箭头键,首页键和结束键击来移动插入符号,并显示如何突出显示所选文本以响应SHIFT + RIGHT ARROW键组合。

WM_CREATE消息的处理期间,示例中显示的窗口过程分配一个用于存储键盘输入的64K缓冲区。它还检索当前加载的字体的度量,保存字体的字符的高度和平均宽度。高度和宽度用于处理WM_SIZE消息,以根据客户端区域的大小计算行长度和最大行数。

窗口过程在处理WM_SETFOCUS消息时创建并显示插入符号。处理WM_KILLFOCUS消息时,它隐藏和删除插入符号。

处理WM_CHAR消息时,窗口过程显示字符,将它们存储在输入缓冲区中,并更新插入符位置。窗口过程还将制表符字符转换为四个连续的空格字符。Backspace,换行符和转义字符会产生一个哔声,但是没有另外处理。

当处理WM_KEYDOWN消息时,窗口过程执行左,右,结束和主页插入符移动。在处理右箭头键的动作时,窗口过程将检查SHIFT键的状态,如果是“关”,则在插入符号移动时选择插入符右侧的字符。

请注意,以下代码将被编写,以便可以以Unicode或ANSI编译。如果源代码定义Unicode,则字符串将以Unicode字符处理;否则,它们被作为ANSI字符处理。

#define BUFSIZE 65535

#define SHIFTED 0x8000

LONG APIENTRY MainWndProc(hwndMain,uMsg,wParam,lParam)

HWND hwndMain;

UINT uMsg;

UINT wParam;

LONG lParam;

{

HDC hdc; /* handle of device context */

TEXTMETRIC tm; /* structure for text metrics */

static DWORD dwCharX; /* average width of characters */

static DWORD dwCharY; /* height of characters */

static DWORD dwClientX; /* width of client area */

static DWORD dwClientY; /* height of client area */

static DWORD dwLineLen; /* line length */

static DWORD dwLines; /* text lines in client area */

static int nCaretPosX = 0; /* horizontal position of caret */

static int nCaretPosY = 0; /* vertical position of caret */

static int nCharWidth = 0; /* width of a character */

static int cch = 0; /* characters in buffer */

static int nCurChar = 0; /* index of current character */

static PTCHAR pchInputBuf; /* address of input buffer */

int i, j; /* loop counters */

int cCR = 0; /* count of carriage returns */

int nCRIndex = 0; /* index of last carriage return */

int nVirtKey; /* virtual-key code */

TCHAR szBuf[128]; /* temporary buffer */

TCHAR ch; /* current character */

PAINTSTRUCT ps; /* required by BeginPaint */

RECT rc; /* output rectangle for DrawText */

SIZE sz; /* string dimensions */

COLORREF crPrevText; /* previous text color */

COLORREF crPrevBk; /* previous background color */

开关(uMsg){

case WM_CREATE:

/ *获取当前字体的指标。*/

hdc = GetDC(hwndMain);

GetTextMetrics(hdc, &tm);

ReleaseDC(hwndMain, hdc);

/ *保存平均字符宽度和高度。*/

dwCharX = tm.tmAveCharWidth;

dwCharY = tm.tmHeight;

/ *分配缓冲区以存储键盘输入。*/

pchInputBuf = (LPTSTR) GlobalAlloc(GPTR,

BUFSIZE * sizeof(TCHAR));

return 0;

case WM_SIZE:

/ *保存客户区域的新宽度和高度。*/

dwClientX = LOWORD(lParam);

dwClientY = HIWORD(lParam);

/*

*计算一行的最大宽度

*客户区域的最大行数。

*/

dwLineLen = dwClientX - dwCharX;

dwLines = dwClientY / dwCharY;

break;

case WM_SETFOCUS:

/*

*创建,定位和显示插入符号

*窗口接收键盘焦点。

*/

CreateCaret(hwndMain, (HBITMAP) 1, 0, dwCharY);

SetCaretPos(nCaretPosX, nCaretPosY * dwCharY);

ShowCaret(hwndMain);

break;

case WM_KILLFOCUS:

/*

*当窗户丢失时,隐藏并摧毁插入符号

*键盘焦点。

*/

HideCaret(hwndMain);

DestroyCaret();

break;

case WM_CHAR:

开关(wParam){

case 0x08: /* backspace */

case 0x0A: /* linefeed */

case 0x1B: /* escape */

MessageBeep(0xFFFFFFFF);

return 0;

case 0x09: /* tab */

/ *将标签转换为四个连续空格。*/

for (i = 0; i < 4; i++)

SendMessage(hwndMain, WM_CHAR, 0x20, 0);

return 0;

case 0x0D: /* carriage return */

/*

*记录回车并定位

*在新行开始的插入符号。

*/

pchInputBuf[cch++] = 0x0D;

nCaretPosX = 0;

nCaretPosY += 1;

break;

默认值:/ *可显示字符* /

ch = (TCHAR) wParam;

HideCaret(hwndMain);

/*

*获取字符的宽度和输出

* 人物。

*/

hdc = GetDC(hwndMain);

GetCharWidth32(hdc,(UINT)wParam,(UINT)wParam,

&nCharWidth);

TextOut(hdc,nCaretPosX,nCaretPosY * dwCharY,

&ch, 1);

ReleaseDC(hwndMain, hdc);

/ *将字符存储在缓冲区中。*/

pchInputBuf[cch++] = ch;

/*

*计算新的水平位置

*插入符号。en如果位置超过最大值,

*插入回车并移动插入符号

*到下一行的开头。

*/

nCaretPosX += nCharWidth;

if((DWORD)nCaretPosX > dwLineLen){

nCaretPosX = 0;

pchInputBuf[cch++] = 0x0D;

++nCaretPosY;

}

nCurChar = cch;

ShowCaret(hwndMain);

break;

}

SetCaretPos(nCaretPosX, nCaretPosY * dwCharY);

break;

case WM_KEYDOWN:

开关(wParam){

case VK_LEFT: /* LEFT ARROW */

/*

*插入符号只能移动到开头

*当前行。

*/

if(nCaretPosX > 0){

HideCaret(hwndMain);

/*

*检索左边的字符

*插入符号,计算字符

* width,然后从中减去宽度

*插入符号的当前水平位置

*获得新职位。

*/

ch = pchInputBuf[--nCurChar];

hdc = GetDC(hwndMain);

GetCharWidth32(hdc, ch, ch, &nCharWidth);

ReleaseDC(hwndMain, hdc);

nCaretPosX = max(nCaretPosX - nCharWidth,

0);

ShowCaret(hwndMain);

}

break;

case VK_RIGHT: /* RIGHT ARROW */

/*

*插入物移动到右边或当一个马车

*返回遇到,到了开始

*下一行。

*/

if(nCurChar < cch){

HideCaret(hwndMain);

/*

*检索右侧的字符

*插入符号。如果是回车,

*在开头位置插入符号

*下一行。

*/

ch = pchInputBuf[nCurChar];

if (ch == 0x0D) {

nCaretPosX = 0;

nCaretPosY++;

}

/*

*如果角色不是马车

*返回,检查看是否SHIFT

*键已关闭如果是,则反转文本

*颜色并输出字符。

*/

else {

hdc = GetDC(hwndMain);

nVirtKey = GetKeyState(VK_SHIFT);

if(nVirtKey & SHIFTED){

crPrevText = SetTextColor(hdc,

RGB(255, 255, 255));

crPrevBk = SetBkColor(hdc,

RGB(0,0,0));

TextOut(hdc,nCaretPosX,

* nCaretPosY dwCharY,

&ch, 1);

SetTextColor(hdc, crPrevText);

SetBkColor(hdc, crPrevBk);

}

/*

*获取字符的宽度

*计算新的水平

*插入符号的位置。

*/

GetCharWidth32(hdc, ch, ch, &nCharWidth);

ReleaseDC(hwndMain, hdc);

nCaretPosX = nCaretPosX + nCharWidth;

}

nCurChar++;

ShowCaret(hwndMain);

break;

}

break;

case VK_UP: /* UP ARROW */

case VK_DOWN: /* DOWN ARROW */

MessageBeep(0xFFFFFFFF);

return 0;

case VK_HOME: /* HOME */

/*

*将插入符的位置设置在左上方

*客户区的角落。

*/

nCaretPosX = nCaretPosY = 0;

nCurChar = 0;

break;

case VK_END: /* END */

/ *将插入符号移动到文本的末尾。*/

for (i=0; i < cch; i++) {

/*

*计算回车并保存

*最后一个索引。

*/

if (pchInputBuf[i] == 0x0D) {

cCR++;

nCRIndex = i + 1;

}

}

nCaretPosY = cCR;

/*

*复制最后一个托架之间的所有文本

*返回和键盘输入的结束

*缓冲区到临时缓冲区。

*/

for (i = nCRIndex, j = 0; i < cch; i++, j++)

szBuf[j] = pchInputBuf[i];

szBuf[j] = TEXT('\0');

/*

*检索文本范围并使用它

*设置水平位置

*插入符号。en

*/

hdc = GetDC(hwndMain);

GetTextExtentPoint32(hdc,szBuf,lstrlen(szBuf),

&sz);

nCaretPosX = sz.cx;

ReleaseDC(hwndMain, hdc);

nCurChar = cch;

break;

默认:

break;

}

SetCaretPos(nCaretPosX, nCaretPosY * dwCharY);

break;

case WM_PAINT:

if (cch == 0) /* nothing in input buffer */

break;

hdc = BeginPaint(hwndMain, &ps);

HideCaret(hwndMain);

/*

*设置裁剪矩形,然后绘制文本

* 进去。

*/

SetRect(&rc, 0, 0, dwLineLen, dwClientY);

DrawText(hdc, pchInputBuf, -1, &rc, DT_LEFT);

ShowCaret(hwndMain);

EndPaint(hwndMain, &ps);

break;

.

./ *处理其他消息。*/

.

case WM_DESTROY:

PostQuitMessage(0);

/ *释放输入缓冲区。*/

GlobalFree((HGLOBAL) pchInputBuf);

UnregisterHotKey(hwndMain, 0xAAAA);

break;

默认:

return DefWindowProc(hwndMain, uMsg, wParam, lParam);

}

return NULL;

}