• Windows程序设计_17_鼠标_1


      老长时间没有更新Windows程序设计的内容了,今天看了一段Windows程序设计文件操作的内容,同时想起鼠标操作还没有更新过

    文字,这里先就写一点关于鼠标文字吧。

    一、鼠标

    (1)

      Windows支持单键、双键和三键鼠标,还可以使用操纵杆或者光笔模拟鼠标。

      1、判断系统是否存在鼠标

      在使用鼠标之前必须判断系统中是否存在鼠标,可通过函数GetSystemMetrics来判断鼠标是否存在。

          bMouse=GetSystemMetrics(SM_MOUSEPRESENT);

      若安装了鼠标,则bMouse将返回TRUE,否则就返回0.

      要点:

        Windows98中无论是否安装鼠标,这个函数都将返回TRUE。

      2、判断鼠标的键数

      通过GetSystemMetrics函数还可以确定安装的鼠标的键鼠,只要将传递给函数是参数改为:SM_CMOUSEBUTTONS 即可判断

    系统中鼠标的键;如果没有安装鼠标,那么函数将返回0;在Windows98中,无论有没有安装鼠标,这个函数都将返回2.

      3、判断鼠标是否切换过左右手

      通过向GetSystemMetrics函数传递SM_SWAPBUTTON是否进行了这种切换;

    (2) windows预定义

      当Windows用户移动鼠标时,在屏幕上将有一个“鼠标光标”的小位图,随着用户的移动而移动。鼠标光标上有一个指向屏幕上精确

    位置的单象素“热点”。

      Windows支持预定义的鼠标光标:IDC_ARROW(箭头光标)、IDC_CROSS(十字光标)、IDC_WAIT(光标);箭头光标的热点在

    箭头的顶端,十字光标的热点在中心。

      Windows支持用户自定义鼠标光标;在定义窗口类的时候,我们可以指定预定义的鼠标光标为窗口默认鼠标。

      通过下面的语句指定窗口默认光标:

              wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);

      鼠标操作术语:

        单击:按下并松开一个鼠标键

        双击:快速按下并松开鼠标键两次

        拖曳:按住鼠标键并移动鼠标

      鼠标键名:

        左键:LBUTTON

        中键:MBUTTON

        右键:RBUTTON

      双键鼠标只有左键与右键,单键鼠标只有一个左键。

    (3)客户区鼠标消息

      鼠标在用户窗口移动、按键窗口都会收到消息;这一点与键盘消息不一样:只有拥有输入焦点的窗口才能接收键盘消息。

      Windows一共定义了21种鼠标消息,其中10种是客户去消息,而有11中是非客户去消息,用户程序经常忽略非客户区消息。当鼠标从窗口移动

    时,窗口会接收到WM_MOUSEMOVE消息;当用户在窗口客户去按下鼠标键的时候会接受到如下鼠标消息:

      只有三键鼠标才会接收到中键鼠标消息,只有双键、三键鼠标才能接收到右键消息;仅当定义的窗口类能接收DBLCLK双击消息之后,窗口

    才能接收到这些消息。

      对于窗口接收到的鼠标消息,lParam参数的值均含有鼠标的位置:低位字为x坐标,高位字为y坐标,lParam参数为32位,字定义为16位;

    当要处理鼠标消息时可以通过:

            x=LOWORD(lParam);

            y=HIWORD(lParam);

      获取当前鼠标消息的热点坐标,x、y的值均是相对于窗口客户区左上角顶点而言;这与通常使用的坐标有点不一样。

      Windows定义wParam参数指示鼠标键及Shift和Ctrl键的状态,在程序中,可以使用WINUSER.H定义的位旗标来测试wParam参数。

      MK代表鼠标消息,可以利用下面的语句测试按键的状态:

            if(wParam&MK_SHIFT)

              statement;

        如果接收到WM_LBUTTONDOWN消息的时候,上面的statement语句能执行,则表示按下左键的时候同时按下了shift键。

      Windows不能在鼠标移动过程中,为热点经过的每个像素都发送WM_MOUSEMOVE消息,窗口接收到消息的速度取决于鼠标移动的速度

    以及窗口过程处理移动消息的速度;即Windows不能用未处理的WM_MOUSEMOVE消息来填充消息队列,(为了验证这个特性,可以利用spy

    程序来监控鼠标消息和窗口处理消息的情况)

      窗口处理鼠标消息的过程如下:

        非活动窗口——>按下鼠标——》窗口变成活动窗口——》发送鼠标消息到窗口过程,

        活动窗口——》按下鼠标——》发送鼠标消息到窗口过程

      上述过程是一般的过程,但是这个过程有时候会变成其他样子,当有模态窗口存在时,这个过程可能变得不一样,需要

    注意。

      窗口接收到的消息也不一定是按下左键/按下右键为接收到第一个鼠标消息;例如我们在第一个窗口按下鼠标左键,而

    后将鼠标移动到第二个窗口释放;那么第二个窗口接收到鼠标消息将会先是WM_MOUSEMOVE,然后是WM_LBUTTONUP消息,

    因此在处理的时候需要注意。

      例外情况:

    (4)处理shift和Ctrl键与鼠标组合消息

      前面说过,可以通过wParam参数和位旗标的与运算来查看是否按下了鼠标和shift/ctrl这样的组合消息。

      在鼠标消息中可以通过下面的语句来确定是否按下了shift和Ctrl键

        if(wParam & MK_SHIFT)

        {

            if(wParam & MK_CONTROL)

              {鼠标消息的同时按下了shift和ctrl键}

            else

              {鼠标键的同时按下shift键}

        }

        else

        {

            if(wParam & MK_CONTROL)

              {鼠标消息的同时按下了ctrl键}

            else

              {仅有鼠标消息}

        }

      在用户程序中可以通过利用鼠标和键盘的组合消息来模拟鼠标消息,这样在单键鼠标的情况下就可以实现右键鼠标消息的处理。具体

    我们就不用实例代码说明了。

      Windows使用函数GetKeyState通过虚拟键码VK_LBUTTON、VK_RBUTTON、VK_MBUTTON、VK_SHIFT、VK_CONTROL来返回

    鼠标键与shift键的状态。如果GetKeySate返回负值,则说明按下了鼠标键或者shift键。因为GetKeyState返回当前正在处理的鼠标键或者shift

    键的状态,所以全部状态消息都与相应的消息时同步的。

    (5)双击鼠标键

      双击鼠标键是指在短时间内单击两次。

      双击条件:   1、两次单击发生时鼠标光标热点的距离必须在系统规定的方位之内

            2、两次单击发生的时间间隔在指定的时间范围内;可以在系统控制面板中改变鼠标双击时间间隔。

      如果要使得窗口能接收双击鼠标消息,那么窗口的风格必须有CS_DBLCLKS位旗标。如下所示:

        wndclass.style=CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

      如果没有设置窗口风格,那么双击时窗口将接收下面一系列的消息:

          

      如果设置了窗口风格将接收到:

      

      如上所示,这两个消息队列,仅是第三个消息发生了变化。

      如果双击中的第一个单击操作完成某个单击功能,则处理双击消息很容易,那么第二次单击消息则用来完成第一次单击以外的事情;

    这里如:

      Windows资源管理器的鼠标的单击选定,而双击打开; 当然可以在系统中设计指向选定而单击打开,不过这不符合大多数人的操

    作习惯。

    (6)非客户区鼠标消息

      如果鼠标在窗口之内,但是在客户区之外,那么窗口将会接收系统发送的非客户区鼠标消息;窗口的非客户区包括标题栏、菜单栏和

    窗口滚动条,一般情况下,用户程序不需要处理非窗口鼠标消息,而将这些消息由DefWindowProc函数处理。

      Windows用“NC” 表示非客户区消息,如果鼠标在窗口的非客户区中移动,那么窗口过程接收到WM_NCMOUSEMOVE消息。非客

    户区消息如下所示:

      因为非客户区有几个区域,因此我们在处理非客户区消息的时候,还需要分辨是在标题栏、菜单栏还是滚动条的鼠标消息。

      为了实现分辨区域:可以借助wParam、lParam参数来分辨。客户区的鼠标消息和非客户区鼠标消息的wParam、lParam参数是不一样的,wParam

    参数指明发送鼠标消息的非客户区位置。当有非客户区鼠标消息时,wParam设定为一HT开始的宏标识符(HT表示命中测试)

      当有非客户区鼠标消息时,lParam参数返回鼠标消息发生时热点的坐标,但是此时的坐标为屏幕坐标,而不是客户区坐标。屏幕坐标以屏幕的左上角顶

    点为坐标原点(0,0);当鼠标往右移动时x增加,鼠标往下移动时y增加。

      可以利用Windows函数在屏幕坐标和客户区坐标进行转换:

          ScreenToClient(hwnd,&pt);

          ClientToScreen(hwnd,&pt);

      

    (8)命中测试消息

      在Windows中设置了命中测试消息WM_NCHITTEST,此消息优先于所有其他的客户区和非客户区鼠标消息,lParam参数含有鼠标位置的

    x和y屏幕坐标,wParam参数没有用。

      Windows应用程序通常把这个消息传递给DefWindowProc,然后Windows用WM_NCHITTEST消息产生基于鼠标位置的其他鼠标消息;

    对于非客户区鼠标消息,当处理WM_NCHITTEST消息时,从DefWindowProc返回的值域将成为鼠标消息中的wParam参数,这个值可以是任

    意非客户区鼠标消息的wParam值再加上以下内容:

      HTCLIENT:  客户区

      HTNOWHERE:不在窗口中

      HTTRANSPARENT:窗口由另一个窗口覆盖

      HTERROR:使DefWindowProc产生蜂鸣声

      如果DefWindowProc在处理WM_NCHITTEST消息后返回HTCLIENT,那么Windows将把屏幕坐标转换为客户区坐标,并产生客户区鼠标消息。

    因为WM_NCHITTEST消息在所有的鼠标消息前处理,因此我们可以利用这一点来禁用所有的鼠标消息:

      在窗口过程函数中我们可以这样做:

        case  WM_NCHITTEST:

          return (LRESULT)WM_NCHITTEST;

       这样就可以禁用所有的窗口鼠标消息。

      利用命中测试消息,Windows程序设计了一个消息产生消息的机制,我们可以利用窗口的系统菜单的鼠标双击来分析这个过程:

      

        鼠标双击窗口系统菜单——》WM_NCHITTEST消息——》DefWindowProc处理WM_NCHITTEST消息,后返回——》DefWindowProc将

    WM_NCLBUTTONDBLCLK消息放到消息队列,并把wParam设置为HTSYSMENU——》通常用户程序不会处理WM_NCLBUTTONDBLCLK

    消息,而把消息交给DefwindowProc函数处理——》DefwindowProc接收到wParam=HTSYSMENU的WM_NCLBUTTONDBLCLK

    消息后;将WM_SYSCOMMAND消息放入消息队列中,并设置wParam=SC_CLOSE参数——》窗口过程把这个WM_SYSCOMMAND消息

    传给DefWindowProc函数处理——》DefwindowProc通过给窗口发送WM_CLOSE消息。

      如果用户程序不处理WM_CLOSE消息,那么DefWindowProc将处理这个消息;DefwindowProc函数接收到WM_CLOSE消息后,将调用

    DestroyWindow函数来处理WM_CLOSE,除了其他处理,DestroyWindow还给窗口过程发送WM_DESTROY消息,窗口过程通常用下列

    代码来处理WM_DESTROY消息:

        case WM_DESTROY:

            PostQiutMessage(0);

            retrun 0;

      PostQiutMessage使Windows把WM_QUIT消息放入消息队列中,这个消息永远不会经由窗口过程处理,因为WM_DESTROY消息将

    是GetMessage函数返回0,终止消息循环,从而退出程序。

      

    (9)捕获鼠标

      有时候,可能在鼠标离开窗口后还想获得鼠标消息,这时候我们就需要捕获鼠标。

      例如:  

        在画图程序中,需要画矩形,我们按下鼠表左键,然后拖曳鼠标到适合大小,接下来释放鼠标,就可以绘出矩形;但是假如在拖曳的过程

    中鼠标离开了窗口的客户区,那么原来的窗口就不能接受鼠标释放的消息,这时没有办法确定矩形的大小,就不知道如何绘制矩形了,

      为了处理上面的问题,可以通过鼠标捕获功能来实现。

      Windows提供了函数捕获鼠标,如下所示:

        SetCapture(hwnd);

      在调用这个函数后,Windows会将以后的所有鼠标消息发送给窗口句柄为hwnd的窗口过程,并且鼠标消息都将是客户区消息,即使鼠标在非客户区;

    lParam参数将指示鼠标在坐标中的位置。不过LOWORD(lParam)和HIORD(lParam)返回的值可能为正也为负,这与鼠标发送消息的位置有关。

      当要释放鼠标时,调用

        ReleaseCapture(hwnd);

      就可以使消息恢复到捕获前的状态。

      我们知道在窗口1按下鼠标键,并且窗口1鼠标被捕获,然后移动到窗口2,接下来释放鼠标键,那么窗口1将不能接收到鼠标释放消息,而窗口2将接收

    鼠标消息,这时将不是捕获鼠标的那个窗口接收鼠标消息,而是由光标下面的窗口来接收鼠标消息;

      为了防止捕获产生的异常状态,只有当鼠标键在窗口的客户区中被按下时才捕获鼠标,当键被释放时才释放鼠标捕获。

  • 相关阅读:
    Vue学习笔记【28】——Vue路由(使用 children 属性实现路由嵌套)
    Vue学习笔记【27】——Vue路由(设置路由)
    Vue学习笔记【26】——Vue路由(什么是路由)
    Vue学习笔记【25】——Vue组件(组件间传值)
    Vue学习笔记【24】——Vue组件(组件切换)
    Vue学习笔记【23】——Vue组件(组件的定义)
    ga统计
    token验证机制
    网站发布(项目上线流程)
    使用CSS将图片转换成黑白(灰色、置灰) & 毛玻璃效果
  • 原文地址:https://www.cnblogs.com/volcanol/p/3021121.html
Copyright © 2020-2023  润新知