⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdi.cpp

📁 A*算法 A*算法 A*算法 A*算法A*算法A*算法
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        wxMenu *popupMenu = wxCurrentPopupMenu;
        wxCurrentPopupMenu = NULL;
        if (popupMenu->MSWCommand(cmd, id))
            return true;
    }

    bool processed;
    if (GetMenuBar() && GetMenuBar()->FindItem(id))
    {
        processed = ProcessCommand(id);
    }
    else
    {
        processed = false;
    }

    return processed;
}

bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate),
                                        WXHWND hwndAct,
                                        WXHWND hwndDeact)
{
    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();

    HMENU menuToSet = 0;

    bool activated;

    if ( m_hWnd == hwndAct )
    {
        activated = true;
        parent->m_currentChild = this;

        HMENU child_menu = (HMENU)GetWinMenu();
        if ( child_menu )
        {
            parent->m_parentFrameActive = false;

            menuToSet = child_menu;
        }
    }
    else if ( m_hWnd == hwndDeact )
    {
        wxASSERT_MSG( parent->m_currentChild == this,
                      wxT("can't deactivate MDI child which wasn't active!") );

        activated = false;
        parent->m_currentChild = NULL;

        HMENU parent_menu = (HMENU)parent->GetWinMenu();

        // activate the the parent menu only when there is no other child
        // that has been activated
        if ( parent_menu && !hwndAct )
        {
            parent->m_parentFrameActive = true;

            menuToSet = parent_menu;
        }
    }
    else
    {
        // we have nothing to do with it
        return false;
    }

    if ( menuToSet )
    {
        MDISetMenu(parent->GetClientWindow(),
                   menuToSet, GetMDIWindowMenu(parent));
    }

    wxActivateEvent event(wxEVT_ACTIVATE, activated, m_windowId);
    event.SetEventObject( this );

    ResetWindowStyle((void *)NULL);

    return GetEventHandler()->ProcessEvent(event);
}

bool wxMDIChildFrame::HandleWindowPosChanging(void *pos)
{
    WINDOWPOS *lpPos = (WINDOWPOS *)pos;
#if defined(__WIN95__)
    if (!(lpPos->flags & SWP_NOSIZE))
    {
        RECT rectClient;
        DWORD dwExStyle = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
        DWORD dwStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE);
        if (ResetWindowStyle((void *) & rectClient) && (dwStyle & WS_MAXIMIZE))
        {
            ::AdjustWindowRectEx(&rectClient, dwStyle, false, dwExStyle);
            lpPos->x = rectClient.left;
            lpPos->y = rectClient.top;
            lpPos->cx = rectClient.right - rectClient.left;
            lpPos->cy = rectClient.bottom - rectClient.top;
        }
#if wxUSE_TOOLBAR
        wxMDIParentFrame* pFrameWnd = (wxMDIParentFrame *)GetParent();
        if (pFrameWnd && pFrameWnd->GetToolBar() && pFrameWnd->GetToolBar()->IsShown())
        {
            pFrameWnd->GetToolBar()->Refresh();
        }
#endif
    }
#endif // Win95

    return false;
}

bool wxMDIChildFrame::HandleGetMinMaxInfo(void *mmInfo)
{
    MINMAXINFO *info = (MINMAXINFO *)mmInfo;

    // let the default window proc calculate the size of MDI children
    // frames because it is based on the size of the MDI client window,
    // not on the values specified in wxWindow m_max variables
    bool processed = MSWDefWindowProc(WM_GETMINMAXINFO, 0, (LPARAM)mmInfo) != 0;

    int minWidth = GetMinWidth(),
        minHeight = GetMinHeight();

    // but allow GetSizeHints() to set the min size
    if ( minWidth != -1 )
    {
        info->ptMinTrackSize.x = minWidth;

        processed = true;
    }

    if ( minHeight != -1 )
    {
        info->ptMinTrackSize.y = minHeight;

        processed = true;
    }

    return processed;
}

// ---------------------------------------------------------------------------
// MDI specific message translation/preprocessing
// ---------------------------------------------------------------------------

WXLRESULT wxMDIChildFrame::MSWDefWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
    return DefMDIChildProc(GetHwnd(),
                           (UINT)message, (WPARAM)wParam, (LPARAM)lParam);
}

bool wxMDIChildFrame::MSWTranslateMessage(WXMSG* pMsg)
{
    // NB: this duplicates the code in wxFrame::MSWTranslateMessage() to avoid
    //     breaking backwards compatibility; cvs HEAD has a better version of
    //     this fix

    if ( wxWindow::MSWTranslateMessage(pMsg) )
        return true;

#if wxUSE_MENUS && wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
    // try the menu bar accels
    wxMenuBar *menuBar = GetMenuBar();
    if ( menuBar )
    {
        const wxAcceleratorTable& acceleratorTable = menuBar->GetAccelTable();

        // the difference with wxFrame version is that we must pass the top
        // level frame to Translate() here, not "this" pointer
        return acceleratorTable.Translate(GetParent(), pMsg);
    }
#endif // wxUSE_MENUS && wxUSE_ACCEL

    return false;
}

// ---------------------------------------------------------------------------
// misc
// ---------------------------------------------------------------------------

void wxMDIChildFrame::MSWDestroyWindow()
{
    invalidHandle = GetHwnd();

    wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent();

    // Must make sure this handle is invalidated (set to NULL) since all sorts
    // of things could happen after the child client is destroyed, but before
    // the wxFrame is destroyed.

    HWND oldHandle = (HWND)GetHWND();
    SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIDESTROY,
                (WPARAM)oldHandle, 0);

    if (parent->GetActiveChild() == (wxMDIChildFrame*) NULL)
        ResetWindowStyle((void*) NULL);

    invalidHandle = 0;

    if (m_hMenu)
    {
        ::DestroyMenu((HMENU) m_hMenu);
        m_hMenu = 0;
    }
    wxRemoveHandleAssociation(this);
    m_hWnd = 0;
}

// Change the client window's extended style so we don't get a client edge
// style when a child is maximised (a double border looks silly.)
bool wxMDIChildFrame::ResetWindowStyle(void *vrect)
{
#if defined(__WIN95__)
    RECT *rect = (RECT *)vrect;
    wxMDIParentFrame* pFrameWnd = (wxMDIParentFrame *)GetParent();
    wxMDIChildFrame* pChild = pFrameWnd->GetActiveChild();
    if (!pChild || (pChild == this))
    {
        HWND hwndClient = GetWinHwnd(pFrameWnd->GetClientWindow());
        DWORD dwStyle = ::GetWindowLong(hwndClient, GWL_EXSTYLE);

        // we want to test whether there is a maximized child, so just set
        // dwThisStyle to 0 if there is no child at all
        DWORD dwThisStyle = pChild
            ? ::GetWindowLong(GetWinHwnd(pChild), GWL_STYLE) : 0;
        DWORD dwNewStyle = dwStyle;
        if ( dwThisStyle & WS_MAXIMIZE )
            dwNewStyle &= ~(WS_EX_CLIENTEDGE);
        else
            dwNewStyle |= WS_EX_CLIENTEDGE;

        if (dwStyle != dwNewStyle)
        {
            // force update of everything
            ::RedrawWindow(hwndClient, NULL, NULL,
                           RDW_INVALIDATE | RDW_ALLCHILDREN);
            ::SetWindowLong(hwndClient, GWL_EXSTYLE, dwNewStyle);
            ::SetWindowPos(hwndClient, NULL, 0, 0, 0, 0,
                           SWP_FRAMECHANGED | SWP_NOACTIVATE |
                           SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
                           SWP_NOCOPYBITS);
            if (rect)
                ::GetClientRect(hwndClient, rect);

            return true;
        }
    }
#endif // Win95

    return false;
}

// ===========================================================================
// wxMDIClientWindow: the window of predefined (by Windows) class which
// contains the child frames
// ===========================================================================

bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style)
{
    m_backgroundColour = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);

    CLIENTCREATESTRUCT ccs;
    m_windowStyle = style;
    m_parent = parent;

    ccs.hWindowMenu = GetMDIWindowMenu(parent);
    ccs.idFirstChild = wxFIRST_MDI_CHILD;

    DWORD msStyle = MDIS_ALLCHILDSTYLES | WS_VISIBLE | WS_CHILD |
                    WS_CLIPCHILDREN | WS_CLIPSIBLINGS;

    if ( style & wxHSCROLL )
        msStyle |= WS_HSCROLL;
    if ( style & wxVSCROLL )
        msStyle |= WS_VSCROLL;

#if defined(__WIN95__)
    DWORD exStyle = WS_EX_CLIENTEDGE;
#else
    DWORD exStyle = 0;
#endif

    wxWindowCreationHook hook(this);
    m_hWnd = (WXHWND)::CreateWindowEx
                       (
                        exStyle,
                        wxT("MDICLIENT"),
                        NULL,
                        msStyle,
                        0, 0, 0, 0,
                        GetWinHwnd(parent),
                        NULL,
                        wxGetInstance(),
                        (LPSTR)(LPCLIENTCREATESTRUCT)&ccs);
    if ( !m_hWnd )
    {
        wxLogLastError(wxT("CreateWindowEx(MDI client)"));

        return false;
    }

    SubclassWin(m_hWnd);

    return true;
}

// Explicitly call default scroll behaviour
void wxMDIClientWindow::OnScroll(wxScrollEvent& event)
{
    // Note: for client windows, the scroll position is not set in
    // WM_HSCROLL, WM_VSCROLL, so we can't easily determine what
    // scroll position we're at.
    // This makes it hard to paint patterns or bitmaps in the background,
    // and have the client area scrollable as well.

    if ( event.GetOrientation() == wxHORIZONTAL )
        m_scrollX = event.GetPosition(); // Always returns zero!
    else
        m_scrollY = event.GetPosition(); // Always returns zero!

    event.Skip();
}

void wxMDIClientWindow::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{
    // Try to fix a problem whereby if you show an MDI child frame, then reposition the
    // client area, you can end up with a non-refreshed portion in the client window
    // (see OGL studio sample). So check if the position is changed and if so,
    // redraw the MDI child frames.

    const wxPoint oldPos = GetPosition();

    wxWindow::DoSetSize(x, y, width, height, sizeFlags | wxSIZE_FORCE);

    const wxPoint newPos = GetPosition();

    if ((newPos.x != oldPos.x) || (newPos.y != oldPos.y))
    {
        if (GetParent())
        {
            wxWindowList::compatibility_iterator node = GetParent()->GetChildren().GetFirst();
            while (node)
            {
                wxWindow *child = node->GetData();
                if (child->IsKindOf(CLASSINFO(wxMDIChildFrame)))
                {
                   ::RedrawWindow(GetHwndOf(child),
                                  NULL,
                                  NULL,
                                  RDW_FRAME |
                                  RDW_ALLCHILDREN |
                                  RDW_INVALIDATE);
                }
                node = node->GetNext();
            }
        }
    }
}

void wxMDIChildFrame::OnIdle(wxIdleEvent& event)
{
    // wxMSW prior to 2.5.3 created MDI child frames as visible, which resulted
    // in flicker e.g. when the frame contained controls with non-trivial
    // layout. Since 2.5.3, the frame is created hidden as all other top level
    // windows. In order to maintain backward compatibility, the frame is shown
    // in OnIdle, unless Show(false) was called by the programmer before.
    if ( m_needsInitialShow )
    {
        Show(true);
    }

    // MDI child frames get their WM_SIZE when they're constructed but at this
    // moment they don't have any children yet so all child windows will be
    // positioned incorrectly when they are added later - to fix this, we
    // generate an artificial size event here
    if ( m_needsResize )
    {
        m_needsResize = false; // avoid any possibility of recursion

        SendSizeEvent();
    }

    event.Skip();
}

// ---------------------------------------------------------------------------
// non member functions
// ---------------------------------------------------------------------------

static void MDISetMenu(wxWindow *win, HMENU hmenuFrame, HMENU hmenuWindow)
{
    ::SendMessage(GetWinHwnd(win), WM_MDISETMENU,
#ifdef __WIN32__
                  (WPARAM)hmenuFrame, (LPARAM)hmenuWindow
#else
                  0, MAKELPARAM(hmenuFrame, hmenuWindow)
#endif
                 );

    // update menu bar of the parent window
    wxWindow *parent = win->GetParent();
    wxCHECK_RET( parent, wxT("MDI client without parent frame? weird...") );

    ::SendMessage(GetWinHwnd(win), WM_MDIREFRESHMENU, 0, 0L);

    ::DrawMenuBar(GetWinHwnd(parent));
}

static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu)
{
    // Try to insert Window menu in front of Help, otherwise append it.
    HMENU hmenu = (HMENU)menu;

    if (subMenu)
    {
        int N = GetMenuItemCount(hmenu);
        bool success = false;
        for ( int i = 0; i < N; i++ )
        {
            wxChar buf[256];
            int chars = GetMenuString(hmenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION);
            if ( chars == 0 )
            {
                wxLogLastError(wxT("GetMenuString"));

                continue;
            }

            wxString strBuf(buf);
            if ( wxStripMenuCodes(strBuf) == wxGetStockLabel(wxID_HELP,false) )
            {
                success = true;
                ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING,
                             (UINT)subMenu, _("&Window"));
                break;
            }
        }

        if ( !success )
        {
            ::AppendMenu(hmenu, MF_POPUP, (UINT)subMenu, _("&Window"));
        }
    }

    MDISetMenu(win, hmenu, subMenu);
}

static void RemoveWindowMenu(wxWindow *win, WXHMENU menu)
{
    HMENU hMenu = (HMENU)menu;

    if ( hMenu )
    {
        wxChar buf[1024];

        int N = ::GetMenuItemCount(hMenu);
        for ( int i = 0; i < N; i++ )
        {
            if ( !::GetMenuString(hMenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION) )
            {
                // Ignore successful read of menu string with length 0 which
                // occurs, for example, for a maximized MDI childs system menu
                if ( ::GetLastError() != 0 )
                {
                    wxLogLastError(wxT("GetMenuString"));
                }

                continue;
            }

            if ( wxStrcmp(buf, _("&Window")) == 0 )
            {
                if ( !::RemoveMenu(hMenu, i, MF_BYPOSITION) )
                {
                    wxLogLastError(wxT("RemoveMenu"));
                }

                break;
            }
        }
    }

    if ( win )
    {
        // we don't change the windows menu, but we update the main one
        MDISetMenu(win, hMenu, NULL);
    }
}

static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam,
                              WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact)
{
    *activate = true;
    *hwndAct = (WXHWND)lParam;
    *hwndDeact = (WXHWND)wParam;
}

#endif // wxUSE_MDI && !defined(__WXUNIVERSAL__)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -