• Windows鼠标键盘消息处理


      1 #include <windows.h>
      2 #include <tchar.h>    //swprintf_s函数所需的头文件
      3 
      4 #pragma comment(lib, "winmm.lib")    //playSound
      5 #pragma comment(lib, "Msimg32.lib")    //TransparentBlt
      6 
      7 #define WINDOW_WIDTH    800
      8 #define WINDOW_HEIGHT    600
      9 #define WINDOW_TITLE    L"Windows鼠标键盘消息处理"
     10 
     11 // 环境,内存句柄
     12 HDC    g_hdc = NULL, g_mdc = NULL, g_bufdc = NULL;
     13 // 四张方向图,存储背景图的句柄, 人物2
     14 HBITMAP g_hSprite[4] = { NULL }, g_hBackGround = NULL, g_hMan = NULL;
     15 // 上一次绘图时间,此次准备绘图的时间
     16 DWORD g_tPre = 0, g_tNow = 0;
     17 // 图号,人物1横纵坐标,鼠标坐标,鼠标控制人物2坐标
     18 int    g_iNum = 0, g_iX = 0, g_iY = 0, g_mouseX = 0, g_mouseY = 0, g_iXnow = 0, g_iYnow = 0;
     19 // 人物移动方向,以0,1,2,3代表人物上,下,左,右
     20 int    g_iDirection = 0;
     21 
     22 // 回调函数,窗口过程函数
     23 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     24 BOOL Game_Init(HWND hwnd);
     25 VOID Game_Paint(HWND hwnd);
     26 BOOL Game_CleanUp(HWND hwnd);
     27 
     28 
     29 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
     30 {
     31     WNDCLASSEX wndClass = { 0 };
     32     wndClass.cbSize = sizeof(WNDCLASSEX);
     33     wndClass.style = CS_HREDRAW | CS_VREDRAW;
     34     wndClass.lpfnWndProc = WndProc;
     35     wndClass.cbClsExtra = 0;
     36     wndClass.cbWndExtra = 0;
     37     wndClass.hInstance = hInstance;
     38     wndClass.hIcon = 0;
     39     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
     40     // 白色画刷句柄
     41     wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
     42     // 用一个以空终止的字符串,指定菜单资源的名字
     43     wndClass.lpszMenuName = NULL;
     44     //窗口类的名字
     45     wndClass.lpszClassName = L"Game Develop";
     46 
     47     if (!RegisterClassEx(&wndClass))
     48         return -1;
     49 
     50     // 正式创建窗口
     51     HWND hwnd = CreateWindow(L"Game Develop", WINDOW_TITLE,
     52         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
     53         WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
     54 
     55     MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);
     56     ShowWindow(hwnd, nShowCmd);
     57     UpdateWindow(hwnd);
     58 
     59     if (!Game_Init(hwnd))
     60     {
     61         MessageBox(hwnd, L"资源初始化失败", L"消息窗口", 0);
     62         return FALSE;
     63     }
     64 
     65     PlaySound(L"music.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
     66 
     67     MSG msg = { 0 };
     68     while (msg.message != WM_QUIT)
     69     {
     70         // 查看应用程序消息队列,有消息时将队列中的消息派发出去
     71         if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
     72         {
     73             TranslateMessage(&msg);
     74             DispatchMessage(&msg);
     75         }
     76         else
     77         {
     78             g_tNow = GetTickCount();
     79             // 重绘
     80             if (g_tNow - g_tPre >= 40)
     81                 Game_Paint(hwnd);
     82         }
     83     }
     84 
     85     // 程序准备结束,注销窗口类
     86     UnregisterClass(L"Game Develop", wndClass.hInstance);  
     87     return 0;
     88 }
     89 
     90 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     91 {
     92 
     93     switch (message)                        
     94     {
     95         //键盘消息
     96     case WM_KEYDOWN:         
     97         switch (wParam)
     98         {
     99             //按下Esc键
    100         case VK_ESCAPE:           
    101             DestroyWindow(hwnd);   
    102             PostQuitMessage(0);  
    103             break;
    104         case VK_UP:                 
    105             g_iY -= 10;
    106             g_iDirection = 0;
    107             if (g_iY < 0)
    108                 g_iY = 0;
    109             break;
    110         case VK_DOWN:             
    111             g_iY += 10;
    112             g_iDirection = 1;
    113             if (g_iY > WINDOW_HEIGHT - 135)
    114                 g_iY = WINDOW_HEIGHT - 135;
    115             break;
    116         case VK_LEFT:                     
    117             g_iX -= 10;
    118             g_iDirection = 2;
    119             if (g_iX < 0)
    120                 g_iX = 0;
    121             break;
    122         case VK_RIGHT:               
    123             g_iX += 10;
    124             g_iDirection = 3;
    125             if (g_iX > WINDOW_WIDTH - 75)
    126                 g_iX = WINDOW_WIDTH - 75;
    127             break;
    128         }
    129         break;    
    130 
    131         // 单击鼠标左键消息
    132     case WM_LBUTTONDOWN:            
    133                 break;
    134 
    135         // 鼠标移动消息
    136     case WM_MOUSEMOVE:   
    137         // 取得鼠标X坐标
    138         g_mouseX = LOWORD(lParam);            
    139         if (g_mouseX > WINDOW_WIDTH - 292)    
    140             g_mouseX = WINDOW_WIDTH - 292;
    141         else if (g_mouseX < 0)
    142             g_mouseX = 0;
    143         // 取得鼠标Y坐标
    144         g_mouseY = HIWORD(lParam);            
    145         if (g_mouseY  > WINDOW_HEIGHT - 190)
    146             g_mouseY = WINDOW_HEIGHT - 190;
    147         else if (g_mouseY  < 0)
    148             g_mouseY = 0;
    149         break;
    150 
    151     case WM_DESTROY:                    
    152         Game_CleanUp(hwnd);            
    153         PostQuitMessage(0);            
    154         break;                                    
    155 
    156         //调用缺省的窗口过程
    157     default:                                        
    158         return DefWindowProc(hwnd, message, wParam, lParam);        
    159     }
    160     return 0;                                
    161 }
    162 
    163 BOOL Game_Init(HWND hwnd)
    164 {
    165     HBITMAP bmp;
    166     g_hdc = GetDC(hwnd);
    167     // 创建一个和hdc兼容的内存DC
    168     g_mdc = CreateCompatibleDC(g_hdc);
    169     // hdc兼容的缓冲DC
    170     g_bufdc = CreateCompatibleDC(g_hdc);
    171     bmp = CreateCompatibleBitmap(g_hdc, WINDOW_WIDTH, WINDOW_HEIGHT);
    172 
    173     g_iX = 100;
    174     g_iY = 350;
    175     g_mouseX = 300;
    176     g_mouseY = 100;
    177     g_iXnow = 300;
    178     g_iYnow = 100;
    179     g_iDirection = 3;
    180     g_iNum = 0;
    181 
    182     SelectObject(g_mdc, bmp);
    183     g_hSprite[0] = (HBITMAP)LoadImage(NULL, L"go1.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE);
    184     g_hSprite[1] = (HBITMAP)LoadImage(NULL, L"go2.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE);
    185     g_hSprite[2] = (HBITMAP)LoadImage(NULL, L"go3.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE);
    186     g_hSprite[3] = (HBITMAP)LoadImage(NULL, L"go4.bmp", IMAGE_BITMAP, 480, 216, LR_LOADFROMFILE);
    187     g_hBackGround = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, WINDOW_WIDTH, WINDOW_HEIGHT, LR_LOADFROMFILE);
    188     g_hMan = (HBITMAP)LoadImage(NULL, L"man2.bmp", IMAGE_BITMAP, 292, 190, LR_LOADFROMFILE);
    189 
    190     POINT pt, lt, rb;
    191     RECT rect;
    192     // 设定光标位置
    193     pt.x = 300;
    194     pt.y = 100;
    195     // 将指定点或者矩形的用户坐标转换成屏幕坐标
    196     ClientToScreen(hwnd, &pt);
    197     SetCursorPos(pt.x, pt.y);
    198     // 隐藏鼠标光标
    199     ShowCursor(false);        
    200     // 限制鼠标光标移动区域
    201     // 取得窗口内部矩形
    202     GetClientRect(hwnd, &rect);  
    203     // 将矩形左上点坐标存入lt中
    204     lt.x = rect.left;
    205     lt.y = rect.top;
    206     // 将矩形右下坐标存入rb中
    207     rb.x = rect.right;
    208     rb.y = rect.bottom;
    209     // 将lt和rb的窗口坐标转换为屏幕坐标
    210     ClientToScreen(hwnd, &lt);
    211     ClientToScreen(hwnd, &rb);
    212     // 以屏幕坐标重新设定矩形区域
    213     rect.left = lt.x;
    214     rect.top = lt.y;
    215     rect.right = rb.x;
    216     rect.bottom = rb.y;
    217     // 限制鼠标光标移动区域
    218     ClipCursor(&rect);
    219 
    220     Game_Paint(hwnd);
    221     return TRUE;
    222 }
    223 
    224 VOID Game_Paint(HWND hwnd)
    225 {
    226     // 先在mdc中贴上背景图
    227     SelectObject(g_bufdc, g_hBackGround);
    228     // 将源矩形区域直接拷贝到目标矩形区域
    229     BitBlt(g_mdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_bufdc, 0, 0, SRCCOPY);
    230 
    231     // 按照目前的移动方向取出对应人物的连续走动图,并确定截取人物图的宽度与高度
    232     SelectObject(g_bufdc, g_hSprite[g_iDirection]);
    233     // 使用AND(与)操作符来将源和目标矩形区域内的颜色合并
    234     BitBlt(g_mdc, g_iX, g_iY, 60, 108, g_bufdc, g_iNum * 60, 108, SRCAND);
    235     // 使用布尔型的OR(或)操作符将源和目标矩形区域的颜色合并
    236     BitBlt(g_mdc, g_iX, g_iY, 60, 108, g_bufdc, g_iNum * 60, 0, SRCPAINT);
    237 
    238     // 计算人物2的贴图坐标,设定每次进行贴图时,其坐标(g_iXnow,g_iYnow)会以每20个单位慢慢向鼠标光标所在的目的点(x,y)接近,直到两个坐标相同为止
    239     if (g_iXnow < g_mouseX)
    240     {
    241         g_iXnow += 20;
    242         if (g_iXnow > g_mouseX)
    243             g_iXnow = g_mouseX;
    244     }
    245     else  
    246     {
    247         g_iXnow -= 20;
    248         if (g_iXnow < g_mouseX)
    249             g_iXnow = g_mouseX;
    250     }
    251 
    252     if (g_iYnow < g_mouseY)  
    253     {
    254         g_iYnow += 20;
    255         if (g_iYnow > g_mouseY)
    256             g_iYnow = g_mouseY;
    257     }
    258     else  
    259     {
    260         g_iYnow -= 20;
    261         if (g_iYnow < g_mouseY)
    262             g_iYnow = g_mouseY;
    263     }
    264     // 贴上人物2图
    265     SelectObject(g_bufdc, g_hMan);
    266     // 对指定的源设备环境中的矩形区域数据进行位块转换,并将结果置于目标设备环境
    267     TransparentBlt(g_mdc, g_iXnow, g_iYnow, 292, 190, g_bufdc, 0, 0, 292, 190, RGB(0, 0, 0));
    268 
    269     HFONT hFont;
    270     // 创建字体
    271     hFont = CreateFont(20, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("微软雅黑"));  
    272     SelectObject(g_mdc, hFont);
    273     // 设置文字背景透明
    274     SetBkMode(g_mdc, TRANSPARENT);
    275     // 设置文字颜色
    276     SetTextColor(g_mdc, RGB(255, 255, 0));  
    277     //在左上角进行文字输出
    278     wchar_t str[20] = {};
    279     swprintf_s(str, L"鼠标X坐标为%d", g_mouseX);
    280     TextOut(g_mdc, 0, 0, str, wcslen(str));
    281     swprintf_s(str, L"鼠标Y坐标为%d", g_mouseY);
    282     TextOut(g_mdc, 0, 20, str, wcslen(str));
    283 
    284     // 贴上背景图
    285     BitBlt(g_hdc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, g_mdc, 0, 0, SRCCOPY);
    286 
    287     // 记录此次绘图时间
    288     g_tPre = GetTickCount();
    289     // go1.bmp有8个人物1动作图,用来实现人物1运动
    290     g_iNum++;
    291     if (g_iNum == 8)
    292         g_iNum = 0;
    293 }
    294 
    295 BOOL Game_CleanUp(HWND hwnd)
    296 {
    297     // 释放资源对象
    298     DeleteObject(g_hBackGround);
    299     for (int i = 0; i<4; i++)
    300     {
    301         DeleteObject(g_hSprite[i]);
    302     }
    303     DeleteObject(g_hMan);
    304     DeleteDC(g_bufdc);
    305     DeleteDC(g_mdc);
    306     ReleaseDC(hwnd, g_hdc);
    307     return TRUE;
    308 }
  • 相关阅读:
    记一次笔试题
    模块模式浅析
    在windows上面实现ubuntu的三种方法
    移动端事件(五)—— 函数防抖和函数节流的封装
    一文分清强弱、动态静态类型语言
    为什么前端要学TypeScript
    OpenSSL SSL_read: Connection was reset, errno 10054
    浅悉http1.0 、http1.1和http2.0的区别
    上班一个月的总结
    从浅入深——理解JSONP的实现原理
  • 原文地址:https://www.cnblogs.com/ht-beyond/p/4445439.html
Copyright © 2020-2023  润新知