Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Titan
In need of some credit
In need of some credit
Posts: 7
Joined: Wed Mar 04, 2020 2:10 pm

Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by Titan » Tue Jun 30, 2020 5:32 pm

Hi,

Is there a way to toggle a wxPopupTransientWindow? I have a simple control with an OnMouseLeftDown and OnMouseLeftUp method, with which I would like to make a wxPopupTransientWindow appear and disappear. But when the popup is shown and I click out, the popup closes (I'm OK with that), so I tried to override the wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown methods ant it doesn't work, I mean the methods are not called... Is it a (known?) problem coming from wxWidgets or am I doing something wrong? Because I simply inherited from wxPopupTransientWindow and overloaded the methods.

Regards,

Titan

catalin
Moderator
Moderator
Posts: 1575
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by catalin » Tue Jun 30, 2020 6:29 pm

wxPopupWindow has no OnDismiss() member. You're probably aiming for wxPopupTransientWindow::OnDismiss(). But mind that it will be called only when Dismiss() was not called.

At least for wxPopupTransientWindow::ProcessLeftDown(), it sounds like you are doing something wrong. Can you show a piece of code? Or maybe you used the keyboard to dismiss the popup?

Titan
In need of some credit
In need of some credit
Posts: 7
Joined: Wed Mar 04, 2020 2:10 pm

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by Titan » Tue Jun 30, 2020 8:22 pm

Yes of course I was wrong, it's wxPopupTransientWindow::OnDismiss().

Here's my code:

myPopup.hpp

Code: Select all

#pragma once

#include <wx/popupwin.h>

class myPopup :
    public wxPopupTransientWindow
{
public:

    myPopup(
        wxWindow* parent,
        wxWindowID id = wxID_ANY,
        wxSize const& size = wxDefaultSize);

    virtual void Popup(wxWindow* focus = NULL) override;

    virtual bool ProcessLeftDown(wxMouseEvent& event) override;

protected:

    virtual void OnDismiss(void) override;
};
myPopup.cpp

Code: Select all

#include "myPopup.hpp"

myPopup::myPopup(
    wxWindow* parent,
    wxWindowID id,
    wxSize const& size
) :
    wxPopupTransientWindow(
        parent,
        wxBORDER_NONE
    )
{
    SetId(id);
    SetSize(size);

    SetBackgroundColour(*wxYELLOW); // TMP
}

void myPopup::Popup(wxWindow* focus)
{
    Position(
        m_parent->GetScreenPosition(),
        m_parent->GetSize());

    wxPopupTransientWindow::Popup(focus);
}

/*
 * This method is not called.
 */
bool myPopup::ProcessLeftDown(wxMouseEvent& WXUNUSED(event))
{
    { // To observe a change :
        SetBackgroundColour(
            wxColour(
                rand() % 255,
                rand() % 255,
                rand() % 255));
        Refresh();
        Update();
    }
    return false;
}


/*
 * This method is not called too.
 */
void myPopup::OnDismiss(void)
{
    { // To observe a change :
        SetBackgroundColour(
            wxColour(
                rand() % 255,
                rand() % 255,
                rand() % 255));
        Refresh();
        Update();
    }
}
myButton.hpp

Code: Select all

#pragma once

#include <wx/control.h>

#include "myPopup.hpp"

class myButton :
    public wxControl
{
public:

    myButton(
        wxWindow* parent,
        wxWindowID id = wxID_ANY,
        wxPoint const& position = wxDefaultPosition,
        wxSize const& size = wxDefaultSize);

    ~myButton(void);

private:

    myPopup* m_popup;

    void OnMouseLeftDown(wxMouseEvent& event);
    void OnMouseLeftUp(wxMouseEvent& event);
};
myButton.cpp

Code: Select all

#include "myButton.hpp"

myButton::myButton(
    wxWindow* parent,
    wxWindowID id,
    wxPoint const& position,
    wxSize const& size
) :
    wxControl(
        parent,
        id,
        position,
        size
    )
{
    SetBackgroundColour(*wxRED); // TMP

    m_popup =
        new myPopup(
            this, wxID_ANY,
            wxSize(300, 200));

    Bind(wxEVT_LEFT_DOWN, &myButton::OnMouseLeftDown, this);
    Bind(wxEVT_LEFT_UP, &myButton::OnMouseLeftUp, this);
}

myButton::~myButton(void)
{
    delete m_popup;
}

void myButton::OnMouseLeftDown(wxMouseEvent& WXUNUSED(event))
{
    // Nothing yet.
}

void myButton::OnMouseLeftUp(wxMouseEvent& WXUNUSED(event))
{
    m_popup->Popup();
}

For the moment in myPopup::ProcessLeftDown I return false like wxPopupWindow::ProcessLeftDown to not hide myPopup. In the future, if the mouse is over his myButton, I would like to say to myButton to not open myPopup again in myButton::OnMouseLeftUp and return true to hide. Because the click on the myButton is actually a click outside the myPopup so it will close automatically. But now the method is not called...
Do you see what I'm trying to say?

Thank you for your help.

catalin
Moderator
Moderator
Posts: 1575
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by catalin » Tue Jun 30, 2020 10:30 pm

Well, FWIW the popup window code is a mess. The "common" code actually contains the OSX and GTK implementations (..not exactly "common"), while the MSW implementation is separate. But you're probably right as it does look like a bug (assuming the reason for not getting those calls is because you're on Windows).

Can you try replacing the Dismiss() call in src/msw/popupwin.cpp, wxPopupTransientWindow::DismissOnDeactivate(), with DismissAndNotify(), and try again?

Titan
In need of some credit
In need of some credit
Posts: 7
Joined: Wed Mar 04, 2020 2:10 pm

Re: Overloaded methods wxPopupTransientWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by Titan » Wed Jul 01, 2020 2:17 pm

I changed the Dismiss() call by DismissAndNotify() as you said, and now the overloaded myPopup::OnDismiss() method is called. It's a big step thank you ! But the myPopup::ProcessLeftDown method is not still called... Do you know if there is a way to do the same "hack" for this method?

catalin
Moderator
Moderator
Posts: 1575
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by catalin » Wed Jul 01, 2020 5:13 pm

Not really, because the latter is used from wxPopupWindowHandler, which is only used by non-MSW implementations.
But it's probably not too difficult to do something similar in your derived class, connecting to the relevant mouse event [and ensure capturing and releasing the mouse when needed].

Titan
In need of some credit
In need of some credit
Posts: 7
Joined: Wed Mar 04, 2020 2:10 pm

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by Titan » Wed Jul 01, 2020 5:37 pm

I see what you mean, but now I can make appear and disappear the myPopup with myButton using the overloaded OnDismiss() method. I really appreciated your help, thank you very much!

By the way, I just have a small question: Is it a good practice to put more complex controls inside a wxPopupWindow/wxPopupTransientWindow? Like sliders, buttons, custom controls, etc.

catalin
Moderator
Moderator
Posts: 1575
Joined: Wed Nov 12, 2008 7:23 am
Location: Romania

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by catalin » Wed Jul 01, 2020 6:24 pm

IIRC whatever you put in there will not get focused. So if you intend to interact with them using only the mouse, all should be fine, but if you need kb input then it might not work as you expected.

Titan
In need of some credit
In need of some credit
Posts: 7
Joined: Wed Mar 04, 2020 2:10 pm

Re: Overloaded methods wxPopupWindow::OnDismiss and wxPopupTransientWindow::ProcessLeftDown are not called

Post by Titan » Wed Jul 01, 2020 6:46 pm

Ok, thank you!

Post Reply