#define BUFFER(x,y) *(pBuffer+y*cxBuffer+x) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent,x,y,i; static DWORD dwCharSet=DEFAULT_CHARSET; static int cxChar,cyChar,cxClient,cyClient,cxBuffer,cyBuffer,xCaret,yCaret; static TCHAR* pBuffer=NULL; PAINTSTRUCT ps; HDC hdc; TEXTMETRIC tm; switch (message) { case WM_INPUTLANGCHANGE: dwCharSet=wParam; case WM_CREATE: hdc=GetDC(hWnd); SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,dwCharSet,0,0,0,FIXED_PITCH,NULL)); GetTextMetrics(hdc,&tm); cxChar=tm.tmAveCharWidth; cyChar=tm.tmHeight; DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT))); ReleaseDC(hWnd,hdc); case WM_SIZE: if(message==WM_SIZE){ cxClient=LOWORD(lParam); cyClient=HIWORD(lParam); } cxBuffer=max(1,cxClient/cxChar); cyBuffer=max(1,cyClient/cyChar); 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)=' '; xCaret=0; yCaret=0; if(hWnd==GetFocus()) SetCaretPos(xCaret*cxChar,yCaret*cyChar); InvalidateRect(hWnd,NULL,TRUE); break; case WM_SETFOCUS: CreateCaret(hWnd,NULL,cxChar,cyChar); SetCaretPos(xCaret*cxChar,yCaret*cyChar); ShowCaret(hWnd); break; case WM_KILLFOCUS: HideCaret(hWnd); DestroyCaret(); break; case WM_KEYDOWN: switch(wParam){ case VK_HOME: xCaret=0; break; case VK_END: xCaret=cxBuffer-1; break; case VK_PRIOR: yCaret=0; break; case VK_NEXT: yCaret=cyBuffer-1; break; case VK_LEFT: xCaret=max(xCaret-1,0); break; case VK_RIGHT: xCaret=min(xCaret+1,cxBuffer-1); break; case VK_UP: yCaret=max(0,yCaret-1); break; case VK_DOWN: yCaret=min(yCaret+1,cyBuffer-1); break; case VK_DELETE: for(x=xCaret;x<cxBuffer-1;x++) BUFFER(x,yCaret)=BUFFER(x+1,yCaret); BUFFER(cxBuffer-1,yCaret)=' '; HideCaret(hWnd); hdc=GetDC(hWnd); SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,dwCharSet,0,0,0,FIXED_PITCH,NULL)); TextOut(hdc,xCaret*cxChar,yCaret*cyChar,&BUFFER(xCaret,yCaret),cxBuffer-xCaret); DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT))); ReleaseDC(hWnd,hdc); ShowCaret(hWnd); break; } SetCaretPos(xCaret*cxChar,yCaret*cyChar); break; case WM_CHAR: for(i=0;i<(int)LOWORD(lParam);i++){ switch(wParam){ case '/b': if(xCaret>0){ xCaret--; SendMessage(hWnd,WM_KEYDOWN,VK_DELETE,1); } break; case '/t': do{ SendMessage(hWnd,WM_CHAR,' ',1); } while(xCaret%8!=0); break; case '/n': if(++yCaret==cyBuffer) yCaret=0; break; case '/r': xCaret=0; if(++yCaret==cyBuffer) yCaret=0; break; case '/x1B': for(y=0;y<cyBuffer;y++) for(x=0;x<cxBuffer;x++) BUFFER(x,y)=' '; xCaret=0; yCaret=0; InvalidateRect(hWnd,NULL,TRUE); break; default: BUFFER(xCaret,yCaret)=(TCHAR)wParam; HideCaret(hWnd); hdc=GetDC(hWnd); SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,dwCharSet,0,0,0,FIXED_PITCH,NULL)); TextOut(hdc,xCaret*cxChar,yCaret*cyChar,&BUFFER(xCaret,yCaret),1); DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT))); ReleaseDC(hWnd,hdc); ShowCaret(hWnd); if(++xCaret==cxBuffer){ xCaret=0; if(++yCaret==cyBuffer) yCaret=0; } } } SetCaretPos(xCaret*cxChar,yCaret*cyChar); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); SelectObject(hdc,CreateFont(0,0,0,0,0,0,0,0,dwCharSet,0,0,0,FIXED_PITCH,NULL)); for(y=0;y<cyBuffer;y++) TextOut(hdc,0,y*cyChar,&BUFFER(0,y),cxBuffer); DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT))); ReleaseDC(hWnd,hdc); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }