Beispiel #1
0
		bool BaseForm::ProcessMessage(WinMessage msg)
		{
			bool rs = BaseControl::ProcessMessage(msg);
			switch (msg.message)
			{
			case WM_CLOSE:
				{
					WindowCloseEventArgs args;
					args.Cancel = false;
					OnClose.Invoke(this, args);
					if (!args.Cancel)
					{
						closed = true;
						SetVisible(false);
						if (Application::GetMainFormHandle() == handle)
						{
							Application::Terminate();
						}
					}
				}
				return true;
			case WM_SHOWWINDOW:
				{
					EventArgs e;
					if (msg.wParam == TRUE)
					{
						OnShow.Invoke(this, e);
						UpdateAccel();
					}
				}
				return false;
			case WM_COMMAND:
				{
					Object * obj = Application::GetObject(LOWORD(msg.wParam));
					MenuItem * mn = dynamic_cast<MenuItem *>(obj);
					if (mn)
					{
						mn->Clicked();
					}
				}
				return false;
			case WM_INITMENUPOPUP:
				{
					Object * obj = Application::GetComponent((HWND)msg.wParam);
					CustomMenu * mn = dynamic_cast<CustomMenu *>(obj);
					if (mn)
					{
						mn->OnPopup();
					}
				}
				return false;
			case WM_ACTIVATE:
				UpdateAccel();
				return false;
			default:
				return false;
			}

			return false;
		}
Beispiel #2
0
void wxMenu::UpdateAccel(wxMenuItem *item)
{
    if ( item->IsSubMenu() )
    {
        wxMenu *submenu = item->GetSubMenu();
        wxMenuItemList::compatibility_iterator node = submenu->GetMenuItems().GetFirst();
        while ( node )
        {
            UpdateAccel(node->GetData());

            node = node->GetNext();
        }
    }
    else if ( !item->IsSeparator() )
    {
        // recurse upwards: we should only modify m_accels of the top level
        // menus, not of the submenus as wxMenuBar doesn't look at them
        // (alternative and arguable cleaner solution would be to recurse
        // downwards in GetAccelCount() and CopyAccels())
        if ( GetParent() )
        {
            GetParent()->UpdateAccel(item);
            return;
        }

        // find the (new) accel for this item
        wxAcceleratorEntry *accel = wxAcceleratorEntry::Create(item->GetItemLabel());
        if ( accel )
            accel->m_command = item->GetId();

        // find the old one
        int n = FindAccel(item->GetId());
        if ( n == wxNOT_FOUND )
        {
            // no old, add new if any
            if ( accel )
                m_accels.Add(accel);
            else
                return;     // skipping RebuildAccelTable() below
        }
        else
        {
            // replace old with new or just remove the old one if no new
            delete m_accels[n];
            if ( accel )
                m_accels[n] = accel;
            else
                m_accels.RemoveAt(n);
        }

        if ( IsAttached() )
        {
            GetMenuBar()->RebuildAccelTable();
        }

        ResetMaxAccelWidth();
    }
    //else: it is a separator, they can't have accels, nothing to do
}
Beispiel #3
0
void wxMenu::UpdateAccel(wxMenuItem *item)
{
    if ( item->IsSubMenu() )
    {
        wxMenu *submenu = item->GetSubMenu();
        wxMenuItemList::compatibility_iterator node = submenu->GetMenuItems().GetFirst();
        while ( node )
        {
            UpdateAccel(node->GetData());

            node = node->GetNext();
        }
    }
    else if ( !item->IsSeparator() )
    {
        // find the (new) accel for this item
        wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
        if ( accel )
            accel->m_command = item->GetId();

        // find the old one
        int n = FindAccel(item->GetId());
        if ( n == wxNOT_FOUND )
        {
            // no old, add new if any
            if ( accel )
                m_accels.Add(accel);
            else
                return;     // skipping RebuildAccelTable() below
        }
        else
        {
            // replace old with new or just remove the old one if no new
            delete m_accels[n];
            if ( accel )
                m_accels[n] = accel;
            else
                m_accels.RemoveAt(n);
        }

        if ( IsAttached() )
        {
            GetMenuBar()->RebuildAccelTable();
        }
    }
    //else: it is a separator, they can't have accels, nothing to do
}
//----------------------------------------------------------------------------------------
//      更新処理を行います.
//----------------------------------------------------------------------------------------
void Spring1D::Update( SIMULATION_TYPE type )
{
    // 加速度を更新.
    UpdateAccel();

    switch( type )
    {
    // 陽的オイラー法で更新.
    case SIMULATION_TYPE_EXPLICIT_EULAR:
        { IntegrateExplicitEular(); }
        break;

    // ベルレ法で更新.
    case SIMULATION_TYPE_VERLET:
        { IntegrateVerlet(); }
        break;
    }
}
Beispiel #5
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    UINT flags = 0;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetText();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // adjust position to account for the title, if any
    if ( !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

    // check if we have something more than a simple text item
#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() )
    {
        // is the item owner-drawn just because of the bitmap?
        if ( pItem->GetBitmap().Ok() &&
                !pItem->GetTextColour().Ok() &&
                    !pItem->GetBackgroundColour().Ok() &&
                        !pItem->GetFont().Ok() )
        {
            // try to use InsertMenuItem() as it's guaranteed to look correctly
            // while our owner-drawning code is not

            // first compile-time check
#ifdef MIIM_BITMAP
            WinStruct<MENUITEMINFO> mii;

            // now run-time one: MIIM_BITMAP only works under WinME/2000+
            if ( wxGetWinVersion() >= wxWinVersion_98 )
            {
                mii.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA | MIIM_BITMAP;
                mii.wID = id;
                mii.cch = itemText.length();
                mii.dwTypeData = wx_const_cast(wxChar *, itemText.c_str());

                // we can't pass HBITMAP directly as hbmpItem for 2 reasons:
                //  1. we can't draw it with transparency then (this is not
                //     very important now but would be with themed menu bg)
                //  2. worse, Windows inverses the bitmap for the selected
                //     item and this looks downright ugly
                //
                // so instead draw it ourselves in MSWOnDrawItem()
                mii.dwItemData = wx_reinterpret_cast(ULONG_PTR, pItem);
                mii.hbmpItem = HBMMENU_CALLBACK;

                ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
                if ( !ok )
                {
                    wxLogLastError(wxT("InsertMenuItem()"));
                }
                else // InsertMenuItem() ok
                {
                    // we need to remove the extra indent which is reserved for
                    // the checkboxes by default as it looks ugly unless check
                    // boxes are used together with bitmaps and this is not the
                    // case in wx API
                    WinStruct<MENUINFO> mi;

                    // don't call SetMenuInfo() directly, this would prevent
                    // the app from starting up under Windows 95/NT 4
                    typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *);

                    wxDynamicLibrary dllUser(_T("user32"));
                    wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser);
                    if ( pfnSetMenuInfo )
                    {
                        mi.fMask = MIM_STYLE;
                        mi.dwStyle = MNS_CHECKORBMP;
                        if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) )
                            wxLogLastError(_T("SetMenuInfo(MNS_NOCHECK)"));
                    }

                    // tell the item that it's not really owner-drawn but only
                    // needs to draw its bitmap, the rest is done by Windows
                    pItem->ResetOwnerDrawn();
                }
            }
#endif // MIIM_BITMAP
        }
Beispiel #6
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    // we should support disabling the item even prior to adding it to the menu
    UINT flags = pItem->IsEnabled() ? MF_ENABLED : MF_GRAYED;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT_PTR id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT_PTR)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetMSWId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetItemLabel();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // Update radio groups data if we're inserting a new radio item.
    //
    // NB: If we supported inserting non-radio items in the middle of existing
    //     radio groups to break them into two subgroups, we'd need to update
    //     m_radioData in this case too but currently this is not supported.
    bool checkInitially = false;
    if ( pItem->GetKind() == wxITEM_RADIO )
    {
        if ( !m_radioData )
            m_radioData = new wxMenuRadioItemsData;

        if ( m_radioData->UpdateOnInsert(pos) )
            checkInitially = true;
    }

    // adjust position to account for the title of a popup menu, if any
    if ( !GetMenuBar() && !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

#if wxUSE_OWNER_DRAWN
    // Under older systems mixing owner-drawn and non-owner-drawn items results
    // in inconsistent margins, so we force this one to be owner-drawn if any
    // other items already are.
    if ( m_ownerDrawn )
        pItem->SetOwnerDrawn(true);
#endif // wxUSE_OWNER_DRAWN

    // check if we have something more than a simple text item
#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() )
    {
#ifndef __DMC__

        if ( !m_ownerDrawn && !pItem->IsSeparator() )
        {
            // MIIM_BITMAP only works under WinME/2000+ so we always use owner
            // drawn item under the previous versions and we also have to use
            // them in any case if the item has custom colours or font
            static const wxWinVersion winver = wxGetWinVersion();
            bool mustUseOwnerDrawn = winver < wxWinVersion_98 ||
                                     pItem->GetTextColour().IsOk() ||
                                     pItem->GetBackgroundColour().IsOk() ||
                                     pItem->GetFont().IsOk();

            if ( !mustUseOwnerDrawn )
            {
                const wxBitmap& bmpUnchecked = pItem->GetBitmap(false),
                                bmpChecked   = pItem->GetBitmap(true);

                if ( (bmpUnchecked.IsOk() && IsGreaterThanStdSize(bmpUnchecked)) ||
                     (bmpChecked.IsOk()   && IsGreaterThanStdSize(bmpChecked)) )
                {
                    mustUseOwnerDrawn = true;
                }
            }

            // use InsertMenuItem() if possible as it's guaranteed to look
            // correct while our owner-drawn code is not
            if ( !mustUseOwnerDrawn )
            {
                WinStruct<MENUITEMINFO> mii;
                mii.fMask = MIIM_STRING | MIIM_DATA;

                // don't set hbmpItem for the checkable items as it would
                // be used for both checked and unchecked state
                if ( pItem->IsCheckable() )
                {
                    mii.fMask |= MIIM_CHECKMARKS;
                    mii.hbmpChecked = GetHBitmapForMenu(pItem, true);
                    mii.hbmpUnchecked = GetHBitmapForMenu(pItem, false);
                }
                else if ( pItem->GetBitmap().IsOk() )
                {
                    mii.fMask |= MIIM_BITMAP;
                    mii.hbmpItem = GetHBitmapForMenu(pItem);
                }

                mii.cch = itemText.length();
                mii.dwTypeData = const_cast<wxChar *>(itemText.wx_str());

                if ( flags & MF_POPUP )
                {
                    mii.fMask |= MIIM_SUBMENU;
                    mii.hSubMenu = GetHmenuOf(pItem->GetSubMenu());
                }
                else
                {
                    mii.fMask |= MIIM_ID;
                    mii.wID = id;
                }

                mii.dwItemData = reinterpret_cast<ULONG_PTR>(pItem);

                ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
                if ( !ok )
                {
                    wxLogLastError(wxT("InsertMenuItem()"));
                }
                else // InsertMenuItem() ok
                {
                    // we need to remove the extra indent which is reserved for
                    // the checkboxes by default as it looks ugly unless check
                    // boxes are used together with bitmaps and this is not the
                    // case in wx API
                    WinStruct<MENUINFO> mi;

                    // don't call SetMenuInfo() directly, this would prevent
                    // the app from starting up under Windows 95/NT 4
                    typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *);

                    wxDynamicLibrary dllUser(wxT("user32"));
                    wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser);
                    if ( pfnSetMenuInfo )
                    {
                        mi.fMask = MIM_STYLE;
                        mi.dwStyle = MNS_CHECKORBMP;
                        if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) )
                        {
                            wxLogLastError(wxT("SetMenuInfo(MNS_NOCHECK)"));
                        }
                    }

                    // tell the item that it's not really owner-drawn but only
                    // needs to draw its bitmap, the rest is done by Windows
                    pItem->SetOwnerDrawn(false);
                }
            }
        }
#endif // __DMC__

        if ( !ok )
        {
            // item draws itself, pass pointer to it in data parameter
            flags |= MF_OWNERDRAW;
            pData = (LPCTSTR)pItem;

            bool updateAllMargins = false;

            // get size of bitmap always return valid value (0 for invalid bitmap),
            // so we don't needed check if bitmap is valid ;)
            int uncheckedW = pItem->GetBitmap(false).GetWidth();
            int checkedW   = pItem->GetBitmap(true).GetWidth();

            if ( m_maxBitmapWidth < uncheckedW )
            {
                m_maxBitmapWidth = uncheckedW;
                updateAllMargins = true;
            }

            if ( m_maxBitmapWidth < checkedW )
            {
                m_maxBitmapWidth = checkedW;
                updateAllMargins = true;
            }

            // make other item ownerdrawn and update margin width for equals alignment
            if ( !m_ownerDrawn || updateAllMargins )
            {
                // we must use position in SetOwnerDrawnMenuItem because
                // all separators have the same id
                int pos = 0;
                wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
                while (node)
                {
                    wxMenuItem* item = node->GetData();

                    if ( !item->IsOwnerDrawn())
                    {
                        item->SetOwnerDrawn(true);
                        SetOwnerDrawnMenuItem(GetHmenu(), pos,
                                              reinterpret_cast<ULONG_PTR>(item), TRUE);
                    }

                    item->SetMarginWidth(m_maxBitmapWidth);

                    node = node->GetNext();
                    pos++;
                }

                // set menu as ownerdrawn
                m_ownerDrawn = true;

                ResetMaxAccelWidth();
            }
            // only update our margin for equals alignment to other item
            else if ( !updateAllMargins )
            {
                pItem->SetMarginWidth(m_maxBitmapWidth);
            }
        }
    }
    else
#endif // wxUSE_OWNER_DRAWN
    {
        // item is just a normal string (passed in data parameter)
        flags |= MF_STRING;

#ifdef __WXWINCE__
        itemText = wxMenuItem::GetLabelText(itemText);
#endif

        pData = (wxChar*)itemText.wx_str();
    }

    // item might have already been inserted by InsertMenuItem() above
    if ( !ok )
    {
        if ( !::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData) )
        {
            wxLogLastError(wxT("InsertMenu[Item]()"));

            return false;
        }
    }


    // Check the item if it should be initially checked.
    if ( checkInitially )
        pItem->Check(true);

    // if we just appended the title, highlight it
    if ( id == (UINT_PTR)idMenuTitle )
    {
        // visually select the menu title
        SetDefaultMenuItem(GetHmenu(), id);
    }

    // if we're already attached to the menubar, we must update it
    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        GetMenuBar()->Refresh();
    }

    return true;
}
Beispiel #7
0
//
// Append a new item or submenu to the menu
//
bool wxMenu::DoInsertOrAppend( wxMenuItem* pItem,
                               size_t      nPos )
{
    wxMenu*    pSubmenu = pItem->GetSubMenu();
    MENUITEM&  rItem = (pSubmenu != NULL)?pSubmenu->m_vMenuData:
                       pItem->m_vMenuData;

    ERRORID    vError;
    wxString   sError;

#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    //
    // If "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    //
    if (m_bDoBreak)
    {
        rItem.afStyle |= MIS_BREAK;
        m_bDoBreak = false;
    }

    //
    // Id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::MM_INSERTITEM message API
    //
    if (pSubmenu != NULL)
    {
        wxASSERT_MSG(pSubmenu->GetHMenu(), wxT("invalid submenu"));
        pSubmenu->SetParent(this);

        rItem.iPosition = 0; // submenus have a 0 position
        rItem.id        = (USHORT)pSubmenu->GetHMenu();
        rItem.afStyle  |= MIS_SUBMENU | MIS_TEXT;
    }
    else
    {
        rItem.id = (USHORT)pItem->GetId();
    }

    char *pData = NULL;

#if wxUSE_OWNER_DRAWN
    if (pItem->IsOwnerDrawn())
    {
        //
        // Want to get {Measure|Draw}Item messages?
        // item draws itself, passing pointer to data doesn't work in OS/2
        // Will eventually need to set the image handle somewhere into vItem.hItem
        //
        rItem.afStyle             |= MIS_OWNERDRAW;
        pData                      = NULL;
        rItem.hItem                = (HBITMAP)pItem->GetBitmap().GetHBITMAP();
        pItem->m_vMenuData.afStyle = rItem.afStyle;
        pItem->m_vMenuData.hItem   = rItem.hItem;
    }
    else
#endif
    if (pItem->IsSeparator())
    {
        rItem.afStyle = MIS_SEPARATOR;
    }
    else
    {
        if (pItem->GetId() == idMenuTitle)
        {
            // Item is an unselectable title to be passed via pData
            rItem.afStyle = MIS_STATIC;
        }
        else
        {
            //
            // Menu is just a normal string (passed in data parameter)
            //
            rItem.afStyle |= MIS_TEXT;
        }
        pData = (char*) pItem->GetItemLabel().wx_str();
    }

    if (nPos == (size_t)-1)
    {
        rItem.iPosition = MIT_END;
    }
    else
    {
        rItem.iPosition = (SHORT)nPos;
    }

    APIRET                          rc;

    rc = (APIRET)::WinSendMsg( GetHmenu()
                              ,MM_INSERTITEM
                              ,(MPARAM)&rItem
                              ,(MPARAM)pData
                             );
#if wxUSE_OWNER_DRAWN
    if (pItem->IsOwnerDrawn())
    {
        MENUITEM                   vMenuItem;

        ::WinSendMsg( GetHmenu()
                     ,MM_QUERYITEM
                     ,MPFROM2SHORT( (USHORT)pItem->GetId()
                                   ,(USHORT)(FALSE)
                                  )
                     ,&vMenuItem
                    );
    }
#endif

    if (rc == (APIRET)MIT_MEMERROR || rc == (APIRET)MIT_ERROR)
    {
        vError = ::WinGetLastError(vHabmain);
        sError = wxPMErrorToStr(vError);
        wxLogError(wxT("Error inserting or appending a menuitem. Error: %s\n"), sError.c_str());
        wxLogLastError(wxT("Insert or AppendMenu"));
        return false;
    }

    //
    // If we're already attached to the menubar, we must update it
    //
    if (IsAttached() && GetMenuBar()->IsAttached())
    {
        GetMenuBar()->Refresh();
    }

    return true;
} // end of wxMenu::DoInsertOrAppend
Beispiel #8
0
void wxMenu::UpdateAccel(
  wxMenuItem*                       pItem
)
{
    if (pItem->IsSubMenu())
    {
        wxMenu*                     pSubmenu = pItem->GetSubMenu();
        wxMenuItemList::compatibility_iterator node = pSubmenu->GetMenuItems().GetFirst();

#if defined(__INTEL_COMPILER) && 1 // VDM auto patch
#   pragma ivdep
#   pragma swp
#   pragma unroll
#endif
#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
        while (node)
        {
            UpdateAccel(node->GetData());
            node = node->GetNext();
        }
    }
    else if (!pItem->IsSeparator())
    {
        //
        // Recurse upwards: we should only modify m_accels of the top level
        // menus, not of the submenus as wxMenuBar doesn't look at them
        // (alternative and arguable cleaner solution would be to recurse
        // downwards in GetAccelCount() and CopyAccels())
        //
        if (GetParent())
        {
            GetParent()->UpdateAccel(pItem);
            return;
        }

        //
        // Find the (new) accel for this item
        //
        wxAcceleratorEntry*         pAccel = wxAcceleratorEntry::Create(pItem->GetItemLabel());

        if (pAccel)
            pAccel->m_command = pItem->GetId();

        //
        // Find the old one
        //
        size_t                      n = FindAccel(pItem->GetId());

        if (n == (size_t)wxNOT_FOUND)
        {
            //
            // No old, add new if any
            //
            if (pAccel)
                m_vAccels.Add(pAccel);
            else
                return;
        }
        else
        {
            //
            // Replace old with new or just remove the old one if no new
            //
            delete m_vAccels[n];
            if (pAccel)
                m_vAccels[n] = pAccel;
            else
                m_vAccels.RemoveAt(n);
        }

        if (IsAttached())
        {
            GetMenuBar()->RebuildAccelTable();
        }
    }
} // wxMenu::UpdateAccel
Beispiel #9
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    // we should support disabling the item even prior to adding it to the menu
    UINT flags = pItem->IsEnabled() ? MF_ENABLED : MF_GRAYED;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT_PTR id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT_PTR)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetMSWId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetItemLabel();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // Update radio groups data if we're inserting a new menu item.
    // Inserting radio and non-radio item has a different impact
    // on radio groups so we have to handle each case separately.
    // (Inserting a radio item in the middle of existing group extends
    // the group, but inserting non-radio item breaks it into two subgroups.)
    //
    bool checkInitially = false;
    if ( pItem->IsRadio() )
    {
        if ( !m_radioData )
            m_radioData = new wxMenuRadioItemsData;

        if ( m_radioData->UpdateOnInsertRadio(pos) )
            checkInitially = true;
    }
    else if ( m_radioData )
    {
        if ( m_radioData->UpdateOnInsertNonRadio(pos) )
        {
            // One of the existing groups has been split into two subgroups.
            wxFAIL_MSG(wxS("Inserting non-radio item inside a radio group?"));
        }
    }

    // Also handle the case of check menu items that had been checked before
    // being attached to the menu: we don't need to actually call Check() on
    // them, so we don't use checkInitially in this case, but we do need to
    // make them checked at Windows level too. Notice that we shouldn't ask
    // Windows for the checked state here, as wxMenuItem::IsChecked() does, as
    // the item is not attached yet, so explicitly call the base class version.
    if ( pItem->IsCheck() && pItem->wxMenuItemBase::IsChecked() )
        flags |= MF_CHECKED;

    // adjust position to account for the title of a popup menu, if any
    if ( !GetMenuBar() && !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

#if wxUSE_OWNER_DRAWN
    // Under older systems mixing owner-drawn and non-owner-drawn items results
    // in inconsistent margins, so we force this one to be owner-drawn if any
    // other items already are.
    if ( m_ownerDrawn )
        pItem->SetOwnerDrawn(true);

    // check if we have something more than a simple text item
    bool makeItemOwnerDrawn = false;
#endif // wxUSE_OWNER_DRAWN

    if (
#if wxUSE_OWNER_DRAWN
            !pItem->IsOwnerDrawn() &&
#endif
        !pItem->IsSeparator() )
            {
                WinStruct<MENUITEMINFO> mii;
                mii.fMask = MIIM_STRING | MIIM_DATA;

                // don't set hbmpItem for the checkable items as it would
                // be used for both checked and unchecked state
                if ( pItem->IsCheckable() )
                {
                    mii.fMask |= MIIM_CHECKMARKS;
                    mii.hbmpChecked = pItem->GetHBitmapForMenu(wxMenuItem::Checked);
                    mii.hbmpUnchecked = pItem->GetHBitmapForMenu(wxMenuItem::Unchecked);
                }
                else if ( pItem->GetBitmap().IsOk() )
                {
                    mii.fMask |= MIIM_BITMAP;
                    mii.hbmpItem = pItem->GetHBitmapForMenu(wxMenuItem::Normal);
                }

                mii.cch = itemText.length();
                mii.dwTypeData = wxMSW_CONV_LPTSTR(itemText);

                if ( flags & MF_POPUP )
                {
                    mii.fMask |= MIIM_SUBMENU;
                    mii.hSubMenu = GetHmenuOf(pItem->GetSubMenu());
                }
                else
                {
                    mii.fMask |= MIIM_ID;
                    mii.wID = id;
                }

                if ( flags & MF_GRAYED )
                {
                    mii.fMask |= MIIM_STATE;
                    mii.fState = MFS_GRAYED;
                }

                if ( flags & MF_CHECKED )
                {
                    mii.fMask |= MIIM_STATE;
                    mii.fState = MFS_CHECKED;
                }

                mii.dwItemData = reinterpret_cast<ULONG_PTR>(pItem);

                ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
                if ( !ok )
                {
                    wxLogLastError(wxT("InsertMenuItem()"));
#if wxUSE_OWNER_DRAWN
            // In case of failure switch new item to the owner-drawn mode.
            makeItemOwnerDrawn = true;
#endif
                }
                else // InsertMenuItem() ok
                {
                    // we need to remove the extra indent which is reserved for
                    // the checkboxes by default as it looks ugly unless check
                    // boxes are used together with bitmaps and this is not the
                    // case in wx API
                    WinStruct<MENUINFO> mi;
                    mi.fMask = MIM_STYLE;
                    mi.dwStyle = MNS_CHECKORBMP;
                    if ( !::SetMenuInfo(GetHmenu(), &mi) )
                    {
                        wxLogLastError(wxT("SetMenuInfo(MNS_NOCHECK)"));
                    }
                }
        }

#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() || makeItemOwnerDrawn )
        {
            // item draws itself, pass pointer to it in data parameter
            flags |= MF_OWNERDRAW;
            pData = (LPCTSTR)pItem;

            bool updateAllMargins = false;

            // get size of bitmap always return valid value (0 for invalid bitmap),
            // so we don't needed check if bitmap is valid ;)
            int uncheckedW = pItem->GetBitmap(false).GetWidth();
            int checkedW   = pItem->GetBitmap(true).GetWidth();

            if ( m_maxBitmapWidth < uncheckedW )
            {
                m_maxBitmapWidth = uncheckedW;
                updateAllMargins = true;
            }

            if ( m_maxBitmapWidth < checkedW )
            {
                m_maxBitmapWidth = checkedW;
                updateAllMargins = true;
            }

            // make other item ownerdrawn and update margin width for equals alignment
            if ( !m_ownerDrawn || updateAllMargins )
            {
                // we must use position in SetOwnerDrawnMenuItem because
                // all separators have the same id
                int position = 0;
                wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
                while (node)
                {
                    wxMenuItem* item = node->GetData();

                    // Current item is already added to the list of items
                    // but is not yet physically attached to the menu
                    // so we have to skip setting it as an owner drawn.
                    // It will be done later on when the item will be created.
                    if ( !item->IsOwnerDrawn() && item != pItem )
                    {
                        item->SetOwnerDrawn(true);
                        SetOwnerDrawnMenuItem(GetHmenu(), position,
                                              reinterpret_cast<ULONG_PTR>(item), TRUE);
                    }

                    item->SetMarginWidth(m_maxBitmapWidth);

                    node = node->GetNext();
                    // Current item is already added to the list of items
                    // but is not yet physically attached to the menu
                    // so it cannot be counted while determining position
                    // in the menu.
                    if ( item != pItem )
                        position++;
                }

                // set menu as ownerdrawn
                m_ownerDrawn = true;

                ResetMaxAccelWidth();
            }
            // only update our margin for equals alignment to other item
            else if ( !updateAllMargins )
            {
                pItem->SetMarginWidth(m_maxBitmapWidth);
            }
        }
#endif // wxUSE_OWNER_DRAWN

    // item might have already been inserted by InsertMenuItem() above
    if ( !ok )
    {
        if ( !::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData) )
        {
            wxLogLastError(wxT("InsertMenu[Item]()"));

            return false;
        }

#if wxUSE_OWNER_DRAWN
        if ( makeItemOwnerDrawn )
        {
            pItem->SetOwnerDrawn(true);
            SetOwnerDrawnMenuItem(GetHmenu(), pos,
                                  reinterpret_cast<ULONG_PTR>(pItem), TRUE);
        }
#endif
    }


    // Check the item if it should be initially checked.
    if ( checkInitially )
        pItem->Check(true);

    // if we just appended the title, highlight it
    if ( id == (UINT_PTR)idMenuTitle )
    {
        // visually select the menu title
        SetDefaultMenuItem(GetHmenu(), id);
    }

    // if we're already attached to the menubar, we must update it
    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        GetMenuBar()->Refresh();
    }

    return true;
}
Beispiel #10
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    UINT flags = 0;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetId();
    }

#ifdef __WXWINCE__
    wxString strippedString;
#endif

    LPCTSTR pData;

#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() ) {  // want to get {Measure|Draw}Item messages?
        // item draws itself, pass pointer to it in data parameter
        flags |= MF_OWNERDRAW;
        pData = (LPCTSTR)pItem;
    }
    else
#endif
    {
        // 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;
    if ( pos == (size_t)-1 )
    {
        ok = ::AppendMenu(GetHmenu(), flags, id, pData);
    }
    else
    {
        ok = ::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData);
    }

    if ( !ok )
    {
        wxLogLastError(wxT("Insert or AppendMenu"));

        return false;
    }

    // if we just appended the title, highlight it
#ifdef __WIN32__
    if ( (int)id == idMenuTitle )
    {
        // visually select the menu title
        SetDefaultMenuItem(GetHmenu(), id);
    }
#endif // __WIN32__

    // if we're already attached to the menubar, we must update it
    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        GetMenuBar()->Refresh();
    }

    return true;
}
Beispiel #11
0
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
    UpdateAccel(pItem);
#endif // wxUSE_ACCEL

    // we should support disabling the item even prior to adding it to the menu
    UINT flags = pItem->IsEnabled() ? MF_ENABLED : MF_GRAYED;

    // if "Break" has just been called, insert a menu break before this item
    // (and don't forget to reset the flag)
    if ( m_doBreak ) {
        flags |= MF_MENUBREAK;
        m_doBreak = false;
    }

    if ( pItem->IsSeparator() ) {
        flags |= MF_SEPARATOR;
    }

    // id is the numeric id for normal menu items and HMENU for submenus as
    // required by ::AppendMenu() API
    UINT_PTR id;
    wxMenu *submenu = pItem->GetSubMenu();
    if ( submenu != NULL ) {
        wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );

        submenu->SetParent(this);

        id = (UINT_PTR)submenu->GetHMenu();

        flags |= MF_POPUP;
    }
    else {
        id = pItem->GetMSWId();
    }


    // prepare to insert the item in the menu
    wxString itemText = pItem->GetItemLabel();
    LPCTSTR pData = NULL;
    if ( pos == (size_t)-1 )
    {
        // append at the end (note that the item is already appended to
        // internal data structures)
        pos = GetMenuItemCount() - 1;
    }

    // adjust position to account for the title, if any
    if ( !m_title.empty() )
        pos += 2; // for the title itself and its separator

    BOOL ok = false;

#if wxUSE_OWNER_DRAWN
    // Under older systems mixing owner-drawn and non-owner-drawn items results
    // in inconsistent margins, so we force this one to be owner-drawn if any
    // other items already are. Later we might want to use a boolean in the
    // wxMenu to avoid search. Also we might make this fix unnecessary by
    // getting the correct margin using NONCLIENTMETRICS.
    static const wxWinVersion winver = wxGetWinVersion();
    if ( winver < wxWinVersion_XP &&
            !pItem->IsOwnerDrawn() && !pItem->IsSeparator() )
    {
        // Check if any other items are ownerdrawn, and make ownerdrawn if so
        wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
        while (node)
        {
            if (node->GetData()->IsOwnerDrawn())
            {
                pItem->SetOwnerDrawn(true);
                break;
            }
            node = node->GetNext();
        }
    }
#endif // wxUSE_OWNER_DRAWN

    // check if we have something more than a simple text item
#if wxUSE_OWNER_DRAWN
    if ( pItem->IsOwnerDrawn() )
    {
#ifndef __DMC__
        // MIIM_BITMAP only works under WinME/2000+ so we always use owner
        // drawn item under the previous versions and we also have to use them
        // in any case if the item has custom colours or font
        bool mustUseOwnerDrawn = winver < wxWinVersion_98 ||
                                 pItem->GetTextColour().Ok() ||
                                 pItem->GetBackgroundColour().Ok() ||
                                 pItem->GetFont().Ok();
        if ( !mustUseOwnerDrawn )
        {
            const wxBitmap& bmpUnchecked = pItem->GetBitmap(false),
                            bmpChecked = pItem->GetBitmap(true);
            if ( (bmpUnchecked.Ok() && !IsLessThanStdSize(bmpUnchecked)) ||
                    (bmpChecked.Ok() && !IsLessThanStdSize(bmpChecked)) )
            {
                mustUseOwnerDrawn = true;
            }
        }

        // use InsertMenuItem() if possible as it's guaranteed to look correct
        // while our owner-drawn code is not
        if ( !mustUseOwnerDrawn )
        {
            WinStruct<MENUITEMINFO> mii;
            mii.fMask = MIIM_STRING | MIIM_DATA;

            if ( pItem->GetBitmap().IsOk() )
            {
                mii.fMask |= MIIM_BITMAP;
                mii.hbmpItem = GetHBitmapForMenu(pItem);
            }

            if ( pItem->IsCheckable() )
            {
                mii.fMask |= MIIM_CHECKMARKS;
                mii.hbmpChecked = GetHBitmapForMenu(pItem, true);
                mii.hbmpUnchecked = GetHBitmapForMenu(pItem, false);
            }

            mii.cch = itemText.length();
            mii.dwTypeData = const_cast<wxChar *>(itemText.wx_str());

            if ( flags & MF_POPUP )
            {
                mii.fMask |= MIIM_SUBMENU;
                mii.hSubMenu = GetHmenuOf(pItem->GetSubMenu());
            }
            else
            {
                mii.fMask |= MIIM_ID;
                mii.wID = id;
            }

            mii.dwItemData = reinterpret_cast<ULONG_PTR>(pItem);

            ok = ::InsertMenuItem(GetHmenu(), pos, TRUE /* by pos */, &mii);
            if ( !ok )
            {
                wxLogLastError(wxT("InsertMenuItem()"));
            }
            else // InsertMenuItem() ok
            {
                // we need to remove the extra indent which is reserved for
                // the checkboxes by default as it looks ugly unless check
                // boxes are used together with bitmaps and this is not the
                // case in wx API
                WinStruct<MENUINFO> mi;

                // don't call SetMenuInfo() directly, this would prevent
                // the app from starting up under Windows 95/NT 4
                typedef BOOL (WINAPI *SetMenuInfo_t)(HMENU, MENUINFO *);

                wxDynamicLibrary dllUser(wxT("user32"));
                wxDYNLIB_FUNCTION(SetMenuInfo_t, SetMenuInfo, dllUser);
                if ( pfnSetMenuInfo )
                {
                    mi.fMask = MIM_STYLE;
                    mi.dwStyle = MNS_CHECKORBMP;
                    if ( !(*pfnSetMenuInfo)(GetHmenu(), &mi) )
                    {
                        wxLogLastError(wxT("SetMenuInfo(MNS_NOCHECK)"));
                    }
                }

                // tell the item that it's not really owner-drawn but only
                // needs to draw its bitmap, the rest is done by Windows
                pItem->ResetOwnerDrawn();
            }
        }
#endif // __DMC__

        if ( !ok )
        {
            // item draws itself, pass pointer to it in data parameter
            flags |= MF_OWNERDRAW;
            pData = (LPCTSTR)pItem;
        }
    }
    else
#endif // wxUSE_OWNER_DRAWN
    {
        // item is just a normal string (passed in data parameter)
        flags |= MF_STRING;

#ifdef __WXWINCE__
        itemText = wxMenuItem::GetLabelText(itemText);
#endif

        pData = (wxChar*)itemText.wx_str();
    }

    // item might have already been inserted by InsertMenuItem() above
    if ( !ok )
    {
        if ( !::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData) )
        {
            wxLogLastError(wxT("InsertMenu[Item]()"));

            return false;
        }
    }


    // if we just appended the title, highlight it
    if ( id == idMenuTitle )
    {
        // visually select the menu title
        SetDefaultMenuItem(GetHmenu(), id);
    }

    // if we're already attached to the menubar, we must update it
    if ( IsAttached() && GetMenuBar()->IsAttached() )
    {
        GetMenuBar()->Refresh();
    }

    return true;
}