//短的函数最好定义为宏
#define BUFFER(x,y) *(y*cxBuffer+x+pBuffer)
//取出一个字符
//字符消息
//WM_CHAR,WM_DEADCHAR,WM_SYSCHAR,WM_SYSDEADCHAR
//前两个是由WM_KEYDOWN/UP消息产生,后两个是由WM_SYSKEYDOWN/UP消息产生
//DEADCHAR是某些国家字母有符号,多种表现形式。有DEADCHAR会组合更多,但是我们有不到这个
//消息参数
//wParam:指定该按键的虚拟键代码
//在下面两种消息中的含义
//----WM_KEYDOWN:虚拟键代码 key
//----WM_CHAR:ANSI或Unicode字符码(看宏定义区别) char
//lParam
//扩展键标记(手册)
//消息排序 假设按下A键并释放,大写状态关闭
//1.WM_KEYDOWN 'A'的虚拟按键代码0x41 无论大小写都是大写的按键代码,区别在WM_CHAR处
//2.WM_CHAR 'a'的虚拟按键代码0x61
//3.WM_KEYUP 'A'的虚拟按键代码0x41
//若是持续按下‘A'键
//会循环1、2步骤,在抬起时走3
//插入符号 一个程序共享一个插入符号 获得焦点(活动窗口) 响应WM_SETFOCUS WM_KILLFOCUS
//createcaret,setcaretpos,showcaret,hidecaret.destroycaret
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
RECT rect; PAINTSTRUCT ps;
TEXTMETRIC tm;
static int cxClient, cyClient;
//客户区大小
static int cxChar, cyChar;
//字体大小
static int cxCaret, cyCaret;
//插入符位置
static int cxBuffer, cyBuffer;
//列数行数
static TCHAR * pBuffer =
NULL;
int x, y, i;
//用于循环使用
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);
break;
case WM_SIZE:
//获取屏幕大小
cxClient =
LOWORD(lParam);
cyClient =
HIWORD(lParam);
//获取行数和列数
cxBuffer = (
int)cxClient /
cxChar;
cyBuffer = (
int)cyClient /
cyChar;
cxBuffer = max(
1, cxBuffer);
cyBuffer = max(
1, cyBuffer);
//设置字符集指针的大小
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) =
' ';
}
}
//设置光标位置,左上角
cxCaret =
0;
cyCaret =
0;
if (hwnd==
GetFocus())
{
SetCaretPos(cxCaret*cxChar, cyCaret*
cyChar);
//设为0,0处,先不需要显示
}
InvalidateRect(hwnd, NULL, TRUE);
break;
case WM_SETFOCUS:
CreateCaret(hwnd, NULL, cxChar, cyChar);
SetCaretPos(cxCaret*cxChar, cyCaret*cyChar);
//左上角
ShowCaret(hwnd);
break;
case WM_KILLFOCUS:
HideCaret(hwnd);
DestroyCaret();
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_DOWN:
cyCaret +=
1;
break;
case VK_UP:
cyCaret -=
1;
break;
case VK_LEFT:
cxCaret -=
1;
break;
case VK_RIGHT:
cxCaret +=
1;
break;
case VK_DELETE:
for (x = cxCaret; x < cxBuffer -
1;x++
)
{
BUFFER(x, cyCaret) = BUFFER(x +
1, cyCaret);
}
BUFFER(cxBuffer -
1, cyCaret) =
' ';
HideCaret(hwnd);
hdc =
GetDC(hwnd);
TextOut(hdc, 0, cyCaret*cyChar, &BUFFER(
0, cyCaret), cxBuffer);
//重绘这一行
ReleaseDC(hwnd, hdc);
ShowCaret(hwnd);
default:
break;
}
cxCaret = max(
0, cxCaret);
cyCaret = max(
0, cyCaret);
cxCaret = min(cxCaret, cxBuffer -
1);
cyCaret = min(cyCaret, cyBuffer -
1);
SetCaretPos(cxCaret*cxChar, cyCaret*
cyChar);
break;
case WM_CHAR:
for (i =
0; i < (
int)LOWORD(lParam);i++)
//用户按键过快时
{
switch (wParam)
{
case '\b':
if (cxCaret>
0)
{
cxCaret--
;
SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1);
}
break;
default:
BUFFER(cxCaret, cyCaret) =
(TCHAR)wParam;
hdc =
GetDC(hwnd);
//先隐藏光标
HideCaret(hwnd);
TextOut(hdc, cxCaret*cxChar, cyCaret*cyChar, &BUFFER(cxCaret, cyCaret),
1);
if (++cxCaret ==
cxBuffer)
{
cxCaret =
0;
if (++cyCaret ==
cyBuffer)
{
cyCaret =
0;
}
}
//显示光标
ShowCaret(hwnd);
ReleaseDC(hwnd, hdc);
}
}
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &
ps);
GetClientRect(hwnd, &
rect);
for (y =
0; y < cyBuffer;y++
)
{
TextOut(hdc, 0, y*cyChar, &pBuffer[y*
cxBuffer], cxBuffer);
}
EndPaint(hwnd, &
ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
转载于:https://www.cnblogs.com/ssyfj/p/8520394.html