qq1242009750 发表于 2018-6-18 17:32:05

会逃跑的按钮 1.0

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

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

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

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

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

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

    switch (message)
    {

        case WM_CREATE:
               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);
                break;

        case WM_SIZE:
                GetClientRect(hWnd, &ClientRect);       
                break;

    case WM_DESTROY:
                      PostQuitMessage(0);
                      break;

    default:
                      return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

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

        switch (message)
        {
        default:
                return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
        }

        return 0;
}

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

        switch (message)
        {
        case WM_MOUSEMOVE:

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

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

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

        default:
                return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
        }

        return 0;
}

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

        switch (message)
        {
        case WM_MOUSEMOVE:

                if (_bMouseTrack)
                {
                        TRACKMOUSEEVENT tme;
                        tme.cbSize = sizeof(TRACKMOUSEEVENT);
                        tme.dwHoverTime = 1000;
                        tme.hwndTrack = hWnd;
                        tme.dwFlags = TME_HOVER | TME_LEAVE;
                        TrackMouseEvent(&tme);
                }
                break;

        case WM_MOUSEHOVER:
                _bMouseTrack = FALSE;
                hdc = GetDC(hWnd);
                SetBkColor(hdc, RGB(255, 255, 0));
                SetWindowText(hWnd, TEXT(""));
                GetWindowRect(hWnd, &rect);
                ScreenToClient(GetParent(hWnd), (POINT*)&rect);
                ScreenToClient(GetParent(hWnd), ((POINT*)&rect) + 1);
               
                pt.x = rect.left;
                pt.y = rect.top;

                if (Hflag)
                {
                        if (ClientRect.right - pt.x >= 100)                //判断此方向是否有足够的位置给按钮移动,没有则改变移动方向
                        {
                                MoveWindow(hWnd, rect.left + 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.left += 50;        //保持移动后的坐标
                                rect.right += 50;        //保持移动后的坐标
                        }
                        else
                        {
                                Hflag = !Hflag;
                        }
                }
                else
                {
                        if (pt.x - ClientRect.left >= 100)
                        {
                                MoveWindow(hWnd, rect.left - 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.left -= 50;
                                rect.right -= 50;
                        }
                        else
                        {
                                Hflag = !Hflag;
                        }
                }


                if (Vflag)
                {
                        if (ClientRect.bottom - pt.y >= 100)
                        {
                                MoveWindow(hWnd, rect.left, rect.top + 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.top += 50;
                                rect.bottom += 50;
                        }
                        else
                        {
                                Vflag = !Vflag;
                        }
                }
                else
                {
                        if (pt.y - ClientRect.top >= 100)
                        {
                                MoveWindow(hWnd, rect.left, rect.top - 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.top -= 50;
                                rect.bottom -= 50;
                        }
                        else
                        {
                                Vflag = !Vflag;
                        }
                }
               
                SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("HOVER"));
                ReleaseDC(hWnd, hdc);
                break;

        case WM_MOUSELEAVE:
                GetCursorPos(&pt);
                _bMouseTrack = TRUE;
                hdc = GetDC(hWnd);
                SetWindowText(hWnd, TEXT("123"));
                SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("LEAVE"));
                ReleaseDC(hWnd, hdc);
                break;

        default:
                return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
        }

        return 0;
}

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

    switch (message)
    {

        case WM_CREATE:
               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);
                break;

        case WM_SIZE:
                GetClientRect(hWnd, &ClientRect);       
                break;

    case WM_DESTROY:
                      PostQuitMessage(0);
                      break;

    default:
                      return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

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

        switch (message)
        {
        case WM_MOUSEMOVE:

                if (_bMouseTrack)
                {
                        TRACKMOUSEEVENT tme;
                        tme.cbSize = sizeof(TRACKMOUSEEVENT);
                        tme.dwHoverTime = 1000;
                        tme.hwndTrack = hWnd;
                        tme.dwFlags = TME_HOVER | TME_LEAVE;
                        TrackMouseEvent(&tme);
                }
                break;

        case WM_MOUSEHOVER:
                _bMouseTrack = FALSE;
                hdc = GetDC(hWnd);
                SetBkColor(hdc, RGB(255, 255, 0));
                SetWindowText(hWnd, TEXT(""));
                GetWindowRect(hWnd, &rect);
                ScreenToClient(GetParent(hWnd), (POINT*)&rect);
                ScreenToClient(GetParent(hWnd), ((POINT*)&rect) + 1);
               
                pt.x = rect.left;
                pt.y = rect.top;

                if (Hflag)
                {
                        if (ClientRect.right - pt.x >= 100)                //判断此方向是否有足够的位置给按钮移动,没有则改变移动方向
                        {
                                MoveWindow(hWnd, rect.left + 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.left += 50;        //保持移动后的坐标
                                rect.right += 50;        //保持移动后的坐标
                        }
                        else
                        {
                                Hflag = !Hflag;
                        }
                }
                else
                {
                        if (pt.x - ClientRect.left >= 100)
                        {
                                MoveWindow(hWnd, rect.left - 50, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.left -= 50;
                                rect.right -= 50;
                        }
                        else
                        {
                                Hflag = !Hflag;
                        }
                }


                if (Vflag)
                {
                        if (ClientRect.bottom - pt.y >= 100)
                        {
                                MoveWindow(hWnd, rect.left, rect.top + 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.top += 50;
                                rect.bottom += 50;
                        }
                        else
                        {
                                Vflag = !Vflag;
                        }
                }
                else
                {
                        if (pt.y - ClientRect.top >= 100)
                        {
                                MoveWindow(hWnd, rect.left, rect.top - 50, rect.right - rect.left, rect.bottom - rect.top, TRUE);
                                rect.top -= 50;
                                rect.bottom -= 50;
                        }
                        else
                        {
                                Vflag = !Vflag;
                        }
                }
               
                SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("HOVER"));
                ReleaseDC(hWnd, hdc);
                break;

        case WM_MOUSELEAVE:
                GetCursorPos(&pt);
                _bMouseTrack = TRUE;
                hdc = GetDC(hWnd);
                SetWindowText(hWnd, TEXT("123"));
                SendMessage(GetDlgItem(GetParent(hWnd), 11), LB_ADDSTRING, 0, (LPARAM)TEXT("LEAVE"));
                ReleaseDC(hWnd, hdc);
                break;

        default:
                return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
        }

        return 0;
}

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

升级啦!
会逃跑的按钮(升级版)
http://bbs.fishc.com/thread-117255-1-1.html
页: [1]
查看完整版本: 会逃跑的按钮 1.0