Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwindowsmenu.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qwindowsmenu.h"
5#include "qwindowscontext.h"
6#include "qwindowswindow.h"
7
8#include <QtGui/qwindow.h>
9#include <QtGui/private/qpixmap_win_p.h>
10#include <QtCore/qdebug.h>
11#include <QtCore/qvariant.h>
12#include <QtCore/qmetaobject.h>
13#include <QtCore/qpointer.h>
14
15#include <algorithm>
16
18
35static uint nextId = 1;
36
37// Find a QPlatformMenu[Item]* in a list of QWindowsMenu[Item], where
38// QList::indexOf() cannot be used since it wants a QWindowsMenu[Item]*
39template <class Derived, class Needle>
40static int indexOf(const QList<Derived *> &v, const Needle *needle)
41{
42 for (int i = 0, size = v.size(); i < size; ++i) {
43 if (v.at(i) == needle)
44 return i;
45 }
46 return -1;
47}
48
49// Helper for inserting a QPlatformMenu[Item]* into a list of QWindowsMenu[Item].
50template <class Derived, class Base>
51static int insertBefore(QList<Derived *> *v, Base *newItemIn, const Base *before = nullptr)
52{
53 int index = before ? indexOf(*v, before) : -1;
54 if (index != -1) {
55 v->insert(index, static_cast<Derived *>(newItemIn));
56 } else {
57 index = v->size();
58 v->append(static_cast<Derived *>(newItemIn));
59 }
60 return index;
61}
62
63static inline const wchar_t *qStringToWChar(const QString &s)
64{
65 return reinterpret_cast<const wchar_t *>(s.utf16());
66}
67
68// Traverse menu and return the item for which predicate
69// "bool Function(QWindowsMenuItem *)" returns true
70template <class Predicate>
72{
73 const QWindowsMenu::MenuItems &items = menu->menuItems();
74 for (QWindowsMenuItem *item : items) {
75 if (p(item))
76 return item;
77 if (item->subMenu()) {
78 if (QWindowsMenuItem *subMenuItem = traverseMenuItems(item->subMenu(), p))
79 return subMenuItem;
80 }
81 }
82 return nullptr;
83}
84
85// Traverse menu bar return the item for which predicate
86// "bool Function(QWindowsMenuItem *)" returns true
87template <class Predicate>
89{
90 const QWindowsMenuBar::Menus &menus = menuBar->menus();
91 for (QWindowsMenu *menu : menus) {
93 return item;
94 }
95 return nullptr;
96}
97
98template <class Menu /* Menu[Bar] */>
100{
101 return traverseMenuItems(menu, [id] (const QWindowsMenuItem *i) { return i->id() == id; });
102}
103
104// Traverse menu and return the menu for which predicate
105// "bool Function(QWindowsMenu *)" returns true
106template <class Predicate>
107static QWindowsMenu *traverseMenus(const QWindowsMenu *menu, Predicate p)
108{
109 const QWindowsMenu::MenuItems &items = menu->menuItems();
110 for (QWindowsMenuItem *item : items) {
111 if (QWindowsMenu *subMenu = item->subMenu()) {
112 if (p(subMenu))
113 return subMenu;
114 if (QWindowsMenu *menu = traverseMenus(subMenu, p))
115 return menu;
116 }
117 }
118 return nullptr;
119}
120
121// Traverse menu bar return the item for which
122// function "bool Function(QWindowsMenu *)" returns true
123template <class Predicate>
125{
126 const QWindowsMenuBar::Menus &menus = menuBar->menus();
127 for (QWindowsMenu *menu : menus) {
128 if (p(menu))
129 return menu;
130 if (QWindowsMenu *subMenu = traverseMenus(menu, p))
131 return subMenu;
132 }
133 return nullptr;
134}
135
136template <class Menu /* Menu[Bar] */>
137static QWindowsMenu *findMenuByHandle(const Menu *menu, HMENU hMenu)
138{
139 return traverseMenus(menu, [hMenu] (const QWindowsMenu *i) { return i->menuHandle() == hMenu; });
140}
141
142template <class MenuType>
143static int findNextVisibleEntry(const QList<MenuType *> &entries, int pos)
144{
145 for (int i = pos, size = entries.size(); i < size; ++i) {
146 if (entries.at(i)->isVisible())
147 return i;
148 }
149 return -1;
150}
151
152static inline void menuItemInfoInit(MENUITEMINFO &menuItemInfo)
153{
154 memset(&menuItemInfo, 0, sizeof(MENUITEMINFO));
155 menuItemInfo.cbSize = sizeof(MENUITEMINFO);
156}
157
158static inline void menuItemInfoSetText(MENUITEMINFO &menuItemInfo, const QString &text)
159{
160 menuItemInfoInit(menuItemInfo);
161 menuItemInfo.fMask = MIIM_STRING;
162 menuItemInfo.dwTypeData = const_cast<wchar_t *>(qStringToWChar(text));
163 menuItemInfo.cch = UINT(text.size());
164}
165
166static UINT menuItemState(HMENU hMenu, UINT uItem, BOOL fByPosition)
167{
168 MENUITEMINFO menuItemInfo;
169 menuItemInfoInit(menuItemInfo);
170 menuItemInfo.fMask = MIIM_STATE;
171 return GetMenuItemInfo(hMenu, uItem, fByPosition, &menuItemInfo) == TRUE ? menuItemInfo.fState : 0;
172}
173
174static void menuItemSetState(HMENU hMenu, UINT uItem, BOOL fByPosition, UINT flags)
175{
176 MENUITEMINFO menuItemInfo;
177 menuItemInfoInit(menuItemInfo);
178 menuItemInfo.fMask = MIIM_STATE;
179 menuItemInfo.fState = flags;
180 SetMenuItemInfo(hMenu, uItem, fByPosition, &menuItemInfo);
181}
182
183static void menuItemSetChangeState(HMENU hMenu, UINT uItem, BOOL fByPosition,
184 bool value, UINT trueState, UINT falseState)
185{
186 const UINT oldState = menuItemState(hMenu, uItem, fByPosition);
187 UINT newState = oldState;
188 if (value) {
189 newState |= trueState;
190 newState &= ~falseState;
191 } else {
192 newState &= ~trueState;
193 newState |= falseState;
194 }
195 if (oldState != newState)
196 menuItemSetState(hMenu, uItem, fByPosition, newState);
197}
198
199// ------------ QWindowsMenuItem
201 : m_parentMenu(parentMenu)
202 , m_id(0)
203{
204 qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this)
205 << "parentMenu=" << parentMenu;
206}
207
209{
210 qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this);
212 freeBitmap();
213}
214
215void QWindowsMenuItem::freeBitmap()
216{
217 if (m_hbitmap) {
218 DeleteObject(m_hbitmap);
219 m_hbitmap = nullptr;
220 }
221}
222
224{
225 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << icon << ')' << this;
226 if (m_icon.cacheKey() == icon.cacheKey())
227 return;
228 m_icon = icon;
229 if (m_parentMenu != nullptr)
230 updateBitmap();
231}
232
233void QWindowsMenuItem::updateBitmap()
234{
235 freeBitmap();
236 if (!m_icon.isNull()) {
237 const int size = m_iconSize ? m_iconSize : GetSystemMetrics(SM_CYMENUCHECK);
238 m_hbitmap = qt_pixmapToWinHBITMAP(m_icon.pixmap(QSize(size, size)), 1);
239 }
240 MENUITEMINFO itemInfo;
241 menuItemInfoInit(itemInfo);
242 itemInfo.fMask = MIIM_BITMAP;
243 itemInfo.hbmpItem = m_hbitmap;
244 SetMenuItemInfo(parentMenuHandle(), m_id, FALSE, &itemInfo);
245}
246
248{
249 qCDebug(lcQpaMenus).nospace().noquote()
250 << __FUNCTION__ << "(\"" << text << "\") " << this;
251 if (m_text == text)
252 return;
253 m_text = text;
254 if (m_parentMenu != nullptr)
255 updateText();
256}
257
258void QWindowsMenuItem::updateText()
259{
260 MENUITEMINFO menuItemInfo;
261 const QString &text = nativeText();
262 menuItemInfoSetText(menuItemInfo, text);
263 SetMenuItemInfo(parentMenuHandle(), m_id, FALSE, &menuItemInfo);
264}
265
267{
268 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuIn << ')' << this;
269 if (menuIn == m_subMenu)
270 return;
271 const uint oldId = m_id;
272 if (menuIn != nullptr) { // Set submenu
273 m_subMenu = static_cast<QWindowsMenu *>(menuIn);
274 m_subMenu->setAsItemSubMenu(this);
275 m_id = m_subMenu->id();
276 if (m_parentMenu != nullptr) {
277 ModifyMenu(m_parentMenu->menuHandle(), oldId, MF_BYCOMMAND | MF_POPUP,
278 m_id, qStringToWChar(m_text));
279 }
280 return;
281 }
282 // Clear submenu
283 m_subMenu = nullptr;
284 if (m_parentMenu != nullptr) {
285 m_id = nextId++;
286 ModifyMenu(m_parentMenu->menuHandle(), oldId, MF_BYCOMMAND,
287 m_id, qStringToWChar(m_text));
288 } else {
289 m_id = 0;
290 }
291}
292
294{
295 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << isVisible << ')' << this;
296 if (m_visible == isVisible)
297 return;
298 m_visible = isVisible;
299 if (m_parentMenu == nullptr)
300 return;
301 // Windows menu items do not implement settable visibility, we need to work
302 // around by removing the item from the menu. It will be kept in the list.
303 if (isVisible)
304 insertIntoMenuHelper(m_parentMenu, false, m_parentMenu->menuItems().indexOf(this));
305 else
306 RemoveMenu(parentMenuHandle(), m_id, MF_BYCOMMAND);
307}
308
310{
311 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << isSeparator << ')' << this;
312 if (m_separator == isSeparator)
313 return;
314 m_separator = isSeparator;
315 if (m_parentMenu == nullptr)
316 return;
317 MENUITEMINFO menuItemInfo;
318 menuItemInfoInit(menuItemInfo);
319 menuItemInfo.fMask = MIIM_FTYPE;
320 menuItemInfo.fType = isSeparator ? MFT_SEPARATOR : MFT_STRING;
321 SetMenuItemInfo(parentMenuHandle(), m_id, FALSE, &menuItemInfo);
322}
323
325{
326 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << checkable << ')' << this;
327 if (m_checkable == checkable)
328 return;
329 m_checkable = checkable;
330 if (m_parentMenu == nullptr)
331 return;
332 UINT state = menuItemState(parentMenuHandle(), m_id, FALSE);
333 if (m_checkable)
334 state |= m_checked ? MF_CHECKED : MF_UNCHECKED;
335 else
336 state &= ~(MF_CHECKED | MF_UNCHECKED);
337 menuItemSetState(parentMenuHandle(), m_id, FALSE, state);
338}
339
341{
342 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << isChecked << ')' << this;
343 if (m_checked == isChecked)
344 return;
345 m_checked = isChecked;
346 // Convenience: Allow to set checkable by calling setChecked(true) for
347 // Quick Controls 1
348 if (isChecked)
349 m_checkable = true;
350 if (m_parentMenu == nullptr || !m_checkable)
351 return;
352 menuItemSetChangeState(parentMenuHandle(), m_id, FALSE, m_checked, MF_CHECKED, MF_UNCHECKED);
353}
354
355#if QT_CONFIG(shortcut)
357{
358 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << shortcut << ')' << this;
359 if (m_shortcut == shortcut)
360 return;
361 m_shortcut = shortcut;
362 if (m_parentMenu != nullptr)
363 updateText();
364}
365#endif
366
368{
369 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << enabled << ')' << this;
370 if (m_enabled == enabled)
371 return;
372 m_enabled = enabled;
373 if (m_parentMenu != nullptr)
374 menuItemSetChangeState(parentMenuHandle(), m_id, FALSE, m_enabled, MF_ENABLED, MF_GRAYED);
375}
376
378{
379 if (m_iconSize == size)
380 return;
381 m_iconSize = size;
382 if (m_parentMenu != nullptr)
383 updateBitmap();
384}
385
387{
388 return m_parentMenu ? m_parentMenu->menuHandle() : nullptr;
389}
390
392{
393 if (m_separator)
394 return MF_SEPARATOR;
395 UINT result = MF_STRING | (m_enabled ? MF_ENABLED : MF_GRAYED);
396 if (m_subMenu != nullptr)
397 result |= MF_POPUP;
398 if (m_checkable)
399 result |= m_checked ? MF_CHECKED : MF_UNCHECKED;
401 result |= MFT_RIGHTORDER;
402 return result;
403}
404
406{
407 QString result = m_text;
408#if QT_CONFIG(shortcut)
409 if (!m_shortcut.isEmpty()) {
410 result += u'\t';
412 }
413#endif
414 return result;
415}
416
418{
419 if (m_id == 0 && m_subMenu == nullptr)
420 m_id = nextId++;
421 insertIntoMenuHelper(menu, append, index);
422 m_parentMenu = menu;
423}
424
425void QWindowsMenuItem::insertIntoMenuHelper(QWindowsMenu *menu, bool append, int index)
426{
427 const QString &text = nativeText();
428
429 UINT_PTR idBefore = 0;
430 if (!append) {
431 // Skip over self (either newly inserted or when called from setVisible()
432 const int nextIndex = findNextVisibleEntry(menu->menuItems(), index + 1);
433 if (nextIndex != -1)
434 idBefore = menu->menuItems().at(nextIndex)->id();
435 }
436
437 if (idBefore)
438 InsertMenu(menu->menuHandle(), idBefore, state(), m_id, qStringToWChar(text));
439 else
440 AppendMenu(menu->menuHandle(), state(), m_id, qStringToWChar(text));
441
442 updateBitmap();
443}
444
446{
447 if (QWindowsMenu *parentMenu = m_parentMenu) {
448 m_parentMenu = nullptr;
449 RemoveMenu(parentMenu->menuHandle(), m_id, MF_BYCOMMAND);
451 return true;
452 }
453 return false;
454}
455
456// ------------ QWindowsMenu
457
461
463 : m_parentMenu(parentMenu)
464 , m_hMenu(menu)
465{
466 qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this)
467 << "parentMenu=" << parentMenu << "HMENU=" << m_hMenu;
468}
469
471{
472 qCDebug(lcQpaMenus).noquote().nospace() << __FUNCTION__
473 << " \"" <<m_text << "\", " << static_cast<const void *>(this);
474 for (int i = m_menuItems.size() - 1; i>= 0; --i)
475 m_menuItems.at(i)->removeFromMenu();
477 DestroyMenu(m_hMenu);
478}
479
481{
482 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuItemIn << ", before=" << before << ')' << this;
483 auto *menuItem = static_cast<QWindowsMenuItem *>(menuItemIn);
484 const int index = insertBefore(&m_menuItems, menuItemIn, before);
485 const bool append = index == m_menuItems.size() - 1;
486 menuItem->insertIntoMenu(this, append, index);
487}
488
490{
491 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuItemIn << ')' << this;
492 static_cast<QWindowsMenuItem *>(menuItemIn)->removeFromMenu();
493}
494
496{
497 qCDebug(lcQpaMenus).nospace().noquote()
498 << __FUNCTION__ << "(\"" << text << "\") " << this;
499 if (m_text == text)
500 return;
501 m_text = text;
502 if (!m_visible)
503 return;
504 const HMENU ph = parentHandle();
505 if (ph == nullptr)
506 return;
507 MENUITEMINFO menuItemInfo;
508 menuItemInfoSetText(menuItemInfo, m_text);
509 SetMenuItemInfo(ph, id(), FALSE, &menuItemInfo);
510}
511
513{
514 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << icon << ')' << this;
515 m_icon = icon;
516}
517
519{
520 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << enabled << ')' << this;
521 if (m_enabled == enabled)
522 return;
523 m_enabled = enabled;
524 if (!m_visible)
525 return;
526 if (const HMENU ph = parentHandle())
527 menuItemSetChangeState(ph, id(), FALSE, m_enabled, MF_ENABLED, MF_GRAYED);
528}
529
531{
532 const auto it = std::find_if(m_menuItems.cbegin(), m_menuItems.cend(),
533 [subMenu] (const QWindowsMenuItem *i) { return i->subMenu() == subMenu; });
534 return it != m_menuItems.cend() ? *it : nullptr;
535}
536
538{
539 UINT_PTR idBefore = 0;
540 if (!append) {
541 // Skip over self (either newly inserted or when called from setVisible()
542 const int nextIndex = findNextVisibleEntry(bar->menus(), index + 1);
543 if (nextIndex != -1)
544 idBefore = bar->menus().at(nextIndex)->id();
545 }
546 m_parentMenuBar = bar;
547 m_parentMenu = nullptr;
548 if (idBefore)
549 InsertMenu(bar->menuBarHandle(), idBefore, MF_POPUP | MF_BYCOMMAND, id(), qStringToWChar(m_text));
550 else
551 AppendMenu(bar->menuBarHandle(), MF_POPUP, id(), qStringToWChar(m_text));
552}
553
555{
556 if (QWindowsMenuBar *bar = m_parentMenuBar) {
557 m_parentMenuBar = nullptr;
558 bar->notifyRemoved(this);
559 return RemoveMenu(bar->menuBarHandle(), id(), MF_BYCOMMAND) == TRUE;
560 }
561 if (QWindowsMenu *menu = m_parentMenu) {
562 m_parentMenu = nullptr;
563 QWindowsMenuItem *item = menu->itemForSubMenu(this);
564 if (item)
565 item->setMenu(nullptr);
566 return item != nullptr;
567 }
568 return false;
569}
570
571void QWindowsMenu::setVisible(bool visible)
572{
573 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << visible << ')' << this;
574 if (m_visible == visible)
575 return;
576 m_visible = visible;
577 const HMENU ph = parentHandle();
578 if (ph == nullptr)
579 return;
580 // Windows menus do not implement settable visibility, we need to work
581 // around by removing the menu from the parent. It will be kept in the list.
582 if (visible) {
583 if (m_parentMenuBar)
584 insertIntoMenuBar(m_parentMenuBar, false, m_parentMenuBar->menus().indexOf(this));
585 } else {
586 RemoveMenu(ph, id(), MF_BYCOMMAND);
587 }
588 if (m_parentMenuBar)
589 m_parentMenuBar->redraw();
590}
591
593{
594 qCDebug(lcQpaMenus) << __FUNCTION__ << position;
595 return position >= 0 && position < m_menuItems.size()
596 ? m_menuItems.at(position) : nullptr;
597}
598
600{
601 return traverseMenuItems(this, [tag] (const QPlatformMenuItem *i) { return i->tag() == tag; });
602}
603
605{
607 qCDebug(lcQpaMenus) << __FUNCTION__ << this << "returns" << result;
608 return result;
609}
610
612{
614 qCDebug(lcQpaMenus) << __FUNCTION__ << this << "returns" << result;
615 return result;
616}
617
619{
620 m_parentMenu = item->parentMenu();
621}
622
624{
625 return m_parentMenu ? m_parentMenu->menuHandle() : nullptr;
626}
627
629{
630 return m_parentMenuBar ? m_parentMenuBar->menuBarHandle() : nullptr;
631}
632
634{
635 if (m_parentMenuBar)
636 return m_parentMenuBar->menuBarHandle();
637 if (m_parentMenu)
638 return m_parentMenu->menuHandle();
639 return nullptr;
640}
641
642// --------------- QWindowsPopupMenu
643
644static QPointer<QWindowsPopupMenu> lastShownPopupMenu;
645
649
650void QWindowsPopupMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
651 const QPlatformMenuItem *item)
652{
653 qCDebug(lcQpaMenus) << __FUNCTION__ << '>' << this << parentWindow << targetRect << item;
654 const auto *window = static_cast<const QWindowsBaseWindow *>(parentWindow->handle());
655 const QPoint globalPos = window->mapToGlobal(targetRect.topLeft());
656 trackPopupMenu(window->handle(), globalPos.x(), globalPos.y());
657}
658
659bool QWindowsPopupMenu::trackPopupMenu(HWND windowHandle, int x, int y)
660{
661 lastShownPopupMenu = this;
662 // Emulate Show()/Hide() signals. Could be implemented by catching the
663 // WM_EXITMENULOOP, WM_ENTERMENULOOP messages; but they do not carry
664 // information telling which menu was opened.
666 const bool result =
667 TrackPopupMenu(menuHandle(),
668 QGuiApplication::layoutDirection() == Qt::RightToLeft ? UINT(TPM_RIGHTALIGN) : UINT(0),
669 x, y, 0, windowHandle, nullptr) == TRUE;
671 return result;
672}
673
675{
677 ? nullptr
679 if (result != nullptr) {
680 qCDebug(lcQpaMenus) << __FUNCTION__ << "id=" << id;
681 emit result->activated();
682 }
683 lastShownPopupMenu = nullptr;
684 return result != nullptr;
685}
686
688{
689 if (lastShownPopupMenu.isNull())
690 return false;
691 if (lastShownPopupMenu->menuHandle() == hmenu) {
692 emit lastShownPopupMenu->aboutToShow();
693 return true;
694 }
697 return true;
698 }
699 return false;
700}
701
702// --------------- QWindowsMenuBar
703
704QWindowsMenuBar::QWindowsMenuBar() : m_hMenuBar(CreateMenu())
705{
706 qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this);
707}
708
710{
711 qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this);
712 for (int m = m_menus.size() - 1; m >= 0; --m)
713 m_menus.at(m)->removeFromParent();
714 removeFromWindow();
715 DestroyMenu(m_hMenuBar);
716}
717
719{
720 qCDebug(lcQpaMenus) << __FUNCTION__ << menuIn << "before=" << before;
721 auto *menu = static_cast<QWindowsMenu *>(menuIn);
722 const int index = insertBefore(&m_menus, menuIn, before);
723 menu->insertIntoMenuBar(this, index == m_menus.size() - 1, index);
724}
725
727{
728 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menu << ')' << this;
729 const int index = indexOf(m_menus, menu);
730 if (index != -1)
731 m_menus[index]->removeFromParent();
732}
733
734// When calling handleReparent() for a QWindow instances that does not have
735// a platform window yet, set the menubar as dynamic property to be installed
736// on platform window creation.
737static const char menuBarPropertyName[] = "_q_windowsNativeMenuBar";
738
740{
741 qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << newParentWindow << ')' << this;
742 if (newParentWindow == nullptr) {
743 removeFromWindow();
744 return; // Happens during Quick Controls 1 property setup
745 }
746 if (QPlatformWindow *platWin = newParentWindow->handle())
747 install(static_cast<QWindowsWindow *>(platWin));
748 else // Store for later creation, see menuBarOf()
749 newParentWindow->setProperty(menuBarPropertyName, QVariant::fromValue<QObject *>(this));
750}
751
753{
754 const QVariant menuBarV = notYetCreatedWindow->property(menuBarPropertyName);
755 return menuBarV.canConvert<QObject *>()
756 ? qobject_cast<QWindowsMenuBar *>(menuBarV.value<QObject *>()) : nullptr;
757}
758
760{
761 const HWND hwnd = window->handle();
762 const BOOL result = SetMenu(hwnd, m_hMenuBar);
763 if (result) {
764 window->setMenuBar(this);
766 }
767}
768
769void QWindowsMenuBar::removeFromWindow()
770{
771 if (QWindowsWindow *window = platformWindow()) {
772 const HWND hwnd = window->handle();
773 SetMenu(hwnd, nullptr);
774 window->setMenuBar(nullptr);
776 }
777}
778
780{
781 return traverseMenus(this, [tag] (const QWindowsMenu *m) { return m->tag() == tag; });
782}
783
785{
787 qCDebug(lcQpaMenus) << __FUNCTION__ << this << "returns" << result;
788 return result;
789}
790
792{
794 if (result != nullptr) {
795 qCDebug(lcQpaMenus) << __FUNCTION__ << "id=" << id;
796 emit result->activated();
797 }
798 return result != nullptr;
799}
800
802{
803 if (QWindowsMenu *menu = findMenuByHandle(this, hmenu)) {
805 return true;
806 }
807 return false;
808}
809
810QWindowsWindow *QWindowsMenuBar::platformWindow() const
811{
813 if (QWindowsWindow *w = ctx->findPlatformWindow(this))
814 return w;
815 }
816 return nullptr;
817}
818
820{
821 if (const QWindowsWindow *window = platformWindow())
822 DrawMenuBar(window->handle());
823}
824
825#ifndef QT_NO_DEBUG_STREAM
826
827template <class M> /* Menu[Item] */
828static void formatTextSequence(QDebug &d, const QList<M *> &v)
829{
830 if (const int size = v.size()) {
831 d << '[' << size << "](";
832 for (int i = 0; i < size; ++i) {
833 if (i)
834 d << ", ";
835 if (!v.at(i)->isVisible())
836 d << "[hidden] ";
837 d << '"' << v.at(i)->text() << '"';
838 }
839 d << ')';
840 }
841}
842
844{
845 if (m_separator)
846 d << "separator, ";
847 else
848 d << '"' << m_text << "\", ";
849 d << static_cast<const void *>(this);
850 if (m_parentMenu)
851 d << ", parentMenu=" << static_cast<const void *>(m_parentMenu);
852 if (m_subMenu)
853 d << ", subMenu=" << static_cast<const void *>(m_subMenu);
854 d << ", tag=" << Qt::showbase << Qt::hex
855 << tag() << Qt::noshowbase << Qt::dec << ", id=" << m_id;
856#if QT_CONFIG(shortcut)
857 if (!m_shortcut.isEmpty())
858 d << ", shortcut=" << m_shortcut;
859#endif
860 if (m_visible)
861 d << " [visible]";
862 if (m_enabled)
863 d << " [enabled]";
864 if (m_checkable)
865 d << ", checked=" << m_checked;
866}
867
869{
870 QDebugStateSaver saver(d);
871 d.nospace();
872 d.noquote();
873 d << "QPlatformMenuItem(";
874 if (i)
875 static_cast<const QWindowsMenuItem *>(i)->formatDebug(d);
876 else
877 d << '0';
878 d << ')';
879 return d;
880}
881
883{
884 d << '"' << m_text << "\", " << static_cast<const void *>(this)
885 << ", handle=" << m_hMenu;
886 if (m_parentMenuBar != nullptr)
887 d << " [on menubar]";
888 if (m_parentMenu != nullptr)
889 d << " [on menu]";
890 if (tag())
891 d << ", tag=" << Qt::showbase << Qt::hex << tag() << Qt::noshowbase << Qt::dec;
892 if (m_visible)
893 d << " [visible]";
894 if (m_enabled)
895 d << " [enabled]";
896 d <<' ';
897 formatTextSequence(d, m_menuItems);
898}
899
901{
902 d << static_cast<const void *>(this) << ' ';
903 formatTextSequence(d, m_menus);
904}
905
907{
908 QDebugStateSaver saver(d);
909 d.nospace();
910 d.noquote();
911 if (m) {
912 d << m->metaObject()->className() << '(';
913 static_cast<const QWindowsMenu *>(m)->formatDebug(d);
914 d << ')';
915 } else {
916 d << "QPlatformMenu(0)";
917 }
918 return d;
919}
920
922{
923 QDebugStateSaver saver(d);
924 d.nospace();
925 d.noquote();
926 d << "QPlatformMenuBar(";
927 if (mb)
928 static_cast<const QWindowsMenuBar *>(mb)->formatDebug(d);
929 else
930 d << '0';
931 d << ')';
932 return d;
933}
934
935#endif // !QT_NO_DEBUG_STREAM
936
\inmodule QtCore
\inmodule QtCore
Qt::LayoutDirection layoutDirection
the default layout direction for this application
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:1019
qint64 cacheKey() const
Returns a number that identifies the contents of this QIcon object.
Definition qicon.cpp:819
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Definition qicon.cpp:834
The QKeySequence class encapsulates a key sequence as used by shortcuts.
bool isEmpty() const
Returns true if the key sequence is empty; otherwise returns false.
QString toString(SequenceFormat format=PortableText) const
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
const_iterator cend() const noexcept
Definition qlist.h:631
const_iterator cbegin() const noexcept
Definition qlist.h:630
void aboutToShow()
This signal is emitted just before the menu is shown to the user.
\inmodule QtCore
Definition qobject.h:103
virtual quintptr tag() const
virtual quintptr tag() const
void aboutToHide()
void aboutToShow()
The QPlatformWindow class provides an abstraction for top-level windows.
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
\inmodule QtCore
Definition qvariant.h:65
bool canConvert(QMetaType targetType) const
Definition qvariant.h:345
\inmodule QtGui
Definition qwindow.h:63
Base class for QWindowsForeignWindow, QWindowsWindow.
Singleton container for all relevant information.
static void forceNcCalcSize(HWND hwnd)
static QWindowsContext * instance()
Windows native menu bar.
static QWindowsMenuBar * menuBarOf(const QWindow *notYetCreatedWindow)
void formatDebug(QDebug &d) const
const Menus & menus() const
void removeMenu(QPlatformMenu *menu) override
void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) override
void notifyRemoved(QWindowsMenu *menu)
bool notifyAboutToShow(HMENU hmenu)
void install(QWindowsWindow *window)
HMENU menuBarHandle() const
~QWindowsMenuBar() override
QPlatformMenu * menuForTag(quintptr tag) const override
bool notifyTriggered(uint id)
void handleReparent(QWindow *newParentWindow) override
QPlatformMenu * createMenu() const override
void redraw() const
void setChecked(bool isChecked) override
void setCheckable(bool checkable) override
void insertIntoMenu(QWindowsMenu *menuItem, bool append, int index)
UINT state() const
QString text() const
void setIconSize(int size) override
void formatDebug(QDebug &d) const
void setIsSeparator(bool isSeparator) override
QString nativeText() const
~QWindowsMenuItem() override
void setIcon(const QIcon &icon) override
void setMenu(QPlatformMenu *menu) override
void setShortcut(const QKeySequence &shortcut) override
void setText(const QString &text) override
bool isVisible() const
QWindowsMenuItem(QWindowsMenu *parentMenu=nullptr)
void setEnabled(bool enabled) override
void setVisible(bool isVisible) override
const QWindowsMenu * parentMenu() const
HMENU parentMenuHandle() const
HMENU parentMenuBarHandle() const
void setText(const QString &text) override
QString text() const
UINT_PTR id() const
HMENU parentHandle() const
void setEnabled(bool enabled) override
const QWindowsMenu * parentMenu() const
void notifyRemoved(QWindowsMenuItem *item)
QPlatformMenu * createSubMenu() const override
void removeMenuItem(QPlatformMenuItem *menuItem) override
QPlatformMenuItem * createMenuItem() const override
const MenuItems & menuItems() const
void formatDebug(QDebug &d) const
HMENU menuHandle() const
QPlatformMenuItem * menuItemAt(int position) const override
void setVisible(bool visible) override
void setIcon(const QIcon &icon) override
HMENU parentMenuHandle() const
QPlatformMenuItem * menuItemForTag(quintptr tag) const override
void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override
QWindowsMenuItem * itemForSubMenu(const QWindowsMenu *subMenu) const
bool removeFromParent()
void setAsItemSubMenu(QWindowsMenuItem *item)
void insertIntoMenuBar(QWindowsMenuBar *bar, bool append, int index)
static bool notifyAboutToShow(HMENU hmenu)
static bool notifyTriggered(uint id)
void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) override
bool trackPopupMenu(HWND windowHandle, int x, int y)
Raster or OpenGL Window.
EGLContext ctx
QString text
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
QTextStream & showbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ShowBase) on stream and r...
@ RightToLeft
QTextStream & noshowbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on stream and ...
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
AudioChannelLayoutTag tag
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static bool isSeparator(char c)
Definition qhsts.cpp:280
#define qCDebug(category,...)
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLenum GLuint id
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLbitfield flags
GLint y
GLdouble s
[6]
Definition qopenglext.h:235
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
#define enabled
static void menuItemSetChangeState(HMENU hMenu, UINT uItem, BOOL fByPosition, bool value, UINT trueState, UINT falseState)
static QWindowsMenu * traverseMenus(const QWindowsMenu *menu, Predicate p)
QDebug operator<<(QDebug d, const QPlatformMenuItem *i)
static QWindowsMenuItem * findMenuItemById(const Menu *menu, uint id)
static int insertBefore(QList< Derived * > *v, Base *newItemIn, const Base *before=nullptr)
static const char menuBarPropertyName[]
static QWindowsMenu * findMenuByHandle(const Menu *menu, HMENU hMenu)
static void menuItemInfoInit(MENUITEMINFO &menuItemInfo)
static void menuItemSetState(HMENU hMenu, UINT uItem, BOOL fByPosition, UINT flags)
static uint nextId
static QWindowsMenuItem * traverseMenuItems(const QWindowsMenu *menu, Predicate p)
static int findNextVisibleEntry(const QList< MenuType * > &entries, int pos)
static const wchar_t * qStringToWChar(const QString &s)
static void menuItemInfoSetText(MENUITEMINFO &menuItemInfo, const QString &text)
static UINT menuItemState(HMENU hMenu, UINT uItem, BOOL fByPosition)
static void formatTextSequence(QDebug &d, const QList< M * > &v)
static QPointer< QWindowsPopupMenu > lastShownPopupMenu
static int indexOf(const QList< Derived * > &v, const Needle *needle)
QObject::connect nullptr
list indexOf("B")
QGraphicsItem * item
edit isVisible()
QList< QTreeWidgetItem * > items
aWidget window() -> setWindowTitle("New Window Title")
[2]
QMenu menu
[5]
QMenuBar * menuBar
[0]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:962