鱼C论坛

 找回密码
 立即注册
查看: 3023|回复: 0

[技术交流] 会逃跑的按钮 1.0

[复制链接]
发表于 2018-6-18 17:32:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 qq1242009750 于 2018-6-20 20:54 编辑

今天写了一个好玩的小程序:让鼠标点击不到按钮。
主要的功能是,当鼠标计入到按钮的范围,按钮就会移动,从而达到点击不到按钮的效果。
我们知道鼠标进入了按钮的区域后,由按钮的消息过程来处理我们的消息。
1.在父窗口上创建一个按钮,要让按钮拥有我们的功能,首先我们要修改按钮的过程函数。(用到CreateWindow函数(创建窗口) SetWindowLong函数(用于更换按钮的消息处理过程))
2.捕获鼠标是否进入了此区域 (用到 WM_MOUSEMOVE WM_MOUSEHOVER WM_MOUSELEAVE 消息 和一个 TRACKMOUSEEVEVT结构体 和 TrakMouseEvent函数)
3.移动按钮 (用到 MoveWindow函数)

按钮移动规则:
先向右移动,让后向下移动
当不能右移动时,向左移动
当不能下移动时,向上移动
**移动范围在主窗口的客户区内
以此类推

**为了省去不需要的步骤在此省略了主窗口的注册和消息循环过程

①.我们在主窗口WM_CREATE消息里创建一个按钮,并修改按钮的消息处理过程

  1. WNDPROC OldProc;        //保存按钮之前的消息处理过程
  2. RECT ClientRect;                //保存住串口客户区的大小
  3. //主窗口消息处理过程
  4. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  5. {

  6.     switch (message)
  7.     {

  8.         case WM_CREATE:
  9.                  OldProc = (WNDPROC)SetWindowLong(CreateWindow(TEXT("BUTTON"), TEXT("123"), WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE, 100, 100, 50, 50, hWnd, (HMENU)IDC_BUTTON1, ((LPCREATESTRUCT)lParam)->hInstance, 0), GWL_WNDPROC, (LONG)WndProc2);
  10.                 break;

  11.         case WM_SIZE:
  12.                 GetClientRect(hWnd, &ClientRect);       
  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. }
复制代码


//按钮控件消息处理过程
  1. LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3.         static BOOL _bMouseTrack = TRUE;        //捕抓标志 FALSE:取消捕抓           TRUE:恢复捕抓

  4.         switch (message)
  5.         {
  6.         default:
  7.                 return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
  8.         }

  9.         return 0;
  10. }
复制代码


②捕获鼠标是否进入了此区域
  1. LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3.         static BOOL _bMouseTrack = TRUE;        //捕抓标志 FALSE:取消捕抓           TRUE:恢复捕抓

  4.         switch (message)
  5.         {
  6.         case WM_MOUSEMOVE:

  7.                 if (_bMouseTrack)
  8.                 {
  9.                         TRACKMOUSEEVENT tme;                                //鼠标捕抓结构体
  10.                         tme.cbSize = sizeof(TRACKMOUSEEVENT);        //结构体的大小
  11.                         tme.dwHoverTime = 1;                                        //悬停的时间 备注:以毫秒为单位,               
  12.                         tme.hwndTrack = hWnd;                                //起作用的窗口句柄
  13.                         tme.dwFlags = TME_HOVER | TME_LEAVE;        //设置消息
  14.                         TrackMouseEvent(&tme);                                //捕抓函数
  15.                 }
  16.                 break;

  17.         case WM_MOUSEHOVER:                //鼠标在按钮悬停1ms时产生
  18.                 _bMouseTrack = FALSE;        //取消TrackMouseEvent函数再次捕抓
  19.                 break;

  20.         case WM_MOUSELEAVE:                //鼠标移出按钮时产生
  21.                 _bMouseTrack = TRUE;                //恢复rackMouseEvent函数再次捕抓
  22.                 break;

  23.         default:
  24.                 return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
  25.         }

  26.         return 0;
  27. }
复制代码


③移动按钮
  1. LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3.         static BOOL _bMouseTrack = TRUE/*捕抓标志 FALSE:取消捕抓           TRUE:恢复捕抓*/, Hflag = TRUE/*水平方向左右移动标志*/, Vflag = TRUE/*垂直方向上下移动标志*/;
  4.         POINT pt;
  5.         static RECT rect;
  6.         static HPEN hpen;
  7.         HDC hdc;

  8.         switch (message)
  9.         {
  10.         case WM_MOUSEMOVE:

  11.                 if (_bMouseTrack)
  12.                 {
  13.                         TRACKMOUSEEVENT tme;
  14.                         tme.cbSize = sizeof(TRACKMOUSEEVENT);
  15.                         tme.dwHoverTime = 1000;
  16.                         tme.hwndTrack = hWnd;
  17.                         tme.dwFlags = TME_HOVER | TME_LEAVE;
  18.                         TrackMouseEvent(&tme);
  19.                 }
  20.                 break;

  21.         case WM_MOUSEHOVER:
  22.                 _bMouseTrack = FALSE;
  23.                 hdc = GetDC(hWnd);
  24.                 SetBkColor(hdc, RGB(255, 255, 0));
  25.                 SetWindowText(hWnd, TEXT(""));
  26.                 GetWindowRect(hWnd, &rect);
  27.                 ScreenToClient(GetParent(hWnd), (POINT*)&rect);
  28.                 ScreenToClient(GetParent(hWnd), ((POINT*)&rect) + 1);
  29.                
  30.                 pt.x = rect.left;
  31.                 pt.y = rect.top;

  32.                 if (Hflag)
  33.                 {
  34.                         if (ClientRect.right - pt.x >= 100)                //判断此方向是否有足够的位置给按钮移动,没有则改变移动方向
  35.                         {
  36.                                 MoveWindow(hWnd, rect.left + 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  37.                                 rect.left += 50;        //保持移动后的坐标
  38.                                 rect.right += 50;        //保持移动后的坐标
  39.                         }
  40.                         else
  41.                         {
  42.                                 Hflag = !Hflag;
  43.                         }
  44.                 }
  45.                 else
  46.                 {
  47.                         if (pt.x - ClientRect.left >= 100)
  48.                         {
  49.                                 MoveWindow(hWnd, rect.left - 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  50.                                 rect.left -= 50;
  51.                                 rect.right -= 50;
  52.                         }
  53.                         else
  54.                         {
  55.                                 Hflag = !Hflag;
  56.                         }
  57.                 }


  58.                 if (Vflag)
  59.                 {
  60.                         if (ClientRect.bottom - pt.y >= 100)
  61.                         {
  62.                                 MoveWindow(hWnd, rect.left, rect.top + 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  63.                                 rect.top += 50;
  64.                                 rect.bottom += 50;
  65.                         }
  66.                         else
  67.                         {
  68.                                 Vflag = !Vflag;
  69.                         }
  70.                 }
  71.                 else
  72.                 {
  73.                         if (pt.y - ClientRect.top >= 100)
  74.                         {
  75.                                 MoveWindow(hWnd, rect.left, rect.top - 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  76.                                 rect.top -= 50;
  77.                                 rect.bottom -= 50;
  78.                         }
  79.                         else
  80.                         {
  81.                                 Vflag = !Vflag;
  82.                         }
  83.                 }
  84.                
  85.                 SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("HOVER"));
  86.                 ReleaseDC(hWnd, hdc);
  87.                 break;

  88.         case WM_MOUSELEAVE:
  89.                 GetCursorPos(&pt);
  90.                 _bMouseTrack = TRUE;
  91.                 hdc = GetDC(hWnd);
  92.                 SetWindowText(hWnd, TEXT("123"));
  93.                 SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("LEAVE"));
  94.                 ReleaseDC(hWnd, hdc);
  95.                 break;

  96.         default:
  97.                 return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
  98.         }

  99.         return 0;
  100. }
复制代码


最后的主窗口和按钮的消息处理过程是这样的:
主窗口:
  1. WNDPROC OldProc;        //保存按钮之前的消息处理过程
  2. RECT ClientRect;                //保存住串口客户区的大小
  3. //主窗口消息处理过程
  4. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  5. {

  6.     switch (message)
  7.     {

  8.         case WM_CREATE:
  9.                  OldProc = (WNDPROC)SetWindowLong(CreateWindow(TEXT("BUTTON"), TEXT("123"), WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE, 100, 100, 50, 50, hWnd, (HMENU)IDC_BUTTON1, ((LPCREATESTRUCT)lParam)->hInstance, 0), GWL_WNDPROC, (LONG)WndProc2);
  10.                 break;

  11.         case WM_SIZE:
  12.                 GetClientRect(hWnd, &ClientRect);       
  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. }
复制代码


按钮消息处理过程:
  1. LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3.         static BOOL _bMouseTrack = TRUE/*捕抓标志 FALSE:取消捕抓           TRUE:恢复捕抓*/, Hflag = TRUE/*水平方向左右移动标志*/, Vflag = TRUE/*垂直方向上下移动标志*/;
  4.         POINT pt;
  5.         static RECT rect;
  6.         static HPEN hpen;
  7.         HDC hdc;

  8.         switch (message)
  9.         {
  10.         case WM_MOUSEMOVE:

  11.                 if (_bMouseTrack)
  12.                 {
  13.                         TRACKMOUSEEVENT tme;
  14.                         tme.cbSize = sizeof(TRACKMOUSEEVENT);
  15.                         tme.dwHoverTime = 1000;
  16.                         tme.hwndTrack = hWnd;
  17.                         tme.dwFlags = TME_HOVER | TME_LEAVE;
  18.                         TrackMouseEvent(&tme);
  19.                 }
  20.                 break;

  21.         case WM_MOUSEHOVER:
  22.                 _bMouseTrack = FALSE;
  23.                 hdc = GetDC(hWnd);
  24.                 SetBkColor(hdc, RGB(255, 255, 0));
  25.                 SetWindowText(hWnd, TEXT(""));
  26.                 GetWindowRect(hWnd, &rect);
  27.                 ScreenToClient(GetParent(hWnd), (POINT*)&rect);
  28.                 ScreenToClient(GetParent(hWnd), ((POINT*)&rect) + 1);
  29.                
  30.                 pt.x = rect.left;
  31.                 pt.y = rect.top;

  32.                 if (Hflag)
  33.                 {
  34.                         if (ClientRect.right - pt.x >= 100)                //判断此方向是否有足够的位置给按钮移动,没有则改变移动方向
  35.                         {
  36.                                 MoveWindow(hWnd, rect.left + 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  37.                                 rect.left += 50;        //保持移动后的坐标
  38.                                 rect.right += 50;        //保持移动后的坐标
  39.                         }
  40.                         else
  41.                         {
  42.                                 Hflag = !Hflag;
  43.                         }
  44.                 }
  45.                 else
  46.                 {
  47.                         if (pt.x - ClientRect.left >= 100)
  48.                         {
  49.                                 MoveWindow(hWnd, rect.left - 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  50.                                 rect.left -= 50;
  51.                                 rect.right -= 50;
  52.                         }
  53.                         else
  54.                         {
  55.                                 Hflag = !Hflag;
  56.                         }
  57.                 }


  58.                 if (Vflag)
  59.                 {
  60.                         if (ClientRect.bottom - pt.y >= 100)
  61.                         {
  62.                                 MoveWindow(hWnd, rect.left, rect.top + 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  63.                                 rect.top += 50;
  64.                                 rect.bottom += 50;
  65.                         }
  66.                         else
  67.                         {
  68.                                 Vflag = !Vflag;
  69.                         }
  70.                 }
  71.                 else
  72.                 {
  73.                         if (pt.y - ClientRect.top >= 100)
  74.                         {
  75.                                 MoveWindow(hWnd, rect.left, rect.top - 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  76.                                 rect.top -= 50;
  77.                                 rect.bottom -= 50;
  78.                         }
  79.                         else
  80.                         {
  81.                                 Vflag = !Vflag;
  82.                         }
  83.                 }
  84.                
  85.                 SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("HOVER"));
  86.                 ReleaseDC(hWnd, hdc);
  87.                 break;

  88.         case WM_MOUSELEAVE:
  89.                 GetCursorPos(&pt);
  90.                 _bMouseTrack = TRUE;
  91.                 hdc = GetDC(hWnd);
  92.                 SetWindowText(hWnd, TEXT("123"));
  93.                 SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("LEAVE"));
  94.                 ReleaseDC(hWnd, hdc);
  95.                 break;

  96.         default:
  97.                 return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
  98.         }

  99.         return 0;
  100. }
复制代码


好啦!以上就是小弟我的不才之作,有更好的Ider,请大家通知我!

升级啦!
会逃跑的按钮(升级版)
http://bbs.fishc.com/thread-117255-1-1.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-28 18:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表