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\n", 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\n", 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\n", 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\n", 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\n", 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\n", 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\n", 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

  运行结果:

  

 

posted @ 2016-06-19 22:58  甩锅侠  阅读(336)  评论(0编辑  收藏  举报