Windows程序设计_17_鼠标_1,C语言Windows程序设计
分类:澳门新萄京

CHECKE君越2程序满含二个键盘接口,内容与CHECKEXC601完全相仿。利用←、→、↑、↓多少个方向键能够在二十三个矩形之间活动鼠标指针。Home键把鼠标指针移动到左上角的矩形;End键使鼠标指针落到右下角的矩形。空格键和回车键都得以切换X形标志。

C语言Windows前后相继设计 -> 第十三天 -> 使用鼠标

 

鼠标的行使雷同是透过得到Windows鼠标音信来博取顾客这段时间的鼠标状态的。

生机勃勃、鼠标的牵线
    鼠标是Computer的输入设备之豆蔻梢头, 在图形化的操作系统上, 鼠标的施用使有个别参差不齐的操作变得轻易, 随着科学和技术的前进, 鼠标的品种也更加的多, 按接口类型可分为串行鼠标、PS/2鼠标、总线鼠标、USB鼠标(多为光电鼠标卡塔 尔(英语:State of Qatar)多种。按其行事原理及其内部结构的分化足以分成机械式,光机式和光电式。
    
    这里大家不商量鼠标的硬件构造, 更加的多关于鼠标的硬件知识请自行查阅有关材料。
    
    1>. 鼠标所在的任务
        在Windows系统下, 顾客移动鼠标时, 在荧屏上相同会以多个斜式的箭头来代表鼠标当前的职位, 那几个箭头实际上是二个位图格式的小Logo, 称为"鼠标指针", 鼠标指针具备一个单像素精度的"抢手"(hot spot), 当鼠标准样本式为箭头时, 那一个"火爆"便是鼠标箭头的终端, 还也可能有局地体裁是"十"字样式, 那样的指针"火热"位于"十"字的骨干地方, 热销在显示设备上提示了三个纯正的职位。 当我们去捕获鼠标指针之处时, 实际上是指鼠标指针的那几个"紧俏"所在的像素单元的职位。
    
    2>. 鼠标的术语
        ①. 单击 : 按下鼠标开关, 然后松开;
        ②. 双击 : 再三再四连忙的按下鼠标同叁个开关然后松开;
        ③. 拖动 : 保持按钮按下意况, 并移动鼠标。
        
        以后大家经常见到的三键鼠标, 八个开关遍布称为左键、中键和右键, 当中左键的标志符简写为LBUTTON, 中键的标志符为MBUTTON, 右键的标记符为RBUTTON。 双键鼠标独有左键和右键, 单键鼠标唯有左键。
        
    3>. 鼠标的体制
        Windows系统为鼠标提供了两种默许的鼠标准样本式, 如: 箭头、计时器、十字照准等, 在原先学习的进程中实际上大家早就接触了动用暗中同意的鼠标准样板式, 回忆那行代码:

        wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ) ;

        那样就是使用一个暗中同意的斜式箭头作为鼠标的指针样式, 斜式箭头样式的标记符为 IDC_ARROW, 这几个标记符定义在 WINUSER.H 头文件中, 其他还应该有以下标记符及其相应的体裁:

图片 1

二、使用鼠标的总结示例
    1>. 示例后生可畏: 获取鼠标指针地方
        在这里个示例中示范怎样获得鼠标的职位, 先说下有关的新闻标记符以至函数。
        信息标志符: WM_MOUSEMOVE 当鼠标指针在顾客区内活动或鼠标指针经过顾客区窗口时会得到那么些新闻。
        获取鼠标地方的函数: GetCursorPos 该函数的原型: BOOL GetCursorPos(LPPOINT lpPoint) ;
        代码片段:

 1     switch(message)   2     {   3     case WM_PAINT:        //处理重绘消息   4         hdc = BeginPaint( hwnd, &ps ) ;   5         wsprintf( szBuffer,  "屏幕坐标:(%i, %i)", pt.x, pt.y );   6         TextOut( hdc, 10, 10, szBuffer, lstrlen(szBuffer) ) ;   7         ScreenToClient( hwnd, &pt ) ;        //将相对于屏幕的坐标转换为相对于窗口客户区的坐标   8         wsprintf( szBuffer,  "客户区坐标:(%i, %i)", pt.x, pt.y );   9         TextOut( hdc, 10, 30, szBuffer, lstrlen(szBuffer) ) ;  10         EndPaint( hwnd, &ps ) ;  11         return 0 ;  12   13     case WM_MOUSEMOVE:        //处理鼠标移动时发来的消息  14         GetCursorPos(&pt) ;  15         InvalidateRect( hwnd, NULL, TRUE ) ;  16         return 0 ;

    完整的演示代码:

图片 2图片 3View Code - GetCursorPosition

 1 #include<windows.h>   2    3 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;   4    5 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )   6 {   7     static TCHAR szAppName[] = TEXT( "UseMouse_Demo" ) ;   8     HWND hwnd ;   9     MSG msg ;  10     WNDCLASS wndclass ;  11   12     wndclass.hInstance        = hInstance ;  13     wndclass.lpfnWndProc    = WndProc ;  14     wndclass.lpszClassName    = szAppName ;  15     wndclass.style            = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;  16     wndclass.hbrBackground    = (HBRUSH) GetStockObject( WHITE_BRUSH ) ;  17     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;  18     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;  19     wndclass.cbClsExtra        = 0 ;  20     wndclass.cbWndExtra        = 0 ;  21     wndclass.lpszMenuName    = 0 ;  22   23     if( !RegisterClass(&wndclass) )  24     {  25         MessageBox( NULL, TEXT("错误, 无法注册窗口类."), TEXT("错误"), MB_OK ) ;  26         return 0 ;  27     }  28   29     hwnd = CreateWindow( szAppName, TEXT("获取鼠标指针位置 - Demo"),  30         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,  31         CW_USEDEFAULT, CW_USEDEFAULT,  32         NULL, NULL, hInstance, NULL ) ;  33   34     ShowWindow( hwnd, iCmdShow ) ;  35     UpdateWindow( hwnd ) ;  36   37     while( GetMessage(&msg, NULL, 0, 0) )  38     {  39         TranslateMessage( &msg ) ;  40         DispatchMessage( &msg ) ;  41     }  42   43     return msg.wParam ;  44 }  45   46 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )  47 {  48     HDC hdc ;  49     PAINTSTRUCT ps ;  50     static POINT pt ;  51     TCHAR szBuffer[128] ;  52   53     switch(message)  54     {  55     case WM_PAINT:  56         hdc = BeginPaint( hwnd, &ps ) ;  57         wsprintf( szBuffer,  "屏幕坐标:(%i, %i)", pt.x, pt.y );  58         TextOut( hdc, 10, 10, szBuffer, lstrlen(szBuffer) ) ;  59         ScreenToClient( hwnd, &pt ) ;  60         wsprintf( szBuffer,  "客户区坐标:(%i, %i)", pt.x, pt.y );  61         TextOut( hdc, 10, 30, szBuffer, lstrlen(szBuffer) ) ;  62         EndPaint( hwnd, &ps ) ;  63         return 0 ;  64   65     case WM_MOUSEMOVE:  66         GetCursorPos(&pt) ;  67         InvalidateRect( hwnd, NULL, TRUE ) ;  68         return 0 ;  69   70     case WM_DESTROY:  71         PostQuitMessage(0) ;  72         return 0 ;  73     }  74   75     return DefWindowProc( hwnd, message, wParam, lParam ) ;  76 }

        说一下完整的思绪, 要即时追踪获取鼠标在显示屏中的坐标, 首先要捕获鼠标的运动新闻 WM_MOUSEMOVE, 当Windows向我们发来以此音信时就代码鼠标在实行活动, 随后大家对那个鼠标移动新闻实行拍卖, 调用 GetCursorPos(&pt) ; 那么些函数获取鼠标以往的职位, 获取到鼠标地方后为了能够立时在窗口中体现出来, 再调用 InvalidateRect( hwnd, NULL, TRUE ) ; 使任何客商区产生无效状态, 进而引发 WM_PAINT 须要重绘顾客区内容的音信, 在拍卖重绘信息时输出刚刚获得的鼠标指针坐标地方。
        
        关于 ScreenToClient( hwnd, &pt ) ; :
            那些函数的机能是将荧屏坐标(相对于漫天荧屏左上角的坐标)转变来相对于窗口顾客区的坐标, 显示器坐标与窗口顾客区坐标的意义如图所示:

图片 4

            GetCursorPos拿到的鼠标地点是显示屏坐标, 倘诺想掌握她在窗口客户区内的争执地方就必要调用ScreenToClient函数将其转变为顾客区坐标。
          其他还有一个WIndows函数是将窗口顾客区坐标转成显示器坐标的, 函数为: ClientToScreen( hwnd, &pt ) ;
          获取鼠标指针的职位还会有此外的主意, 这里只是当中的生龙活虎种。
    
    
    2>. 示例二: 处理鼠标左键单击事件
        鼠标左键在客商区被单击时发来的新闻: WM_LBUTTONDOWN

 1     switch(message)   2     {   3     case WM_PAINT:   4         hdc = BeginPaint( hwnd, &ps ) ;   5         EndPaint( hwnd, &ps ) ;   6         return 0 ;   7    8     case WM_LBUTTONDOWN:    //处理鼠标左键单击被按下时产生的消息   9         x = LOWORD( lParam ) ;    //获取鼠标位置x坐标信息  10         y = HIWORD( lParam ) ;    //获取鼠标位置y坐标信息  11         wsprintf( szBuffer,  "鼠标左键被单击, 击中位置: (%i, %i)", x, y );  12         MessageBox( hwnd, szBuffer, TEXT("鼠标动作"), MB_OK ) ;  13         return 0 ;  14   15     case WM_DESTROY:  16         PostQuitMessage(0) ;  17         return 0 ;  18     }

    完整的身体力行代码:

图片 5图片 6View Code - WM_LBUTTONDOWN

 1 #include<windows.h>   2    3 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ;   4    5 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )   6 {   7     static TCHAR szAppName[] = TEXT( "UseMouse_Demo" ) ;   8     HWND hwnd ;   9     MSG msg ;  10     WNDCLASS wndclass ;  11   12     wndclass.hInstance        = hInstance ;  13     wndclass.lpfnWndProc    = WndProc ;  14     wndclass.lpszClassName    = szAppName ;  15     wndclass.style            = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;  16     wndclass.hbrBackground    = (HBRUSH) GetStockObject( WHITE_BRUSH ) ;  17     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW ) ;  18     wndclass.hIcon            = LoadIcon( NULL, IDI_APPLICATION ) ;  19     wndclass.cbClsExtra        = 0 ;  20     wndclass.cbWndExtra        = 0 ;  21     wndclass.lpszMenuName    = 0 ;  22   23     if( !RegisterClass(&wndclass) )  24     {  25         MessageBox( NULL, TEXT("错误, 无法注册窗口类."), TEXT("错误"), MB_OK ) ;  26         return 0 ;  27     }  28   29     hwnd = CreateWindow( szAppName, TEXT("处理鼠标单击事件 - Demo"),  30         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,  31         CW_USEDEFAULT, CW_USEDEFAULT,  32         NULL, NULL, hInstance, NULL ) ;  33   34     ShowWindow( hwnd, iCmdShow ) ;  35     UpdateWindow( hwnd ) ;  36   37     while( GetMessage(&msg, NULL, 0, 0) )  38     {  39         TranslateMessage( &msg ) ;  40         DispatchMessage( &msg ) ;  41     }  42   43     return msg.wParam ;  44 }  45   46 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )  47 {  48     HDC hdc ;  49     PAINTSTRUCT ps ;  50     static POINT pt ;  51     TCHAR szBuffer[128] ;  52     static int x, y ;  53   54     switch(message)  55     {  56     case WM_PAINT:  57         hdc = BeginPaint( hwnd, &ps ) ;  58         EndPaint( hwnd, &ps ) ;  59         return 0 ;  60   61     case WM_LBUTTONDOWN:  62         x = LOWORD( lParam ) ;  63         y = HIWORD( lParam ) ;  64         wsprintf( szBuffer,  "鼠标左键被单击, 击中位置: (%i, %i)", x, y );  65         MessageBox( hwnd, szBuffer, TEXT("鼠标动作"), MB_OK ) ;  66         return 0 ;  67   68     case WM_DESTROY:  69         PostQuitMessage(0) ;  70         return 0 ;  71     }  72   73     return DefWindowProc( hwnd, message, wParam, lParam ) ;  74 }

    这么些示例演示的是当鼠标在客商区按下时弹出二个会话框, 对话框的剧情是鼠标被按下时鼠标指针的职位消息, 能够看到, 这里我们尚无动用 GetCursorPos 函数来博取鼠标指针的职责, 而是通过

        x = LOWORD( lParam ) ;    //获取鼠标位置x坐标信息          y = HIWORD( lParam ) ;    //获取鼠标位置y坐标信息

    来获取的, 参数lParam带有了鼠标指针的岗位新闻, 个中未有字节表示x坐标, 高位字节表示y坐标, 利用LOWORDHIWORD宏可以得到这几个坐标值, 这里获得的坐标指的是周旋于窗口客商区的坐标。

 

三、顾客区鼠标新闻
    与键盘音信区别, 在键盘消息中, Windows只把键盘新闻发送到当前有着输入核心的窗口, 而鼠标新闻无论窗口是或不是获得关节, 只要鼠标经过顾客区, 恐怕在客商区内被单击窗口进度都会选取鼠标音信, 被点击(包含双击/单击/拖动)的窗口将产生活动窗口。与客商区消息相对应的称呼非客户区新闻, 非客商区新闻是指鼠标指针在窗口内并在在顾客区外的移动或单击/双击等, 非客商区富含窗口的标题栏、菜单栏、滚动条、窗口的边框, 那些就要背后举办斟酌, 这里先说客户区鼠标消息。
    
    1>. 鼠标单击
        鼠标在用户区单击时各样鼠标按钮所发生的音信如下:

鼠标按键 按下时产生的消息 释放时产生的消息
左键 WM_LBUTTONDOWN WM_LBUTTONUP
中键 WM_MBUTTONDOWN WM_MBUTTONUP
右键 WM_RBUTTONDOWN WM_RBUTTONUP

                 

 

 

    示例第22中学已经演示了贰个处理鼠标左键单击的自己要作为轨范遵守规则, 对于中键和右键管理的法子是意气风发律的, 只要等待Windows发来新闻然后管理这几个音信就能够了。
        
    2>. wParam参数中的内容
        参数wParam中的值表示了鼠标按键、Shift键和Ctrl键的景观。 将wParam与"鼠标键"标记符实行按位与(&)运算能够得到鼠标开关与鼠标键的事态, 此前缀MK_为带头的标志符称为"鼠标键", 好似下鼠标键:

            #define MK_LBUTTON          0x0001            //按下左键              #define MK_RBUTTON          0x0002            //按下右键
            #define MK_MBUTTON          0x0010            //按下中键              #define MK_SHIFT            0x0004            //按下Shift键              #define MK_CONTROL          0x0008            //按下Ctrl键  

        比方, 当选择到 WM_LBUTTONDOWN 消息时, 若

            wParam & MK_SHIFT 

        的值为TRUE(非零), 则代表按下左键的同一时候也按下了Shift键。
        例如:

        case WM_LBUTTONDOWN:              if( wParam & MK_CONTROL )              {                  MessageBox( hwnd, TEXT("Ctrl键与鼠标左键同时被按下!"), TEXT("鼠标动作"), MB_OK ) ;                  return 0 ;              }              return 0 ;

        唯有当鼠标左键与键盘的Ctrl键同有的时候间被按下时我们弹出个对话框表达"Ctrl键与鼠标左键同不经常间被按下!", 不然什么也不做。
        
        3>. 鼠标双击
            双击对三遍击中之处以至时光间距都有必然供给, 独有当三回高速的单击在概况地点上靠的相当的近何况时间间隔超短的情况下才算双击。
            
            假设想让窗口进程接收鼠标双击音信, 须要在登记窗口类(RegisterClass)时, 开首化wndclass中的style成员的天性中再拉长CS_DBLCLKS标识符:

                wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;

            要是在窗口类的style成员中绝非包涵 CS_DBLCLKS 标记符, 那么固然当客户双击时不会发生双击新闻, 而是发生风流倜傥串如下的信息:

                WM_LBUTTONDOWN                  WM_LBUTTONUP                  WM_LBUTTONDOWN                  WM_LBUTTONUP

            由于客户在接连一回按下鼠标左键时要求自然时间, 即便这几个时刻非常短暂, 可是在这里个历程中前后相继依然有希望收到任何消息的, 举例客商在高速的三遍单击中手的微微抖动就可以在里头插入壹个WM_MOUSEMOVE的新闻, 这里前段时间忽视当中插入的新闻, 假使新闻正是连连的这么些。
            
            当窗口类的style成员只中带有CS_DBLCLKS标志符后, 客商再度双击就能够生出如此的后生可畏串音信:

                WM_LBUTTONDOWN                  WM_LBUTTONUP                  WM_LBUTTONDBLCLK                  WM_LBUTTONUP

            能够观望, 在加盟 CS_DBLCLKS 标记符后, 第六个音讯 WM_LBUTTONDOWN 只是被轻松的替换来了 WM_LBUTTONDBLCLK 消息。
            
            鼠标种种开关双击时第八个音信所对应替换的音讯如下:

            #define WM_LBUTTONDBLCLK                0x0203            //左键              #define WM_MBUTTONDBLCLK                0x0209            //中键              #define WM_RBUTTONDBLCLK                0x0206            //右键

 

四、非客户区鼠标音讯
    非顾客区新闻大致与客商区新闻完全对应, 只是在标志符中多了三个"NC"字符(noclient), 当鼠标指针在窗口的非客商区移动时(比方标题栏), 窗口进程就能够收到到 WM_NCMOUSEMOVE 音信, 在客商区外鼠标按下发生的音讯如下:

鼠标按键 按下 释放 第二次按下(双击)
左键 WM_NCLBUTTONDWON WM_NCLBUTTONUP WM_NCLBUTTONDBLCLK
中键 WM_NCMBUTTONDOWN WM_NCMBUTTONUP WM_NCMBUTTONDBLCLK
右键 WM_NCRBUTTONDOWN WM_NCRBUTTONUP WM_NCRBUTTONDBLCLK

 

 

 

  别的与客商区消息分化的是, 这里的 wParam 参数中的值与客户区中的含义有所不一致, 这里的 wParam 表示非客户区鼠标移动或单击的职位, 他的值被设定成一些以 HT 初叶的标志符中, 表示 "猜中测量试验"(Hit Test), 关于击中测量试验与以HT初始的标记符将要底下讲到。
    
    参数 lParam 中的值照旧是鼠标指针的职位音讯, 但那个时候的信息正好与顾客区中的 lParam 的坐标新闻相反, 客商区中的 lParam 的值是相持于窗口顾客区的坐标, 而这里的(非客商区) lParam 中所包罗的坐标音讯是显示器坐标, 在地点已经提到过, 使用ScreenToClientClientToScreen能够实现显示器坐标与客商区坐标之间的中间转播。
    
    管理非顾客区左键单击示例:

    switch(message)      {      case WM_PAINT:          hdc = BeginPaint( hwnd, &ps ) ;          EndPaint( hwnd, &ps ) ;          return 0 ;        case WM_NCLBUTTONDOWN:        //处理非客户区鼠标左键单击事件          MessageBox( hwnd, TEXT("非客户区鼠标左键被单击"), TEXT("鼠标动作"), MB_OK ) ;          return 0 ;        case WM_DESTROY:          PostQuitMessage(0) ;          return 0 ;      }

 

五、关于"击中测验"音信 WM_NCHITTEST
    WM_NCHITTEST代表"非客商区击中测量试验", 所谓的命中测验正是测量试验鼠标当前所在之处, 这一个音讯的事先级高于其余具有的客商区和非客商区音信, 参数 lParam 中包括绝对于显示屏坐标的x值与y值, wParam 参数另有用处。
    
    日常的话, WM_NCHITTEST 音信是交给 DefWindowProc 私下认可的音讯处理函数举办管理的, 对于客商区中, Windows会利用 WM_NCHITTEST 音信来爆发负有和其他鼠标位置相关的鼠标音讯。对于非客商区消息以来, DefWindowProc 管理 WM_NCHITTEST 消息后赶回一个 wParam 值, 这一个值可以是放肆三个非客商区鼠标信息的 wParam 参数的值, 这么些 wParam 值用来判定鼠标的各州的职分。
    
    譬世尊讲, 即使 DefWindowProc 函数在拍卖 WM_NCHITTEST 新闻后再次回到四个 HTCLIENT , BlackBerryLIENT 代表鼠标在顾客区, 当时Windows会将显示器坐标转变到顾客区坐标,并发生一个相关的顾客区的鼠标音信;
    当再次来到值为 HTCAPTION 表示鼠标当时在二个标题栏中, 所以Windows会将那时鼠标的坐标地点转成显示器坐标并发送有关的非客商区新闻。
    
    那么些重返的标记符定义在WINUSER.H头文件中, 相关的概念如下:

#define HTERROR             (-2)                    //在屏幕的后面或在窗体之间的线上(使函数DefWindowProc产生一个警示音)  #define HTTRANSPARENT       (-1)                    //在一个被其它窗口覆盖的窗口中  #define HTNOWHERE           0                        //在屏幕背景或窗口之间的分界线  #define HTCLIENT            1                        //在客户区中  #define HTCAPTION           2                        //在标题栏中  #define HTSYSMENU           3                        //在一个窗口菜单栏或子窗口的关闭按钮上  #define HTGROWBOX           4                        //在尺寸框中  #define HTSIZE              HTGROWBOX                //同HTGROWBOX  #define HTMENU              5                        //在菜单区域  #define HTHSCROLL           6                        //在水平滚动条上  #define HTVSCROLL           7                        //在垂直滚动条上  #define HTMINBUTTON         8                        //在最小化按钮上  #define HTMAXBUTTON         9                        //在最大化按钮上  #define HTLEFT              10                        //在窗口的左边框上  #define HTRIGHT             11                        //在窗口的右边框上  #define HTTOP               12                        //在窗口水平边框的上方  #define HTTOPLEFT           13                        //在窗口边框的左上角  #define HTTOPRIGHT          14                        //在窗口边框的右上角  #define HTBOTTOM            15                        //在窗口的水平边框的底部  #define HTBOTTOMLEFT        16                        //在窗口边框的左下角  #define HTBOTTOMRIGHT       17                        //在窗口边框的右下角  #define HTBORDER            18                        //在不具有可变大小边框的窗口的边框上  #define HTREDUCE            HTMINBUTTON                //同HTMINBUTTON  #define HTZOOM              HTMAXBUTTON                //同HTMAXBUTTON  #define HTSIZEFIRST         HTLEFT                    //同HTLEFT  #define HTSIZELAST          HTBOTTOMRIGHT             //同HTBOTTOMRIGHT  #define HTOBJECT            19                        //忽略该标识符, 已废弃  #define HTCLOSE             20                        //在关闭按钮上  #define HTHELP              21                        //在帮助按钮上

    那样在收获非客商区音信时大家就可以依照 wParam 中的值判断鼠标在窗口的位置了, 像那样:

    case WM_NCLBUTTONDOWN:        //处理非客户区的鼠标左键单击事件          x = LOWORD( lParam ) ;    //通过lParam获取鼠标位置          y = HIWORD( lParam ) ;          switch(wParam)            //通过wParam判断鼠标在窗口的位置          {          case HTCAPTION:        //在标题上              wsprintf( szBuffer,  "鼠标左键在标题栏中被单击, 击中位置: (%i, %i)", x, y ) ;              MessageBox( hwnd, szBuffer, TEXT("鼠标动作"), MB_OK ) ;              break ;          case HTMINBUTTON:    //在最小化按钮上              wsprintf( szBuffer,  "鼠标左键在最小化按钮上被单击, 击中位置: (%i, %i)", x, y ) ;              MessageBox( hwnd, szBuffer, TEXT("鼠标动作"), MB_OK ) ;              break ;          case HTMAXBUTTON:    //在最大化按钮上              wsprintf( szBuffer,  "鼠标左键在最大化按钮上被单击, 击中位置: (%i, %i)", x, y ) ;              MessageBox( hwnd, szBuffer, TEXT("鼠标动作"), MB_OK ) ;              break ;          }          return 0 ;

    首先捕获 鼠标左键在非客商区的单击事件, 然后再经过 wParam 推断鼠标在窗口的职责, 这里得到鼠标地点是经过 LOWOKoleosD 和 HIWOKoleosD 宏实现的, 还应该有三个职能肖似的宏也能够用来拿到lParam中的鼠标消息, 他们是 GET_X_LPARAM 宏和 GET_Y_LPARAM, 然而那五个宏是定义在 WINDOWSX.H 头文件中的, 如若要运用那多少个宏需要将 WINDOWSX.H 包罗进来。
    举例:

    xPos = GET_X_LPARAM(lParam) ;      yPos = GET_Y_LPARAM(lParam) ;

 

 


wid, 2012.11.30

 

上风流倜傥篇: C语言Windows程序设计 -> 第十天 -> 响应键盘事件

 


  老长时间从没立异Windows程序设计的内容了,今日看了生龙活虎段Windows程序设计文本操作的内容,同期想起鼠标操作还尚无更新过

图片 7图片 8

文字,这里先就写一些有关鼠标文字吗。

  1 /*---------------------------------------------
  2 CHECKER2.C -- Mouse Hit-Test Demo Program No.2
  3               (c) Charles Petzold, 1998
  4 ---------------------------------------------*/
  5 
  6 #include <Windows.h>
  7 
  8 #define DIVISIONS 5
  9 
 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 11 
 12 int WINAPI WinMain( __in HINSTANCE hInstance
 13                     , __in_opt HINSTANCE hPrevInstance
 14                     , __in LPSTR lpCmdLine
 15                     , __in int nShowCmd )
 16 {
 17     static TCHAR szAppName[] = TEXT("Checker2");
 18     HWND hwnd;
 19     MSG msg;
 20     WNDCLASS wndclass;
 21 
 22     wndclass.style = CS_HREDRAW | CS_VREDRAW;
 23     wndclass.lpfnWndProc = WndProc;
 24     wndclass.cbClsExtra = 0;
 25     wndclass.cbWndExtra = 0;
 26     wndclass.hInstance = hInstance;
 27     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 28     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
 29     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
 30     wndclass.lpszMenuName = NULL;
 31     wndclass.lpszClassName = szAppName;
 32 
 33     if (!RegisterClass(&wndclass))
 34     {
 35         MessageBox(NULL, TEXT("Program requires Windows NT!")
 36             , szAppName, MB_ICONERROR);
 37         return 0;
 38     }
 39 
 40     hwnd = CreateWindow(szAppName, TEXT("Checker2 Mouse Hit-Test Demo")
 41         , WS_OVERLAPPEDWINDOW
 42         , CW_USEDEFAULT, CW_USEDEFAULT
 43         , CW_USEDEFAULT, CW_USEDEFAULT
 44         , NULL, NULL, hInstance, NULL);
 45 
 46     ShowWindow(hwnd, nShowCmd);
 47     UpdateWindow(hwnd);
 48 
 49     while (GetMessage(&msg, NULL, 0, 0))
 50     {
 51         TranslateMessage(&msg);
 52         DispatchMessage(&msg);
 53     }
 54 
 55     return msg.wParam;
 56 }
 57 
 58 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 59 {
 60     static BOOL fState[DIVISIONS][DIVISIONS];
 61     static int cxBlock, cyBlock;
 62     HDC hdc;
 63     int x, y;
 64     PAINTSTRUCT ps;
 65     POINT point;
 66     RECT rect;
 67 
 68     switch (message)
 69     {
 70     case WM_SIZE:
 71         cxBlock = LOWORD(lParam) / DIVISIONS;
 72         cyBlock = HIWORD(lParam) / DIVISIONS;
 73         return 0;
 74 
 75     case WM_SETFOCUS:
 76         ShowCursor(TRUE);
 77         return 0;
 78 
 79     case WM_KILLFOCUS:
 80         ShowCursor(FALSE);
 81         return 0;
 82 
 83     case WM_KEYDOWN:
 84         GetCursorPos(&point);
 85         ScreenToClient(hwnd, &point);
 86 
 87         x = max(0, min(DIVISIONS - 1, point.x / cxBlock));
 88         y = max(0, min(DIVISIONS - 1, point.y / cyBlock));
 89 
 90         switch (wParam)
 91         {
 92         case VK_UP:
 93             --y;
 94             break;
 95 
 96         case VK_DOWN:
 97               y;
 98             break;
 99 
100         case VK_LEFT:
101             --x;
102             break;
103 
104         case VK_RIGHT:
105               x;
106             break;
107 
108         case VK_HOME:
109             x = y = 0;
110             break;
111 
112         case VK_END:
113             x = y = DIVISIONS - 1;
114             break;
115 
116         case VK_RETURN:
117         case VK_SPACE:
118             SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(x * cxBlock, y * cyBlock));
119             break;
120         }
121 
122         x = (x   DIVISIONS) % DIVISIONS;
123         y = (y   DIVISIONS) % DIVISIONS;
124 
125         point.x = x * cxBlock   cxBlock / 2;
126         point.y = y * cyBlock   cyBlock / 2;
127 
128         ClientToScreen(hwnd, &point);
129         SetCursorPos(point.x, point.y);
130         return 0;
131 
132     case WM_LBUTTONDOWN:
133         x = LOWORD(lParam) / cxBlock;
134         y = HIWORD(lParam) / cyBlock;
135 
136         if (x < DIVISIONS && y < DIVISIONS)
137         {
138             fState[x][y] ^= 1;
139 
140             rect.left = x * cxBlock;
141             rect.top = y * cyBlock;
142             rect.right = (x   1) * cxBlock;
143             rect.bottom = (y   1) * cyBlock;
144 
145             InvalidateRect(hwnd, &rect, FALSE);
146         }
147         else
148             MessageBeep(0);
149         return 0;
150 
151     case WM_PAINT:
152         hdc = BeginPaint(hwnd, &ps);
153 
154         for (x = 0; x < DIVISIONS;   x)
155             for (y = 0; y < DIVISIONS;   y)
156             {
157                 Rectangle(hdc, x * cxBlock, y * cyBlock
158                     , (x   1) * cxBlock, (y   1) * cyBlock);
159                 
160                 if (fState[x][y])
161                 {
162                     MoveToEx(hdc, x * cxBlock, y * cyBlock, NULL);
163                     LineTo(hdc, (x   1) * cxBlock, (y   1) * cyBlock);
164                     MoveToEx(hdc, x * cxBlock, (y   1) * cyBlock, NULL);
165                     LineTo(hdc, (x   1) * cxBlock, y * cyBlock);
166                 }
167             }
168 
169         EndPaint(hwnd, &ps);
170         return 0;
171 
172     case WM_DESTROY:
173         PostQuitMessage(0);
174         return 0;
175     }
176 
177     return DefWindowProc(hwnd, message, wParam, lParam);
178 }

一、鼠标

CHECKER2.C

(1)

在CHECKER2程序中,处理WM_KEYDOWN时采用GetCursorPos判定指针的职位,并运用ScreenToClient将荧屏坐标调换到顾客区坐标,然后将坐标值除以矩形块的宽和高,拿到x和y。这么些x和y的值表示了矩形在5*5数组中之处。当按下有些键时,鼠标指针可能在客商区也或许不在顾客区内,由此x和y必需含有在min和max的宏管理中,有限支持它们的限量处于0和4里头。

  Windows扶持单键、双键和三键鼠标,还足以运用操纵杆可能光笔模拟鼠标。

对于方向键,CHECKE大切诺基2程序相应的充实或减弱x和y的值。若按下回车键或空格键,CHECKEEscort2程序调用SendMessage给本人发送二个WM_LBUTTONDOWN消息。最后,WM_KEYDOWN管理逻辑计算拿到针对性矩形中央的客商区坐标,并调用ClientToScreen将其调换到显示屏坐标,最终调用SetCursorPos设置指针的职位。

  1、判别系统是还是不是留存鼠标

  在利用鼠标早先必得认清系统中是或不是留存鼠标,可通过函数GetSystemMetrics来推断鼠标是还是不是留存。

      bMouse=GetSystemMetrics(SM_MOUSEPRESENT);

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

  要点:

    Windows9第88中学不管是还是不是安装鼠标,这些函数都将回来TRUE。

  2、推断鼠标的键数

  通过GetSystemMetrics函数还是能够规定安装的鼠标的键鼠,只要将传递给函数是参数改为:SM_CMOUSEBUTTONS 就能够判断

系统中鼠标的键;若无安装鼠标,那么函数将重临0;在Windows9第88中学,无论有没有安装鼠标,那么些函数都将回来2.

  3、判定鼠标是不是切换过左左臂

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

(2) windows预定义

  当Windows顾客移动鼠标时,在荧屏中将有四个“鼠标光标”的小位图,随着客商的移位而运动。鼠标光标上有四个照准显示屏上准确

职位的单象素“火爆”。

  Windows补助预订义的鼠标光标:IDC_A福特ExplorerROW(箭头光标)、IDC_CROSS(十字光标卡塔尔国、IDC_WAIT(光标卡塔 尔(英语:State of Qatar);箭头光标的走俏在

箭头的上边,十字光标的走俏在主旨。

  Windows辅助客户自定义鼠标光标;在概念窗口类的时候,我们得以钦定预订义的鼠标光标为窗口暗中认可鼠标。

  通过下面包车型地铁口舌钦赐窗口暗中同意光标:

          wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);

  鼠标操作术语:

    单击:按下并松手两个鼠标键

    双击:火速按下并放手鼠标键五次

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

  鼠标键名:

    左键:LBUTTON

    中键:MBUTTON

    右键:RBUTTON

  双键鼠标独有左键与右键,单键鼠标唯有贰个左键。

(3卡塔尔国客户区鼠标音信

  鼠标在客户窗口移动、开关窗口都会抽出音信;那点与键盘音信不风流洒脱致:唯有具有输入核心的窗口技巧选拔键盘音讯。

  Windows风流罗曼蒂克共定义了21种鼠标音讯,此中10种是客商去新闻,而有1第11中学是非客商去新闻,客户程序平时忽视非客户区新闻。当鼠标从窗口移动

时,窗口会收到到WM_MOUSEMOVE音讯;当顾客在窗口顾客去按下鼠标键的时候会经受到如下鼠标音信:

图片 9

  独有三键鼠标才会选择到中键鼠标音讯,唯有双键、三键鼠标技巧收到到右键音讯;仅当定义的窗口类能接过DBLCLK双击音讯随后,窗口

技能收到到这个音信。

  对于窗口接纳到的鼠标新闻,lParam参数的值均满含鼠标的岗位:低位字为x坐标,高位字为y坐标,lParam参数为叁拾肆人,字定义为十多少人;

当要管理鼠标音信时能够透过:

        x=LOWORD(lParam);

        y=HIWORD(lParam);

  获取当前鼠标音信的走俏坐标,x、y的值均是相持于窗口客商区左上角顶点来讲;那与成千成万接纳的坐标有一点点不后生可畏致。

  Windows定义wParam参数提示鼠标键及Shift和Ctrl键的场合,在前后相继中,能够运用WINUSERubicon.H定义的位旗标来测量检验wParam参数。

图片 10

  MK代表鼠标音讯,能够采纳上边包车型客车讲话测量试验开关的事态:

        if(wParam&MK_SHIFT)

          statement;

    假使接受到WM_LBUTTONDOWN音讯的时候,上边的statement语句能实施,则象征按下左键的时候还要按下了shift键。

  Windows无法在鼠标移动进程中,为火热经过的每一种像素都发送WM_MOUSEMOVE新闻,窗口接受到新闻的快慢决计于鼠标移动的进度

以至窗口进程管理移动新闻的快慢;即Windows无法用未管理的WM_MOUSEMOVE新闻来填充音信队列,(为了证实这几个特性,能够使用spy

次第来监督鼠标消息和窗口管理新闻的情事卡塔 尔(阿拉伯语:قطر‎

  窗口管理鼠标音讯的经过如下:

    非活动窗口——>按下鼠标——》窗口形成活动窗口——》发送鼠标音讯到窗口进度,

    活动窗口——》按下鼠标——》发送鼠标音讯到窗口进程

  上述进程是相符的经过,可是这几个进度有的时候候会化为任何样子,当有模态窗口存在时,那一个进度可能变得不相符,需求

注意。

  窗口选择到的消息也不必然是按下左键/按下右键为接受到第三个鼠标新闻;例如我们在第叁个窗口按下鼠标左键,而

后将鼠标移动到第一个窗口释放;那么第四个窗口采取到鼠标音信将会率先WM_MOUSEMOVE,然后是WM_LBUTTONUP消息,

为此在处理的时候须求注意。

  例外意况:

图片 11

 

(4卡塔 尔(英语:State of Qatar)管理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;

  若无安装窗口作风,那么双击时窗口将收到上面一文山会海的新闻:

      图片 12

  假使设置了窗口作风将吸收接纳到:

  图片 13

  如上所示,那五个音信队列,仅是第多少个新闻产生了改换。

  借使双击中的第叁个单击操作完毕有些单击效能,则管理双击音信超级轻巧,那么第叁次单击音讯则用来成功首回单击以外的工作;

这里如:

  Windows能源微电脑的鼠标的单击选定,而双击展开; 当然能够在系统中安顿指向性选定而单击打开,但是这不切合大多数人的操

作习惯。

(6卡塔尔非客商区鼠标新闻

  假若鼠标在窗口之内,可是在顾客区之外,那么窗口将会收到系统一发布送的非客商区鼠标音讯;窗口的非顾客区满含标题栏、菜单栏和

窗口滚动条,平时情状下,顾客程序不须求管理非窗口鼠标新闻,而将那个音信由DefWindowProc函数管理。

  Windows用“NC” 表示非客户区新闻,假若鼠标在窗口的非客户区中活动,那么窗口过程接收到WM_NCMOUSEMOVE消息。非客

户区音信如下所示:

图片 14

  因为非客商区有多少个区域,由此大家在拍卖非客户区新闻的时候,还索要分辨是在标题栏、菜单栏依旧滚动条的鼠标新闻。

  为了贯彻分辨区域:能够依附wParam、lParam参数来甄别。顾客区的鼠标新闻和非客商区鼠标音信的wParam、lParam参数是不平等的,wParam

参数指明发送鼠标消息的非顾客区地方。当有非顾客区鼠标信息时,wParam设定为意气风发HT起头的宏标志符(HT表示命中测量检验卡塔 尔(阿拉伯语:قطر‎

  当有非客商区鼠标音讯时,lParam参数重临鼠标信息产生时火热的坐标,可是这时的坐标为屏幕坐标,并不是客商区坐标。显示器坐标以显示屏的左上角顶

点为坐标原点(0,0卡塔尔;当鼠标往右移动时x扩充,鼠标往下活动时y增添。

  能够应用Windows函数在显示屏坐标和客户区坐标进行改换:

      ScreenToClient(hwnd,&pt);

      ClientToScreen(hwnd,&pt);

图片 15

  

(8卡塔 尔(阿拉伯语:قطر‎命中测验消息

  在Windows中设置了命中测量试验新闻WM_NCHITTEST,此新闻优先于具备其余的顾客区和非顾客区鼠标音信,lParam参数含有鼠标地方的

x和y显示屏坐标,wParam参数未有用。

Windows程序设计_17_鼠标_1,C语言Windows程序设计。  Windows应用程序经常把这几个音讯传递给DefWindowProc,然后Windows用WM_NCHITTEST音信发生基于鼠标地方的别的鼠标音信;

对于非客商区鼠标新闻,当管理WM_NCHITTEST新闻时,从DefWindowProc重返的值域将变为鼠标音信中的wParam参数,这么些值能够是任

意非顾客区鼠标新闻的wParam值再加多以下内容:

  HTCLIENT:  客户区

  HTNOWHERE:不在窗口中

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

  HTE奥迪Q7RO传祺:使DefWindowProc发生蜂鸣声

  如果DefWindowProc在处理WM_NCHITTEST消息后回去三星(Samsung卡塔尔LIENT,那么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参数将指令鼠标在坐标中之处。可是LOWOSportageD(lParam)和HIOLANDD(lParam)重临的值可能为正也为负,那与鼠标发送消息的职责有关。

  当要释放鼠标时,调用

    ReleaseCapture(hwnd);

  就能够使消息苏醒到捕获前的情形。

  大家领会在窗口1按下鼠标键,况兼窗口1鼠标被抓获,然后移动到窗口2,接下去释放鼠标键,那么窗口1将无法吸收接纳到鼠标释放新闻,而窗口2将抽出

鼠标音讯,那个时候将不是捕获鼠标的不行窗口选取鼠标音讯,而是由光标上边包车型客车窗口来接过鼠标音讯;

  为了幸免捕获发生的丰裕意况,独有当鼠标键在窗口的顾客区中被按下时才捕获鼠标,当键被放出时才放走鼠标捕获。

本文由澳门新萄京发布于澳门新萄京,转载请注明出处:Windows程序设计_17_鼠标_1,C语言Windows程序设计

上一篇:澳门新萄京:批管理装置Windows服务,闪退的化解 下一篇:没有了
猜你喜欢
热门排行
精彩图文