加载中…
个人资料
jh_saya
jh_saya
  • 博客等级:
  • 博客积分:0
  • 博客访问:29,708
  • 关注人气:7
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

GDI编程3(键盘/鼠标)

(2012-03-26 12:32:04)
标签:

附加信息

消息

键盘

处理

函数

分类: GDI/GDI+/DX图像学

键盘消息

  1. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){}

消息处理函数常见的键盘处理消息(message)有3种:

  1. WM_KEYDOWN     // 按下按键消息
  2. WM_KEYUP       // 松开按键消息
  3. WM_CHAR        // 字符消息

处理按下按键消息时如果判断按下的是哪个键可以由附加信息wParam得知.例子:

  1. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3.     switch (message)
  4.     {
  5.         case WM_KEYDOWN:          // 按下键盘消息
  6.             switch (wParam)
  7.             {
  8.                 case VK_ESCAPE:   // 按下Esc键
  9.                     break;
  10.                 case VK_UP:       // 按下↑键
  11.                     break;
  12.             }
  13.             break;
  14.         case WM_DESTROY:         // 窗口结束消息
  15.             PostQuitMessage(0);
  16.             break;
  17.         default:                 // 其他消息
  18.             return DefWindowProc(hWnd, message, wParam, lParam);
  19.     }
  20.     return 0;
  21. }

--------------------------------------------------------------------------------------------------

鼠标消息

message:

  1. WM_LBUTTONDBLCLK     // 双击鼠标左键消息
  2. WM_LBUTTONDOWN       // 单击鼠标左键消息
  3. WM_LBUTTONUP         // 松开鼠标左键消息
  4. WM_MBUTTONDBLCLK     // 双击鼠标中键消息
  5. WM_MBUTTONDOWN       // 单击鼠标中键消息
  6. WM_MBUTTONUP         // 松开鼠标中键消息
  7. WM_RBUTTONDBLCLK     // 双击鼠标右键消息
  8. WM_RBUTTONDOWN       // 单击鼠标右键消息
  9. WM_RBUTTONUP         // 松开鼠标右键消息
  10. WM_MOUSEMOVE         // 鼠标移动消息
  11. WM_MOUSEWHEEL        // 鼠标中键转动消息

lParam参数的值可分为高位字节与低位字节两个部分,其中高位字节部分存储的是鼠标光标所在的X坐标值,低位字节部分存储的则是鼠标光标所在的Y坐标值.可以用下面的这两个函数来取得鼠标的坐标值:

  1. LOWORD(lParam);   // 返回鼠标光标所在的X坐标值
  2. HIWORD(lParam);   // 返回鼠标光标所在的Y坐标值

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

  1. // 测试标志
  2. MK_LBUTTON     // 按下鼠标左键
  3. MK_RBUTTON     // 按下鼠标中键
  4. MK_MBUTTON     // 按下鼠标右键
  5. MK_SHIFT       // 按下Shift键
  6. MK_CONTROL     // 按下Ctrl键

在某一鼠标消息发生时,要测试以上按键是否也被按下,例子:

  1. if(wParam && MK_LBUTTON)
  2. {
  3.     ......  // 鼠标左键被按下
  4. }

WM_MOUSEWHEEL鼠标中键(滚轮)转动消息发生时,wParam参数分成高位字节与低位字节两部分.低位字节和上面一样记录着鼠标按键及键盘Ctrl键和Shift键的状态信息,而高位字节的值是"120"或"-120"."120"表示鼠标中键向前转动,"-120"表示向后转动.可以用下面的这两个函数来取得组值:

  1. LOWORD(wParam);   // 高位组,值为"120"或"-120"
  2. HIWORD(wParam);   // 低位组,鼠标键及Ctrl和Shift键的状态信息

--------------------------------------------------------------------------------------------------

鼠标相关函数

获取窗口外鼠标消息:

  1. HWND SetCapture(HWND hWnd);   // 设定获取窗口外的鼠标消息
  2. BOOL ReleaseCapture(VOID);    // 释放获取窗口外的鼠标消息

设定鼠标光标位置:

  1. BOOL SetCursorPos(int x, int y);    // 设定鼠标光标位置(相对屏幕左上角坐标)

但屏幕左上角坐标不一定和窗口左上角坐标相同,可以用下面一个函数转换:

  1. BOOL ClientToScreen(HWND hWnd, LPPOINT lpPoint);   // 窗口坐标转换为屏幕坐标

例子:

  1. POINT pt;
  2. pt.x = 0;
  3. pt.y = 0;
  4. ClientToScreen(hWnd, &pt);  // pt的坐标值转换成屏幕坐标值
  5. SetCursorPos(pt.x, pt.y)    // 设定鼠标光标位置

另外还有一个将屏幕坐标转换为窗口坐标的函数:

  1. BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint);   // 屏幕坐标转换为窗口坐标

显示与隐藏鼠标光标函数:

  1. int ShowCursor(BOOL true或false);    // true表示显示鼠标光标,false表示隐藏

限制鼠标光标移动区域:

  1. BOOL ClipCursor(COMST RECT *lpRect);    // 限制鼠标光标移动区域
  2. BOOL ClipCursor(NULL);                  // 解除限制 

上面光标移动区域类型RECT的结构为:

  1. typedef struct tagRECT{
  2. LONG left;     // 左
  3. LONG top;      // 顶
  4. LONG right;    // 右
  5. LONG bottom;   // 底
  6. }RECT;

取得窗口区域的函数: 

  1. BOOL GetWindowRect(HWND hWnd, LPRECT lpRect);    // 取得窗口外部区域矩形
  2. BOOL GetClientRect(HWND hWnd, LPRECT lpRect);    // 取得窗口内部区域矩形 

由于ClipCursor()函数限制的区域必须是屏幕坐标,因此如果取得的是窗口内部区域,还必须进行窗口坐标转换成屏幕坐标操作:

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

--------------------------------------------------------------------------------------------------

射击游戏(背景滚动+动画跟随鼠标+子弹动画)例子: 

  1. // 全局变量
  2. int X,Y,nowX,nowY;   // 鼠标位置X,Y.动画位置nowX,nowY
  3. struct BULLET        // 子弹结构
  4. {
  5.     int x,y;         // 子弹坐标
  6.     bool exist;      // 子弹存在标志
  7. }b[5];               // 子弹数组

 

  1. void update_bg_gif_b(HDC hdc) // 更新背景滚动+动画跟随鼠标
  2. {
  3.     // 声明
  4.     HDC mdc,mdc_all;
  5.     HBITMAP hbmp_bg,hbmp_gif,hbmp_b,hbmp_all;
  6.     static int bg_x,gif_i;
  7.     int i;
  8.     float moveX,moveY,moveX_ratio,moveY_ratio;
  9.     moveX = X-nowX;
  10.     moveY = Y-nowY;
  11.     if(moveX<0)
  12.         moveX *= (-1);
  13.     if(moveY<0)
  14.         moveY *= (-1);
  15.     // 创建DC
  16.     mdc = CreateCompatibleDC(hdc);
  17.     mdc_all = CreateCompatibleDC(hdc);
  18.     // 创建位图对象
  19.     hbmp_bg = (HBITMAP)LoadImage(NULL, "bj.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  20.     hbmp_gif = (HBITMAP)LoadImage(NULL, "gif.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  21.     hbmp_b = (HBITMAP)LoadImage(NULL, "b.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  22.     hbmp_all = CreateCompatibleBitmap(hdc, 640, 480);
  23.     // 贴图
  24.     SelectObject(mdc_all, hbmp_all);
  25.     SelectObject(mdc, hbmp_bg);
  26.     BitBlt(mdc_all, -bg_x, 0, 640, 480, mdc, 0, 0, SRCCOPY);
  27.     BitBlt(mdc_all, 640-bg_x, 0, 640, 480, mdc, 0, 0, SRCCOPY);
  28.     if(nowX != X)
  29.     {
  30.         if(nowX < X)
  31.         {
  32.             moveX_ratio = moveX/moveY;
  33.             if(moveX_ratio < 1)
  34.                 nowX += moveX_ratio * 10;
  35.             else
  36.                 nowX += 10;
  37.             if(nowX > X)
  38.                 nowX = X;
  39.         }
  40.         else
  41.         {
  42.             moveX_ratio = moveX/moveY;
  43.             if(moveX_ratio < 1)
  44.                 nowX -= moveX_ratio * 10;
  45.             else
  46.                 nowX -= 10;
  47.             if(nowX < X)
  48.                 nowX = X;
  49.            }
  50.     }
  51.     if(nowY != Y)
  52.     {
  53.         if(nowY < Y)
  54.         {
  55.             moveY_ratio = moveY/moveX;
  56.             if(moveY_ratio < 1)
  57.                 nowY += moveY_ratio * 10;
  58.             else
  59.                 nowY += 10;
  60.             if(nowY > Y)
  61.                 nowY = Y;
  62.         }
  63.         else
  64.         {
  65.             moveY_ratio = moveY/moveX;
  66.             if(moveY_ratio < 1)
  67.                 nowY -= moveY_ratio * 10;
  68.             else
  69.                 nowY -= 10;
  70.             if(nowY < Y)
  71.                 nowY = Y;
  72.         }
  73.     }
  74.     SelectObject(mdc, hbmp_gif);
  75.     BitBlt(mdc_all, nowX, nowY, 65, 70, mdc, gif_i*65, 0, SRCCOPY);
  76.     for(i=0;i<5;i++)
  77.         if(b[i].exist)
  78.         {
  79.             BitBlt(mdc_all, b[i].x, b[i].y, 8, 8, mdc, 0, 0, SRCCOPY);
  80.             b[i].x -= 10;
  81.             if(b[i].x < 0)
  82.                 b[i].exist = false;
  83.         }
  84.     BitBlt(hdc, 0, 0, 640, 480, mdc_all, 0, 0, SRCCOPY);
  85.     // 变量操作
  86.     if(gif_i>=3)
  87.         gif_i = 0;
  88.     else
  89.         gif_i++;
  90.     if(bg_x>=640)
  91.         bg_x = 0;
  92.     else
  93.         bg_x++;
  94.     // 释放
  95.     DeleteDC(mdc);
  96.     DeleteDC(mdc_all);
  97.     DeleteObject(hbmp_bg);
  98.     DeleteObject(hbmp_gif);
  99.     DeleteObject(hbmp_b);
  100.     DeleteObject(hbmp_all);
  101. }

 

  1. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3.     int i;
  4.     switch (message)
  5.     {
  6.         case WM_LBUTTONDOWN:                     // 鼠标左键消息(发射子弹)
  7.             for(i=0;i<5;i++)
  8.             {
  9.                 if(!b[i].exist)
  10.                 {
  11.                     b[i].x = nowX;
  12.                     b[i].y = nowY + 30;
  13.                     b[i].exist = true;
  14.                     break;
  15.                 }
  16.             }
  17.             break;
  18.         case WM_MOUSEMOVE:                       // 鼠标移动消息(动画移动)
  19.             X = LOWORD(lParam);
  20.             Y = HIWORD(lParam);
  21.             break;
  22.         case WM_DESTROY:                         // 窗口销毁消息
  23.             PostQuitMessage(0);
  24.             break;
  25.         default:                                 // 其他消息
  26.             return DefWindowProc(hWnd, message, wParam, lParam);
  27.     }
  28.     return 0;
  29. }

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有