6.1-键盘之综合示例
来源:互联网 发布:三挫仑在淘宝上叫什么 编辑:程序博客网 时间:2024/05/15 20:03
第六章—–键盘
windows程序中,对于键盘消息的处理,分为击键消息和字符消息。
击键消息
包括WM_KEYDOWM,WM_KEYUP,WM_SYSKEYDOWM,WM_SYSKEYUP,其中windows会自动处理WM_SYSKEYDOWM,WM_SYSKEYUP,应用程序则负责其他两种。
字符消息
也分为四种。
大多数情况下,我们只用处理非系统字符消息WM_CHAR就行。
综合示例之typer源程序。下面是一些核心代码。
宏定义:
#define BUFFER(x,y) *(pBuffer+y*cxBuffer+x) //表示光标所在处的内容
常量和一些变量定义
static DWORD dwCharSet=DEFAULT_CHARSET; //默认字体 static int cxChar,cyChar,cxClient,cyClient,cxBuffer, cyBuffer,xCaret,yCaret; static TCHAR *pBuffer=NULL; HDC hdc; int x,y,i; PAINTSTRUCT ps; TEXTMETRIC tm;
核心窗口处理过程:
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);
详解CreateFont函数,
nHeight,nWidth参数为0 ,表示的取默认高度和宽度,即SYSTEM _FONT。
同时由于该函数动态分配了内存,所以在获取字体属性不再使用后就释放掉,DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT)))
case WM_SIZE: //发送WM_Paint的前期工作 if(message==WM_SIZE) { cxClient=LOWORD(lParam); cyClient=HIWORD(lParam); } cxBuffer=max(1,cxClient/cxChar); //只要尺寸发生改变,就要更新一次cxClient,cyClient,cxBuffer,cyBuffer 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); return 0;
为什么要在焦点集中窗口时,创建和显示插入符号,而不是即使一个程序中有多个窗口就同时创建多个插入符号?咋听着就很别扭了,的确。
第一,没必要多个窗口都闪烁着插入符号,插入符号的作用是提示用户焦点在该窗口。
第二,一个消息队列仅能够支持一个插入符号,如果你的应用程序有多个窗口,那么也只能共享一个插入符号。
case WM_SETFOCUS: //创建和显示插入符号 CreateCaret(hwnd,NULL,cxChar,cyChar); SetCaretPos(xCaret*cxChar,yCaret*cyChar); ShowCaret(hwnd); return 0; case WM_KILLFOCUS: //隐藏和干掉插入符号 HideCaret(hwnd); DestroyCaret(); return 0;
处理击键消息 WM_KEYDOWM,表示某个键的按下。VK_表示虚拟键盘的意思
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); //最小值为0 break; case VK_RIGHT: xCaret=min(xCaret+1,cxBuffer-1); //最大值为cxBuffer-1 break; case VK_UP: yCaret=max(yCaret-1,0); 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), //&BUFFER(xCaret,yCaret)取当前位置的地址,表示当前位置到末尾的内容 cxBuffer-xCaret); DeleteObject(SelectObject(hdc,GetStockObject(SYSTEM_FONT))); ReleaseDC(hwnd,hdc); ShowCaret(hwnd); break; } SetCaretPos(xCaret*cxChar,yCaret*cyChar); //这里统一刷新插入符号的位置 return 0;
这里主要观察窗口过程如何处理message,wParam,lParam,可见message主要表名消息类型,wParam,lParam则具体消息内容
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': //tab键,也是删除后继内容,而不是整体移动。 do { SendMessage(hwnd,WM_CHAR,' ',1); } while(xCaret%8!=0); break; case '\n': 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,FALSE); 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; } break; } } SetCaretPos(xCaret*cxChar,yCaret*cyChar); return 0;
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))); EndPaint(hwnd,&ps); return 0;
完整示例程序:http://download.csdn.net/detail/u014034497/8918517
- 6.1-键盘之综合示例
- Opencv 学习笔记之图像线性滤波综合示例
- java 泛型知识点综合 之 示例程序
- SWT综合布局示例
- python step1综合示例
- 综合查询示例
- GCD 综合使用示例
- STL-综合示例
- 霍夫线变换综合示例
- 依赖注入综合示例
- 神经网络实战示例一:手写数字识别综合示例研究1 之 MyEclipse中安装Git
- 样式与定位综合示例
- Ext.grid.Panel综合示例
- Oracle基础查询综合示例
- Oracle分页查询综合示例
- 线性图像滤波综合示例
- 仿射变换综合示例
- 日语键盘示例图
- 知识储备:JSON数据解析
- Swift学习笔记系列——(10)方法
- 235 Lowest Common Ancestor of a Binary Search Tree
- 【舶来】 Cydia Substrate框架官网对 '与Xposed对比' 的说明
- java处理高并发高负载类网站的优化方法
- 6.1-键盘之综合示例
- ListView的OnItemClickListener失效的解决办法
- 数据库字符集引发的血案
- 12天学好C语言——记录我的C语言学习之路(Day 4)
- piwik取ip:ip与16进制互转
- 来到亚信第一周---学习内容
- NSString的常用方法
- 8张图理解Java
- 黑马程序员——Java学习总结:IO常用方法练习