MFC Window程序设计(第二版)精华浓缩笔记(三)

原创 2002年07月09日 16:20:00

第三章、键盘和鼠标

精华浓缩:

    键盘和鼠标恐怕是用电脑的人摸的最多的两样东西(当然,DIYer们除外),也正因为有很直观的印象,要理解它们并不难。
       在windows中,键盘和鼠标输入是以消息的形式出现的。首先,设备驱动程序接收并处理鼠标和键盘中断,通过中断处理(ISR)把最初的电脉冲信号转换为系统识别的事件通知(就是消息)放入系统消息队列中。操作系统核心有一个专门的线程(应该就是user32.dll)来监控系统消息队列,通过它把消息分发到各应用程序线程消息队列中。以后,就是应用程序对消息的检索处理,在MFC开发中,就是第一章讲到的消息映射机制了。
    学习如何响应键盘和鼠标的输入关键是要了解该处理哪个消息以及和处理相关的一些MFC和API函数。
    鼠标消息首先分为两大类,即客户区消息和非客户区消息。再按不同输入动作,又细分为左(右、中)键单击、双击和按下、弹起以及鼠标移动消息等。例如WM_LBUTTONDOWN, 表示这是客户区鼠标左键按下消息,而WM_NCMBUTTONUP, 则表示这是非客户区(Not Client)鼠标中键弹起消息。鼠标事件和对应消息的详情可参考MSDN 。

       在MFC中,客户区鼠标消息处理函数的原型为:
        afx_msg void OnMsgName(UINT nFlags,CPoint point)
其中,point指示当前光标位置,这个位置坐标是以相对于窗口客户区左上角的设备坐标而言的。如有必要,可用CDC::DPtoLP()将其转换为逻辑坐标。nFlags参数指出消息生成时鼠标键以及Shift和Ctrl的状态。通常用于判断鼠标或键盘状态,如 if(nFlags & MK_LBUTTON) ...。
    非客户区消息的处理函数原型为:
        afx_msg void OnMsgName(UINT nHitTest,CPoint point)
其中,point指示事件在窗口中发生的位置,但这个位置是屏幕坐标。可用CWnd::ScreenToClient()把屏幕坐标转换为客户区坐标。nHitTest参数包含标识窗口非客户区事件发生地方的命中测试码。如HTCAPTION、HTCLOSE、HTSYSMENU等。可在WM_NCHITTEST或CWnd::OnNcHitTest()的帮助文档中找到完整的命中测试码列表。实际应用与nFlags类似。
    鼠标光标是鼠标与用户之间的接口。我们知道,每个窗口都有相应的WNDCLASS, 其特性在WNDCLASS结构中定义。其中的hCursor字段保存了窗口类型光标的句柄,该光标就是在窗口客户区上的图象。在鼠标移动时,windows通过重画光标的背景把光标从旧位置上清除。然后,它给光标下的窗口发送包含命中测试码的WM_SETCURSOR消息。对此消息系统的默认响应是调用::SetCursor()API函数。如果命中测试码是HTCLIENT(即在客户区中),则显示设置的类型光标,否则显示默认箭头光标。光标将根据鼠标移动时周期的捕获命中测试码自动更新。这个技巧也可以应用到其他图象处理过程中。
    设置光标的方法总结:
    1.注册WNDCLASS(如何注册,在后面知识点部分有总结),并指定希望的光标类型为窗口类光标;
    2.或在OnSetCursor消息处理函数中调用API函数::SetCursor()响应WM_SETCURSOR消息。
   
     windows应用程序了解键盘事件的方式与了解鼠标事件相同:都是通过消息。键盘消息只有三种,即
    WM_KEYDOWN  键盘按下
    WM_KEYUP    键盘抬起
    WM_CHAR     可打印字符键按下或抬起(这是为了简化字符处理过程)
   
       windows总是把键盘消息送到拥有输入焦点的窗口。它用WM_SETFOCUS和WM_KILLFOCUS消息通知即将通知接收或失去输入焦点的窗口。CWnd::SetFocus()把输入焦点转移到另一个窗口;CWnd::GetFocus()用于找到当前用于输入焦点的窗口,它的返回类型为CWnd。
    一个键盘处理函数会接收很多有关击键的消息,其中包括一个代码用来标识被按下或释放的键值。原型如下:
         afx_msg void OnMsgName(UINT nChar,UINT nRepCnt,UINT nFlags)
 其中,nChar是被按下或释放的键的虚拟键值,nRepCnt是重复次数,通常为1。nFlags参数包含键的扫描码以及一些位标志(详情可参考MSDN)。
    和鼠标与光标关联一样,与键盘有关的系统资源是插入符。但光标是全局共享资源,而插入符是单线程共享资源,它被运行在同一线程上的所有窗口共享。
    插入符的使用有一些简单规则:
    1.插入符应在接收到输入焦点时创建,在失去输入焦点时“销毁”。相关函数有CreateCaret、CreateGrayCaret、::DestroyCaret等;
    2.直到调用ShowCaret才能使创建的插入符可见,而调用HideCaret可将使其隐藏;
    3.调用SetCaretPos来移动插入符,永远记住,控制插入符的移动是你自己的工作。对插入符位置的检索可用GetCaretPos。
   

一些知识点:
1.自定义窗口类型:在MFC中,可以用全局函数AfxRigisterWndClass注册窗口类型。这需要初始化WNDCLASS结构中的字段。AfxRigisterWndClass已为你自动填充了大多数字段,你一般只需要关心4个值。AfxRigisterWndClass的函数原型为:
   LPCTSTR AfxRigisterWndClass(UINT nClassStyle,HCURSOR hCursor=0,HBRUSH hbrBackground=0,HICON hIcon=0)
其中,nClassStyle指定窗口类型样式(不是显示类型),而是窗口允许的某种操作特性。如CS_OWNDC,表示由WNDCLASS创建的窗口均有自己的设备描述表(DC);hCursor为由WNDCLASS创建的窗口标识“类型光标”。可通过AfxGetApp()->LoadStandardCursor(IDC_XXX)获得;hbrBackground参数定义了窗口的默认背景颜色;最后一个参数hIcon指定windows用来在桌面上、任务栏等地方代表应用程序的大、小图标。
    在MFC中,调用此函数通常通过覆盖PreCreateWindow虚函数完成。

2.一些非主流的鼠标消息:
1)WM_NCHITTEST消息:窗口在接受一个客户区或非客户区鼠标消息之前,首先接收到光标的屏幕坐标和WM_NCHITTEST消息。windows一般默认处理它。一个使用OnNcHitTest处理函数的技巧是用HTCAPTION命中测试码代替HTCLIENT,以创建一个可在客户区拖动的窗口:
       UINT CMainWindow::OnNcHitTest(CPoint point)
       {
          UINT nHitTest = CFrameWnd::OnNcHitTest(point);
          if(nHitTest == HTCLIENT)
               nHitTest=HICAPTION;
          return nHitTest;
       }
2)WM_MOUSELEAVE和WM_MOUSEHOVER消息:这两个消息可以使你知道鼠标何时进入窗口或在窗口中移动了。与此相关的API函数是::TrackMouseEvent(),通过它,一个程序可以注册,当光标离开窗口时接收WM_MOUSELEAVE消息,而光标在窗口中停滞时接收WM_MOUSEHOVER消息。::TrackMouseEvent()函数只有一个参数,是一个指向TRACKMOUSEEVENT结构的指针。
3)WM_MOUSEWHEEL消息: windows的ON_WM_MOUSEWHEEL宏将WM_MOUSEWHEEL消息映射到消息处理函数OnMouseWheel,其原型为:
        BOOL OnMouseWheel(UINT nFlags,short zDelta,CPoint point)
其中,nFlags和point与其他鼠标处理函数意义相同,zDelta的值等于WHEEL_DELTA(向前滚动一个增量)或-WHEEL_DELTA(向后滚动一个增量)。

3.鼠标的捕获:这通常用于“橡皮筋”画图操作中。用CWnd::SetCapture捕获鼠标,相应的用::ReleaseCapture释放它。

 

   
       

lua程序设计第二版 读书笔记(9-10章)

书本下载地址                       http://download.csdn.net/detail/myy2012/5349646 本部分下载地址             ...
  • myy2012
  • myy2012
  • 2013年05月10日 15:44
  • 1048

《java语言程序设计》(第二版)——笔记(一)

作者:郎波     出版社:清华大学出版社         第一章   绪论 1.java语言特点:简单,面向对象,分布式,解释型,强壮,安全,体系结构中立,可移植,高性能,多线程,动态。 简单:去掉...
  • sunset91
  • sunset91
  • 2013年11月21日 20:58
  • 758

《挑战程序设计竞赛》 勘误 (转载+自己补充)

P113: 倒数第二段第一句“min(y1,y2)1,x2)”应改为“min(y1,y2)1,y2)”。 P130: 上面问题描述的限制条件“1NP P132: Milliona...
  • bat67
  • bat67
  • 2016年07月23日 19:41
  • 585

C语言程序设计现代方法第二版基础部分读书笔记(【美】K.N.King 著)

哈喽!我是甜筒科技【Aice】的大虫,首先先简单的谈谈本人对这本书的一些看法吧,刚刚从图书馆看到这本书的时候就感觉和其他书不一样,除了厚以外,简介的封面设计也吸引到了我。ps:为什么说感觉和其他书不一...
  • aice_dachong
  • aice_dachong
  • 2016年02月27日 11:14
  • 1094

深入java虚拟机第二版阅读笔记(不断整理中)

1 class文件是如何被调入内存执行的? 加载原理?   深入探讨 Java 类加载器:http://www.ibm.com/developerworks/cn/java/j-lo-classloa...
  • ajian005
  • ajian005
  • 2014年03月05日 11:25
  • 1350

ROS机器人程序设计(原书第2版)学习镜像分享及使用说明

ROS机器人程序设计(原书第2版)学习镜像分享及使用说明 系统用于ROS爱好者学习交流,也可用于其他用途,并不局限于ROS。 这款镜像文件是基于一年前的Ubuntu ROS Arduino Gazeb...
  • ZhangRelay
  • ZhangRelay
  • 2016年11月24日 20:54
  • 12246

《MFC游戏开发》笔记三 游戏贴图与透明特效的实现

本系列文章由七十一雾央编写,转载请注明出处。 http://blog.csdn.net/u011371356/article/details/9313239 作者:七十一雾央 新浪微博:h...
  • lsybryant
  • lsybryant
  • 2014年09月08日 13:46
  • 1215

Effective java第二版读书笔记

下面对Effective java第二版中的技术点进行总结 技巧 优点 缺点及注意事项 用静态工厂方法代替构造器 有名称, 不必在每次调用时都创建一个新对象,可返回原返回类型的任何子...
  • smileiam
  • smileiam
  • 2017年05月16日 17:39
  • 296

《Erlang 程序设计》练习答案 -- 第八章 顺序编程补遗

% (1).复习这一张关于Mod:module_info()的部分。输入命令dict:module_info()。这个模块返回了多少函数?% (2).code:all_loaded() 命令会返回一个...
  • wwh578867817
  • wwh578867817
  • 2015年11月16日 15:58
  • 616

大学数据结构(c++版) 王红梅版 学习札记与疑惑——绪论

我知道如果我写些自己真实的学习心得,就一定会暴露我的真实水平,从而会被业内很多人耻笑为小学狗,所以我打算随便扯些鸡 巴玩意,然后复制粘贴,这样你们只能说我是水比,但不能说我是傻 逼,但是我这句话就已经...
  • dickgiant941018
  • dickgiant941018
  • 2014年09月16日 12:57
  • 739
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MFC Window程序设计(第二版)精华浓缩笔记(三)
举报原因:
原因补充:

(最多只允许输入30个字)