Added wxTopLevelWindow::MSWGetSystemMenu() method.

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
This commit is contained in:
Vadim Zeitlin 2011-08-08 09:32:42 +00:00
parent 960493053b
commit ddae52629c
5 changed files with 126 additions and 2 deletions

View File

@ -467,6 +467,7 @@ GTK:
MSW:
- Added wxGCDC(wxEnhMetaFileDC) ctor (Marcin Wojdyr).
- Added wxTopLevelWindow::MSWGetSystemMenu().
2.9.2: (released 2011-07-05)

View 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);
};

View 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.

View 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()

View 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)