popup-menu.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #if defined(Hiro_PopupMenu)
  2. namespace hiro {
  3. auto pPopupMenu::construct() -> void {
  4. hwnd = CreateWindow(L"hiroPopupMenu", L"", ResizableStyle, 0, 0, 0, 0, 0, 0, GetModuleHandle(0), 0);
  5. }
  6. auto pPopupMenu::destruct() -> void {
  7. if(hmenu) { DestroyMenu(hmenu); hmenu = nullptr; }
  8. DestroyWindow(hwnd);
  9. }
  10. auto pPopupMenu::append(sAction action) -> void {
  11. }
  12. auto pPopupMenu::remove(sAction action) -> void {
  13. }
  14. auto pPopupMenu::setFont(const Font& font) -> void {
  15. }
  16. auto pPopupMenu::setVisible(bool visible) -> void {
  17. if(!visible) return;
  18. if(hmenu) DestroyMenu(hmenu);
  19. hmenu = CreatePopupMenu();
  20. MENUINFO mi{sizeof(MENUINFO)};
  21. mi.fMask = MIM_STYLE;
  22. mi.dwStyle = MNS_NOTIFYBYPOS; //| MNS_MODELESS;
  23. SetMenuInfo(hmenu, &mi);
  24. unsigned position = 0;
  25. for(auto& action : state().actions) {
  26. if(!action->self()) continue;
  27. action->self()->position = position;
  28. unsigned enabled = action->enabled() ? 0 : MF_GRAYED;
  29. MENUITEMINFO mii{sizeof(MENUITEMINFO)};
  30. mii.fMask = MIIM_DATA;
  31. mii.dwItemData = (ULONG_PTR)action.data();
  32. if(auto menu = dynamic_cast<mMenu*>(action.data())) {
  33. if(menu->visible()) {
  34. menu->self()->_update();
  35. AppendMenu(hmenu, MF_STRING | MF_POPUP | enabled, (UINT_PTR)menu->self()->hmenu, utf16_t(menu->text()));
  36. if(auto bitmap = menu->self()->hbitmap) {
  37. //Windows XP and below displays MIIM_BITMAP + hbmpItem in its own column (separate from check/radio marks)
  38. //this causes too much spacing, so use a custom checkmark image instead
  39. mii.fMask |= MIIM_CHECKMARKS;
  40. mii.hbmpUnchecked = bitmap;
  41. }
  42. SetMenuItemInfo(hmenu, position++, true, &mii);
  43. }
  44. }
  45. #if defined(Hiro_MenuSeparator)
  46. else if(auto menuSeparator = dynamic_cast<mMenuSeparator*>(action.data())) {
  47. if(menuSeparator->visible()) {
  48. AppendMenu(hmenu, MF_SEPARATOR | enabled, position, L"");
  49. SetMenuItemInfo(hmenu, position++, true, &mii);
  50. }
  51. }
  52. #endif
  53. #if defined(Hiro_MenuItem)
  54. else if(auto menuItem = dynamic_cast<mMenuItem*>(action.data())) {
  55. if(menuItem->visible()) {
  56. AppendMenu(hmenu, MF_STRING | enabled, position, utf16_t(menuItem->text()));
  57. if(auto bitmap = menuItem->self()->hbitmap) {
  58. mii.fMask |= MIIM_CHECKMARKS;
  59. mii.hbmpUnchecked = bitmap;
  60. }
  61. SetMenuItemInfo(hmenu, position++, true, &mii);
  62. }
  63. }
  64. #endif
  65. #if defined(Hiro_MenuCheckItem)
  66. else if(auto menuCheckItem = dynamic_cast<mMenuCheckItem*>(action.data())) {
  67. if(menuCheckItem->visible()) {
  68. AppendMenu(hmenu, MF_STRING | enabled, position, utf16_t(menuCheckItem->text()));
  69. SetMenuItemInfo(hmenu, position++, true, &mii);
  70. if(menuCheckItem->checked()) menuCheckItem->setChecked();
  71. }
  72. }
  73. #endif
  74. #if defined(Hiro_MenuRadioItem)
  75. else if(auto menuRadioItem = dynamic_cast<mMenuRadioItem*>(action.data())) {
  76. if(menuRadioItem->visible()) {
  77. AppendMenu(hmenu, MF_STRING | enabled, position, utf16_t(menuRadioItem->text()));
  78. SetMenuItemInfo(hmenu, position++, true, &mii);
  79. if(menuRadioItem->checked()) menuRadioItem->setChecked();
  80. }
  81. }
  82. #endif
  83. }
  84. POINT point{0};
  85. GetCursorPos(&point);
  86. TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y, 0, hwnd, nullptr);
  87. }
  88. }
  89. #endif