【问题标题】:Is it possible to catch global mouse events是否可以捕获全局鼠标事件
【发布时间】:2019-03-28 06:43:44
【问题描述】:

我有一个包含一些按钮的简单框架。我的目标是,在单击GetMousePosition 按钮 后,获得第一个鼠标单击位置。我尝试捕捉鼠标点击,即使我在正在运行的应用程序之外点击。

这是一个在 Windows 上运行的桌面应用程序。我尝试了一些 wxwidgets 提供的鼠标事件,但我无法处理下一次单击事件。我尝试使用以下代码找到解决方案,但如果有其他解决方案,我可以将该代码扔进垃圾桶。

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_BUTTON(BUTTON_GetPos, MyFrame::OnButtonClick)
EVT_MOUSE_EVENTS(MyFrame::OnMouseEvent)
EVT_MOUSE_CAPTURE_LOST(MyFrame::OnMouseCaptureLost)
END_EVENT_TABLE()

//some more code

void MyFrame::OnButtonClick(wxCommandEvent & WXUNUSED(event))
{
    //Start Capturing for next mouse left-click
    if (!HasCapture())
        CaptureMouse();
}


void MyFrame::OnMouseEvent(wxMouseEvent &event)
{
    if (event.LeftDown()) {
        //GetMousePosition
        if (HasCapture())
            ReleaseMouse();
    }
}

void MyFrame::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
{
}

我希望在按下按钮后的第一次左键单击时获得鼠标位置。

【问题讨论】:

    标签: c++ wxwidgets


    【解决方案1】:

    您发布的代码看起来应该可以工作。如果有问题,它可能在您省略的代码中。无论如何,这是一个显示您想要的行为的小示例应用程序。此示例的底层逻辑与您发布的代码相同,只是此示例使用动态绑定而不是事件表。

    // For compilers that support precompilation, includes "wx/wx.h".
    #include "wx/wxprec.h"
    
    #ifdef __BORLANDC__
        #pragma hdrstop
    #endif
    
    // for all others, include the necessary headers (this file is usually all you
    // need because it includes almost all "standard" wxWidgets headers)
    #ifndef WX_PRECOMP
        #include "wx/wx.h"
    #endif
    
    class MyFrame : public wxFrame
    {
        public:
            MyFrame(wxWindow* parent);
    
        protected:
            void OnButtonClick(wxCommandEvent& event);
            void OnMouseCapLost(wxMouseCaptureLostEvent& event);
            void OnLeftDown(wxMouseEvent&);
    
            void CleanUp();
    
        private:
            wxTextCtrl* m_textCtrl;
    };
    
    class MyApp : public wxApp
    {
        public:
            virtual bool OnInit() wxOVERRIDE;
    };
    
    MyFrame::MyFrame(wxWindow* parent)
            :wxFrame(parent, wxID_ANY, "Demo", wxDefaultPosition, wxDefaultSize,
                     wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL)
    {
        wxPanel* panel =  new wxPanel(this, wxID_ANY );
        wxButton* button = new wxButton(panel, wxID_ANY, "Click Me");
        m_textCtrl = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
                                     wxDefaultPosition, wxDefaultSize,
                                     wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY);
    
        wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
        bSizer->Add(button, 0, wxALL, 5);
        bSizer->Add(m_textCtrl, 1, wxALL|wxEXPAND, 5);
        panel->SetSizer(bSizer);
        Layout();
    
        button->Bind(wxEVT_BUTTON,&MyFrame::OnButtonClick,this);
    }
    
    void MyFrame::OnButtonClick(wxCommandEvent& event)
    {
        if ( !HasCapture() )
        {
            CaptureMouse();
            m_textCtrl->AppendText("Mouse captured.\n");
    
            Bind(wxEVT_LEFT_DOWN, &MyFrame::OnLeftDown, this);
            Bind(wxEVT_MOUSE_CAPTURE_LOST, &MyFrame::OnMouseCapLost, this);
        }
    }
    
    void MyFrame::CleanUp()
    {
        if ( HasCapture() )
            ReleaseMouse();
        Unbind(wxEVT_LEFT_DOWN, &MyFrame::OnLeftDown, this);
        Unbind(wxEVT_MOUSE_CAPTURE_LOST, &MyFrame::OnMouseCapLost, this);
    }
    
    void MyFrame::OnMouseCapLost(wxMouseCaptureLostEvent& event)
    {
        m_textCtrl->AppendText("Mouse cap lost.\n");
        CleanUp();
    }
    
    void MyFrame::OnLeftDown(wxMouseEvent& event)
    {
        m_textCtrl->AppendText("Click recorded.\n");
        CleanUp();
    }
    
     bool MyApp::OnInit()
    {
        MyFrame* frame = new MyFrame(NULL);
        frame->Show();
        return true;
    }
    
    wxIMPLEMENT_APP(MyApp);
    

    我希望这会有所帮助。

    编辑:这是一个使用事件表的版本:

    // For compilers that support precompilation, includes "wx/wx.h".
    #include "wx/wxprec.h"
    
    #ifdef __BORLANDC__
        #pragma hdrstop
    #endif
    
    // for all others, include the necessary headers (this file is usually all you
    // need because it includes almost all "standard" wxWidgets headers)
    #ifndef WX_PRECOMP
        #include "wx/wx.h"
    #endif
    
    #define BUTTON_ID 101
    
    class MyFrame : public wxFrame
    {
        public:
            MyFrame(wxWindow* parent);
    
        protected:
            void OnButtonClick(wxCommandEvent& event);
            void OnMouseCapLost(wxMouseCaptureLostEvent& event);
            void OnMouseEvent(wxMouseEvent&);
    
            void CleanUp();
    
        private:
            wxTextCtrl* m_textCtrl;
    
            wxDECLARE_EVENT_TABLE();
    };
    
    class MyApp : public wxApp
    {
        public:
            virtual bool OnInit() wxOVERRIDE;
    };
    
    wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
        EVT_BUTTON(BUTTON_ID, MyFrame::OnButtonClick)
        EVT_MOUSE_EVENTS(MyFrame::OnMouseEvent)
        EVT_MOUSE_CAPTURE_LOST(MyFrame::OnMouseCapLost)
    wxEND_EVENT_TABLE()
    
    MyFrame::MyFrame(wxWindow* parent)
            :wxFrame(parent, wxID_ANY, "Demo", wxDefaultPosition, wxDefaultSize,
                     wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL)
    {
        wxPanel* panel =  new wxPanel(this, wxID_ANY );
        wxButton* button = new wxButton(panel, BUTTON_ID, "Click Me");
        m_textCtrl = new wxTextCtrl(panel, wxID_ANY, wxEmptyString,
                                     wxDefaultPosition, wxDefaultSize,
                                     wxTE_DONTWRAP|wxTE_MULTILINE|wxTE_READONLY);
    
        wxBoxSizer* bSizer = new wxBoxSizer(wxVERTICAL);
        bSizer->Add(button, 0, wxALL, 5);
        bSizer->Add(m_textCtrl, 1, wxALL|wxEXPAND, 5);
        panel->SetSizer(bSizer);
        Layout();
    }
    
    void MyFrame::OnButtonClick(wxCommandEvent& event)
    {
        if ( !HasCapture() )
        {
            CaptureMouse();
            m_textCtrl->AppendText("Mouse captured.\n");
        }
    }
    
    void MyFrame::CleanUp()
    {
        if ( HasCapture() )
            ReleaseMouse();
    }
    
    void MyFrame::OnMouseCapLost(wxMouseCaptureLostEvent& event)
    {
        m_textCtrl->AppendText("Mouse cap lost.\n");
        CleanUp();
    }
    
    void MyFrame::OnMouseEvent(wxMouseEvent& event)
    {
        if( HasCapture() && event.LeftIsDown() )
        {
            m_textCtrl->AppendText("Click recorded.\n");
            CleanUp();
        }
    
    }
    
     bool MyApp::OnInit()
    {
        MyFrame* frame = new MyFrame(NULL);
        frame->Show();
        return true;
    }
    
    wxIMPLEMENT_APP(MyApp);
    

    【讨论】:

    • 我尝试了您共享的代码,并且成功了。我想知道为什么它不适用于其他方式。您对导致该问题的动态绑定和使用事件表之间的区别有任何想法吗?
    • 我不记得如何使用事件表,但我发布了第二个使用它们的示例,它似乎与第一个示例一样工作。所以我认为您遇到的问题可能与事件处理无关。
    猜你喜欢
    • 1970-01-01
    • 2010-10-19
    • 2011-09-01
    • 1970-01-01
    • 2018-09-17
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多