X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dca0f651782d5c2659203c97b3243f613966998d..107defe36a68091303be9a11c8abb83432acee8c:/src/msw/toplevel.cpp diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 65dfa44586..5fb5fd504f 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -78,17 +78,6 @@ static inline bool IsZoomed(HWND WXUNUSED(hwnd)) { return false; } LONG APIENTRY _EXPORT wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); -// ---------------------------------------------------------------------------- -// globals -// ---------------------------------------------------------------------------- - -// the name of the default wxWidgets class -#ifdef __WXWINCE__ -extern wxChar *wxCanvasClassName; -#else -extern const wxChar *wxCanvasClassName; -#endif - // ---------------------------------------------------------------------------- // wxTLWHiddenParentModule: used to manage the hidden parent window (we need a // module to ensure that the window is always deleted) @@ -139,7 +128,7 @@ void wxTopLevelWindowMSW::Init() m_fsIsMaximized = false; m_fsIsShowing = false; - m_winLastFocused = (wxWindow *)NULL; + m_winLastFocused = NULL; #if defined(__SMARTPHONE__) && defined(__WXWINCE__) m_MenuBarHWND = 0; @@ -299,7 +288,7 @@ WXHWND wxTopLevelWindowMSW::MSWGetParent() const if ( !parent ) { // this flag doesn't make sense then and will be ignored - wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") ); + wxFAIL_MSG( wxT("wxFRAME_FLOAT_ON_PARENT but no parent?") ); } else { @@ -384,29 +373,10 @@ bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate, // no dialogs support under MicroWin yet return CreateFrame(title, pos, size); #else // !__WXMICROWIN__ - wxWindow *parent = GetParent(); - - // for the dialogs without wxDIALOG_NO_PARENT style, use the top level - // app window as parent - this avoids creating modal dialogs without - // parent - if ( !parent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT) ) - { - parent = wxTheApp->GetTopWindow(); - - if ( parent ) - { - // don't use transient windows as parents, this is dangerous as it - // can lead to a crash if the parent is destroyed before the child - // - // also don't use the window which is currently hidden as then the - // dialog would be hidden as well - if ( (parent->GetExtraStyle() & wxWS_EX_TRANSIENT) || - !parent->IsShown() ) - { - parent = NULL; - } - } - } + // static cast is valid as we're only ever called for dialogs + wxWindow * const + parent = static_cast(this)-> + GetParentForModalDialog(GetParent()); m_hWnd = (WXHWND)::CreateDialogIndirect ( @@ -494,7 +464,8 @@ bool wxTopLevelWindowMSW::CreateFrame(const wxString& title, exflags |= WS_EX_LAYOUTRTL; #endif - return MSWCreate(wxCanvasClassName, title.wx_str(), pos, sz, flags, exflags); + return MSWCreate(MSWGetRegisteredClassName(), + title.wx_str(), pos, sz, flags, exflags); } bool wxTopLevelWindowMSW::Create(wxWindow *parent, @@ -505,19 +476,15 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, long style, const wxString& name) { - bool ret wxDUMMY_INITIALIZE(false); - wxSize sizeReal = size; if ( !sizeReal.IsFullySpecified() ) { sizeReal.SetDefaults(GetDefaultSize()); } - m_windowStyle = style; - - SetName(name); - - m_windowId = id == wxID_ANY ? NewControlId() : id; + bool ret = CreateBase(parent, id, pos, sizeReal, style, name); + if ( !ret ) + return false; wxTopLevelWindows.Append(this); @@ -545,7 +512,13 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, // reuse the code in MSWGetStyle() but correct the results slightly for // the dialog - dlgTemplate->style = MSWGetStyle(style, &dlgTemplate->dwExtendedStyle); + // + // NB: we need a temporary variable as we can't pass pointer to + // dwExtendedStyle directly, it's not aligned correctly for 64 bit + // architectures + WXDWORD dwExtendedStyle; + dlgTemplate->style = MSWGetStyle(style, &dwExtendedStyle); + dlgTemplate->dwExtendedStyle = dwExtendedStyle; // all dialogs are popups dlgTemplate->style |= WS_POPUP; @@ -603,6 +576,8 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, wxTopLevelWindowMSW::~wxTopLevelWindowMSW() { + SendDestroyEvent(); + #if defined(__SMARTPHONE__) || defined(__POCKETPC__) SHACTIVATEINFO* info = (SHACTIVATEINFO*) m_activateInfo; delete info; @@ -634,6 +609,14 @@ void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd) m_iconized = nShowCmd == SW_MINIMIZE; } +void wxTopLevelWindowMSW::ShowWithoutActivating() +{ + if ( !wxWindowBase::Show(true) ) + return; + + DoShowWindow(SW_SHOWNA); +} + bool wxTopLevelWindowMSW::Show(bool show) { // don't use wxWindow version as we want to call DoShowWindow() ourselves @@ -655,6 +638,11 @@ bool wxTopLevelWindowMSW::Show(bool show) m_maximizeOnShow = false; } + else if ( m_iconized ) + { + // iconize and show + nShowCmd = SW_MINIMIZE; + } else // just show { // we shouldn't use SW_SHOW which also activates the window for @@ -738,7 +726,17 @@ bool wxTopLevelWindowMSW::IsMaximized() const void wxTopLevelWindowMSW::Iconize(bool iconize) { - DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE); + if ( IsShown() ) + { + // change the window state immediately + DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE); + } + else // hidden + { + // iconizing the window shouldn't show it so just remember that we need + // to become iconized when shown later + m_iconized = true; + } } bool wxTopLevelWindowMSW::IsIconized() const @@ -746,6 +744,9 @@ bool wxTopLevelWindowMSW::IsIconized() const #ifdef __WXWINCE__ return false; #else + if ( !IsShown() ) + return m_iconized; + // don't use m_iconized, it may be briefly out of sync with the real state // as it's only modified when we receive a WM_SIZE and we could be called // from an event handler from one of the messages we receive before it, @@ -807,7 +808,7 @@ void wxTopLevelWindowMSW::DoGetPosition(int *x, int *y) const return; } - wxLogLastError(_T("GetWindowPlacement")); + wxLogLastError(wxT("GetWindowPlacement")); } //else: normal case @@ -832,7 +833,7 @@ void wxTopLevelWindowMSW::DoGetSize(int *width, int *height) const return; } - wxLogLastError(_T("GetWindowPlacement")); + wxLogLastError(wxT("GetWindowPlacement")); } //else: normal case @@ -966,7 +967,7 @@ wxString wxTopLevelWindowMSW::GetTitle() const return GetLabel(); } -void wxTopLevelWindowMSW::DoSelectAndSetIcon(const wxIconBundle& icons, +bool wxTopLevelWindowMSW::DoSelectAndSetIcon(const wxIconBundle& icons, int smX, int smY, int i) @@ -977,15 +978,33 @@ void wxTopLevelWindowMSW::DoSelectAndSetIcon(const wxIconBundle& icons, if ( icon.Ok() ) { ::SendMessage(GetHwnd(), WM_SETICON, i, (LPARAM)GetHiconOf(icon)); + return true; } + + return false; } void wxTopLevelWindowMSW::SetIcons(const wxIconBundle& icons) { wxTopLevelWindowBase::SetIcons(icons); - DoSelectAndSetIcon(icons, SM_CXSMICON, SM_CYSMICON, ICON_SMALL); - DoSelectAndSetIcon(icons, SM_CXICON, SM_CYICON, ICON_BIG); + if ( icons.IsEmpty() ) + { + // FIXME: SetIcons(wxNullIconBundle) should unset existing icons, + // but we currently don't do that + wxASSERT_MSG( m_icons.IsEmpty(), "unsetting icons doesn't work" ); + return; + } + + bool anySet = + DoSelectAndSetIcon(icons, SM_CXSMICON, SM_CYSMICON, ICON_SMALL); + if ( DoSelectAndSetIcon(icons, SM_CXICON, SM_CYICON, ICON_BIG) ) + anySet = true; + + if ( !anySet ) + { + wxFAIL_MSG( "icon bundle doesn't contain any suitable icon" ); + } } bool wxTopLevelWindowMSW::EnableCloseButton(bool enable) @@ -1006,7 +1025,7 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable) MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED)) == -1 ) { - wxLogLastError(_T("EnableMenuItem(SC_CLOSE)")); + wxLogLastError(wxT("EnableMenuItem(SC_CLOSE)")); return false; } @@ -1014,7 +1033,7 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable) // update appearance immediately if ( !::DrawMenuBar(GetHwnd()) ) { - wxLogLastError(_T("DrawMenuBar")); + wxLogLastError(wxT("DrawMenuBar")); } #endif #endif // !__WXMICROWIN__ @@ -1027,7 +1046,7 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable) bool wxTopLevelWindowMSW::SetShape(const wxRegion& region) { wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false, - _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); + wxT("Shaped windows must be created with the wxFRAME_SHAPED style.")); // The empty region signifies that the shape should be removed from the // window. @@ -1035,7 +1054,7 @@ bool wxTopLevelWindowMSW::SetShape(const wxRegion& region) { if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0) { - wxLogLastError(_T("SetWindowRgn")); + wxLogLastError(wxT("SetWindowRgn")); return false; } return true; @@ -1056,13 +1075,13 @@ bool wxTopLevelWindowMSW::SetShape(const wxRegion& region) DWORD dwStyle = ::GetWindowLong(GetHwnd(), GWL_STYLE); DWORD dwExStyle = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE); ::GetClientRect(GetHwnd(), &rect); - ::AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle); + ::AdjustWindowRectEx(&rect, dwStyle, ::GetMenu(GetHwnd()) != NULL, 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")); + wxLogLastError(wxT("SetWindowRgn")); return false; } return true; @@ -1080,12 +1099,12 @@ void wxTopLevelWindowMSW::RequestUserAttention(int flags) #if defined(FLASHW_STOP) && defined(VK_XBUTTON1) && wxUSE_DYNLIB_CLASS // available in the headers, check if it is supported by the system typedef BOOL (WINAPI *FlashWindowEx_t)(FLASHWINFO *pfwi); - FlashWindowEx_t s_pfnFlashWindowEx = NULL; + static FlashWindowEx_t s_pfnFlashWindowEx = NULL; if ( !s_pfnFlashWindowEx ) { - wxDynamicLibrary dllUser32(_T("user32.dll")); + wxDynamicLibrary dllUser32(wxT("user32.dll")); s_pfnFlashWindowEx = (FlashWindowEx_t) - dllUser32.GetSymbol(_T("FlashWindowEx")); + dllUser32.GetSymbol(wxT("FlashWindowEx")); // we can safely unload user32.dll here, it's going to remain loaded as // long as the program is running anyhow @@ -1125,15 +1144,23 @@ bool wxTopLevelWindowMSW::SetTransparent(wxByte alpha) { #if wxUSE_DYNLIB_CLASS typedef DWORD (WINAPI *PSETLAYEREDWINDOWATTR)(HWND, DWORD, BYTE, DWORD); - static PSETLAYEREDWINDOWATTR pSetLayeredWindowAttributes = NULL; + static PSETLAYEREDWINDOWATTR + pSetLayeredWindowAttributes = (PSETLAYEREDWINDOWATTR)-1; - if ( pSetLayeredWindowAttributes == NULL ) + if ( pSetLayeredWindowAttributes == (PSETLAYEREDWINDOWATTR)-1 ) { - wxDynamicLibrary dllUser32(_T("user32.dll")); + wxDynamicLibrary dllUser32(wxT("user32.dll")); + + // use RawGetSymbol() and not GetSymbol() to avoid error messages under + // Windows 95: there is nothing the user can do about this anyhow pSetLayeredWindowAttributes = (PSETLAYEREDWINDOWATTR) - dllUser32.GetSymbol(wxT("SetLayeredWindowAttributes")); + dllUser32.RawGetSymbol(wxT("SetLayeredWindowAttributes")); + + // it's ok to destroy dllUser32 here, we link statically to user32.dll + // anyhow so it won't be unloaded } - if ( pSetLayeredWindowAttributes == NULL ) + + if ( !pSetLayeredWindowAttributes ) return false; #endif // wxUSE_DYNLIB_CLASS @@ -1175,49 +1202,14 @@ bool wxTopLevelWindowMSW::CanSetTransparent() void wxTopLevelWindowMSW::DoFreeze() { - if ( IsShown() ) - { - for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - node; - node = node->GetNext() ) - { - wxWindow *child = node->GetData(); - if ( child->IsTopLevel() ) - continue; - - child->Freeze(); - } - } + // do nothing: freezing toplevel window causes paint and mouse events + // to go through it any TLWs under it, so the best we can do is to freeze + // all children -- and wxWindowBase::Freeze() does that } void wxTopLevelWindowMSW::DoThaw() { - if ( IsShown() ) - { - for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - node; - node = node->GetNext() ) - { - wxWindow *child = node->GetData(); - if ( child->IsTopLevel() ) - continue; - - child->Thaw(); - } - } -} - - -void wxTopLevelWindowMSW::AddChild(wxWindowBase *child) -{ - // adding a child while frozen will assert when thawn, so freeze it as if - // it had been already present when we were frozen - if ( child && !child->IsTopLevel() && IsFrozen() ) - { - child->Freeze(); - } - - wxTopLevelWindowBase::AddChild(child); + // intentionally empty -- see DoFreeze() } @@ -1233,7 +1225,7 @@ void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event) { // restore focus to the child which was last focused unless we already // have it - wxLogTrace(_T("focus"), _T("wxTLW %p activated."), m_hWnd); + wxLogTrace(wxT("focus"), wxT("wxTLW %p activated."), m_hWnd); wxWindow *winFocus = FindFocus(); if ( !winFocus || wxGetTopLevelParent(winFocus) != this ) @@ -1256,7 +1248,9 @@ void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event) if ( m_winLastFocused ) { // let it know that it doesn't have focus any more - m_winLastFocused->HandleKillFocus((WXHWND)NULL); + // But this will already be done via WM_KILLFOCUS, so we'll get two kill + // focus events if we call it explicitly. + // m_winLastFocused->HandleKillFocus((WXHWND)NULL); // and don't remember it if it's a child from some other frame if ( wxGetTopLevelParent(m_winLastFocused) != this ) @@ -1265,8 +1259,8 @@ void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event) } } - wxLogTrace(_T("focus"), - _T("wxTLW %p deactivated, last focused: %p."), + wxLogTrace(wxT("focus"), + wxT("wxTLW %p deactivated, last focused: %p."), m_hWnd, m_winLastFocused ? GetHwndOf(m_winLastFocused) : NULL); @@ -1340,7 +1334,7 @@ void wxTLWHiddenParentModule::OnExit() { if ( !::DestroyWindow(ms_hwnd) ) { - wxLogLastError(_T("DestroyWindow(hidden TLW parent)")); + wxLogLastError(wxT("DestroyWindow(hidden TLW parent)")); } ms_hwnd = NULL; @@ -1350,7 +1344,7 @@ void wxTLWHiddenParentModule::OnExit() { if ( !::UnregisterClass(ms_className, wxGetInstance()) ) { - wxLogLastError(_T("UnregisterClass(\"wxTLWHiddenParent\")")); + wxLogLastError(wxT("UnregisterClass(\"wxTLWHiddenParent\")")); } ms_className = NULL; @@ -1364,7 +1358,7 @@ HWND wxTLWHiddenParentModule::GetHWND() { if ( !ms_className ) { - static const wxChar *HIDDEN_PARENT_CLASS = _T("wxTLWHiddenParent"); + static const wxChar *HIDDEN_PARENT_CLASS = wxT("wxTLWHiddenParent"); WNDCLASS wndclass; wxZeroMemory(wndclass); @@ -1375,7 +1369,7 @@ HWND wxTLWHiddenParentModule::GetHWND() if ( !::RegisterClass(&wndclass) ) { - wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")")); + wxLogLastError(wxT("RegisterClass(\"wxTLWHiddenParent\")")); } else { @@ -1387,7 +1381,7 @@ HWND wxTLWHiddenParentModule::GetHWND() (HMENU)NULL, wxGetInstance(), NULL); if ( !ms_hwnd ) { - wxLogLastError(_T("CreateWindow(hidden TLW parent)")); + wxLogLastError(wxT("CreateWindow(hidden TLW parent)")); } }