]> git.saurik.com Git - wxWidgets.git/commitdiff
Added wxTopLevelWindow::MSWGetSystemMenu() method.
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 8 Aug 2011 09:32:42 +0000 (09:32 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 8 Aug 2011 09:32:42 +0000 (09:32 +0000)
Also generate events corresponding to WM_SYSCOMMAND messages for the custom
items of the system menu.

Add a small snippet to test the new functionality to the dialogs sample.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@68596 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/msw/toplevel.h
interface/wx/toplevel.h
samples/dialogs/dialogs.cpp
src/msw/toplevel.cpp

index 92f145027fbed42a026eea328224e5086f6c468c..d467990b48b34c58d141736e1a581bc16e0e34c1 100644 (file)
@@ -467,6 +467,7 @@ GTK:
 MSW:
 
 - Added wxGCDC(wxEnhMetaFileDC) ctor (Marcin Wojdyr).
+- Added wxTopLevelWindow::MSWGetSystemMenu().
 
 
 2.9.2: (released 2011-07-05)
index 52905cc32a5e831555331c51165578546f51bc5c..39756b355b86fa86508696b2ba3fff8f4d0b12e5 100644 (file)
@@ -77,6 +77,19 @@ public:
     virtual bool CanSetTransparent();
 
 
+    // MSW-specific methods
+    // --------------------
+
+    // Return the menu representing the "system" menu of the window. You can
+    // call wxMenu::AppendWhatever() methods on it but removing items from it
+    // is in general not a good idea.
+    //
+    // The pointer returned by this method belongs to the window and will be
+    // deleted when the window itself is, do not delete it yourself. May return
+    // NULL if getting the system menu failed.
+    wxMenu *MSWGetSystemMenu() const;
+
+
     // implementation from now on
     // --------------------------
 
@@ -214,6 +227,10 @@ private:
     void* m_activateInfo;
 #endif
 
+    // The system menu: initially NULL but can be set (once) by
+    // MSWGetSystemMenu(). Owned by this window.
+    wxMenu *m_menuSystem;
+
     DECLARE_EVENT_TABLE()
     wxDECLARE_NO_COPY_CLASS(wxTopLevelWindowMSW);
 };
index 55be716a7d228bc696e0213b7782eb12a8fe4413..32e09f7e6f365b378c1490cf2967d986c7a8cf97 100644 (file)
@@ -262,6 +262,33 @@ public:
     */
     virtual void Maximize(bool maximize = true);
 
+    /**
+        MSW-specific function for accessing the system menu.
+
+        Returns a wxMenu pointer representing the system menu of the window
+        under MSW. The returned wxMenu may be used, if non-@c NULL, to add
+        extra items to the system menu. The usual @c wxEVT_COMMAND_MENU_SELECTED
+        events (that can be processed using @c EVT_MENU event table macro) will
+        then be generated for them. All the other wxMenu methods may be used as
+        well but notice that they won't allow you to access any standard system
+        menu items (e.g. they can't be deleted or modified in any way
+        currently).
+
+        Notice that because of the native system limitations the identifiers of
+        the items added to the system menu must be multiples of 16, otherwise
+        no events will be generated for them.
+
+        The returned pointer must @em not be deleted, it is owned by the window
+        and will be only deleted when the window itself is destroyed.
+
+        This function is not available in the other ports by design, any
+        occurrences of it in the portable code must be guarded by @code #ifdef
+        __WXMSW__ @endcode preprocessor guards.
+
+        @since 2.9.3
+     */
+    wxMenu *MSWGetSystemMenu() const;
+
     /**
         Use a system-dependent way to attract users attention to the window when
         it is in background.
index 14f1a8031898e6d1b93a337b095488c73e5898b6..eeeecdac1f1db15c3d60f4f5f4bdbe1e975919e8 100644 (file)
@@ -648,6 +648,24 @@ MyFrame::MyFrame(const wxString& title)
     // covers our entire client area to avoid jarring colour jumps
     SetOwnBackgroundColour(m_canvas->GetBackgroundColour());
 #endif // wxUSE_INFOBAR
+
+#ifdef __WXMSW__
+    // Test MSW-specific function allowing to access the "system" menu.
+    wxMenu * const menu = MSWGetSystemMenu();
+    if ( menu )
+    {
+        menu->AppendSeparator();
+
+        // The ids of the menu commands in MSW system menu must be multiple of
+        // 16 so we can't use DIALOGS_ABOUTDLG_SIMPLE here because it might not
+        // satisfy this condition and need to define and connect a separate id.
+        static const int DIALOGS_SYSTEM_ABOUT = 0x4010;
+
+        menu->Append(DIALOGS_SYSTEM_ABOUT, "&About...");
+        Connect(DIALOGS_SYSTEM_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
+                wxCommandEventHandler(MyFrame::ShowSimpleAboutDialog));
+    }
+#endif // __WXMSW__
 }
 
 MyFrame::~MyFrame()
index 45ef33843b35da278e3e9690163fe512691aab36..856e761b392eb2fcb350d49624d8ff50265b3d39 100644 (file)
@@ -141,6 +141,8 @@ void wxTopLevelWindowMSW::Init()
 
     m_activateInfo = (void*) info;
 #endif
+
+    m_menuSystem = NULL;
 }
 
 WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const
@@ -326,9 +328,9 @@ WXLRESULT wxTopLevelWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WX
     WXLRESULT rc = 0;
     bool processed = false;
 
-#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
     switch ( message )
     {
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
         case WM_ACTIVATE:
         {
             SHACTIVATEINFO* info = (SHACTIVATEINFO*) m_activateInfo;
@@ -355,8 +357,32 @@ WXLRESULT wxTopLevelWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WX
             }
             break;
         }
+#endif // __SMARTPHONE__ || __POCKETPC__
+
+        case WM_SYSCOMMAND:
+            // We may need to generate events for the items added to the system
+            // menu if it had been created (and presumably modified).
+            if ( m_menuSystem )
+            {
+                // From MSDN:
+                //
+                //      ... the four low-order bits of the wParam parameter are
+                //      used internally by the system. To obtain the correct
+                //      result when testing the value of wParam, an application
+                //      must combine the value 0xFFF0 with the wParam value by
+                //      using the bitwise AND operator.
+                unsigned id = wParam & 0xfff0;
+
+                // SC_SIZE is the first of the system-defined commands and we
+                // leave those to DefWindowProc().
+                if ( id < SC_SIZE )
+                {
+                    if ( m_menuSystem->MSWCommand(0 /* unused anyhow */, id) )
+                        processed = true;
+                }
+            }
+            break;
     }
-#endif
 
     if ( !processed )
         rc = wxTopLevelWindowBase::MSWWindowProc(message, wParam, lParam);
@@ -578,6 +604,8 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent,
 
 wxTopLevelWindowMSW::~wxTopLevelWindowMSW()
 {
+    delete m_menuSystem;
+
     SendDestroyEvent();
 
 #if defined(__SMARTPHONE__) || defined(__POCKETPC__)
@@ -1226,6 +1254,39 @@ void wxTopLevelWindowMSW::RequestUserAttention(int flags)
     }
 }
 
+wxMenu *wxTopLevelWindowMSW::MSWGetSystemMenu() const
+{
+    if ( !m_menuSystem )
+    {
+        HMENU hmenu = ::GetSystemMenu(GetHwnd(), FALSE);
+        if ( !hmenu )
+        {
+            wxLogLastError(wxT("GetSystemMenu()"));
+            return NULL;
+        }
+
+        wxTopLevelWindowMSW * const
+            self = const_cast<wxTopLevelWindowMSW *>(this);
+
+        self->m_menuSystem = wxMenu::MSWNewFromHMENU(hmenu);
+
+        // We need to somehow associate this menu with this window to ensure
+        // that we get events from it. A natural idea would be to pretend that
+        // it's attached to our menu bar but this wouldn't work if we don't
+        // have any menu bar which is a common case for applications using
+        // custom items in the system menu (they mostly do it exactly because
+        // they don't have any other menus).
+        //
+        // So reuse the invoking window pointer instead, this is not exactly
+        // correct but doesn't seem to have any serious drawbacks.
+        m_menuSystem->SetInvokingWindow(self);
+    }
+
+    return m_menuSystem;
+}
+
+// ----------------------------------------------------------------------------
+// Transparency support
 // ---------------------------------------------------------------------------
 
 bool wxTopLevelWindowMSW::SetTransparent(wxByte alpha)