zoukankan      html  css  js  c++  java
  • Windows程序设计(七)--鼠标

    7.2 客户区鼠标消息

    当鼠标移过窗口的显示区域时,窗口消息处理程序收到WM_MOUSEMOVE消息。当在窗口的显示区域中按下或者释放一个鼠标按键时,窗口消息处理程序会接收到下面这些消息:

     

    按下

    释放

    按下(双键)

    WM_LBUTTONDOWN

    WM_LBUTTONUP

    WM_LBUTTONDBLCLK

    WM_MBUTTONDOWN

    WM_MBUTTONUP

    WM_MBUTTONDBLCLK

    WM_RBUTTONDOWN

    WM_RBUTTONUP

    WM_RBUTTONDBLCLK

    要接受到双键消息,需要在wndclass.style处增加CS_DBLCLKS

    在WM_MOUSEMOVE中,可以用LOWORD和HIWORD宏来提取鼠标的位置:

    x = LOWORD (lParam) ;
    y = HIWORD (lParam) ;

    wParam中包含信息。MK前缀代表「鼠标按键」。

    MK_LBUTTON

    按下左键

    MK_MBUTTON

    按下中键

    MK_RBUTTON

    按下右键

    MK_SHIFT

    按下Shift键

    MK_CONTROL

    按下Ctrl键

    当您把鼠标移过窗口的显示区域时,Windows并不为鼠标的每个可能的图素位置都产生一个WM_MOUSEMOVE消息。您的程序接收到WM_MOUSEMOVE消息的次数,依赖于鼠标硬件,以及您的窗口消息处理程序在处理鼠标移动消息时的速度。

    1. 窗口消息处理程序可以「拦截鼠标」并且连续地接收鼠标消息,即使此时鼠标在该窗口显示区域之外。您将在本章的后面学习如何拦截鼠标。
    2. 如果正在显示一个系统模态消息框或者系统模态对话框,那么其它程序就不能接收鼠标消息。当系统模态消息框或者对话框活动时,禁止切换到其它窗口或者程序。一个显示系统模态消息框的例子,是当您关闭Windows时。

    实例

    #include<windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("Mouse Move");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
    
        wndclass.hInstance = hInstance;
        wndclass.lpfnWndProc = WndProc;
        wndclass.lpszClassName = szAppName;
        wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.lpszMenuName = 0;
    
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("错误, 无法注册窗口类."), TEXT("错误"), MB_OK);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName, TEXT("Mouse Move"),
            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
            CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, hInstance, NULL);
    
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static POINT pt[1000];
        HDC hdc;
        static int iCount;
        PAINTSTRUCT ps;
        int i, j;
    
        switch (message) {
        case WM_LBUTTONDOWN:
            iCount = 0;
            InvalidateRect(hwnd, NULL, TRUE);//重画时擦除背景
            return 0;
        case WM_MOUSEMOVE:
            if (wParam && MK_LBUTTON && iCount < 1000) {
                pt[iCount].x = LOWORD(lParam);
                pt[iCount++].y = HIWORD(lParam);
                hdc = GetDC(hwnd);
                SetPixel(hdc, LOWORD(lParam), HIWORD(lParam), 0);
                ReleaseDC(hwnd, hdc);
            }
            return 0;
        case WM_LBUTTONUP:
            InvalidateRect(hwnd, NULL, FALSE);//重画时不擦除背景
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);//显示鼠标
            for (i = 0; i < iCount - 1; ++i) {
                for (j = i + 1; j < iCount; ++j) {
                    MoveToEx(hdc, pt[i].x, pt[i].y, NULL);
                    LineTo(hdc, pt[j].x, pt[j].y);
                }
            }
            SetCursor(LoadCursor(NULL, IDC_ARROW));
            ShowCursor(FALSE);//隐藏鼠标
            EndPaint(hwnd, &ps);
        }
    
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    7.2.2 处理shift

    组合键测试

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message) {
        case WM_MOUSEMOVE:
            if (wParam & MK_CONTROL) {
                if (wParam & MK_SHIFT) {
                    MessageBox(hwnd, TEXT("按下Ctrl+Shift键"), TEXT("test!"), NULL);
                    return 0;
                }
            }
        }
    
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    7.2.3 鼠标双击

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message) {
        case WM_LBUTTONDBLCLK:
            MessageBox(hwnd, TEXT("左键双击"), TEXT("test!"), NULL);
            return 0;
        }
    
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    客户区鼠标消息简单应用

    #include<windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("Mouse Move");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
    
        wndclass.hInstance = hInstance;
        wndclass.lpfnWndProc = WndProc;
        wndclass.lpszClassName = szAppName;
        wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.lpszMenuName = 0;
    
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("错误, 无法注册窗口类."), TEXT("错误"), MB_OK);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName, TEXT("Mouse Move"),
            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
            600, 600,
            NULL, NULL, hInstance, NULL);
    
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static int cxClient, cyClient;
        static POINT point;
        HDC hdc;
        PAINTSTRUCT ps;
        TCHAR szBuffer[100];
    
        switch (message) {
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_MOUSEMOVE:
            GetCursorPos(&point);
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            TextOut(hdc, cxClient / 2 - 30, cyClient / 2 - 30, szBuffer, wsprintf(szBuffer, TEXT("屏幕坐标(%d, %d)"), point.x, point.y));
            ScreenToClient(hwnd, &point);
            TextOut(hdc, cxClient / 2 - 30, cyClient / 2 , szBuffer, wsprintf(szBuffer, TEXT("客户区坐标(%d, %d)"), point.x, point.y));
            EndPaint(hwnd, &ps);
            return 0;
        }
    
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    7.3 非客户区鼠标消息

    按下

    释放

    按下(双击)

    WM_NCLBUTTONDOWN

    WM_NCLBUTTONUP

    WM_NCLBUTTONDBLCLK

    WM_NCMBUTTONDOWN

    WM_NCMBUTTONUP

    WM_NCMBUTTONDBLCLK

    WM_NCRBUTTONDOWN

    WM_NCRBUTTONUP

    WM_NCRBUTTONDBLCLK

    可以用两个Windows函数将屏幕坐标转换为显示区域坐标或者反之:

    ScreenToClient (hwnd, &pt) ;
    ClientToScreen (hwnd, &pt) ;

    7.3.1 击中测试消息

    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将把屏幕坐标转换为显示区域坐标并产生显示区域鼠标消息。

    #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                        //在帮助按钮上
    #include<windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("Mouse Move");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
    
        wndclass.hInstance = hInstance;
        wndclass.lpfnWndProc = WndProc;
        wndclass.lpszClassName = szAppName;
        wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.lpszMenuName = 0;
    
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("错误, 无法注册窗口类."), TEXT("错误"), MB_OK);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName, TEXT("Mouse Move"),
            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
            600, 600,
            NULL, NULL, hInstance, NULL);
    
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        TCHAR szBuffer[100];
        static POINT pt;
    
        switch (message) {
        case WM_NCLBUTTONDOWN:
            pt.x = LOWORD(lParam);
            pt.y = HIWORD(lParam);
            ScreenToClient(hwnd, &pt);
            switch (wParam) {
            case HTCAPTION:
                wsprintf(szBuffer, TEXT("击中标题栏,客户区坐标(%d, %d)"), pt.x, pt.y);
                MessageBox(hwnd, szBuffer, TEXT("test"), NULL);
                break;
            case HTMINBUTTON:
                wsprintf(szBuffer, TEXT("击中最小化,客户区坐标(%d, %d)"), pt.x, pt.y);
                MessageBox(hwnd, szBuffer, TEXT("test"), NULL);
                break;
            case HTMAXBUTTON:
                wsprintf(szBuffer, TEXT("击中最大化,客户区坐标(%d, %d)"), pt.x, pt.y);
                MessageBox(hwnd, szBuffer, TEXT("test"), NULL);
                break;
            }
            return 0;
        }
    
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

  • 相关阅读:
    html-----018----HTML Web Server/HTML URL 字符编码
    html-----017
    SQL Server 2008 R2评估期已过的解决办法和sqlserver 服务器打不开问题
    Eclipse快捷键大全
    with递归
    PIVOT使用
    SSH框架搭建
    更换开发环境后设置Tomcat和jdk版本
    MyBatis 一对多和多对一关联查询
    MyBatis 使用接口增删改查和两表一对一级联查询
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11445104.html
Copyright © 2011-2022 走看看