X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0472ece753aa3c018dd2cc9816d3cd755f28efe8..b5435dccd098ae153c3b7b3b8fca8dd0d763986c:/src/msw/menu.cpp diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index ec96dc7bc8..ca6ab1b99c 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -5,8 +5,8 @@ // Modified by: Vadim Zeitlin // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // =========================================================================== @@ -44,6 +44,20 @@ #include "wx/msw/private.h" +#ifdef __WXWINCE__ +#include +#include +#include +#include +#include +#include + +#ifndef TBSTYLE_NO_DROPDOWN_ARROW +#define TBSTYLE_NO_DROPDOWN_ARROW 0x0080 +#endif + +#endif + // other standard headers #include @@ -67,6 +81,7 @@ static const int idMenuTitle = -2; // make the given menu item default static void SetDefaultMenuItem(HMENU hmenu, UINT id) { +#ifndef __WXWINCE__ MENUITEMINFO mii; wxZeroMemory(mii); mii.cbSize = sizeof(MENUITEMINFO); @@ -77,8 +92,22 @@ static void SetDefaultMenuItem(HMENU hmenu, UINT id) { wxLogLastError(wxT("SetMenuItemInfo")); } +#endif } +#ifdef __WXWINCE__ +UINT GetMenuState(HMENU hMenu, UINT id, UINT flags) +{ + MENUITEMINFO info; + wxZeroMemory(info); + info.cbSize = sizeof(info); + info.fMask = MIIM_STATE; + if ( !GetMenuItemInfo(hMenu, id, flags & MF_BYCOMMAND ? FALSE : TRUE, & info) ) + wxLogLastError(wxT("GetMenuItemInfo")); + return info.fState; +} +#endif + // ============================================================================ // implementation // ============================================================================ @@ -163,7 +192,7 @@ void wxMenu::UpdateAccel(wxMenuItem *item) if ( item->IsSubMenu() ) { wxMenu *submenu = item->GetSubMenu(); - wxMenuItemList::Node *node = submenu->GetMenuItems().GetFirst(); + wxMenuItemList::compatibility_iterator node = submenu->GetMenuItems().GetFirst(); while ( node ) { UpdateAccel(node->GetData()); @@ -245,6 +274,10 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) id = pItem->GetId(); } +#ifdef __WXWINCE__ + wxString strippedString; +#endif + LPCTSTR pData; #if wxUSE_OWNER_DRAWN @@ -259,7 +292,12 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) // menu is just a normal string (passed in data parameter) flags |= MF_STRING; +#ifdef __WXWINCE__ + strippedString = wxStripMenuCodes(pItem->GetText()); + pData = (wxChar*)strippedString.c_str(); +#else pData = (wxChar*)pItem->GetText().c_str(); +#endif } BOOL ok; @@ -299,28 +337,6 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) void wxMenu::EndRadioGroup() { - if ( m_startRadioGroup == -1 ) - { - // nothing to do - return; - } - - wxMenuItemList::Node *nodeStart = GetMenuItems().Item(m_startRadioGroup); - wxCHECK_RET( nodeStart, _T("where is the radio group start item?") ); - - int endRadioGroup = GetMenuItemCount(); - - wxMenuItemList::Node *node = nodeStart; - for ( int n = m_startRadioGroup; n < endRadioGroup && node; n++ ) - { - wxMenuItem *item = (wxMenuItem *)node->GetData(); - item->SetRadioGroup(m_startRadioGroup, endRadioGroup - 1); - - node = node->GetNext(); - } - - nodeStart->GetData()->Check(TRUE); - // we're not inside a radio group any longer m_startRadioGroup = -1; } @@ -329,12 +345,38 @@ bool wxMenu::DoAppend(wxMenuItem *item) { wxCHECK_MSG( item, FALSE, _T("NULL item in wxMenu::DoAppend") ); - if ( item->GetKind() == wxItem_Radio ) + bool check = FALSE; + + if ( item->GetKind() == wxITEM_RADIO ) { + int count = GetMenuItemCount(); + if ( m_startRadioGroup == -1 ) { // start a new radio group - m_startRadioGroup = GetMenuItemCount(); + m_startRadioGroup = count; + + // for now it has just one element + item->SetAsRadioGroupStart(); + item->SetRadioGroupEnd(m_startRadioGroup); + + // ensure that we have a checked item in the radio group + check = TRUE; + } + else // extend the current radio group + { + // we need to update its end item + item->SetRadioGroupStart(m_startRadioGroup); + wxMenuItemList::compatibility_iterator node = GetMenuItems().Item(m_startRadioGroup); + + if ( node ) + { + node->GetData()->SetRadioGroupEnd(count); + } + else + { + wxFAIL_MSG( _T("where is the radio group start item?") ); + } } } else // not a radio item @@ -342,7 +384,18 @@ bool wxMenu::DoAppend(wxMenuItem *item) EndRadioGroup(); } - return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item); + if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) ) + { + return FALSE; + } + + if ( check ) + { + // check the item initially + item->Check(TRUE); + } + + return TRUE; } bool wxMenu::DoInsert(size_t pos, wxMenuItem *item) @@ -354,7 +407,7 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) { // we need to find the items position in the child list size_t pos; - wxMenuItemList::Node *node = GetMenuItems().GetFirst(); + wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst(); for ( pos = 0; node; pos++ ) { if ( node->GetData() == item ) @@ -452,12 +505,26 @@ void wxMenu::SetTitle(const wxString& label) else { // modify the title +#ifdef __WXWINCE__ + MENUITEMINFO info; + wxZeroMemory(info); + info.cbSize = sizeof(info); + info.fMask = MIIM_TYPE; + info.fType = MFT_STRING; + info.cch = m_title.Length(); + info.dwTypeData = (LPTSTR) m_title.c_str(); + if ( !SetMenuItemInfo(hMenu, 0, TRUE, & info) ) + { + wxLogLastError(wxT("SetMenuItemInfo")); + } +#else if ( !ModifyMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING, (unsigned)idMenuTitle, m_title) ) { wxLogLastError(wxT("ModifyMenu")); } +#endif } } @@ -485,7 +552,8 @@ bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id) // useless anyhow (as it could be retrieved using GetId()) and // uncompatible with wxGTK, so now we use the command int instead // to pass the checked status - SendEvent(id, ::GetMenuState(GetHmenu(), id, MF_BYCOMMAND) & MF_CHECKED); + UINT menuState = ::GetMenuState(GetHmenu(), id, MF_BYCOMMAND) ; + SendEvent(id, menuState & MF_CHECKED); } return TRUE; @@ -513,6 +581,9 @@ void wxMenuBar::Init() { m_eventHandler = this; m_hMenu = 0; +#ifdef __WXWINCE__ + m_toolBar = NULL; +#endif } wxMenuBar::wxMenuBar() @@ -542,6 +613,20 @@ wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[]) wxMenuBar::~wxMenuBar() { + // In Windows CE, the menubar is always associated + // with a toolbar, which destroys the menu implicitly. +#ifdef __WXWINCE__ + if (GetToolBar()) + GetToolBar()->SetMenuBar(NULL); +#else + // we should free Windows resources only if Windows doesn't do it for us + // which happens if we're attached to a frame + if (m_hMenu && !IsAttached()) + { + ::DestroyMenu((HMENU)m_hMenu); + m_hMenu = (WXHMENU)NULL; + } +#endif } // --------------------------------------------------------------------------- @@ -552,11 +637,59 @@ void wxMenuBar::Refresh() { wxCHECK_RET( IsAttached(), wxT("can't refresh unattached menubar") ); +#ifdef __WXWINCE__ + if (GetToolBar()) + { + CommandBar_DrawMenuBar((HWND) GetToolBar()->GetHWND(), 0); + } +#else DrawMenuBar(GetHwndOf(GetFrame())); +#endif } WXHMENU wxMenuBar::Create() { + // Note: this totally doesn't work on Smartphone, + // since you have to use resources. + // We'll have to find another way to add a menu + // by changing/adding menu items to an existing menu. +#ifdef __WXWINCE__ + if ( m_hMenu != 0 ) + return m_hMenu; + + if (!GetToolBar()) + return 0; + + HWND hCommandBar = (HWND) GetToolBar()->GetHWND(); + HMENU hMenu = (HMENU)::SendMessage(hCommandBar, SHCMBM_GETMENU, (WPARAM)0, (LPARAM)0); + if (hMenu) + { + TBBUTTON tbButton; + memset(&tbButton, 0, sizeof(TBBUTTON)); + tbButton.iBitmap = I_IMAGENONE; + tbButton.fsState = TBSTATE_ENABLED; + tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE; + + size_t i; + for (i = 0; i < GetMenuCount(); i++) + { + HMENU hPopupMenu = (HMENU) GetMenu(i)->GetHMenu() ; + tbButton.dwData = (DWORD)hPopupMenu; + wxString label = wxStripMenuCodes(GetLabelTop(i)); + tbButton.iString = (int) label.c_str(); + + int position = i; + + tbButton.idCommand = NewControlId(); + if (!::SendMessage(hCommandBar, TB_INSERTBUTTON, position, (LPARAM)&tbButton)) + { + wxLogLastError(wxT("TB_INSERTBUTTON")); + } + } + } + m_hMenu = (WXHMENU) hMenu; + return m_hMenu; +#else if ( m_hMenu != 0 ) return m_hMenu; @@ -568,11 +701,12 @@ WXHMENU wxMenuBar::Create() } else { - size_t count = GetMenuCount(); - for ( size_t i = 0; i < count; i++ ) + size_t count = GetMenuCount(), i; + wxMenuList::iterator it; + for ( i = 0, it = m_menus.begin(); i < count; i++, it++ ) { if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING, - (UINT)m_menus[i]->GetHMenu(), + (UINT)(*it)->GetHMenu(), m_titles[i]) ) { wxLogLastError(wxT("AppendMenu")); @@ -581,6 +715,7 @@ WXHMENU wxMenuBar::Create() } return m_hMenu; +#endif } // --------------------------------------------------------------------------- @@ -633,11 +768,26 @@ void wxMenuBar::SetLabelTop(size_t pos, const wxString& label) id = pos; } +#ifdef __WXWINCE__ + MENUITEMINFO info; + wxZeroMemory(info); + info.cbSize = sizeof(info); + info.fMask = MIIM_TYPE; + info.fType = MFT_STRING; + info.cch = label.Length(); + info.dwTypeData = (LPTSTR) label.c_str(); + if ( !SetMenuItemInfo(GetHmenu(), id, TRUE, & info) ) + { + wxLogLastError(wxT("SetMenuItemInfo")); + } + +#else if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld, - id, label) == (int)0xFFFFFFFF ) + id, label) == (int)0xFFFFFFFF ) { wxLogLastError(wxT("ModifyMenu")); } +#endif Refresh(); } @@ -658,7 +808,8 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) { wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title); if ( !menuOld ) - return FALSE; + return NULL; + m_titles[pos] = title; if ( IsAttached() ) @@ -699,13 +850,34 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) if ( IsAttached() ) { +#ifdef __WXWINCE__ + if (!GetToolBar()) + return FALSE; + TBBUTTON tbButton; + memset(&tbButton, 0, sizeof(TBBUTTON)); + tbButton.iBitmap = I_IMAGENONE; + tbButton.fsState = TBSTATE_ENABLED; + tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE; + + HMENU hPopupMenu = (HMENU) menu->GetHMenu() ; + tbButton.dwData = (DWORD)hPopupMenu; + wxString label = wxStripMenuCodes(title); + tbButton.iString = (int) label.c_str(); + + tbButton.idCommand = NewControlId(); + if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton)) + { + wxLogLastError(wxT("TB_INSERTBUTTON")); + return FALSE; + } +#else if ( !::InsertMenu(GetHmenu(), pos, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT)GetHmenuOf(menu), title) ) { wxLogLastError(wxT("InsertMenu")); } - +#endif #if wxUSE_ACCEL if ( menu->HasAccels() ) { @@ -732,16 +904,39 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title) if ( IsAttached() ) { +#ifdef __WXWINCE__ + if (!GetToolBar()) + return FALSE; + TBBUTTON tbButton; + memset(&tbButton, 0, sizeof(TBBUTTON)); + tbButton.iBitmap = I_IMAGENONE; + tbButton.fsState = TBSTATE_ENABLED; + tbButton.fsStyle = TBSTYLE_DROPDOWN | TBSTYLE_NO_DROPDOWN_ARROW | TBSTYLE_AUTOSIZE; + + size_t pos = GetMenuCount(); + HMENU hPopupMenu = (HMENU) menu->GetHMenu() ; + tbButton.dwData = (DWORD)hPopupMenu; + wxString label = wxStripMenuCodes(title); + tbButton.iString = (int) label.c_str(); + + tbButton.idCommand = NewControlId(); + if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_INSERTBUTTON, pos, (LPARAM)&tbButton)) + { + wxLogLastError(wxT("TB_INSERTBUTTON")); + return FALSE; + } +#else if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING, (UINT)submenu, title) ) { wxLogLastError(wxT("AppendMenu")); } +#endif #if wxUSE_ACCEL if ( menu->HasAccels() ) { - // need to rebuild accell table + // need to rebuild accelerator table RebuildAccelTable(); } #endif // wxUSE_ACCEL @@ -760,11 +955,20 @@ wxMenu *wxMenuBar::Remove(size_t pos) if ( IsAttached() ) { +#ifdef __WXWINCE__ + if (GetToolBar()) + { + if (!::SendMessage((HWND) GetToolBar()->GetHWND(), TB_DELETEBUTTON, (UINT) pos, (LPARAM) 0)) + { + wxLogLastError(wxT("TB_DELETEBUTTON")); + } + } +#else if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) ) { wxLogLastError(wxT("RemoveMenu")); } - +#endif #if wxUSE_ACCEL if ( menu->HasAccels() ) { @@ -776,7 +980,7 @@ wxMenu *wxMenuBar::Remove(size_t pos) Refresh(); } - m_titles.Remove(pos); + m_titles.RemoveAt(pos); return menu; } @@ -788,9 +992,10 @@ void wxMenuBar::RebuildAccelTable() // merge the accelerators of all menus into one accel table size_t nAccelCount = 0; size_t i, count = GetMenuCount(); - for ( i = 0; i < count; i++ ) + wxMenuList::iterator it; + for ( i = 0, it = m_menus.begin(); i < count; i++, it++ ) { - nAccelCount += m_menus[i]->GetAccelCount(); + nAccelCount += (*it)->GetAccelCount(); } if ( nAccelCount ) @@ -798,9 +1003,9 @@ void wxMenuBar::RebuildAccelTable() wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount]; nAccelCount = 0; - for ( i = 0; i < count; i++ ) + for ( i = 0, it = m_menus.begin(); i < count; i++, it++ ) { - nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]); + nAccelCount += (*it)->CopyAccels(&accelEntries[nAccelCount]); } m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries); @@ -822,8 +1027,6 @@ void wxMenuBar::Attach(wxFrame *frame) void wxMenuBar::Detach() { - m_hMenu = (WXHMENU)NULL; - wxMenuBarBase::Detach(); }