У меня есть подкласс Window
в моем проекте, и во время выполнения экземпляр создается и полностью отображается на стороне QML. Я знаю, что я могу предотвратить минимизацию окна, не включая WindowMinimizeButtonHint
во flags:
но мне действительно нужно, чтобы кнопка минимизации была включена и включена, но можно перехватить кнопку "Свернуть", отменить фактическое минимизацию и сделать что-то еще (FYI мой клиент требует этого нестандартного поведения окон, а не меня).
Пока что единственное, что мне удалось достичь, - это onWindowStateChanged:
событие onWindowStateChanged:
проверить, является ли windowState === Qt.WindowStateMinimized
и вызывать show()
из таймера (вызов его внутри обработчика событий напрямую ничего не делает). Это приводит к тому, что окно переходит к системному лотку, а затем неожиданно возвращается в нормальное состояние.
Есть ли способ сделать это, что-то вроде события OnMinimized
которое можно отменить?
Изменение: на основе ответа Бенджамина Т, я по крайней мере частично способ решения OSX:
#import <AppKit/AppKit.h>
bool NativeFilter::nativeEventFilter(const QByteArray &eventType,
void *message, long *result)
{
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = static_cast<NSEvent *>(message);
if ([event type] == NSKeyDown) {
return true;
}
}
return false;
}
В этом примере я могу перехватывать и отменять все события NSKeyDown (оставляя при этом другие события, такие как щелчки мыши и т.д.). Оставшаяся проблема заключается в том, что я до сих пор не знаю, чтобы перехватить событие минимизации - NSEvent.h, похоже, не имеет ничего, что покрывает это. Может быть, мне нужно перевести на другой тип события?
Редактировать 2 - рабочее решение:
Я не смог найти способ перехватить событие минимизации надлежащим образом и отменить его, поэтому мой обходной путь заключается в том, чтобы вместо этого перехватить щелчок по окну, определить, находится ли щелчок по кнопке минимизации (или кнопкам закрытия или масштабирования) и отменить событие if so (и отправить уведомление в мое окно qml, которое произошло нажатием). Я также обрабатываю случай двойного щелчка на заголовке, чтобы увеличить окно, и используя клавиши Command-M для минимизации окна.
Первый шаг - реализовать QAbstractNativeEventFilter
. В вашем заголовке:
#include <QAbstractNativeEventFilter>
class NativeFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray &eventType, void *message,
long *result);
};
Реализация:
#import <AppKit/AppKit.h>
#import <AppKit/NSWindow.h>
#import <AppKit/NSButton.h>
bool NativeFilter::nativeEventFilter(const QByteArray &eventType, void
*message, long *result)
{
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = static_cast<NSEvent *>(message);
NSWindow *win = [event window];
// TODO: determine whether or not this is a window whose
// events you want to intercept. I did this by checking
// [win title] but you may want to find and use the
// window id instead.
// Detect a double-click on the titlebar. If the zoom button
// is enabled, send the full-screen message to the window
if ([event type] == NSLeftMouseUp) {
if ([event clickCount] > 1) {
NSPoint pt = [event locationInWindow];
CGRect rect = [win frame];
// event coordinates have y going in the opposite direction from frame coordinates, very annoying
CGFloat yInverted = rect.size.height - pt.y;
if (yInverted <= 20) {
// TODO: need the proper metrics for the height of the title bar
NSButton *btn = [win standardWindowButton:NSWindowZoomButton];
if (btn.enabled) {
// notify qml of zoom button click
}
return true;
}
}
}
if ([event type] == NSKeyDown) {
// detect command-M (for minimize app)
if ([event modifierFlags] & NSCommandKeyMask) {
// M key
if ([event keyCode] == 46) {
// notify qml of miniaturize button click
return true;
}
}
// TODO: we may be requested to handle keyboard actions for close and zoom buttons. e.g. ctrl-cmd-F is zoom, I think,
// and Command-H is hide.
}
if ([event type] == NSLeftMouseDown) {
NSPoint pt = [event locationInWindow];
CGRect rect = [win frame];
// event coordinates have y going in the opposite direction from frame coordinates, very annoying
CGFloat yInverted = rect.size.height - pt.y;
NSButton *btn = [win standardWindowButton:NSWindowMiniaturizeButton];
CGRect rectButton = [btn frame];
if ((yInverted >= rectButton.origin.y) && (yInverted <= (rectButton.origin.y + rectButton.size.height))) {
if ((pt.x >= rectButton.origin.x) && (pt.x <= (rectButton.origin.x + rectButton.size.width))) {
// notify .qml of miniaturize button click
return true;
}
}
btn = [win standardWindowButton:NSWindowZoomButton];
rectButton = [btn frame];
if (btn.enabled) {
if ((yInverted >= rectButton.origin.y) && (yInverted <= (rectButton.origin.y + rectButton.size.height))) {
if ((pt.x >= rectButton.origin.x) && (pt.x <= (rectButton.origin.x + rectButton.size.width))) {
// notify qml of zoom button click
return true;
}
}
}
btn = [win standardWindowButton:NSWindowCloseButton];
rectButton = [btn frame];
if ((yInverted >= rectButton.origin.y) && (yInverted <= (rectButton.origin.y + rectButton.size.height))) {
if ((pt.x >= rectButton.origin.x) && (pt.x <= (rectButton.origin.x + rectButton.size.width))) {
// notify qml of close button click
return true;
}
}
}
return false;
}
return false;
}
Затем в main.cpp:
Application app(argc, argv);
app.installNativeEventFilter(new NativeFilter());