zoukankan      html  css  js  c++  java
  • 10.windows消息机制(五)

    3.鼠标消息

      (1)基本鼠标消息

        WM_LBUTTONDOWN - 鼠标左键按下消息

        WM_LBUTTONUP - 鼠标左键抬起消息

        WM_RBUTTONDOWN - 鼠标右键按下消息

        WM_RBUTTONUP - 鼠标右键抬起消息

        WM_MOUSEMOVE - 鼠标移动消息

        消息参数:wPARAM - 其他按键状态,例如Ctrl/Shift等

                      lPARAM - 鼠标的位置,窗口客户区坐标系

               LOWORD - X坐标位置,HIWORD - Y坐标位置

        使用:一般情况下鼠标按下/抬起成对出现,鼠标移动过程中,会根据移动速度产生一系列的WM_MOUSEMOVE消息。

      (2)双击消息

        WM_LBUTTONDBLCLK - 鼠标左键双击消息

        WM_RBUTTONDBLCLK - 鼠标右键双击消息

        消息参数:wPARAM - 其他按键的状态,例如Ctrl/Shift等

               lPARAM - 鼠标的位置,窗口客户区坐标系。

               LOWORD - X坐标位置,HIWORD - Y坐标位置

        使用:使用时需要在注册窗口类的时候添加CS_DBCLKS风格。

        消息产生顺序:(以WM_LBUTTONDBCLK为例)

                 WM_LBUTTONDOWN

               WM_LBUTTONUP

               WM_LBUTTONDBLCLK

               WM_LBUTTONUP

      (3)滚轮消息

        WM_MOUSEWHEEL - 鼠标滚轮消息

        消息参数:wPARAM:

              LOWORD - 其他按键的状态

              HIWORD - 滚轮的偏移量,是120的倍数,通过正负值表示滚动方向

             lPARAM:鼠标的位置,屏幕坐标系

              LOWORD - X坐标

              HIWORD - Y坐标

        使用:通过偏移量,获取滚动的方向和倍数

      下面是相关代码: 

    #include "stdafx.h"
    #include <stdio.h>
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    HANDLE g_hOutput = 0;
    
    void OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "WM_LBUTTONDOWN:按键状态:%08x, x=%d, y=%d
    ", wParam, LOWORD(lParam), HIWORD(lParam));
        //WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    void OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "WM_LBUTTONUP:按键状态:%08x, x=%d, y=%d
    ", wParam, LOWORD(lParam), HIWORD(lParam));
        //WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    void OnMouseMove(HWND hWnd, LPARAM lParam)
    {
        short nX = LOWORD(lParam);
        short nY = HIWORD(lParam);
        char szText[256] = { 0 };
        sprintf_s(szText, "鼠标位置:x=%d, y=%d
    ", nX, nY);
        //WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    void OnLButtonDblClk(HWND hWnd, LPARAM lParam)
    {
        short nX = LOWORD(lParam);
        short nY = HIWORD(lParam);
        char szText[256] = { 0 };
        sprintf_s(szText, "WM_LBUTTONDBLCLK:x=%d, y=%d
    ", nX, nY);
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    void OnMouseWheel(HWND hWnd, WPARAM wParam)
    {
        short nDelta = HIWORD(wParam);
        char szText[265] = { 0 };
        sprintf_s(szText, "偏移量:%d
    ", nDelta);
        //WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    //窗口处理函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_MOUSEWHEEL:
            OnMouseWheel(hWnd, wParam);
            break;
        case WM_LBUTTONDBLCLK:
            OnLButtonDblClk(hWnd, lParam);
            break;
        case WM_MOUSEMOVE:
            OnMouseMove(hWnd, lParam);
            break;
        case WM_LBUTTONDOWN:
            OnLButtonDown(hWnd, wParam, lParam);
            break;
        case WM_LBUTTONUP:
            OnLButtonUp(hWnd, wParam, lParam);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize = sizeof(wce);
        wce.cbClsExtra = 200;
        wce.cbClsExtra = 200;
        wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hIconSm = NULL;
        wce.hInstance = g_hInstance;
        wce.lpfnWndProc = wndProc;
        wce.lpszClassName = lpClassName;
        wce.lpszMenuName = NULL;
        wce.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }//显示窗口
    void Display(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    //消息循环
    void Message()
    {
        MSG nMsg = { 0 };
        while (GetMessage(&nMsg, NULL, 0, 0))
        {
            TranslateMessage(&nMsg);
            DispatchMessage(&nMsg);
        }
    }
    
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
        AllocConsole();
        g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        g_hInstance = hInstance;
        Register("Main", WndProc);
        HWND hWnd = CreateMainWindow("Main", "window");
        Display(hWnd);
        Message();
    
        return 0;
    }
    View Code

      (4)定时器消息

        可以再程序中设置定时器,当到达时间间隔时,定时器会向程序触发一个WM_TIMER消息(准确说是GetMessage函数发送消息)。

        定时器的精度是毫秒,但是准确度很低。例如设置时间间隔为1000ms,但是会在非1000ms内到达。

        消息参数:wPARAM - 定时器ID

             lPARAM - 定时器处理函数的指针

        使用:

          a.创建定时器

            UINT_PTR SetTimer( HWND         hWnd,            //定时器窗口句柄,指定处理消息的窗口

                                                        UINT_PTR     nIDEvent,       //定时器ID

                           UINT             uElapse,         //时间间隔

                           TIMERPROC   lpTimerFunc);  //定时器处理函数指针

            创建成功返回非0。

            lpTimerFunc非空,使用定时器处理函数处理定时器(WM_TIMER)消息。

            lpTimerFunc为NULL,使用指定窗口的窗口处理函数处理定时器(WM_TIMER)消息。

            定时器处理函数:

                VOID CALLBACK TimerProc( HWND       hWnd,    //窗口句柄

                                                                              UINT          uMsg,     //消息ID,WM_TIMER

                                                                              UINT_PTR   idEvent,   //定时器ID

                                                                              DWORD     dwTime);  //当前系统时间

          b.处理WM_TIMER

          c.关闭定时器

            BOOL  KillTimer( HWND      hWnd,         //定时器窗口句柄

                                                  UINT_PTR  uIDEvent);  //定时器ID

            附:GetClientRect - 获取窗口客户区大小

          介绍会用到的函数

          画圆:

            BOOL Ellipse( HDC   hdc,                //dc句柄(BeginPaint返回)

                                           int     nLeftRect,        //左上角x坐标

                                           int     nTopRect,        //左上角y坐标

                                           int     nRightRect,      //右下角x坐标

                                           int     nBottomRect);  //右下角y坐标

          获取窗口的边界信息:

            BOOL GetClientRect( HWND    hWnd,   //窗口句柄

                                                         LPRECT  lpRect);  //返回窗口的边界信息

      下面是用定时器让一个小圆移动的代码: 

    #include "stdafx.h"
    #include "stdio.h"
    
    HINSTANCE g_hInstance = 0;  //接收当前程序实例句柄
    HANDLE g_hOutput = 0;
    //圆的位置
    int g_xPos = 100;
    int g_yPos = 100;
    //圆运动的方向
    BOOL Left_Right = TRUE;
    BOOL Right_Left = FALSE;
    BOOL Up_Down = TRUE;
    BOOL Down_Up = FALSE;
    
    
    void OnTimer(HWND hWNd, WPARAM wParam)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "定时器%d
    ", wParam);
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
        RECT rc = { 0 };
        GetClientRect(hWNd, &rc);
        if (g_xPos <= rc.left)
        {
            Left_Right = TRUE;
            Right_Left = FALSE;
        }
        else if (g_xPos >= rc.right-50)
        {
            Right_Left = TRUE;
            Left_Right = FALSE;
        }
        if (Left_Right)
        {
            g_xPos++;
        }
        else if (Right_Left)
        {
            g_xPos--;
        }
        if (g_yPos >= rc.bottom - 50)
        {
            Down_Up = TRUE;
            Up_Down = FALSE;
        }
        else if (g_yPos <= rc.top)
        {
            Up_Down = TRUE;
            Down_Up = FALSE;
        }
        if (Up_Down)
        {
            g_yPos++;
        }
        else if (Down_Up)
        {
            g_yPos--;
        }
        InvalidateRect(hWNd, NULL, FALSE);
    }
    void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
        char szText[256] = { 0 };
        sprintf_s(szText, "定时器处理函数处理:%d
    ", idEvent);
        WriteConsole(g_hOutput, szText, strlen(szText), NULL, NULL);
    }
    
    void OnPaint(HWND hWnd)
    {
        PAINTSTRUCT ps = { 0 };
        HDC hdc = BeginPaint(hWnd, &ps);
        Ellipse(hdc, g_xPos, g_yPos, g_xPos+50, g_yPos+50);
        EndPaint(hWnd, &ps);
    }
    //窗口处理函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_PAINT:
            OnPaint(hWnd);
            break;
        case WM_TIMER:
            OnTimer(hWnd, wParam);
            break;
        case WM_CREATE:
            {
                SetTimer(hWnd, 1, 10, NULL);
                //SetTimer(hWnd, 2, 2000, TimerProc);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    //注册窗口类
    BOOL Register(LPSTR lpClassName, WNDPROC wndProc)
    {
        WNDCLASSEX wce = { 0 };
    
        wce.cbSize = sizeof(wce);
        wce.cbClsExtra = 200;
        wce.cbClsExtra = 200;
        wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        wce.hCursor = NULL;
        wce.hIcon = NULL;
        wce.hIconSm = NULL;
        wce.hInstance = g_hInstance;
        wce.lpfnWndProc = wndProc;
        wce.lpszClassName = lpClassName;
        wce.lpszMenuName = NULL;
        wce.style = CS_HREDRAW | CS_VREDRAW;
    
        ATOM nAtom = RegisterClassEx(&wce);
        if (0 == nAtom)
        {
            return FALSE;
        }
        return TRUE;
    }
    //创建主窗口
    HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName)
    {
        HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            NULL, NULL, g_hInstance, NULL);
        return hWnd;
    }//显示窗口
    void Display(HWND hWnd)
    {
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);
    }
    //消息循环
    void Message()
    {
        MSG nMsg = { 0 };
        while (GetMessage(&nMsg, NULL, 0, 0))
        {
            TranslateMessage(&nMsg);
            DispatchMessage(&nMsg);
        }
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
    {
        AllocConsole();
        g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        g_hInstance = hInstance;
        Register("Main", WndProc);
        HWND hWnd = CreateMainWindow("Main", "window");
        Display(hWnd);
        Message();
    
        return 0;
    }
    View Code

      运行结果:

      

  • 相关阅读:
    渗透测试中的文件传输通道1- cmd下下载文件
    内网渗透常用命令
    技术剖析中国菜刀原理
    win8 iis安装及网站发布
    C++与C的区别一
    C语言实现单链表,并完成链表常用API函数
    C语言实现数组及链表的快速排序
    使用C语言封装数组,动态实现增删改查
    C语言中静态断言的使用
    二分查找法C语言实现
  • 原文地址:https://www.cnblogs.com/csqtech/p/5599146.html
Copyright © 2011-2022 走看看