//短的函数最好定义为宏 #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 '': 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); }