这章总结以下鼠标和键盘事件,先上示例程序:
//消息处理函数
long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)
{
#define BufSize 15 //设置存放字符的缓冲区大小
static char cCharBuf[BufSize]; //设置静态字符数组,存放输入的字符,字符个数不能超出缓冲区大小
static int nNumChar=0; //现有字符个数
static int nArrayPos=0; //字符的位置
static int nLnHeight;
static int nCharWidth;
int x;
HDC hDC;
TEXTMETRIC tm;
PAINTSTRUCT PtStr; //定义指向包含绘图信息的结构体变量
switch(iMessage) //处理消息
{
case WM_CHAR: //遇到非系统字符所作的处理
{
if(wParam==VK_BACK) //处理“遇到回退键的消息”
{
if(nArrayPos==0) //如果已经在一行文字的开始处,则提示用户"不能回退"
MessageBox(hWnd,"当前位置是文本的起始位置,不能回退",NULL,MB_OK);
else
{
nArrayPos=nArrayPos-1; //每按一次回退键就回退一个字符的位置
nNumChar=nNumChar-1; //对现有字符总数进行计数
InvalidateRect(hWnd,NULL,TRUE); //刷新用户区,并向应用程序发送WM_PAINT消息
}
break;
}
if(wParam==VK_ESCAPE) //处理按下Escape键消息
{
MessageBox(hWnd,"您现在不能按ESC键,请继续其它操作",NULL,MB_OK);
break;
}
if(nNumChar>=BufSize) //如果写入的字符数超过缓冲区大小,则报警
{
MessageBox(hWnd,"缓冲区已满,不能再输入字符了\n若需要删除字符,请用BackSpace键",NULL,MB_OK);
break;
}
for(x=nNumChar;x>nArrayPos;x=x-1)
cCharBuf[x]=cCharBuf[x-1];
cCharBuf[nArrayPos]=(unsigned char)wParam;
nArrayPos=nArrayPos+1;
nNumChar=nNumChar+1;
InvalidateRect(hWnd,NULL,TRUE);
}
break;
case WM_CREATE: //处理窗口创建消息
{
hDC=GetDC(hWnd);
GetTextMetrics(hDC,&tm); //获取字体信息
nLnHeight=tm.tmHeight+tm.tmExternalLeading;
nCharWidth=tm.tmAveCharWidth;
ReleaseDC(hWnd,hDC);
}
break;
case WM_KEYDOWN: //处理按下键消息
{
switch(wParam)
{
case VK_END: //处理按下键为End时的消息
nArrayPos=nNumChar; //输入位置从本行的末尾开始
break;
case VK_HOME: //处理按下键为Home时的消息
nArrayPos=0; //输入位置为本行的起始位置
break;
case VK_DELETE: //处理按下键为Delete时的消息
if(nArrayPos==nNumChar) //输入位置处于本行的末尾
MessageBox(hWnd,"缓冲区已空,没有字符可供删除",NULL,MB_OK);
else
{
for(x=nArrayPos;x<nNumChar;x=x+1)
cCharBuf[x]=cCharBuf[x+1]; //每删除一个字符,缓冲区中总字符数减1
nNumChar=nNumChar-1;
InvalidateRect(hWnd,NULL,TRUE); //用户区刷新
}
break;
case VK_LEFT: //处理按下左方向键时的消息
if(nArrayPos>0)
nArrayPos=nArrayPos-1; //当前输入位置往前移一个位置,再输入字符时,等于插入字符
else //已经移到起始输入位置,不能再往前了
MessageBox(hWnd,"您已经移动到起始位置,不能再往左移动了",NULL,MB_OK);
break;
case VK_RIGHT://处理按下右方向键时的消息
if(nArrayPos<nNumChar) //如果当前位置没有到缓冲区的最后位置,还能向右移动
nArrayPos=nArrayPos+1;
else
MessageBox(hWnd,"已经到缓冲区的末尾,不能再向右移动了",NULL,MB_OK);
break;
}
}
break;
case WM_PAINT: //处理重画消息
{
hDC=BeginPaint(hWnd,&PtStr);
TextOut(hDC,nCharWidth,nLnHeight,cCharBuf,nNumChar); //输出缓冲区中的文本
EndPaint(hWnd,&PtStr);
}
break;
case WM_DESTROY: //处理结束应用程序消息
PostQuitMessage(0);//结束应用程序
break;
default://其他消息处理程序
return(DefWindowProc(hWnd,iMessage,wParam,lParam)) ;
}
return 0;
}
键盘事件处理还是比较的简单,发出的消息是WM_CHAR(非系统键)和WM_KEYDOWN,然后通过wparam判断出按下的是哪个键进而进行处理。这里还用了InvalidateRect(hWnd,NULL,TRUE)用于发出重画消息。
鼠标操作主要就是改变光标类型,如如下程序所示
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)
{
WORD x,y; //定义表示坐标的变量
HCURSOR hCursor; //定义表示鼠标的变量
switch(iMessage) //消息处理
{
case WM_MOUSEMOVE: //处理鼠标移动消息
x=LOWORD(lParam); //取得鼠标所在位置的坐标值
y=HIWORD(lParam);
if(x>=50&&x<=400&&y>=50&&y<=300) //在此矩形区域中改变光标的形状
{
if(x>=50&&x<=100&&y>=50&&y<=100)
{
hCursor=LoadCursor(NULL,IDC_CROSS); //定义一个"十"字型光标
SetCursor(hCursor); //设置当前光标
}
if(x>=100&&x<=150&&y>=50&&y<=100)
{
hCursor=LoadCursor(NULL,IDC_SIZEALL); //带东西南北箭头的十字光标
SetCursor(hCursor);
}
if(x>=150&&x<=200&&y>=50&&y<=100)
{
hCursor=LoadCursor(NULL,IDC_HELP); //带有一个箭头带问号的光标
SetCursor(hCursor);
}
if(x>=50&&x<=100&&y>=100&&y<=150)
{
hCursor=LoadCursor(NULL,IDC_SIZENESW); //带有东北-西南箭头的光标
SetCursor(hCursor);
}
if(x>=100&&x<=250&&y>=100&&y<=150)
{
hCursor=LoadCursor(NULL,IDC_SIZENS); //带有南-北双向箭头的光标
SetCursor(hCursor);
}
if(x>=250&&x<=400&&y>=100&&y<=150)
{
hCursor=LoadCursor(NULL,IDC_SIZENWSE); //带有西北-东南箭头的光标
SetCursor(hCursor);
}
if(x>=50&&x<=100&&y>=150&&y<=300)
{
hCursor=LoadCursor(NULL,IDC_SIZEWE); //带有东-西双向箭头的光标
SetCursor(hCursor);
}
if(x>=100&&x<=250&&y>=150&&y<=300)
{
hCursor=LoadCursor(NULL,IDC_UPARROW); //向上箭头的光标
SetCursor(hCursor);
}
if(x>=250&&x<=400&&y>=150&&y<=300)
{
hCursor=LoadCursor(NULL,IDC_WAIT); //沙漏光标
SetCursor(hCursor);
}
}
else
{
hCursor=LoadCursor(NULL,IDC_ARROW); //其他区域设置成普通的箭头光标
SetCursor(hCursor);
}
return 0;
case WM_DESTROY: //处理结束应用程序消息
PostQuitMessage(0); //结束应用程序
return 0;
default://其他消息处理程序
return(DefWindowProc(hWnd,iMessage,wParam,lParam)) ;
}
}