toplevel.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,171 行 · 第 1/3 页

CPP
1,171
字号
        }

        SetSize(rect);

        // now flush the window style cache and actually go full-screen
        long flags = SWP_FRAMECHANGED;

        // showing the frame full screen should also show it if it's still
        // hidden
        if ( !IsShown() )
        {
            // don't call wxWindow version to avoid flicker from calling
            // ::ShowWindow() -- we're going to show the window at the correct
            // location directly below -- but do call the wxWindowBase version
            // to sync the internal m_isShown flag
            wxWindowBase::Show();

            flags |= SWP_SHOWWINDOW;
        }

        SetWindowPos(GetHwnd(), HWND_TOP,
                     rect.x, rect.y, rect.width, rect.height,
                     flags);

#if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400))
        ::SHFullScreen(GetHwnd(), SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON);
#endif

        // finally send an event allowing the window to relayout itself &c
        wxSizeEvent event(rect.GetSize(), GetId());
        GetEventHandler()->ProcessEvent(event);
    }
    else // stop showing full screen
    {
#if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400))
        ::SHFullScreen(GetHwnd(), SHFS_SHOWTASKBAR | SHFS_SHOWSIPBUTTON);
#endif
        Maximize(m_fsIsMaximized);
        SetWindowLong(GetHwnd(),GWL_STYLE, m_fsOldWindowStyle);
        SetWindowPos(GetHwnd(),HWND_TOP,m_fsOldSize.x, m_fsOldSize.y,
            m_fsOldSize.width, m_fsOldSize.height, SWP_FRAMECHANGED);
    }

    return true;
}

// ----------------------------------------------------------------------------
// wxTopLevelWindowMSW misc
// ----------------------------------------------------------------------------

void wxTopLevelWindowMSW::SetIcon(const wxIcon& icon)
{
    SetIcons( wxIconBundle( icon ) );
}

void wxTopLevelWindowMSW::SetIcons(const wxIconBundle& icons)
{
    wxTopLevelWindowBase::SetIcons(icons);

#if defined(__WIN95__) && !defined(__WXMICROWIN__)
    const wxIcon& sml = icons.GetIcon( wxSize( 16, 16 ) );
    if( sml.Ok() && sml.GetWidth() == 16 && sml.GetHeight() == 16 )
    {
        ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_SMALL,
                       (LPARAM)GetHiconOf(sml) );
    }

    const wxIcon& big = icons.GetIcon( wxSize( 32, 32 ) );
    if( big.Ok() && big.GetWidth() == 32 && big.GetHeight() == 32 )
    {
        ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_BIG,
                       (LPARAM)GetHiconOf(big) );
    }
#endif // __WIN95__
}

bool wxTopLevelWindowMSW::EnableCloseButton(bool enable)
{
#if !defined(__WXMICROWIN__)
    // get system (a.k.a. window) menu
    HMENU hmenu = GetSystemMenu(GetHwnd(), FALSE /* get it */);
    if ( !hmenu )
    {
        // no system menu at all -- ok if we want to remove the close button
        // anyhow, but bad if we want to show it
        return !enable;
    }

    // enabling/disabling the close item from it also automatically
    // disables/enables the close title bar button
    if ( ::EnableMenuItem(hmenu, SC_CLOSE,
                          MF_BYCOMMAND |
                          (enable ? MF_ENABLED : MF_GRAYED)) == -1 )
    {
        wxLogLastError(_T("EnableMenuItem(SC_CLOSE)"));

        return false;
    }
#ifndef __WXWINCE__
    // update appearance immediately
    if ( !::DrawMenuBar(GetHwnd()) )
    {
        wxLogLastError(_T("DrawMenuBar"));
    }
#endif
#endif // !__WXMICROWIN__

    return true;
}

#ifndef __WXWINCE__

bool wxTopLevelWindowMSW::SetShape(const wxRegion& region)
{
    wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
                 _T("Shaped windows must be created with the wxFRAME_SHAPED style."));

    // The empty region signifies that the shape should be removed from the
    // window.
    if ( region.IsEmpty() )
    {
        if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0)
        {
            wxLogLastError(_T("SetWindowRgn"));
            return false;
        }
        return true;
    }

    // Windows takes ownership of the region, so
    // we'll have to make a copy of the region to give to it.
    DWORD noBytes = ::GetRegionData(GetHrgnOf(region), 0, NULL);
    RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
    ::GetRegionData(GetHrgnOf(region), noBytes, rgnData);
    HRGN hrgn = ::ExtCreateRegion(NULL, noBytes, rgnData);
    delete[] (char*) rgnData;

    // SetWindowRgn expects the region to be in coordinants
    // relative to the window, not the client area.  Figure
    // out the offset, if any.
    RECT rect;
    DWORD dwStyle =   ::GetWindowLong(GetHwnd(), GWL_STYLE);
    DWORD dwExStyle = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
    ::GetClientRect(GetHwnd(), &rect);
    ::AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle);
    ::OffsetRgn(hrgn, -rect.left, -rect.top);

    // Now call the shape API with the new region.
    if (::SetWindowRgn(GetHwnd(), hrgn, TRUE) == 0)
    {
        wxLogLastError(_T("SetWindowRgn"));
        return false;
    }
    return true;
}

#endif // !__WXWINCE__

void wxTopLevelWindowMSW::RequestUserAttention(int flags)
{
    // check if we can use FlashWindowEx(): unfortunately a simple test for
    // FLASHW_STOP doesn't work because MSVC6 headers do #define it but don't
    // provide FlashWindowEx() declaration, so try to detect whether we have
    // real headers for WINVER 0x0500 by checking for existence of a symbol not
    // declated in MSVC6 header
#if defined(FLASHW_STOP) && defined(VK_XBUTTON1)
    // available in the headers, check if it is supported by the system
    typedef BOOL (WINAPI *FlashWindowEx_t)(FLASHWINFO *pfwi);
    FlashWindowEx_t s_pfnFlashWindowEx = NULL;
    if ( !s_pfnFlashWindowEx )
    {
        wxDynamicLibrary dllUser32(_T("user32.dll"));
        s_pfnFlashWindowEx = (FlashWindowEx_t)
                                dllUser32.GetSymbol(_T("FlashWindowEx"));

        // we can safely unload user32.dll here, it's going to remain loaded as
        // long as the program is running anyhow
    }

    if ( s_pfnFlashWindowEx )
    {
        WinStruct<FLASHWINFO> fwi;
        fwi.hwnd = GetHwnd();
        fwi.dwFlags = FLASHW_ALL;
        if ( flags & wxUSER_ATTENTION_INFO )
        {
            // just flash a few times
            fwi.uCount = 3;
        }
        else // wxUSER_ATTENTION_ERROR
        {
            // flash until the user notices it
            fwi.dwFlags |= FLASHW_TIMERNOFG;
        }

        s_pfnFlashWindowEx(&fwi);
    }
    else // FlashWindowEx() not available
#endif // FlashWindowEx() defined
    {
        wxUnusedVar(flags);
#ifndef __WXWINCE__
        ::FlashWindow(GetHwnd(), TRUE);
#endif // __WXWINCE__
    }
}

// ----------------------------------------------------------------------------
// wxTopLevelWindow event handling
// ----------------------------------------------------------------------------

// Default activation behaviour - set the focus for the first child
// subwindow found.
void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event)
{
    if ( event.GetActive() )
    {
        // restore focus to the child which was last focused unless we already
        // have it
        wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), (int) m_hWnd);

        wxWindow *winFocus = FindFocus();
        if ( !winFocus || wxGetTopLevelParent(winFocus) != this )
        {
            wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
                                                : NULL;
            if ( !parent )
            {
                parent = this;
            }

            wxSetFocusToChild(parent, &m_winLastFocused);
        }
    }
    else // deactivating
    {
        // remember the last focused child if it is our child
        m_winLastFocused = FindFocus();

        if ( m_winLastFocused )
        {
            // let it know that it doesn't have focus any more
            m_winLastFocused->HandleKillFocus((WXHWND)NULL);

            // and don't remember it if it's a child from some other frame
            if ( wxGetTopLevelParent(m_winLastFocused) != this )
            {
                m_winLastFocused = NULL;
            }
        }

        wxLogTrace(_T("focus"),
                   _T("wxTLW %08x deactivated, last focused: %08x."),
                   (int) m_hWnd,
                   (int) (m_winLastFocused ? GetHwndOf(m_winLastFocused)
                                           : NULL));

        event.Skip();
    }
}

// the DialogProc for all wxWidgets dialogs
LONG APIENTRY _EXPORT
wxDlgProc(HWND hDlg,
          UINT message,
          WPARAM WXUNUSED(wParam),
          LPARAM WXUNUSED(lParam))
{
    if ( message == WM_INITDIALOG )
    {
        // under CE, add a "Ok" button in the dialog title bar and make it full
        // screen
        //
        // TODO: find the window for this HWND, and take into account
        // wxMAXIMIZE and wxCLOSE_BOX. For now, assume both are present.
        //
        // Standard SDK doesn't have aygshell.dll: see
        // include/wx/msw/wince/libraries.h
#if defined(__WXWINCE__) && !defined(__WINCE_STANDARDSDK__) && !defined(__HANDHELDPC__)
        SHINITDLGINFO shidi;
        shidi.dwMask = SHIDIM_FLAGS;
        shidi.dwFlags = SHIDIF_SIZEDLG // take account of the SIP or menubar
#ifndef __SMARTPHONE__
                        | SHIDIF_DONEBUTTON
#endif
                        ;
        shidi.hDlg = hDlg;
        SHInitDialog( &shidi );
#else // no SHInitDialog()
        wxUnusedVar(hDlg);
#endif

        // eVC3 with PPC SDK 2002 seem to miss initial positioning
        // of subcontrols so we force it making dummy resize
#if defined(__POCKETPC__) && (defined(__WXWINCE__) && _WIN32_WCE < 400)
        RECT r = wxGetWindowRect(hDlg);

        (void)::PostMessage(hDlg, WM_SIZE, SIZE_RESTORED,
                            MAKELPARAM(r.right - r.left, r.bottom - r.top));
#endif
    }

    // for almost all messages, returning FALSE means that we didn't process
    // the message
    //
    // for WM_INITDIALOG, returning TRUE tells system to set focus to
    // the first control in the dialog box, but as we set the focus
    // ourselves, we return FALSE for it as well
    return FALSE;
}

// ============================================================================
// wxTLWHiddenParentModule implementation
// ============================================================================

HWND wxTLWHiddenParentModule::ms_hwnd = NULL;

const wxChar *wxTLWHiddenParentModule::ms_className = NULL;

bool wxTLWHiddenParentModule::OnInit()
{
    ms_hwnd = NULL;
    ms_className = NULL;

    return true;
}

void wxTLWHiddenParentModule::OnExit()
{
    if ( ms_hwnd )
    {
        if ( !::DestroyWindow(ms_hwnd) )
        {
            wxLogLastError(_T("DestroyWindow(hidden TLW parent)"));
        }

        ms_hwnd = NULL;
    }

    if ( ms_className )
    {
        if ( !::UnregisterClass(ms_className, wxGetInstance()) )
        {
            wxLogLastError(_T("UnregisterClass(\"wxTLWHiddenParent\")"));
        }

        ms_className = NULL;
    }
}

/* static */
HWND wxTLWHiddenParentModule::GetHWND()
{
    if ( !ms_hwnd )
    {
        if ( !ms_className )
        {
            static const wxChar *HIDDEN_PARENT_CLASS = _T("wxTLWHiddenParent");

            WNDCLASS wndclass;
            wxZeroMemory(wndclass);

            wndclass.lpfnWndProc   = DefWindowProc;
            wndclass.hInstance     = wxGetInstance();
            wndclass.lpszClassName = HIDDEN_PARENT_CLASS;

            if ( !::RegisterClass(&wndclass) )
            {
                wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")"));
            }
            else
            {
                ms_className = HIDDEN_PARENT_CLASS;
            }
        }

        ms_hwnd = ::CreateWindow(ms_className, wxEmptyString, 0, 0, 0, 0, 0, NULL,
                                 (HMENU)NULL, wxGetInstance(), NULL);
        if ( !ms_hwnd )
        {
            wxLogLastError(_T("CreateWindow(hidden TLW parent)"));
        }
    }

    return ms_hwnd;
}


⌨️ 快捷键说明

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