Qt Mac - App not restoring after closing - c++

In Mac when we press the close button apps by default hide to dock. The same happens with my Qt app too, but it does not restore afterwards as expected. There are many posts which provide code to detect click on dock icon.
I don't need to detect, I just want the default functionality, that it should restore.
It restores if I minimize but not on close.
The fix I used is:
void myAPP::closeEvent(QCloseEvent *event)
{
#ifdef Q_OS_MAC
event->ignore();
this->setWindowState(Qt::WindowMinimized) ;
return;
#endif
}
It makes it minimize on close and than my app restores properly. But now the issue is that it is preventing shutdown on Mac unless I exit the application. Shutdown makes the app minimize.
I am using Qt 5.4

To fix the issue, I wanted to know the source of Close Event. If source is user than minimize, else if source is OS shutdown event than exit.
We can use event->spontaneous() to check that. Following is the working solution:
void myAPP::closeEvent(QCloseEvent *event)
{
#ifdef Q_OS_MAC
if(event->spontaneous())
{
event->ignore();
this->setWindowState(Qt::WindowMinimized) ;
return;
}
#endif
}

Related

wxWidgets dark mode on macOS

According to the release notes for 3.1.3 (https://raw.githubusercontent.com/wxWidgets/wxWidgets/v3.1.3/docs/changes.txt) dark mode support has been added to wxWidgets for Mojave+.
For the documentation for wxSysColourChanged, it still states that this is for Windows only but I thought the dark mode support for macOS should include this too? Dark mode is only a recent addition to Windows UWP apps and not Win32 (see dark mode on Windows 10 for a discussion of that on the forum).
In any case I cannot get the event to fire, although switching to dark mode does indeed correctly update the GUI elements eg. wxlistctrl and wxbutton without me having to manually enforce colour changes.
I am trying to capture the system colour change event so that I can manually redraw my own "owner-drawn" custom GUI elements correctly dark/light.
I hook up the Bind in the constructor to my event but nothing works:
Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);
void myFrame::OnSystemColourChanged(wxSysColourChangedEvent &event)
{
wxSystemAppearance s = wxSystemSettings::GetAppearance();
wxString dark = s.IsDark() ? "it's dark" : "it's light";
wxString m("System colour changed - ");
m += dark;
::wxMessageBox(m);
event.Skip();
}
I have got this open as a query on the forum (here) and they recommended the mailing list but I notice that wxWidgets questions are quickly addressed on here, particularly by VZ so here's hoping!
Am I missing some method of detecting colour changes?
OK, I managed to get the code to hit. I debugged it by adding a wxApp-level HandleEvent override function to see what events were being handled by the application (yes all events go through here):
void myApp::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const
{
wxApp::HandleEvent(handler, func, event);
}
wxSysColourChanged events are indeed passing through this.
I managed to get my main frame's handler to hit by hooking up differently. Instead of
Bind(wxEVT_SYS_COLOUR_CHANGED, &myFrame::OnSystemColourChanged, this);
I used this instead:
Bind(wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler(myFrame::OnSystemColourChanged), this);
I have no idea why &myFrame::OnSystemColourChanged wouldn't be recognised.
Also, I could not get any message boxes to show up in my event handler. ::wxMessageBox and wxMessageDialog did not show. cout output did show up but no popup GUI dialogs.
I am not going to be showing message boxes in this handler anyway so it isn't a problem but was trying to show a message for debugging/testing purposes.

QT/c++ How to check globaly is mouse press or release?

void MainWindow::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
timer->start(timer_time);
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
timer->stop();
}
}
This code works when i use it inside my appliacation, but if I want use it outside it won't be working. How can I do this?
It should start timer when LeftButton is pressed and stop when LeftButton release.
SOLUTION: understanding-the-low-level-mouse-and-keyboard-hook-win32
It sounds like hooks are what you're looking for.
Basically, hooks let you interact with the activity within your system, and can be used alter its behavior.
The event listeners in your code will only catch the mouse events that your OS delegates to your QT application. This is why your code only works when you use it inside your application. Using hooks, you can intercept mouse events at a system level and have them handled them in your app instead of letting the OS decide where they should be handled.
Here's what to use to set them up, and here's a little guide on the implementation details.

How to keep the application running when the last window is closed?

I'm working on a very basic GUI project in Qt (using c++) and want to be able to close the main window in my program without the program quitting all the way. By default, it will exit when the main window is closed. How to prevent that?
Set the QApplication::quitOnLastWindowClosed property to false:
qApp->setQuitOnLastWindowClosed(false);
If you still need your window to exist, you would probably like to reimplement your closeEvent method like this:
void MainWindow::closeEvent(QCloseEvent *event)
{
hide();
event->ignore();
}
or use QGuiApplication::setQuitOnLastWindowClosed(false)
If you want to perform some pre-exit operation as saving settings, connect some slot doing what you want to QCoreApplication::aboutToQuit()

Disable event handler in Visual Studio MFC based application

I am working on a project. It has GUI and i add Start button on it , which is handled by some function. and after clicking on start ,that Gui shows the output. I want to disable that handler function. Whenever i debug that project, start button should automatically started and GUI shows the output.
This is the code of that handler. What should i change or move that function ?
void CServerSocketDlg::OnBtnStart()
{
UpdateData();
StartX();
}
Need your suggestion. Thanks
So add something like this in an appropriate location. For example, in a dialog, you could put it in OnInitDialog:
#ifdef _DEBUG
if(IsDebuggerPresent())
{
/* code here to automatically do whatever you need when a debugger is attached */
}
#endif
This code will only be compiled in the "Debug" versions of the application and will execute only if the application is running under the debugger.

HowTo correctly close QDialog when main windows is hidden?

I have some kind of dilemma.
I'm using:
MSVS 2008
Qt 4.7.3 (with Qt VS Add-in 1.1.9)
I wrote small Qt application, base on QMainWindow class, where also exists settings dialog (QDialog). Every works fine in GUI mode. After that I started to change my project to make it visible only in tray. Just comment in main.cpp show() method, like this:
MainWindow w;
//w.show();
return app.exec();
But from tray, I need to launch settings dialog, which is implemented in mainwindow.h/.cpp files. I added to tray menu action (QAction) which is starts that settings dialog. And here comes the unexpected problem: when I tried to close this settings dialog with [ X ] close button (in top right corner) my app closed!
Here is the action slot:
void MainWindow::onOpenSettingsDlgClicked()
{
SettingsDlg dlg( this );
dlg.exec();
}
I have tried to reimplement virtual reject() method for the settings dialog class, and set there only hide() function, but that solution not helped.
What I'm doing wrong?
Thanks you!
You should turn off the quitOnLastWindowClosed property which is turned on by default as defined in the doc (http://doc.qt.nokia.com/latest/qapplication.html#quitOnLastWindowClosed-prop)
This said, you'll have to handle the termination of your QApplication yourself, maybe with an [quit] entry in the tray menu.
Just found another option which seems better is to override closeEvent of the QDialog to only hide it.
void PrefDialog::closeEvent(QCloseEvent *event) {
this->hide();
event->ignore();
}
I found this seems better because it doesn't change the global application behaviour.