界面编程5鼠标键盘与光标 1.docx

上传人:b****5 文档编号:5235879 上传时间:2022-12-14 格式:DOCX 页数:14 大小:31.98KB
下载 相关 举报
界面编程5鼠标键盘与光标 1.docx_第1页
第1页 / 共14页
界面编程5鼠标键盘与光标 1.docx_第2页
第2页 / 共14页
界面编程5鼠标键盘与光标 1.docx_第3页
第3页 / 共14页
界面编程5鼠标键盘与光标 1.docx_第4页
第4页 / 共14页
界面编程5鼠标键盘与光标 1.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

界面编程5鼠标键盘与光标 1.docx

《界面编程5鼠标键盘与光标 1.docx》由会员分享,可在线阅读,更多相关《界面编程5鼠标键盘与光标 1.docx(14页珍藏版)》请在冰豆网上搜索。

界面编程5鼠标键盘与光标 1.docx

界面编程5鼠标键盘与光标1

第7章界面编程5-鼠标、键盘与光标

Windows是一种基于消息的交互式GUI操作系统,用户的操作主要通过鼠标和键盘进行。

Windows利用消息来处理由用户操作所引发的鼠标和键盘事件,程序员一般通过在视图类中添加相应的消息响应函数,并编写具体响应代码来处理鼠标和键盘消息。

鼠标的当前位置由屏幕上的光标来表示,程序员可以根据需要来动态设置不同形状的光标。

本章先介绍鼠标与键盘消息及其响应,然后再讨论设置与隐藏光标的方法,最后给出一个综合利用鼠标与键盘消息响应和光标设置的实例。

7.1鼠标

鼠标(mouse)是GUI中最常用的指示跟踪设备,由美国斯坦福研究所的DouglasEngelbart和BillEnglish于1963年发明,BillEnglish于1972年发明滚球式(ball)纯机械鼠标,1983年罗技(Logitech)公司发明了第一只光学机械式(简称为光机式或机械式)鼠标,1999年微软与安捷伦(Aeilent,后改组为安华高,Avago)公司合作推出了IntelliEye光学引擎和世界上第一款不需专业鼠标垫的光电鼠标,2003年微软和罗技分别推出蓝牙无线鼠标,2005年罗技与安华高合作推出了第一款(无线)激光鼠标,2008年微软推出了采用BlueTrack技术几乎兼容所有表面的蓝光鼠标。

现代鼠标一般为带滚轮的三键光电或激光式有线或无线(蓝牙或红外)鼠标。

7.1.1鼠标事件与消息

鼠标事件(mouseevent)指用户的鼠标操作,基本的鼠标操作有:

按下(press)和松开(release)鼠标键、单击(click)或双击(double-click)鼠标键、移动(move)或拖动(drag)鼠标,其中左鼠标键按下/松开、移动/拖动鼠标在编程中最常用。

大多数鼠标操作都有相对应的Windows消息(参见表7-1)。

按照鼠标事件发生时鼠标光标所处的窗口区域,可以把鼠标消息分成两类:

●客户区(clientarea)鼠标消息:

鼠标光标位于窗口的客户区时所产生的鼠标消息。

●非客户区(nonclientarea)鼠标消息:

鼠标光标位于窗口的非客户区(如边框、标题条、系统菜单图标、最大化/最小化/还原按钮、关闭按钮、菜单、工具条、滚动条、状态条)时所产生的鼠标消息。

其中,只有客户区鼠标消息是常用的。

至于非客户区鼠标消息,除了Windows自己用于系统管理外一般很少使用。

在本课程中我们只讨论客户区鼠标消息及其处理。

在Windows的SDK编程中,必须将非客户区鼠标消息交给DefWindowProc函数处理。

表7-1鼠标事件与消息

事件

客户区鼠标消息

非客户区鼠标消息

双击左键

WM_LBUTTONDBLCLK

WM_NCLBUTTONDBLCLK

按下左键

WM_LBUTTONDOWN

WM_NCLBUTTONDOWN

释放左键

WM_LBUTTONUP

WM_NCLBUTTONUP

双击中键

WM_MBUTTONDBLCLK

WM_NCMBUTTONDBLCLK

按下中键

WM_MBUTTONDOWN

WM_NCMBUTTONDOWN

释放中键

WM_MBUTTONUP

WM_NCMBUTTONUP

鼠标移动

WM_MOUSEMOVE

WM_NCMOUSEMOVE

双击右键

WM_RBUTTONDBLCLK

WM_NCRBUTTONDBLCLK

按下右键

WM_RBUTTONDOWN

WM_NCRBUTTONDOWN

释放右键

WM_RBUTTONUP

WM_NCRBUTTONUP

因为有的鼠标没有中键,所以应用程序很少使用与中键有关的三个消息。

另外,双击的最大时间间隔可用下列函数获取或设置(默认为500毫秒):

UINTGetDoubleClickTime(VOID);//返回间隔的毫秒数

BOOLSetDoubleClickTime(UINTuInterval);//若成功返回非0值

其中,uInterval为时间间隔值(毫秒数)。

7.1.2响应鼠标消息

可以用MFC的类向导,为视图类或对话框类等CCmdTarget类的派生类,添加鼠标消息响应函数。

常用的鼠标消息响应函数的原型为:

afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);

afx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);

afx_msgvoidOnLButtonUp(UINTnFlags,CPointpoint);

afx_msgvoidOnLButtonDblClk(UINTnFlags,CPointpoint);

afx_msgvoidOnRButtonUp(UINTnFlags,CPointpoint);

其中的参数:

point为鼠标的位置坐标(相对于客户区的左上角)、nFlags为标志参数——可取表7-2中所列的符号常量值(二进制位,可以用“与”来判断,用“或”来组合)。

表7-2鼠标响应函数中标志参数nFlags的取值

符号常量

数值

含义

MK_CONTROL

8

Ctrl键被按下

MK_LBUTTON

1

左鼠标键被按下

MK_MBUTTON

16

中鼠标键被按下

MK_RBUTTON

2

右鼠标键被按下

MK_SHIFT

4

Shift键被按下

与菜单项的事件处理程序类似,每次当你添加一个鼠标消息(如WM_MOUSEMOVE)响应时,MFC类向导会做如下一系列工作:

●在头文件(*.h)的类定义中,添加消息响应函数的原型。

如:

afx_msgvoidOnMouseMove(UINTnFlags,CPointpoint);

●在代码文件(*.cpp)尾部,添加含默认代码的消息响应函数体。

如:

voidCStudentView:

:

OnMouseMove(UINTnFlags,CPointpoint)

{

//TODO:

在此添加消息处理程序代码和/或调用默认值

CView:

:

OnMouseMove(nFlags,point);

}

●在代码文件(*.cpp)头部,添加对应的消息映射宏。

如:

BEGIN_MESSAGE_MAP(CStudentView,CView)

……

ON_WM_MOUSEMOVE()

END_MESSAGE_MAP()

7.1.3单击和拖动

注意,在Windows的鼠标消息中,并没有单击和拖动消息。

编程中,单击操作一般用松开左鼠标键消息WM_LBUTTONUP来代替,如:

voidCStudentView:

:

OnLButtonUp(UINTnFlags,CPointpoint){

......

CView:

:

OnLButtonUp(nFlags,point);

}

而拖动操作则在鼠标移动的消息响应中判断左鼠标键是否被按下来区分。

如:

voidCStudentView:

:

OnMouseMove(UINTnFlags,CPointpoint){

if(nFlags&MK_LBUTTON){

......

}

CView:

:

OnMouseMove(nFlags,point);

}

7.1.4捕捉鼠标

因为鼠标消息只发给位于当前光标之下的窗口,所以如果用户在客户区按下鼠标,拖动鼠标到客户区外后才释放鼠标,则应用程序得不到鼠标被释放的消息,可能会产生错误的响应操作。

为避免这种事情发生,可以调用从CWnd类继承的成员函数SetCapture来捕捉鼠标,使得以后的鼠标消息都发给自己,而不论鼠标的光标是否在自己窗口的客户区。

当程序不再需要鼠标消息后,必须调用API中的全局函数ReleaseCapture释放对鼠标的捕捉,从而使其他程序可以获得它自己的鼠标消息。

在窗口失去对鼠标的捕捉时,会收到Windows发送的WM_CAPTURECHANGED消息。

还可以调用从CWnd类继承来的成员函数GetCapture来获得当前捕捉鼠标的窗口的指针。

这些函数的原型如下:

CWnd*SetCapture();

BOOLReleaseCapture();

staticCWnd*PASCALGetCapture();

Windows应用程序一般是在用户按下鼠标键时设置鼠标捕捉,而在用户释放鼠标键后释放鼠标捕捉。

如:

voidCDrawView:

:

OnLButtonDown(UINTnFlags,CPointpoint){

m_bLButtonDown=TRUE;

SetCapture();

......

CView:

:

OnLButtonDown(nFlags,point);

}

voidCDrawView:

:

OnLButtonUp(UINTnFlags,CPointpoint){

......

m_bLButtonDown=FALSE;

ReleaseCapture();

CView:

:

OnLButtonUp(nFlags,point);

}

7.2键盘

与鼠标一样,当用户敲击键盘时,会产生键盘事件(keyboardevent)。

在MFC中,它们也是由消息、消息映射宏和消息响应函数来处理。

7.2.1按键

Windows中的按键有两类:

●普通按键:

在拥有键盘输入焦点的窗口中,在没有按下Alt键时情况下,所按的各种(组合)键。

●系统按键:

按下Alt键时的各种按键;或在没有任何拥有键盘输入焦点的窗口时,所按下的任意(组合)键。

为了保证像Alt+F4(关闭窗口、程序或操作系统)这样的系统命令能被正确的执行,Windows总是将系统按键所产生的各种键盘消息,发送给CWnd类的对应系统消息响应函数作默认处理。

7.2.2输入焦点

由于Windows为多用户多任务的操作系统,正在运行的程序可能有多个。

对于鼠标,Windows可根据其当前光标位置之下的窗口是哪一个,来决定将鼠标消息发送给哪个窗口(设置了鼠标捕捉时除外)。

而对于键盘,只有拥有键盘输入焦点的窗口才能接收到Windows所发送的键盘消息。

通常情况下,拥有键盘输入焦点的窗口是当前被激活的窗口。

活动窗口(包括对话框、各种控件和图标)会被高亮显示。

窗口在获得或失去输入焦点时,会收到Windows发送的WM_SETFOCUS或WM_KILLFOCUS消息。

可在相应的响应函数OnSetFocus或OnKillFocus中加入自己的处理代码。

如:

voidCStudentView:

:

OnSetFocus(CWnd*pOldWnd)

{

CView:

:

OnSetFocus(pOldWnd);

//TODO:

在此处添加消息处理程序代码

……

}

也可以自己调用(全局)API函数SetFocus和GetFocus来设置和获得输入焦点:

HWNDSetFocus(HWNDhWnd);//hWnd为将获得输入焦点的窗口句柄

//返回失去输入焦点的窗口句柄

HWNDGetFocus(VOID);//返回拥有输入焦点的窗口句柄

7.2.3键盘消息

Windows中的键盘消息有两类:

●击键消息(keystrokemessage):

由键盘动作直接产生的消息,如键按下或释放。

⏹普通击键消息:

WM_KEYDOWN、WM_KEYUP。

⏹系统击键消息:

WM_SYSKEYDOWN、WM_SYSKEYUP。

●字符消息(charactermessage):

由击键消息转化而产生的消息。

⏹普通字符消息:

WM_CHAR。

⏹系统字符消息:

WM_SYSCHAR。

其中。

常用的是WM_KEYDOWN和WM_CHAR。

7.2.4消息响应

普通的击键和字符消息WM_KEYDOWN、WM_KEYUP和WM_CHAR所对应的消息响应函数的原型为:

afx_msgvoidOnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags);

afx_msgvoidOnKeyUp(UINTnChar,UINTnRepCnt,UINTnFlags);

afx_msgvoidOnChar(UINTnChar,UINTnRepCnt,UINTnFlags);

它们的输入参数相同:

●nChar:

⏹对OnKeyDown和OnKeyUp为不区分大小写的虚拟键码(virtual-keycode),如’0’、’A’、VK_F1、VK_LEFT等。

⏹对OnChar为ASCII字符码(charactercode)。

●nFlags:

标志。

⏹对OnChar,一般不用。

⏹对OnKeyDown和OnKeyUp,nFlags中各位的意义见表7-3。

表7-3键盘消息响应的标志参数nFlags中各位的意义

意义

0~7

8位扫描码(值依赖于OEM)

8

为扩展键*时为1否则为0

9~10

没有使用

11~12

由Windows在内部使用

13

Alt键被按下时为1否则为0

14

键原来的状态(按下为1,松开为0)

XX文库-让每个人平等地提升自我*扩展键:

指非基本键盘中的键,如Insert/Delete/Home/End/PageUp/PageDown、方向键、Windows键/应用键和数字键盘中的NumLock、/、Enter键等。

●nRepCnt:

为按住键不放时,所产生的重复按键计数值,一般为1。

可以调用API函数GetKeyState来获得指定虚键的状态,其函数原型为:

SHORTGetKeyState(intnVirtKey);

返回值类型SHORT是short的typedef类型,当指定的键被按下时,返回值的高位为1;当指定的键被锁住时,返回值的低位为1。

例如

if(GetKeyState(VK_SHIFT)&1<<15)...;//Shift键被按下

if(GetKeyState(VK_CAPITAL)&1)...;//CapsLock键被锁住

7.2.5虚拟键表

Windows的虚拟键代码(virtual-keycode)见表7-4。

表7-4虚拟键代码表

键类别

代码值

键类别

代码值

字母

A

‘A’

控制

LeftWindows

VK_LWIN

NumLock

VK_NUMLOCK

Z

’Z’

PageDown

VK_NEXT

数字

(主键盘)

0)

‘0’

PageUp

VK_PRIOR

PrintScreen

SysRq

VK_SNAPSHOT

9(

’9’

RightWindows

VK_RWIN

数字

(数字键盘)

0Ins

VK_NUMPAD0

ScrollLock

VK_SCROLL

Shift

VK_SHIFT

9PgUp

VK_NUMPAD9

Tab

VK_TAB

功能

F1

VK_F1

符号

SpaceBar

VK_SPACE

+

VK_ADD

F12

VK_F12

-

VK_SUBTRACT

方向

VK_UP

*

VK_MULTIPLY

VK_DOWN

/

VK_DIVIDE

VK_LEFT

.Del

VK_DECIMAL

VK_RIGHT

;:

186/0xBA

控制

Alt

VK_MENU

=+

187/0xBB

Applications

VK_APPS

<

188/0xBC

Backspace

VK_BACK

-_

189/0xBD

CapsLock

VK_CAPITAL

.>

190/0xBE

Ctrl

VK_CONTROL

/?

191/0xBF

Delete

VK_DELETE

`~

192/0xC0

End

VK_END

[{

219/0xDB

Enter

VK_RETURN

\|

220/0xDC

Esc

VK_ESCAPE

]}

221/0xDD

Home

VK_HOME

‘“

222/0xDE

Insert

VK_INSERT

7.3光标

光标(cursor)是一种具有热点(hotspot)的特殊位图资源(一般为32*32或64*64像素),用于表示鼠标位置和操作状态。

Windows的默认光标为指向左上方的箭头。

光标文件的扩展名为*.cur,在Windows操作系统的光标子目录(如C:

\Windows\Cursors)中,含有许多常用的光标文件。

7.3.1装入与设置光标

应用程序有时需要设置和显示自己选择或创建的光标,这需要调用SDK的API函数SetCursor和LoadCursor,它们的函数原型为:

HCURSORSetCursor(//返回原来光标的句柄

HCURSORhCursor//光标的句柄

);

HCURSORLoadCursor(//返回新装入光标的句柄

HINSTANCEhInstance,//应用程序实例的句柄

LPCTSTRlpCursorName//名串或光标资源ID

);

其中,hInstance一般置为NULL,lpCursorName可取若干符号常量值(参见表7-5)。

表7-5lpCursorName的常用取值(预定义光标)

符号常量

光标

形状

操作

IDC_ARROW

标准箭头(Standardarrow)

指向

IDC_CROSS

十字标线(Crosshair)

绘图

IDC_IBEAM

I形条(I-beam)

文本

IDC_WAIT

沙漏(Hourglass)

等待

IDC_APPSTARTING

标准箭头与小沙漏

等待

IDC_HAND

手形(Win2K以上)

超链接

IDC_HELP

箭头与问号(mark)

相关帮助

IDC_NO

斜圆(Slashedcircle)

禁止

IDC_SIZEALL

四箭头

移动

IDC_SIZENESW

下斜双箭头

改变大小

IDC_SIZENS

垂直双箭头

改变高度

IDC_SIZENWSE

上斜双箭头

改变大小

IDC_SIZEWE

水平双箭头

改变宽度

IDC_UPARROW

上箭头

选择列

例如,装入并设置沙漏光标:

SetCursor(LoadCursor(NULL,IDC_WAIT));

在CWinApp类中也有两个LoadCursor函数,其原型为:

HCURSORLoadCursor(LPCTSTRlpszResourceName)const;

HCURSORLoadCursor(UINTnIDResource)const;

其中,返回值都为新装入光标的句柄,lpszResourceName与nIDResource分别为光标资源的名串与ID。

externCDrawApptheApp;

SetCursor(theApp.LoadCursor(IDC_MYCURSOR));

注意:

若类光标非空(默认为非空),则在设置光标后,每当用户移动鼠标时,Windows系统就会自动恢复类光标。

解决办法是在移动鼠标消息的响应函数OnMouseMove中来设置光标,如:

voidCDrawView:

:

OnMouseMove(UINTnFlags,CPointpoint){

SetCapture();

SetCursor(LoadCursor(NULL,IDC_CROSS));

......

CView:

:

OnMouseMove(nFlags,point);

}

也可在设置光标的同时也设置鼠标捕捉,则Windows会在释放鼠标捕捉后才恢复类光标。

如:

SetCapture();

SetCursor(LoadCursor(NULL,IDC_CROSS));

7.3.2显示与隐藏光标

系统为每个应用程序维护一个显示与隐藏光标的内部显示计数(internaldisplaycounter),当此计数的值≥0时,显示鼠标光标。

装入鼠标时计数的初始值为0。

可用API函数ShowCursor来增加/减少此计数,其函数原型为:

intShowCursor(BOOLbShow);//返回新的计数值

其中,bShow=TRUE/FALSE对应于计数+1/-1。

7.3.3裁剪光标

可以用API函数ClipCursor将你的光标限制在由lpRect指定的矩形区域内:

BOOLClipCursor(CONSTRECT*lpRect);//成功返回非0

其中,矩形区域的坐标是相对于整个屏幕的,若lpRect为NULL,则取消对鼠标移动的限制。

例如:

CRectrect(100,100,300,300);

ClipCursor(&rect);

ClipCursor(NULL);

可以用API函数GetClipCursor来获得当前鼠标的裁剪区域,坐标也为屏幕的坐标。

若无裁剪区,则lpRect中的矩形为整个屏幕。

其函数原型为:

BOOLGetClipCursor(LPRECTlpRect);//成功返回非0

7.3.4获取与设置光标位置

除了可在鼠标消息的响应函数中,由输入参数point得到鼠标位置外,还可以在任何地方调用API函数GetCursorPos来得到当前的鼠标位置,该函数的原型为:

BOOLGetCursorPos(LPPOINTlpPoint);//成功返回非0

其中,lpPoint的坐标为屏幕的坐标,而且与映射模式无关。

还可以调用另一个API函数SetCursorPos来设置鼠标位置(也为屏幕的坐标):

BOOLSetCursorPos(intX,intY);//成功返回非0

注意,调用此设置光标位置函数,会自动触发鼠标移动事件。

7.4例子

在以后绘图和其他程序中,会用到多种鼠标与键盘消息及其响应操作,有时也需要设置自己的光标。

作为练习,下面给出一个综合使用鼠标键盘消息响应和设置光标的实例。

7.4.1程序要求

程序的功能是:

设置十字光标,用户通过按方向键来移动鼠标位置,每次移动1个像素、+Shift键后每次移动5个像素、+Ctrl键后每次移动10个像素,并且在定制的状态行上显示当前鼠标位置的坐标。

7.4.2创建项目

为了简单,我们新创建一个名为MouseKey的单文档传统MFC应用程序,按4.2.3介绍过的方法定制可显示当前鼠标位置的状态条、为视图类添加鼠标移动消息的响应以显示当前鼠标位置的x、y坐标。

我们还需要为视图类添加击键消息WM_KEYDOWN的响应函数,来完成用方向键移动鼠标位置的功能。

7.4.3相关代码

下面是部分参考代码

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1