游戏开发笔记十三 游戏输入消息处理(二) 鼠标消息处理

2023-11-01

本系列文章由zhmxy555编写,转载请注明出处。 http://blog.csdn.net/zhmxy555/article/details/7405479

作者:毛星云    邮箱: happylifemxy@qq.com    欢迎邮件交流编程心得




上一节我们讲解了键盘消息处理相关的知识。键盘加鼠标作为目前人机交互方式依旧的主流,在讲完键盘消息处理之后接着讲鼠标消息处理,自然是理所当然的。


 这一节主要介绍各种鼠标消息的处理方式以及一些相关函数的运用方法,然后用一个小实例来巩固本节所学。


一,鼠标消息的处理方式


大家都知道,目前市场上主流鼠标规格为两个按键加上一个滚轮。那么,我们先列出Windows中这种鼠标设备输入时的消息:


WM_LBUTTONDBLCLK      双击鼠标左键消息

WM_LBUTTONDOWN       单击鼠标左键消息

WM_LBUTTONUP           松开鼠标左键消息

WM_MBUTTONDBLCLK     双击鼠标中键(滚轮)消息

WM_MBUTTONDOWN      单击鼠标中键(滚轮)消息

WM_MBUTTONUP          松开鼠标中键(滚轮)消息

WM_RBUTTONDBLCLK      双击鼠标右键消息

WM_RBUTTONDOWN       单击鼠标右键消息

WM_RBUTTONUP           松开鼠标右键消息

WM_MOUSEMOVE          鼠标移动消息

WM_MOUSEWHEEL         鼠标滚轮转动消息


处理鼠标消息的方法与处理键盘消息的方法类似,同样是在消息处理函数中加入要处理的鼠标消息类型,当鼠标消息发生时,输入的参数“wParam”与“lParam”则储存了鼠标状态的相关信息。




下面我们分别来展开讲解一下“wParam”与“lParam”参数以及滚轮消息。


<l>Param参数

lParam参数的值可分为高位字节与低位字节两个部分,其中高节部分储存的是鼠标光标所在的X坐标值,低位字节部分存储的则是鼠标光标所在的Y坐标值。

我们可以用下面两个函数来取得鼠标的坐标值:

WORD LOWORD(lParam参数);           //返回鼠标光标所在的X坐标值

WORD HIWORD(lParam参数);           //返回鼠标光标所在的Y坐标值

这两个两个函数所返回的鼠标光标位置的坐标是相对于内部窗口左上点坐标的。


<2>wParam参数

 "wParam"参数的值记录着鼠标按键及键盘【Ctrl】键与【Shift】键的状态信息,通过下面的这些定义在“WINUSER.H”中的测试标志与“wParam”参数来检查上述按键的按下状态。

MK_LBUTTON            按下鼠标右键

MK_MBUTTON           按下鼠标中(滚轮)键

MK_RBUTTON            按下鼠标右键

MK_SHIFT                按下【Shift】键

MK_CONTROL            按下【Ctrl】键

【例子1】例如某一鼠标消息发生时,要测试鼠标左键是否也被按下,程序代码如下:

  1. if(wParam & MK_LBUTTON)      //这里应该是按位与&,之前我写错了,谢谢 a443475601 的指出,  
  2. {  
  3. //鼠标左键被按下  
  4. }  



这是利用wParam参数与测试标志来测试鼠标键是否被按下的方法。当按键被按下时,条件式“wParam && MK_LBUTTON”所传回的结果会为“true”。当然,若消息函数接收到“WM_LBUTTONDOWN”消息,同样也可以知道鼠标键被按下而不必再去额外做这样的测试。

【例子2】如果要测试鼠标左键与【Shift】键的按下状态,那么程序代码如下:


  1. If(wParam & MK_LBUTTON)  
  2. {  
  3. If(wParam & MK_SHIFT)  
  4. {  
  5. //单击鼠标左键  
  6. //按下【Shift】键   
  7. }  
  8. else  
  9. {  
  10. //单击鼠标左键   
  11. //未按下【Shift】键  
  12. }  
  13. }  
  14. else  
  15. {  
  16. If(wParam & MK_SHIFT)  
  17. {  
  18. //未单击鼠标左键   
  19. //按下【Shift】键  
  20. }  
  21. else  
  22. {  
  23. //未单击鼠标左键  
  24. //未按下【Shift】键   
  25. }  
  26. }  

我们通过这个例子可以清楚,如何利用“wParam”参数与测试标志来测试鼠标键及【Shift】键和【Ctrl】键是否被按下的方法。


<3>滚轮消息

这里我们要特别提一下鼠标滚轮转动消息(WM_MOUSEWHEEL)。当鼠标滚轮转动消息发生时,“lParam”参数中的值同样是记录光标所在的位置的,而“wParam”参数则分为高位字节与低位字节两部分,低位字节部分跟前面一样是储存鼠标键与【Shift】【Ctrl】键的状态信息的,而高位字节部分的值会是“120”或“-120”。“120”表示鼠标滚轮向前转动,而“-120”则表示向后转动。


这里“wParam”高位组值与低位组值所在的函数同样是HIWORD( )与LOWORD( )。

HIWORD(wParam);//高位组,值为“120”或“-120”

LOWORD(wParam);//低位组,鼠标键及【Shift】和【Ctrl】键的状态信息



二,相关函数的讲解


对各种鼠标输入消息及鼠标状态信息的获取方法有了基本认识之后,下面我们将介绍一些游戏程序中以鼠标来做输出设备时常用到的函数。


1.获取窗口外鼠标消息的函数

为了确保程序可以正确地取得鼠标的输入消息,需要在必要的时候以下面的函数来设定窗口,以取得鼠标在窗口外所发出的消息。

HWND SetCapture(HWND hWnd) ;   //设定获取窗口外的鼠标消息

如果调用了上面的SetCapture( )函数,并输入要取得鼠标消息的窗口代号,那么便可取得鼠标在窗口外所发出的消息。这种方法也适用于多窗口的程序,与SetCapture( )函数相对应的函数为ReleaseCapture( )函数,用于释放窗口取得窗口外鼠标消息的函数。

BOOL ReleaseCapture(VOID);    //释放获取窗口外的鼠标消息


2.设定鼠标光标位置的函数

BOOL SetCursorPos(int X坐标,int Y坐标);     //设定鼠标光标位置

上面这个SetCursorPos()函数中所设定的坐标是相对于屏幕左上角的屏幕坐标而言。实际上,我们经常需要将这个屏幕坐标转换为游戏窗口中的游戏窗口坐标。因此需要用到API中的一个将窗口坐标转换到屏幕坐标的函数,即ClientToScreen()。

屏幕坐标和窗口坐标转换的函数

BOOL ClientToScreen(HWND hWnd,     //屏幕坐标转换为窗口坐标

LPPOINT lpPoint屏幕点坐标);

   同理,我们得到:

窗口坐标转换为屏幕坐标的函数:

BOOL ScreenToClient(   LPPOINT lpPoint窗口点坐标 )   //窗口坐标转换为屏幕坐标


3.显示与隐藏鼠标光标的函数

Int ShowCursor(BOOL true或flase);    //隐藏及显示鼠标光标

其中,true代表显示光标,false代表隐藏光标。


4.限制鼠标光标移动区域的函数

Windows API中提供的ClipCursor()函数可以用来设置限制鼠标光标的移动区域和解除鼠标光标移动区域的限制。

BOOL ClipCursor(CONST RECT 移动区域矩形);  //限制鼠标光标移动区域

BOOL ClipCursor(NOOL);                     //解除限制

这里有一个RECT移动区域矩形,我们在MSDN中找出它的声明:

  1. typedef struct tagRECT {   
  2.         LONG left;  //矩形区域右上点X坐         
  3.      LONG top;  //矩形区域右上点Y坐标  
  4.         LONG right;  //矩形区域左上点X坐标  
  5.         LONG bottom;  //矩形区域左上点Y坐标  
  6. } RECT;  


5.取得窗口外部区域及内部区域的API函数

我们还需知道取得窗口外部区域及内部区域的API函数。

BOOL GetWindowRect(HWND hWND,LPRECT 矩形结构);//取得窗口外部区域矩形

BOOL GetClientRect(HWND hWnd,LPRECT 矩形结构体); //取得窗口内部区域矩形

这里需要注意的是,GetWindowRect()返回的坐标类型是屏幕坐标。

       GetClientRect()返回的坐标类型是窗口坐标。

由于限制鼠标光标移动区域的ClipCursor()函数中输入的矩形区域必须是屏幕坐标,因此如果取得的是窗口内部区域,那么还必须将窗口坐标转换为屏幕坐标的操作,下面我们以一段程序代码来说明将鼠标光标限制在窗口内部区域移动的过程:

  1. RECT rect;  
  2. POINT lt,rb;  
  3. GetClientRect(hWnd,&rect);  //取得窗口内部矩形  
  4. //将矩形左上点坐标存入lt中  
  5. lt.x = rect.left;  
  6. lt.y = rect.top;  
  7. //将矩形右下坐标存入rb中  
  8. rb.x = rect.right;  
  9. rb.y = rect.bottom;  
  10. //将lt和rb的窗口坐标转换为屏幕坐标  
  11. ClientToScreen(hWnd,<);  
  12. ClientToScreen(hWnd,&rb);  
  13. //以屏幕坐标重新设定矩形区域  
  14. rect.left = lt.x;  
  15. rect.top = lt.y;  
  16. rect.right = rb.x;  
  17. rect.bottom = rb.y;  
  18. //限制鼠标光标移动区域   
  19. ClipCursor(&rect);  



三,在实例中融会贯通


讲了这么多的windows API函数了,也早该到了我们的showtime了,依然,我们通过一个实例来把本节所讲的内容融会贯通。

这个实例处理鼠标移动消息使飞机在窗口中移动,并且处理单击鼠标左键消息来让飞机发射子弹,而且设定了鼠标光标的位置,隐藏了鼠标光标,还有限制了鼠标光标移动的区域。(背景贴图采用循环背景滚动,其实很简单,就是每次都把窗口右边多余的部分再贴到窗口坐标来,以后有机会我会作为一节笔记具体讲)


同样的,我们贴出详细注释好的代码:


  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3.   
  4. //定义结构体   
  5. struct BULLET       //bullet结构体代表飞机子弹  
  6. {  
  7.     int x,y;        //子弹坐标  
  8.     bool exist;     //子弹是否存在  
  9. };  
  10.   
  11. //全局变量声明  
  12. HINSTANCE hInst;  
  13. HBITMAP bg,ship,bullet;     //存储背景图,飞机图,子弹图  
  14. HDC     hdc,mdc,bufdc;  
  15. HWND    hWnd;  
  16. DWORD   tPre,tNow;  
  17. int     x,y,nowX,nowY;    //x,y代表鼠标光标所在位置,nowX,nowY代表飞机坐标,也是贴图的位置  
  18. int     w=0,bcount;       //w为滚动背景所要裁剪的区域宽度,bcount记录飞机现有子弹数目  
  19. BULLET  b[30];           //声明一个“bullet”类型的数组,用来存储飞机发出的子弹  
  20.   
  21. //全局函数声明  
  22. ATOM                MyRegisterClass(HINSTANCE hInstance);  
  23. BOOL                InitInstance(HINSTANCEint);  
  24. LRESULT CALLBACK    WndProc(HWNDUINTWPARAMLPARAM);  
  25. void                MyPaint(HDC hdc);  
  26.   
  27. //****WinMain函数,程序入口点函数**************************************  
  28. int APIENTRY WinMain(HINSTANCE hInstance,  
  29.                      HINSTANCE hPrevInstance,  
  30.                      LPSTR     lpCmdLine,  
  31.                      int       nCmdShow)  
  32. {  
  33.     MSG msg;  
  34.   
  35.     MyRegisterClass(hInstance);  
  36.   
  37.     //初始化  
  38.     if (!InitInstance (hInstance, nCmdShow))   
  39.     {  
  40.         return FALSE;  
  41.     }  
  42.   
  43.     //消息循环  
  44.      GetMessage(&msg,NULL,NULL,NULL);            //初始化msg      
  45.     while( msg.message!=WM_QUIT )  
  46.     {  
  47.         if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )  
  48.         {  
  49.             TranslateMessage( &msg );  
  50.             DispatchMessage( &msg );  
  51.         }  
  52.         else  
  53.         {  
  54.             tNow = GetTickCount();  
  55.             if(tNow-tPre >= 40)  
  56.                 MyPaint(hdc);  
  57.         }  
  58.     }  
  59.   
  60.     return msg.wParam;  
  61. }  
  62.   
  63. //****设计一个窗口类,类似填空题,使用窗口结构体*********************  
  64. ATOM MyRegisterClass(HINSTANCE hInstance)  
  65. {  
  66.     WNDCLASSEX wcex;  
  67.   
  68.     wcex.cbSize = sizeof(WNDCLASSEX);   
  69.     wcex.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;  
  70.     wcex.lpfnWndProc    = (WNDPROC)WndProc;  
  71.     wcex.cbClsExtra     = 0;  
  72.     wcex.cbWndExtra     = 0;  
  73.     wcex.hInstance      = hInstance;  
  74.     wcex.hIcon          = NULL;  
  75.     wcex.hCursor        = NULL;  
  76.     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  77.     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  
  78.     wcex.lpszMenuName   = NULL;  
  79.     wcex.lpszClassName  = "canvas";  
  80.     wcex.hIconSm        = NULL;  
  81.   
  82.     return RegisterClassEx(&wcex);  
  83. }  
  84.   
  85. //****初始化函数*************************************  
  86. // 1.设定飞机初始位置   
  87. // 2.设定鼠标光标位置及隐藏  
  88. // 3.限制鼠标光标移动区域  
  89. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)  
  90. {  
  91.     HBITMAP bmp;  
  92.     POINT pt,lt,rb;  
  93.     RECT rect;  
  94.   
  95.     hInst = hInstance;  
  96.   
  97.     hWnd = CreateWindow("canvas""绘图窗口" , WS_OVERLAPPEDWINDOW,  
  98.         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);  
  99.   
  100.     if (!hWnd)  
  101.     {  
  102.         return FALSE;  
  103.     }  
  104.   
  105.     MoveWindow(hWnd,10,10,640,480,true);  
  106.     ShowWindow(hWnd, nCmdShow);  
  107.     UpdateWindow(hWnd);  
  108.   
  109.     hdc = GetDC(hWnd);  
  110.     mdc = CreateCompatibleDC(hdc);  
  111.     bufdc = CreateCompatibleDC(hdc);  
  112.   
  113.     bmp = CreateCompatibleBitmap(hdc,640,480);  
  114.     SelectObject(mdc,bmp);  
  115.   
  116.     bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,648,480,LR_LOADFROMFILE);  
  117.     ship = (HBITMAP)LoadImage(NULL,"ship.bmp",IMAGE_BITMAP,100,148,LR_LOADFROMFILE);  
  118.     bullet = (HBITMAP)LoadImage(NULL,"bullet.bmp",IMAGE_BITMAP,10,20,LR_LOADFROMFILE);  
  119.       
  120.     //设定鼠标光标的x,y值,并设定飞机贴图坐标的“nowX”和“nowY”的值为(300,300)  
  121.     x = 300;  
  122.     y = 300;  
  123.     nowX = 300;  
  124.     nowY = 300;  
  125.   
  126.     //设定光标位置   
  127.     pt.x = 300;  
  128.     pt.y = 300;  
  129.     ClientToScreen(hWnd,&pt);  
  130.     SetCursorPos(pt.x,pt.y);  
  131.       
  132.     ShowCursor(false);      //隐藏鼠标光标  
  133.   
  134.     //限制鼠标光标移动区域  
  135.     GetClientRect(hWnd,&rect);  //取得窗口内部矩形  
  136.     //将矩形左上点坐标存入lt中  
  137.     lt.x = rect.left;  
  138.     lt.y = rect.top;  
  139.     //将矩形右下坐标存入rb中  
  140.     rb.x = rect.right;  
  141.     rb.y = rect.bottom;  
  142.     //将lt和rb的窗口坐标转换为屏幕坐标  
  143.     ClientToScreen(hWnd,<);  
  144.     ClientToScreen(hWnd,&rb);  
  145.     //以屏幕坐标重新设定矩形区域  
  146.     rect.left = lt.x;  
  147.     rect.top = lt.y;  
  148.     rect.right = rb.x;  
  149.     rect.bottom = rb.y;  
  150.     //限制鼠标光标移动区域  
  151.     ClipCursor(&rect);  
  152.   
  153.     MyPaint(hdc);  
  154.   
  155.     return TRUE;  
  156. }  
  157.   
  158. //****自定义绘图函数*********************************  
  159. // 1.设定飞机坐标并进行贴图  
  160. // 2.设定所有子弹坐标并进行贴图  
  161. // 3.显示真正的鼠标光标所在坐标  
  162. void MyPaint(HDC hdc)  
  163. {  
  164.     char str[20] = "";  
  165.     int i;  
  166.   
  167.     //贴上背景图  
  168.     SelectObject(bufdc,bg);  
  169.     BitBlt(mdc,0,0,w,480,bufdc,640-w,0,SRCCOPY);  
  170.     BitBlt(mdc,w,0,640-w,480,bufdc,0,0,SRCCOPY);  
  171.       
  172.     //计算飞机的贴图坐标,设定每次进行飞机贴图时,其贴图坐标(nowX,nowY)会以10个单位慢慢向鼠标光标所在的目的点(x,y)接近,直到两个坐标相同为止  
  173.     if(nowX < x)  
  174.     {  
  175.         nowX += 10;  
  176.         if(nowX > x)  
  177.             nowX = x;  
  178.     }  
  179.     else  
  180.     {  
  181.         nowX -=10;  
  182.         if(nowX < x)  
  183.             nowX = x;  
  184.     }  
  185.   
  186.     if(nowY < y)  
  187.     {  
  188.         nowY += 10;  
  189.         if(nowY > y)  
  190.             nowY = y;  
  191.     }  
  192.     else  
  193.     {  
  194.         nowY -= 10;  
  195.         if(nowY < y)  
  196.             nowY = y;  
  197.     }  
  198.   
  199.     //贴上飞机图  
  200.     SelectObject(bufdc,ship);  
  201.     BitBlt(mdc,nowX,nowY,100,74,bufdc,0,74,SRCAND);  
  202.     BitBlt(mdc,nowX,nowY,100,74,bufdc,0,0,SRCPAINT);  
  203.   
  204.     //子弹的贴图,先判断子弹数目“bcount”的值是否为“0”。若不为0,则对子弹数组中各个还存在的子弹按照其所在的坐标(b[i].x,b[i].y)循环进行贴图操作  
  205.     SelectObject(bufdc,bullet);  
  206.     if(bcount!=0)  
  207.         for(i=0;i<30;i++)  
  208.             if(b[i].exist)  
  209.             {  
  210.                 //贴上子弹图  
  211.                 BitBlt(mdc,b[i].x,b[i].y,10,10,bufdc,0,10,SRCAND);  
  212.                 BitBlt(mdc,b[i].x,b[i].y,10,10,bufdc,0,0,SRCPAINT);  
  213.   
  214.                 //设置下一个子弹的坐标。子弹是又右向左发射的,因此,每次其X轴上的坐标值递减10个单位,这样贴图会产生往左移动的效果。而如果子弹下次的坐标已超出窗口的可见范围(h[i].x<0),那么子弹设为不存在,并将子弹总数bcount变量值减1.  
  215.                 b[i].x -= 10;  
  216.                 if(b[i].x < 0)  
  217.                 {  
  218.                     bcount--;  
  219.                     b[i].exist = false;  
  220.                 }  
  221.             }  
  222.   
  223.     //显示鼠标坐标  
  224.     sprintf(str,"鼠标X坐标为%d    ",x);  
  225.     TextOut(mdc,0,0,str,strlen(str));  
  226.     sprintf(str,"鼠标Y坐标为%d    ",y);  
  227.     TextOut(mdc,0,20,str,strlen(str));  
  228.   
  229.     BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);  
  230.   
  231.     tPre = GetTickCount();  
  232.   
  233.     w += 10;  
  234.     if(w==640)  
  235.         w = 0;  
  236. }  
  237.   
  238. //****消息处理函数***********************************  
  239. // 1.处理WM_LBUTTONDOWN消息发射子弹  
  240. // 2.处理WM_MOUSEMOVE消息设定飞机贴图坐标  
  241. // 3.在窗口结束时恢复鼠标移动区域  
  242. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
  243. {  
  244.     int i;  
  245.   
  246.     switch (message)  
  247.     {  
  248.         case WM_KEYDOWN:                //按键按下消息  
  249.             if(wParam==VK_ESCAPE)       //按下【Esc】键  
  250.                 PostQuitMessage(0);  
  251.             break;  
  252.         case WM_LBUTTONDOWN:            //单击鼠标左键消息  
  253.             for(i=0;i<30;i++)  
  254.             {  
  255.                 if(!b[i].exist)  
  256.                 {  
  257.                     b[i].x = nowX;      //子弹x坐标  
  258.                     b[i].y = nowY + 30; //子弹y坐标  
  259.                     b[i].exist = true;  
  260.                     bcount++;           //累加子弹数目  
  261.                     break;  
  262.                 }  
  263.             }  
  264.         case WM_MOUSEMOVE:  
  265.             x = LOWORD(lParam);         //取得鼠标X坐标  
  266.             if(x > 530)                  //设置临界坐标  
  267.                 x = 530;  
  268.             else if(x < 0)  
  269.                 x = 0;  
  270.   
  271.             y = HIWORD(lParam);         //取得鼠标y坐标  
  272.             if(y > 380)  
  273.                 y = 380;  
  274.             else if(y < 0)  
  275.                 y = 0;  
  276.                   
  277.             break;  
  278.         case WM_DESTROY:                //窗口结束消息  
  279.             ClipCursor(NULL);           //恢复鼠标移动区域  
  280.   
  281.             DeleteDC(mdc);  
  282.             DeleteDC(bufdc);  
  283.             DeleteObject(bg);  
  284.             DeleteObject(bullet);  
  285.             DeleteObject(ship);  
  286.             ReleaseDC(hWnd,hdc);  
  287.   
  288.             PostQuitMessage(0);  
  289.             break;  
  290.         default:                        //其他消息  
  291.             return DefWindowProc(hWnd, message, wParam, lParam);  
  292.    }  
  293.    return 0;  
  294. }  


下面是这个例子的效果图:





我们移动鼠标,小飞机会跟着鼠标的移动而移动;点击鼠标,小飞机就会发射出绿色的子弹来;按下Esc键,这个小游戏就退出了。



当然,这个小游戏还有些的不足,比如小飞机对鼠标的跟随有小小的延迟,也没有进行WndProc函数中case分支的拆分(在这里感谢yao050421103的提醒)。

关于这个小游戏的改进,是以后我们需要去做的。比如后面我们会找机会用DirectX中的DirectInput函数(也是处理输出消息的函数)来写一下这个小游戏的升级版,无论是画面上还是实现效果上都将进行升级。



在之前的笔记里有朋友(感谢pxg789的提醒)提到,用MFC和ATL共享的新类CImage进行贴图会更加简单和先进,在这里说明一下,在后面的笔记里面会专门花一节来讲CImage类,目前和之前的笔记还是采用传统的GDI进行贴图操作。



笔记十三到这里就结束了。

本节笔记的源代码请点击这里下载:   【Visual C++】Code_Note_13


感谢一直支持【Visual C++】游戏开发笔记系列专栏的朋友们,也请大家继续关注我的专栏,我一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。


精通游戏开发的路还很长很长,非常希望能和大家一起交流,共同学习,共同进步。



大家看过后觉得值得一看的话,可以顶一下这篇文章,让更多的朋友有机会看到它。

如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。

最后,谢谢你们一直的支持~~~


The end.


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

游戏开发笔记十三 游戏输入消息处理(二) 鼠标消息处理 的相关文章

  • Java - 调整图像大小而不损失质量

    我有 10 000 张照片需要调整大小 因此我有一个 Java 程序来执行此操作 不幸的是 图像的质量损失很大 而且我无法访问未压缩的图像 import java awt Graphics import java awt AlphaComp
  • 如何使用Android opencv使图像的白色部分透明

    我无法链接超过 2 个网址 因此我将我的照片发布到此博客 请在这里查看我的问题 http blog naver com mail1001 220650041897 http blog naver com mail1001 220650041
  • 如何使使用 css 调整大小的图像在 IE 中看起来不错?

    当使用 css 宽度 高度或属性宽度 高度缩放图像时 IE6 和 IE7 无法很好地缩放网页中的图像 我不确定它默认使用哪种算法 但这不好 在这些浏览器中缩放时 缩放图像会显示锯齿伪影 幸运的是 有一种方法可以通过简单的 css 规则强制
  • react-native - 图像需要来自 JSON 的本地路径

    你好社区 我正在react native中开发一个测试应用程序 并尝试从本地存储位置获取图像 我实际在做什么 我将图像直接链接源提供给 var 并在渲染函数中调用此方法 react 0 14 8 react native 0 23 1 np
  • JavaFX ImageView 未更新

    因此 我尝试将图像加载并保存到 imageView 中 其中图像的位置是通过文件浏览器选择的 我已经为此工作好几天了 如果我不能解决这个问题 我就会中风 我已经尝试了我能想到的一切 预先感谢您的帮助 UPDATED 这是我的主要课程 pub
  • flutter应用程序中有图像编辑器的api吗?我需要在图像中添加文本

    是否可以编辑图像 例如旋转以及在图像上添加文本 有没有什么插件可以做到这一点 我需要一个图像编辑器来添加具有各种字体和颜色的文本 谢谢 你应该使用重画边界 https docs flutter io flutter widgets Repa
  • 如何在wpf中翻转图像

    我最近学习了如何使用 TransformedBitmap 和 RotateTransformed 类旋转 BitmapImage 现在我可以对图像进行顺时针旋转 但如何翻转图像呢 我找不到执行 BitmapImage 水平和垂直翻转的类 请
  • 如果没有找到值,如何让 MySQL 中的 SUM 函数返回“0”?

    假设我在 MySQL 中有一个简单的函数 SELECT SUM Column 1 FROM Table WHERE Column 2 Test 如果没有条目Column 2 包含文本 Test 然后该函数返回NULL 而我希望它返回 0 我
  • 如何将 .ashx 处理程序与 asp:Image 对象一起使用?

    我有一个 ashx 处理程序 using System using System Web public class Thumbnail IHttpHandler public void ProcessRequest HttpContext
  • 响应式 CSS 图像锚点标签 - 图像地图样式

    我一直在开发一个响应式网站 并且在图像映射方面遇到了一些问题 图像映射似乎不适用于基于百分比的坐标 经过一番谷歌搜索后 我发现了一个 JS 解决方法 http mattstow com experiment responsive image
  • Java元数据读写

    是否可以以通用方式 对于所有图像类型 在 Java 中读取和写入元数据 我找到了一些示例 但它们总是特定的 例如 JPEG 或 PNG 我需要一些足够通用的东西 而不是到处都有 if else 语句 我不想重写源代码 但这是一个很好的例子
  • 如何从 SQL Server 2008 查询结果中删除“NULL”

    我有一个包含 59 列和超过 17K 行的表 很多行都有NULL在某些列中 我想删除NULL以便查询返回空白 而不是NULL 我可以运行一些更新功能来替换所有NULL with 使用 SQL Server 2008R2 Management
  • Avro ENUM 字段

    我正在尝试在 Avro 模式中创建 Union 字段并用它发送相应的 JSON 消息 但要拥有其中一个字段 null https avro apache org docs 1 8 2 spec html Unions https avro
  • 可以使用 jQuery 或 Javascript 将图片的特定部分用作链接吗?

    我有这个想法 将图片 而不是文本 的各个部分链接到不同的页面或网站 并且我想在不实际创建不同的照片并将它们彼此靠近的情况下完成 这样看起来就像是一张完整的图片 这里有人知道如何使用 JavaScript 的变体 例如 jQuery 或纯 J
  • SwiftUI 全屏图像背景

    我想在背景中显示全屏图像 我已经实现了这个 struct LoginView View var body some View VStack Spacer Text Hallo Text Hallo2 Text Hallo2 Text Hal
  • 有没有一种简单的方法(工具?)来比较不同格式的图像像素?

    好吧 我现在已经用 java 编写了一个基本的无损 jpeg 连接器 但我想将它生成的文件与原始文件进行比较 我只能在十六进制编辑器中比较这么多 有谁知道一种简单的方法 基于软件或基于java 最好是软件 因为我现在不想再编码了 我可以比较
  • OpenCV:RGB 到 YUV 转换,并显示维基百科等通道

    我一直在寻找这种转换有一段时间了 在Linux上使用Python将RGB图像转换为YUV图像并访问Y U和V通道有哪些方法 使用 opencv skimage 等 更新 我用的是opencv img yuv cv2 cvtColor ima
  • 在opencv中将三个灰度[R,G,B]图像合并为单个彩色图像

    我有 3 个使用 split 函数创建的灰度图像 现在我想重新生成彩色图像 我尝试了以下代码 但它不起作用 我得到的结果图像仍然是灰度的 cv Mat R cv imread home r secret R png 0 cv Mat G c
  • 带有 Null 的 Soap WSDL

    我需要在函数中指定一个可为空的参数 这不起作用
  • 从服务器下载图像(cUrl,但接受建议)C++

    我试图通过从服务器 网站 下载图像来设置旋转背景图像 并尝试使用curl 来执行此操作 但是在执行此操作方面取得了0 成功 我的代码的 缩短的 版本如下 我没有收到错误 但是 如何 临时 保存该图像以将其显示为背景 是否有图像 类型变量 或

随机推荐

  • Android项目工程结构介绍

    Android项目工程结构介绍 1 gradle和 idea Android Studio自动生成的文件 打包的时候一般会删掉再进行打包 2 app 项目的代码资源都在其中 也是我们工作的核心目录 build 编译生成文件 生成的apk就在
  • Scroller与computeScroll处理滑动

    背景 最近在纯手写一个 slidingMenu 里面用到了 Scroller与computeScroll处理滑动 由于我也是第一次遇到这种东西 我这暴脾气 实在忍不住要记住一下 以供大家参考 更重要的是方便自己以后回忆 知识点讲解 实现滚动
  • 01_08_桶排序(Bucket Sort)

    桶排序 Bucket Sort 桶排序 Bucket Sort 介绍 是一种排序算法 适用于数据范围较小且分布均匀的浮点数数据 它将待排序序列划分为若干个桶 区间 对每个桶中的元素进行排序 然后按顺序合并所有桶的元素得到最终有序序列 桶排序
  • RFID 复杂事件检测算法-毕业论文

    摘 要 本论文首先介绍了RFID技术的概念 工作原理 发展过程 应用背景等信息 然后对本系统所需的硬件条件 即RFID阅读器的特性和配置等信息进行说明 接下来介绍了基于RFID的仓储管理系统的开发背景 探讨了数据库的功能特点 做出了系统需求
  • shell grep 详解说明,实战造就英雄,苦练成就神话

    shell grep 详解说明 当您使用Shell中的grep命令时 它允许您在文本文件或标准输入中搜索匹配某个模式的行 并输出结果 下面是grep命令的详细说明和参数介绍表格 参数 描述 i 忽略大小写进行匹配 默认情况下 grep区分大
  • 制作cmd小游戏_小伙利用Python自制一个推箱子小游戏!

    导语 月初更波python制作小游戏系列吧用python写了个推箱子小游戏 在这里分享给大家 让我们愉快地开始吧 小伙利用Python自制一个推箱子小游戏 开发工具 Python版本 3 6 4 相关模块 pygame模块 以及一些Pyth
  • [转]QT中窗口刷新事件的学习总结

    QT中窗口刷新事件的学习总结 一 主要理解一下几个方法和属性 1 QWidget QScrollView viewport const 2 void QWidget paintEvent QPaintEvent 虚 保护 3 void QW
  • Hive 窗口函数大全

    目录 窗口函数概述 窗口序列函数 row number dense rank 窗口边界 滑动窗口 lag 获取上一行数据 lead 获取下一行数据 窗口专用计算函数 sum累加函数 max最大值 min最小值 avg平均值 count累计次
  • vue的组件通信方法(9种)

    1 传 在 组件的标签上定义属性 组件通过props来进 接收 可以通过数组或者对象的 式接收 如果 组件没有传递属性 组件可以default来设置默认值 父传子的使用场景 封装列表的时候 把数据传到子组件渲染 2 传 组件通过this e
  • 深度学习(30)—— DeformableDETR(1)

    深度学习 30 DeformableDETR 1 原本想在一篇文章中就把理论和debug的过程都呈现 但是发现内容很多 所以就分开两篇 照常先记录理论学习过程 然后是实践过程 注 大家一定不要看过理论就完事儿了 去扣代码 看人家怎么完成的
  • qt5.6.0 opengl —— 纹理贴图

    对于CUBE这个例子 之前分析了它的框架 至于图怎么弄上去的还怎么细看 现在尝试弄了一下 首先分析它怎么对应的 原本是一张图 怎么分成六面的 于是像高中时代那样开始了计算理解 这样就清楚多了 一张图 划分为6个块 一个面一块 至于归一化 可
  • k8s如何对外公布一个应用程序

    一 Kubernetes Service 服务 概述 事实上 Pod 容器组 有自己的 生命周期 opens new window 当 worker node 节点 故障时 节点上运行的 Pod 容器组 也会消失 然后 Deployment
  • Spring Security快速入门

    Spring Security是一个框架 提供 认证 authentication 授权 authorization 和 保护 以抵御常见的攻击 它对保护命令式和响应式应用程序有一流的支持 是保护基于Spring的应用程序的事实标准 spr
  • Java中的集合及深拷贝与浅拷贝

    Java中的集合及深拷贝与浅拷贝 Java是一种面向对象的编程语言 其中集合是常用的数据结构之一 具有方便快捷的特点 在Java开发中 我们常常需要对集合进行复制 拷贝 操作 但是 拷贝操作并不是简单的复制 而应该分为浅拷贝和深拷贝两种不同
  • MySQL学习笔记1:MySQL字符集和字符集编码

    MySQL学习笔记索引 MySQL学习笔记1 MySQL字符集和字符集编码 MySQL学习笔记2 如何避免数据库乱码 MySQL学习笔记3 排序规则和排序规则的影响 MySQL学习笔记4 排序规则的修改 文章目录 一 基本概念 二 mysq
  • 【学习笔记】应用与编排管理:Deployment

    学习笔记 应用与编排管理 Deployment 需求来源 背景问题 Deployment 管理部署发布的控制器 架构设计 管理模式 Deployment 控制器 ReplicaSet 控制器 发布模拟 spec 字段解析 升级策略字段解析
  • 闭包使用的3种情景

    定义 通俗讲 闭包是函数里面再定义一个函数 里层函数能访问到外层函数的局部变量 也就是说闭包是一个能访问外层函数局部变量的函数 常用情景有以下3种 1 在window下有个全局变量a 在函数checkScope内部有个局部变量a 需求 在w
  • Parkour World 游戏内测攻略详解

    Parkour World 是一款将赛博朋克风格与跑酷元素结合的运动类PC端游戏 玩家通过在虚拟世界中进行跑酷 从而获取相应的奖励 Parkour World结合区块链技术 采用保值NFT以及独特的3token Arb Hood Yuri
  • Spring源码分析(七)Bean生命周期源码解析5:Bean的销毁

    Bean的销毁过程 应用场景 通过实现DisposableBean接口 或者使用注解 PreDestroy都行 Component public class OrderService implements DisposableBean pu
  • 游戏开发笔记十三 游戏输入消息处理(二) 鼠标消息处理

    本系列文章由zhmxy555编写 转载请注明出处 http blog csdn net zhmxy555 article details 7405479 作者 毛星云 邮箱 happylifemxy qq com 欢迎邮件交流编程心得 上一