【问题标题】:C++ WINAPI How can I run an event of mouse only once?C++ WINAPI 如何只运行一次鼠标事件?
【发布时间】:2021-11-24 00:09:08
【问题描述】:

我的无窗口框架中的这段代码是一个类似于按钮的区域,但有些代码我只想运行一次,直到鼠标下次移动到该区域为止。 所有这些代码都在 WM_MOUSEMOVE 中。

int ClickAreaPtInfo(HWND hWnd, int x, int y, int sizex, int sizey, LPARAM lParam,int &value)
    {
        POINT pt;
        pt.x = LOWORD(lParam);
        pt.y = HIWORD(lParam);
        RECT rect;
        GetClientRect(hWnd, &rect);
        RECT  rc = { x,y,x + sizex,y + sizey };
        if (PtInRect(&rc, pt))
        {
            value = 1;
            return -1;
        }
        else
        {
            value = 0;
            return -1;
        }
        return -1;
    }
int _CreateMouseEvent(HWND hWnd, int x, int y, int sizex, int sizey, LPARAM lParam,RUNFUN function(), const wchar_t* Panelid, const wchar_t* CtlName)
        {
            int val = 0;
            int msg = 0;


            //int ist = 0;            int istprev = 0;
            RECT winrc;
            GetClientRect(hWnd, &winrc);
            RECT rc;
            RectTypeConvert(rc,x, y, sizex, sizey);

            if (Panelid == PanelID)
            {
                int nst = 1;
                //OutputDebugString(L"HOVER!\n");
                msg = 1;
                ClickAreaPtInfo(hWnd, x, y, sizex, sizey, lParam, val);
                if (val == 1)
                {

                    if (ClickMsg == 1) //Click(Get from WM_LBUTTONUP)
                    {
                        ClickMsg = 0;
                        function();
                    }
                    else
                    {
//It must be run for only once until the mouse leave next time,or it will  lead to a lot of resource occupation
                        if (CtlName == L"Button") //HOVER
                        {

                            if (nst == 1)
                            {
                                HDC hdc = GetDC(hWnd);
                                CreateSimpleButtonEx(hWnd, hdc, x, y, sizex, sizey, UICOLOR_GREENSEA, 1, ButtonText);
                                ReleaseDC(hWnd, hdc);
                                nst = 0;
                                return 0;
                            }
                            else
                            {
                                nst = 0;
                                return 0;
                            }
                            return 0;
                        }
                        if (CtlName == L"CloseButton") ///HOVER
                        {
                            if (nst == 1)
                            {
                                HDC hdc = GetDC(hWnd);
                                CreateRect(hWnd, hdc, x, y, sizex, sizey, UICOLOR_PEACHRED);
                                PanelDrawCloseBtn(hWnd, hdc, rc.right - 40, 0, 40, 40, 12, UICOLOR_WHITE);
                                ReleaseDC(hWnd, hdc);
                                nst = 0;
                                return 0;
                            }
                            else
                            {
                                nst = 0;
                                return 0;
                            }
                            return 0;
                        }
                        else
                        {
                            return 0;
                        }
                    }

                }
                if (val == 0) //Leave
                {
                        nst = 1;
                        InvalidateRect(hWnd, &rc, 0); //It must be run for only once until the mouse leave next time,or it will  lead to a lot of resource(CPU) occupation
 
                }
            }
            if (Panelid == PrevPanelID)
            {
                msg = 1;
            }

            else
            {
                msg = 0;
            }
            

            return 0;
        }

然后在 WM_MOUSEMOVE 中处理 CreateMouseEvent:

case WM_MOUSEMOVE:
{
    CreateMouseEvent(hWnd, 20, 60, 140, 40, lParam, test, L"Init",L"Button");
    CreateMouseEvent(hWnd, 20, 120, 140, 40, lParam, test3, L"Init", L"Button");
    CreateMouseEvent(hWnd, 20, 180, 140, 40, lParam, btn3, L"Init",L"Button");
    CreateMouseEvent(hWnd, rc.right - 40, 0, 40, 40, lParam, CloseWindow, L"Init",L"CloseButton");
    break;
}

而且我也会给这个问题一个图片! http://db.vertexstudio.xyz/lnk/PanelPic/debuginf.png

任何解决方案?谢谢!

【问题讨论】:

  • 每次鼠标移到按钮上时,您都会调用CreateSimpleButtonEx。你是故意的吗?您似乎期望局部变量 nst 的值会在调用之间以某种方式保留。
  • 这里我只想在鼠标离开时运行一次:if (val == 0) //Leave { nst = 1; InvalidateRect(hWnd, &rc, 0); //必须只运行一次,直到下次鼠标离开,否则会导致大量资源(CPU)占用 }
  • 如果我创建了一个全局变量,并且面板中有多个 MouseEvent 会导致另一个错误
  • 所以你需要设计一种方法来为每个按钮单独维护持久状态。
  • 基本上,您想要实现假设的WM_MOUSEENTER 消息。请参阅Why is there no WM_MOUSEENTER message? 了解如何做到这一点。

标签: c++ winapi


【解决方案1】:

上面已经提到了你的一些问题。

您的示例中没有定义一些变量,既不是类型也不是值,但我至少可以推断出一些。

此外,在几个地方,您尝试直接将 C 样式字符串指针(不是 std::string!)与另一个 C 样式字符串指针进行比较。

    if (Panelid == PanelID) is one place
    
    if (CtlName == L"Button") //HOVER  === is another

    if (CtlName == L"CloseButton") ///HOVER another

您可以使用 int _wcsnicmp( const wchar_t *string1,const wchar_t *string2, size_t count); 之类的东西或您的编译器支持的任何东西。或者,您可以只使用std::wstring

至于点击,你需要保存你用GetClientRect(hWnd, &winrc);得到的rect它需要持久化,即保存在函数之外并且可以访问。然后与这个矩形进行比较并采取相应的行动。

【讨论】:

  • 你能给我一个实现的方法吗?谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
相关资源
最近更新 更多