以下示例演示了如何在简单的文本编辑器中使用插入符号。该示例在用户键入可打印字符时更新插入符位置,并使用各种键移动通过客户端区域。
#define TEXTMATRIX(x,y)*(pTextMatrix +(y * nWindowCharsX)+ x)
//全局变量
HINSTANCE hinst; //当前实例
HBITMAP hCaret; //插入位图
HDC hdc; //设备上下文
PAINTSTRUCT ps; //客户区画面信息
static char *pTextMatrix = NULL; //指向文本矩阵
static int nCharX, // char的宽度。以逻辑单位
nCharY, // char的高度以逻辑单位
nWindowX, //客户区域的宽度
nWindowY, //客户区域的高度
nWindowCharsX, //客户区域的宽度
nWindowCharsY, //客户区域的高度
nCaretPosX, //插入符的x位置
nCaretPosY; //插入符的y位置
static UINT uOldBlink; //以前的眨眼速率
int x, y; //用于文本矩阵中的x和y坐标
TEXTMETRIC tm; //字体信息
龙APIENTRY MainWndProc(
HWND hwnd, //窗口句柄
UINT message, //消息类型
UINT wParam, // 附加信息
LONG lParam) // 附加信息
{
开关(讯息)
{
case WM_CREATE:
//选择固定宽度的系统字体,并获取其文本度量。
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
ReleaseDC(hwnd, hdc);
//保存平均字符的宽度和高度。
nCharX = tm.tmAveCharWidth;
nCharY = tm.tmHeight;
return 0;
case WM_SIZE:
//确定客户区域的宽度,以像素为单位
//和字符数。
nWindowX = LOWORD(lParam);
nWindowCharsX = max(1, nWindowX/nCharX);
//确定客户区域的高度
//像素和字符数。
nWindowY = HIWORD(lParam);
nWindowCharsY = max(1, nWindowY/nCharY);
//清除保存文本输入的缓冲区。
if (pTextMatrix != NULL)
free(pTextMatrix);
//如果有足够的内存,请为此分配空间
//文本输入缓冲区。
pTextMatrix = malloc(nWindowCharsX * nWindowCharsY);
if (pTextMatrix == NULL)
ErrorHandler("Not enough memory.");
其他
for (y = 0; y < nWindowCharsY; y++)
for (x = 0; x < nWindowCharsX; x++)
TEXTMATRIX(x, y) = ' ';
//将插入符号移动到原点。
SetCaretPos(0, 0);
return 0;
case WM_KEYDOWN:
开关(wParam)
{
case VK_HOME: //首页
nCaretPosX = 0;
break;
case VK_END: // 结束
nCaretPosX = nWindowCharsX - 1;
break;
case VK_PRIOR: //向上翻页
nCaretPosY = 0;
break;
case VK_NEXT: // 向下翻页
nCaretPosY = nWindowCharsY -1;
break;
case VK_LEFT: // 左箭头
nCaretPosX = max(nCaretPosX - 1, 0);
break;
case VK_RIGHT: // 右箭头
nCaretPosX = min(nCaretPosX + 1,
nWindowCharsX - 1);
break;
case VK_UP: // 向上箭头
nCaretPosY = max(nCaretPosY - 1, 0);
break;
case VK_DOWN: //向下箭头
nCaretPosY = min(nCaretPosY + 1,
nWindowCharsY - 1);
break;
case VK_DELETE: //删除
//移动后面的所有字符
//删除的字符(在同一行)一个
//空格返回(向左)矩阵。
for (x = nCaretPosX; x < nWindowCharsX; x++)
TEXTMATRIX(x, nCaretPosY) =
TEXTMATRIX(x + 1, nCaretPosY);
//替换最后一个字符
//有一个空格。
TEXTMATRIX(nWindowCharsX - 1,
nCaretPosY) = ' ';
//应用程序将在外面绘制
// WM_PAINT消息处理,所以隐藏插入符号。
HideCaret(hwnd);
//重绘行,调整为
//已删除的字符。
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc,nCaretPosX * nCharX,
nCaretPosY陈,
& TEXTMATRIX(nCaretPosX,nCaretPosY),
nWindowCharsX - nCaretPosX);
ReleaseDC(hwnd, hdc);
//显示插入符号。
ShowCaret(hwnd);
break;
}
//调整插入符号位置
//虚拟键处理。
SetCaretPos(nCaretPosX * nCharX,
nCaretPosY * nCharY);
return 0;
case WM_CHAR:
开关(wParam)
{
case 0x08: //退格
//将插入符号移回一个空格,然后
//处理这个像DEL键。
if(nCaretPosX > 0)
{
nCaretPosX--;
sendMessage(hwnd,WM_KEYDOWN,
VK_DELETE, 1L);
}
break;
case 0x09: // 标签
// Tab停止每四个空格存在,所以添加
//空格,直到用户点击下一个选项卡。
do
{
SendMessage(hwnd, WM_CHAR, ' ', 1L);
} while (nCaretPosX % 4 != 0);
break;
case 0x0D: //回车返回
//转到下一行的开始。
//底线包裹在顶部。
nCaretPosX = 0;
if (++nCaretPosY == nWindowCharsY)
nCaretPosY = 0;
break;
case 0x1B: //逃脱
case 0x0A: //换行
MessageBeep((UINT) -1);
break;
默认:
//将字符添加到文本缓冲区。
TEXTMATRIX(nCaretPosX, nCaretPosY) =
(char) wParam;
//应用程序将在外面绘制
// WM_PAINT消息处理,所以隐藏插入符号。
HideCaret(hwnd);
//在屏幕上绘制字符
hdc = GetDC(hwnd);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
TextOut(hdc,nCaretPosX * nCharX,
nCaretPosY陈,
&TEXTMATRIX(nCaretPosX, nCaretPosY), 1);
ReleaseDC(hwnd, hdc);
//显示插入符号。
ShowCaret(hwnd);
//如果你到达,准备回来
// 队伍的尽头。
if (++nCaretPosX == nWindowCharsX)
{
nCaretPosX = 0;
if (++nCaretPosY == nWindowCharsY)
nCaretPosY = 0;
}
break;
}
//调整插入符号位置
//字符处理。
SetCaretPos(nCaretPosX * nCharX,
nCaretPosY * nCharY);
return 0;
case WM_PAINT:
//逐行绘制缓冲区中的所有字符。
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc,
GetStockObject(SYSTEM_FIXED_FONT));
for (y = 0; y < nWindowCharsY; y++)
TextOut(hdc,0,y * nCharY,& TEXTMATRIX(0,y),
nWindowCharsX);
EndPaint(hwnd, &ps);
case WM_SETFOCUS:
//窗口有输入焦点。加载
//应用程序定义的插入符资源。
hCaret = LoadBitmap(hinst, MAKEINTRESOURCE(120));
//创建插入符号。
CreateCaret(hwnd, hCaret, 0, 0);
//调整插入位置。
SetCaretPos(nCaretPosX * nCharX,
nCaretPosY * nCharY);
//显示插入符号。
ShowCaret(hwnd);
break;
case WM_KILLFOCUS:
//窗口正在丢失输入焦点,
//所以摧毁插入符号。
DestroyCaret();
break;
默认:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return NULL;
}