wxEVT_LEFT_DOWN on menuBar 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
mxoliveira73
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sun May 05, 2019 7:12 am

wxEVT_LEFT_DOWN on menuBar

Post by mxoliveira73 »

wxEVT_LEFT_DOWN doesn't work over a wxMenuBar?

Code: Select all

OnLeftDown(wxMouseEvent& event);

wxmenuBar* menuBar = new wxMenuBar();

menuBar->Bind(wxEVT_LEFT_DOWN,&MyFrame::OnLeftDown,this);

void MyFrame::OnLeftDown(wxMouseEvent& event)
{
// do something here
}
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxEVT_LEFT_DOWN on menuBar

Post by evstevemd »

what do you want to accomplish?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
Deluge
Earned some good credits
Earned some good credits
Posts: 122
Joined: Fri Apr 30, 2010 4:52 am
Location: USA
Contact:

Re: wxEVT_LEFT_DOWN on menuBar

Post by Deluge »

I think this is because of wxMenuBar's implicit handling of mouse events. I'm not sure how you would override it.

Tested it out with this code:

Code: Select all

#include <iostream>
#include <wx/wx.h>

using namespace std;


class MyFrame : public wxFrame {
public:
	MyFrame();
private:
	void OnLeftDown(wxMouseEvent& event);
} *frame;

MyFrame::MyFrame() :
		wxFrame(NULL, wxID_ANY, _T("Testing Mouse Event")) {
	wxMenuBar* menuBar = new wxMenuBar();
	menuBar->Append(new wxMenu(), _T("File"));

	SetMenuBar(menuBar);

	// bind to wxMenuBar
	menuBar->Bind(wxEVT_LEFT_DOWN, &MyFrame::OnLeftDown, this);
	// bind to wxFrame
	Bind(wxEVT_LEFT_DOWN, &MyFrame::OnLeftDown, this);

	// test OnLeftDown method at initialization
	wxPostEvent(menuBar, wxMouseEvent(wxEVT_LEFT_DOWN));
}

void MyFrame::OnLeftDown(wxMouseEvent& event) {
	cout << "Left mouse down event\n";
}


class MyApp : public wxApp {
public:
	virtual bool OnInit();
} *app;

bool MyApp::OnInit() {
	frame = new MyFrame();
	SetTopWindow(frame);
	frame->Show(true);

	return true;
}


int main(int argc, char** argv) {
	cout << "Starting test ...\n";

	app = new MyApp();
	wxApp::SetInstance(app);
	wxEntry(argc, argv);

	return 0;
}
Binding to the wxFrame works, but not binding to the menu bar.

--- Edit ---

Might be able to make your own custom menu bar class derived from wxMenu bar & call Unbind or Disconnect in the constructor. But, not sure if that will work.
Projects:
Debreate
MyABCs
Stendhal

OSes:
Windows 10 Home (missing my Linux & Freebsd :()
mxoliveira73
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sun May 05, 2019 7:12 am

Re: wxEVT_LEFT_DOWN on menuBar

Post by mxoliveira73 »

Responding to evstevemd

ask: what do you want to accomplish?

R: Drag the menuBar and togheter the Frame.
Create app whitout Title Bar; then, to move the frame in the screen, drag the menuBar whit the cursor mouse. Togheter drag Frame.

It's possible, if the menuBar react to the Evt_LEFT_DOWN. But, it seems not possible.

The right question is:

Is it possible the menuBar react to the EVT_LEFT_DOWN mouse event?
Last edited by mxoliveira73 on Wed Jul 03, 2019 6:06 pm, edited 1 time in total.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxEVT_LEFT_DOWN on menuBar

Post by doublemax »

Is it possible the menuBar react to the EVT_LEFT_DOWN mouse event?
There is not much you can do wrong here, and i tested it myself. Apparently the answer is no, at least under Windows. I didn't test on other platforms.

If you really need this i would try without a menubar and use a toolbar to mimic the functionality of the menubar. Of course it won't look exactly the same.

Or you could use the empty spots in the main window for dragging. It depends on the type of application and potential user base if that's a realistic solution.
Use the source, Luke!
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4204
Joined: Sun Jan 03, 2010 5:45 pm

Re: wxEVT_LEFT_DOWN on menuBar

Post by PB »

I would say that at least on MSW, it probably cannot work.

While wxMenuBar is in wxWidgets derived from wxWindow, the native menu is not a window (it does not have a HWND, it is a HMENU). The menubar there is considered part of the non-client area and DefWindowProc returns HTMENU in response to WM_NCHITTEST where the coordinates match the menubar.

I mashed up this UNTESTED example (without error handling) how to drag a window by the "empty" area of a frame's menubar on MSW. The code pretends that the area of the menubar not taken up by menus (minus some gap) is the window caption. No idea whether this is a proper solution, just one that came to my mind as easy and seemingly working. The code for computing the menubar area does not account for the situation where menubar overflows to more than one row, but that should be easy to handle. However, the code may have some serious problems I am not aware of, who knows - probably not suitable for production.

Anyway, in the test app one can grab the menubar (after about 30 pixels after the last item) and drag the window around.

Code: Select all

#include <wx/wx.h>

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, _("Test"), wxDefaultPosition, wxSize(800, 600))
    {
        wxMenu* fileMenu = new wxMenu;
        fileMenu->Append(wxID_OPEN);
        fileMenu->Append(wxID_SAVE);

        wxMenu* editMenu = new wxMenu;
        editMenu->Append(wxID_CUT);
        editMenu->Append(wxID_COPY);

        wxMenuBar* menuBar = new wxMenuBar();
        menuBar->Append(fileMenu, _("&File"));
        menuBar->Append(editMenu, _("&Edit"));
        SetMenuBar(menuBar);

        wxTextCtrl* logCtrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
            wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH2);
        wxLog::SetActiveTarget(new wxLogTextCtrl(logCtrl));
    }

#ifdef __WXMSW__ 
    WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) override
    {
        WXLRESULT result = wxFrame::MSWWindowProc(nMsg, wParam, lParam);

        if ( nMsg == WM_NCHITTEST && result == HTMENU && GetMenuBar() )
        {
            size_t menuCount = GetMenuBar()->GetMenuCount();

            if ( menuCount )
            {
                static const LONG gap = 30; // between last menu item and draggable area
                
                RECT menuItemRect{0};
                POINT mousePos{0};

                ::GetMenuItemRect(GetHandle(), GetMenuBar()->GetHMenu(), menuCount - 1, &menuItemRect);
                ::MapWindowPoints(nullptr, GetHandle(), (LPPOINT)&menuItemRect, 2);

                mousePos.x = LOWORD(lParam);
                mousePos.y = HIWORD(lParam);
                ::ScreenToClient(GetHandle(), &mousePos);

                if ( mousePos.x > menuItemRect.right + gap )
                {
                    wxLogMessage("Pretending this part of menubar is caption.");
                    result = HTCAPTION;
                }
            }            
        }

        return result;
    }
#endif // #ifdef __WXMSW__
};

class MyApp : public wxApp
{
public:
    bool OnInit() override
    {
        (new MyFrame)->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);
EDIT I forgot to add that I consider this approach user unfriendly. Unlike other modifications of the NC area in applications such as those using ribbon or web browsers, you would not have any window caption nor the min, max/restore, and close buttons.
mxoliveira73
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sun May 05, 2019 7:12 am

Re: wxEVT_LEFT_DOWN on menuBar

Post by mxoliveira73 »

Amazing. It works fine in MS Windows the code of PB. Big big thanks, PB, evstevemd, deluge, doublemax... I'm almost finishing my app. Would be impossible whitout the help of you.... Really, this point it's level so high to me, only a bigginner. I'm styuding the code to underst it... thanks a lot... It's had been a good experience to me this fórum and WxWidgets... It's very quicly in aplication...
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2409
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Re: wxEVT_LEFT_DOWN on menuBar

Post by evstevemd »

Welcome to wxWidgets community. Keep going =D>
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxEVT_LEFT_DOWN on menuBar

Post by ONEEYEMAN »

Hi,
On top of what PB said - this solutio is very hackish and un-portable.
Frame title bar's are exist for a reason - not just to show the application name and some other info but in order to be able to drag the window around.

You should re-consider you design and add the menu to "Exit fullscreen mode" to make the window as "normal".

Thank you.
Post Reply