- Allow creating wxCursor from ANI files (Catalin Raceanu).
- Add wxIcon::CreateFromHICON() (troelsk).
- Improve wxCURSOR_RIGHT_ARROW appearance (DoltAlya).
+- Generate menu highlight events for popup menus in wxDialog (Sam Partington).
wxOSX/Cocoa:
// event handlers
bool HandleSize(int x, int y, WXUINT flag);
bool HandleCommand(WXWORD id, WXWORD cmd, WXHWND control);
- bool HandleMenuSelect(WXWORD nItem, WXWORD nFlags, WXHMENU hMenu);
// tooltip management
#if wxUSE_TOOLTIPS
// get the currently active menu: this is the same as the frame menu for
// normal frames but is overridden by wxMDIParentFrame
virtual WXHMENU MSWGetActiveMenu() const { return m_hMenu; }
+
+ // Look up the menu in the menu bar.
+ virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu);
#endif // wxUSE_MENUS
protected:
// wxMDIChildFrame
bool MSWDoTranslateMessage(wxFrame *frame, WXMSG *msg);
-#if wxUSE_MENUS
- // handle WM_EXITMENULOOP message for Win95 only
- bool HandleExitMenuLoop(WXWORD isPopup);
-
- // handle WM_(UN)INITMENUPOPUP message to generate wxEVT_MENU_OPEN/CLOSE
- bool HandleMenuPopup(wxEventType evtType, WXHMENU hMenu);
-
- // Command part of HandleMenuPopup() and HandleExitMenuLoop().
- bool DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup);
-#endif // wxUSE_MENUS
-
-
virtual bool IsMDIChild() const { return false; }
// get default (wxWidgets) icon for the frame
// returns true if the platform should explicitly apply a theme border
virtual bool CanApplyThemeBorder() const { return false; }
+#if wxUSE_MENUS
+ bool HandleMenuSelect(WXWORD nItem, WXWORD nFlags, WXHMENU hMenu);
+
+ // handle WM_EXITMENULOOP message for Win95 only
+ bool HandleExitMenuLoop(WXWORD isPopup);
+
+ // handle WM_(UN)INITMENUPOPUP message to generate wxEVT_MENU_OPEN/CLOSE
+ bool HandleMenuPopup(wxEventType evtType, WXHMENU hMenu);
+
+ // Command part of HandleMenuPopup() and HandleExitMenuLoop().
+ bool DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup);
+
+ // Find the menu corresponding to the given handle.
+ virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu);
+#endif // wxUSE_MENUS
+
protected:
// common part of all ctors
void Init();
wxWindow *SetTmpDefaultItem(wxWindow *win)
{ wxWindow *old = GetDefaultItem(); m_winTmpDefault = win; return old; }
-
// implementation only from now on
// -------------------------------
virtual void SetRepresentedFilename(const wxString& WXUNUSED(filename)) { }
+#if wxUSE_MENUS || wxUSE_TOOLBAR
+ // show help text for the currently selected menu or toolbar item
+ // (typically in the status bar) or hide it and restore the status bar text
+ // originally shown before the menu was opened if show == false
+ virtual void DoGiveHelp(const wxString& WXUNUSED(text), bool WXUNUSED(show)) {}
+#endif
+
protected:
// the frame client to screen translation should take account of the
// toolbar which may shift the origin of the client area
void OnClearLog(wxCommandEvent& event);
void OnClearLogUpdateUI(wxUpdateUIEvent& event);
#endif // USE_LOG_WINDOW
+ void OnShowDialog(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnMenuOpen(wxMenuEvent& event)
{
#if USE_LOG_WINDOW
- LogMenuOpenOrClose(event, wxT("opened")); event.Skip();
+ LogMenuOpenCloseOrHighlight(event, wxT("opened")); event.Skip();
#endif
}
void OnMenuClose(wxMenuEvent& event)
{
#if USE_LOG_WINDOW
- LogMenuOpenOrClose(event, wxT("closed")); event.Skip();
+ LogMenuOpenCloseOrHighlight(event, wxT("closed")); event.Skip();
+#endif
+ }
+ void OnMenuHighlight(wxMenuEvent& event)
+ {
+#if USE_LOG_WINDOW
+ LogMenuOpenCloseOrHighlight(event, wxT("highlighted")); event.Skip();
#endif
}
void OnSize(wxSizeEvent& event);
private:
- void LogMenuOpenOrClose(const wxMenuEvent& event, const wxChar *what);
+#if USE_LOG_WINDOW
+ void LogMenuOpenCloseOrHighlight(const wxMenuEvent& event, const wxChar *what);
+#endif
void ShowContextMenu(const wxPoint& pos);
wxMenu *CreateDummyMenu(wxString *title);
DECLARE_EVENT_TABLE()
};
+class MyDialog : public wxDialog
+{
+public:
+ MyDialog(wxWindow* parent);
+
+#if USE_CONTEXT_MENU
+ void OnContextMenu(wxContextMenuEvent& event);
+#else
+ void OnRightUp(wxMouseEvent& event)
+ { ShowContextMenu(event.GetPosition()); }
+#endif
+
+ void OnMenuOpen(wxMenuEvent& event)
+ {
+#if USE_LOG_WINDOW
+ LogMenuOpenCloseOrHighlight(event, wxT("opened")); event.Skip();
+#endif
+ }
+ void OnMenuClose(wxMenuEvent& event)
+ {
+#if USE_LOG_WINDOW
+ LogMenuOpenCloseOrHighlight(event, wxT("closed")); event.Skip();
+#endif
+ }
+ void OnMenuHighlight(wxMenuEvent& event)
+ {
+#if USE_LOG_WINDOW
+ LogMenuOpenCloseOrHighlight(event, wxT("highlighted")); event.Skip();
+#endif
+ }
+
+private:
+#if USE_LOG_WINDOW
+ void LogMenuOpenCloseOrHighlight(const wxMenuEvent& event, const wxChar *what);
+#endif
+ void ShowContextMenu(const wxPoint& pos);
+
+#if USE_LOG_WINDOW
+ // the control used for logging
+ wxTextCtrl *m_textctrl;
+#endif
+
+ DECLARE_EVENT_TABLE()
+};
+
// A small helper class which intercepts all menu events and logs them
class MyEvtHandler : public wxEvtHandler
{
#if USE_LOG_WINDOW
Menu_File_ClearLog = 100,
#endif
+ Menu_File_ShowDialog,
Menu_MenuBar_Toggle = 200,
Menu_MenuBar_Append,
EVT_MENU(Menu_File_ClearLog, MyFrame::OnClearLog)
EVT_UPDATE_UI(Menu_File_ClearLog, MyFrame::OnClearLogUpdateUI)
#endif
+ EVT_MENU(Menu_File_ShowDialog, MyFrame::OnShowDialog)
EVT_MENU(Menu_Help_About, MyFrame::OnAbout)
EVT_MENU_OPEN(MyFrame::OnMenuOpen)
EVT_MENU_CLOSE(MyFrame::OnMenuClose)
+ EVT_MENU_HIGHLIGHT_ALL(MyFrame::OnMenuHighlight)
EVT_SIZE(MyFrame::OnSize)
END_EVENT_TABLE()
+BEGIN_EVENT_TABLE(MyDialog, wxDialog)
+#if USE_CONTEXT_MENU
+ EVT_CONTEXT_MENU(MyDialog::OnContextMenu)
+#else
+ EVT_RIGHT_UP(MyDialog::OnRightUp)
+#endif
+ EVT_MENU_OPEN(MyDialog::OnMenuOpen)
+ EVT_MENU_CLOSE(MyDialog::OnMenuClose)
+ EVT_MENU_HIGHLIGHT_ALL(MyDialog::OnMenuHighlight)
+END_EVENT_TABLE()
+
BEGIN_EVENT_TABLE(MyEvtHandler, wxEvtHandler)
EVT_MENU(wxID_ANY, MyEvtHandler::OnMenuEvent)
END_EVENT_TABLE()
fileMenu->AppendSeparator();
#endif // USE_LOG_WINDOW
+ fileMenu->Append(Menu_File_ShowDialog, wxT("Show &Dialog\tCtrl-D"),
+ wxT("Show a dialog"));
+ fileMenu->AppendSeparator();
+
fileMenu->Append(Menu_File_Quit, wxT("E&xit\tAlt-X"), wxT("Quit menu sample"));
wxMenu *menubarMenu = new wxMenu;
#endif // USE_LOG_WINDOW
+void MyFrame::OnShowDialog(wxCommandEvent& WXUNUSED(event))
+{
+ MyDialog dlg(this);
+ dlg.ShowModal();
+}
+
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
(void)wxMessageBox(wxT("wxWidgets menu sample\n(c) 1999-2001 Vadim Zeitlin"),
}
#if USE_LOG_WINDOW
-void MyFrame::LogMenuOpenOrClose(const wxMenuEvent& event, const wxChar *what)
+void MyFrame::LogMenuOpenCloseOrHighlight(const wxMenuEvent& event, const wxChar *what)
{
wxString msg;
msg << wxT("A ")
<< ( event.IsPopup() ? wxT("popup ") : wxT("") )
<< wxT("menu has been ")
- << what
- << wxT(".");
+ << what;
+
+ if ( event.GetEventType() == wxEVT_MENU_HIGHLIGHT )
+ {
+ msg << wxT(" (id=") << event.GetId() << wxT(")");
+ }
+
+ msg << wxT(".");
wxLogStatus(this, msg.c_str());
}
#endif // __WXUNIVERSAL__
}
+// ----------------------------------------------------------------------------
+// MyDialog
+// ----------------------------------------------------------------------------
+
+MyDialog::MyDialog(wxWindow* parent)
+ : wxDialog(parent, wxID_ANY, "Test Dialog")
+{
+#if USE_LOG_WINDOW
+ // create the log text window
+ m_textctrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
+ wxDefaultPosition, wxDefaultSize,
+ wxTE_MULTILINE);
+ m_textctrl->SetEditable(false);
+
+ m_textctrl->AppendText(wxT("Dialogs do not have menus, but popup menus should function the same\n\n")
+ wxT("Right click this text ctrl to test popup menus.\n"));
+#endif
+#ifdef __POCKETPC__
+ EnableContextMenu();
+#endif
+}
+
+#if USE_LOG_WINDOW
+void MyDialog::LogMenuOpenCloseOrHighlight(const wxMenuEvent& event, const wxChar *what)
+{
+ wxString msg;
+ msg << wxT("A ")
+ << ( event.IsPopup() ? wxT("popup ") : wxT("") )
+ << wxT("menu has been ")
+ << what;
+ if ( event.GetEventType() == wxEVT_MENU_HIGHLIGHT )
+ {
+ msg << wxT(" (id=") << event.GetId() << wxT(")");
+ }
+ msg << wxT(".\n");
+
+ m_textctrl->AppendText(msg);
+}
+#endif // USE_LOG_WINDOW
+#if USE_CONTEXT_MENU
+void MyDialog::OnContextMenu(wxContextMenuEvent& event)
+{
+ wxPoint point = event.GetPosition();
+ // If from keyboard
+ if (point.x == -1 && point.y == -1) {
+ wxSize size = GetSize();
+ point.x = size.x / 2;
+ point.y = size.y / 2;
+ } else {
+ point = ScreenToClient(point);
+ }
+ ShowContextMenu(point);
+}
+#endif
+
+void MyDialog::ShowContextMenu(const wxPoint& pos)
+{
+ wxMenu menu;
+
+ menu.Append(Menu_Help_About, wxT("&About"));
+ menu.Append(Menu_Popup_ToBeDeleted, wxT("To be &deleted"));
+ menu.AppendCheckItem(Menu_Popup_ToBeChecked, wxT("To be &checked"));
+ menu.Append(Menu_Popup_ToBeGreyed, wxT("To be &greyed"),
+ wxT("This menu item should be initially greyed out"));
+ menu.AppendSeparator();
+ menu.Append(Menu_File_Quit, wxT("E&xit"));
+
+ menu.Delete(Menu_Popup_ToBeDeleted);
+ menu.Check(Menu_Popup_ToBeChecked, true);
+ menu.Enable(Menu_Popup_ToBeGreyed, false);
+
+ PopupMenu(&menu, pos);
+}
}
if ( !processed )
- rc = wxWindow::MSWWindowProc(message, wParam, lParam);
+ rc = wxDialogBase::MSWWindowProc(message, wParam, lParam);
return rc;
}
#endif // wxUSE_MENUS_NATIVE
+#if wxUSE_MENUS
+wxMenu* wxFrame::MSWFindMenuFromHMENU(WXHMENU hMenu)
+{
+ return GetMenuBar() ? GetMenuBar()->MSWGetMenu(hMenu) : NULL;
+}
+#endif // wxUSE_MENUS
+
// Responds to colour changes, and passes event on to children.
void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
{
return wxFrameBase::HandleCommand(id, cmd, control);;
}
-#if wxUSE_MENUS
-
-bool
-wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU WXUNUSED(hMenu))
-{
- // sign extend to int from unsigned short we get from Windows
- int item = (signed short)nItem;
-
- // WM_MENUSELECT is generated for both normal items and menus, including
- // the top level menus of the menu bar, which can't be represented using
- // any valid identifier in wxMenuEvent so use an otherwise unused value for
- // them
- if ( flags & (MF_POPUP | MF_SEPARATOR) )
- item = wxID_NONE;
-
- wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
- event.SetEventObject(this);
-
- if ( HandleWindowEvent(event) )
- return true;
-
- // by default, i.e. if the event wasn't handled above, clear the status bar
- // text when an item which can't have any associated help string in wx API
- // is selected
- if ( item == wxID_NONE )
- DoGiveHelp(wxEmptyString, true);
-
- return false;
-}
-
-bool
-wxFrame::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup)
-{
- wxMenuEvent event(evtType, popup ? wxID_ANY : 0, menu);
- event.SetEventObject(menu);
-
- return HandleWindowEvent(event);
-}
-
-bool wxFrame::HandleExitMenuLoop(WXWORD isPopup)
-{
- return DoSendMenuOpenCloseEvent(wxEVT_MENU_CLOSE,
- isPopup ? wxCurrentPopupMenu : NULL,
- isPopup != 0);
-}
-
-bool wxFrame::HandleMenuPopup(wxEventType evtType, WXHMENU hMenu)
-{
- bool isPopup = false;
- wxMenu* menu = NULL;
- if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetHMenu() == hMenu )
- {
- menu = wxCurrentPopupMenu;
- isPopup = true;
- }
- else if ( GetMenuBar() )
- {
- menu = GetMenuBar()->MSWGetMenu(hMenu);
- }
-
-
- return DoSendMenuOpenCloseEvent(evtType, menu, isPopup);
-}
-
-#endif // wxUSE_MENUS
-
// ---------------------------------------------------------------------------
// the window proc for wxFrame
// ---------------------------------------------------------------------------
break;
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
-#if wxUSE_MENUS
- case WM_INITMENUPOPUP:
- processed = HandleMenuPopup(wxEVT_MENU_OPEN, (WXHMENU)wParam);
- break;
-
- case WM_MENUSELECT:
- {
- WXWORD item, flags;
- WXHMENU hmenu;
- UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
-
- processed = HandleMenuSelect(item, flags, hmenu);
- }
- break;
-
- case WM_EXITMENULOOP:
- // Under Windows 98 and 2000 and later we're going to get
- // WM_UNINITMENUPOPUP which will be used to generate this event
- // with more information (notably the menu that was closed) so we
- // only need this one under old Windows systems where the newer
- // event is never sent.
- if ( wxGetWinVersion() < wxWinVersion_98 )
- processed = HandleExitMenuLoop(wParam);
- break;
-
- case WM_UNINITMENUPOPUP:
- processed = HandleMenuPopup(wxEVT_MENU_CLOSE, (WXHMENU)wParam);
- break;
-#endif // wxUSE_MENUS
-
case WM_QUERYDRAGICON:
{
const wxIcon& icon = GetIcon();
#define ICON_SMALL 0
#endif
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+#if wxUSE_MENUS || wxUSE_MENUS_NATIVE
+ extern wxMenu *wxCurrentPopupMenu;
+#endif // wxUSE_MENUS || wxUSE_MENUS_NATIVE
+
+
// ----------------------------------------------------------------------------
// stubs for missing functions under MicroWindows
// ----------------------------------------------------------------------------
#endif // #ifndef __WXUNIVERSAL__
}
break;
+
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+#if wxUSE_MENUS
+ case WM_INITMENUPOPUP:
+ processed = HandleMenuPopup(wxEVT_MENU_OPEN, (WXHMENU)wParam);
+ break;
+
+ case WM_MENUSELECT:
+ {
+ WXWORD item, flags;
+ WXHMENU hmenu;
+ UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu);
+
+ processed = HandleMenuSelect(item, flags, hmenu);
+ }
+ break;
+
+ case WM_EXITMENULOOP:
+ // Under Windows 98 and 2000 and later we're going to get
+ // WM_UNINITMENUPOPUP which will be used to generate this event
+ // with more information (notably the menu that was closed) so we
+ // only need this one under old Windows systems where the newer
+ // event is never sent.
+ if ( wxGetWinVersion() < wxWinVersion_98 )
+ processed = HandleExitMenuLoop(wParam);
+ break;
+
+ case WM_UNINITMENUPOPUP:
+ processed = HandleMenuPopup(wxEVT_MENU_CLOSE, (WXHMENU)wParam);
+ break;
+#endif // wxUSE_MENUS
+#endif // !__WXMICROWIN__
}
if ( !processed )
}
}
+#if wxUSE_MENUS
+
+bool
+wxTopLevelWindowMSW::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU WXUNUSED(hMenu))
+{
+ // sign extend to int from unsigned short we get from Windows
+ int item = (signed short)nItem;
+
+ // WM_MENUSELECT is generated for both normal items and menus, including
+ // the top level menus of the menu bar, which can't be represented using
+ // any valid identifier in wxMenuEvent so use an otherwise unused value for
+ // them
+ if ( flags & (MF_POPUP | MF_SEPARATOR) )
+ item = wxID_NONE;
+
+ wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item);
+ event.SetEventObject(this);
+
+ if ( HandleWindowEvent(event) )
+ return true;
+
+ // by default, i.e. if the event wasn't handled above, clear the status bar
+ // text when an item which can't have any associated help string in wx API
+ // is selected
+ if ( item == wxID_NONE )
+ DoGiveHelp(wxEmptyString, true);
+
+ return false;
+}
+
+bool
+wxTopLevelWindowMSW::DoSendMenuOpenCloseEvent(wxEventType evtType, wxMenu* menu, bool popup)
+{
+ wxMenuEvent event(evtType, popup ? wxID_ANY : 0, menu);
+ event.SetEventObject(menu);
+
+ return HandleWindowEvent(event);
+}
+
+bool wxTopLevelWindowMSW::HandleExitMenuLoop(WXWORD isPopup)
+{
+ return DoSendMenuOpenCloseEvent(wxEVT_MENU_CLOSE,
+ isPopup ? wxCurrentPopupMenu : NULL,
+ isPopup != 0);
+}
+
+bool wxTopLevelWindowMSW::HandleMenuPopup(wxEventType evtType, WXHMENU hMenu)
+{
+ bool isPopup = false;
+ wxMenu* menu = NULL;
+ if ( wxCurrentPopupMenu && wxCurrentPopupMenu->GetHMenu() == hMenu )
+ {
+ menu = wxCurrentPopupMenu;
+ isPopup = true;
+ }
+ else
+ {
+ menu = MSWFindMenuFromHMENU(hMenu);
+ }
+
+
+ return DoSendMenuOpenCloseEvent(evtType, menu, isPopup);
+}
+
+wxMenu* wxTopLevelWindowMSW::MSWFindMenuFromHMENU(WXHMENU WXUNUSED(hMenu))
+{
+ // We don't have any menus at this level.
+ return NULL;
+}
+
+#endif // wxUSE_MENUS
+
+
+
// the DialogProc for all wxWidgets dialogs
LONG APIENTRY _EXPORT
wxDlgProc(HWND hDlg,