X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4c53c74335270f8bd696293fe60fc7f0b238b105..19e30148e18cc99296b26503c155e5cef59045f4:/src/msw/toplevel.cpp diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 6df5465062..8283ec20d6 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -39,13 +39,21 @@ #include "wx/msw/private.h" +#ifndef ICON_BIG + #define ICON_BIG 1 +#endif + +#ifndef ICON_SMALL + #define ICON_SMALL 0 +#endif + // ---------------------------------------------------------------------------- // stubs for missing functions under MicroWindows // ---------------------------------------------------------------------------- #ifdef __WXMICROWIN__ -static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return FALSE; } +// static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return FALSE; } static inline bool IsZoomed(HWND WXUNUSED(hwnd)) { return FALSE; } #endif // __WXMICROWIN__ @@ -64,21 +72,25 @@ extern const wxChar *wxCanvasClassName; // wxTopLevelWindowMSW implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// wxDialog helpers +// ---------------------------------------------------------------------------- + // Dialog window proc LONG APIENTRY _EXPORT -wxDlgProc(HWND WXUNUSED(hWnd), UINT message, WPARAM WXUNUSED(wParam), LPARAM WXUNUSED(lParam)) +wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { - if ( message == WM_INITDIALOG ) + switch ( message ) { - // for this message, returning TRUE tells system to set focus to the - // first control in the dialog box - return TRUE; - } - else - { - // for all the other ones, FALSE means that we didn't process the - // message - return FALSE; + case WM_INITDIALOG: + // for this message, returning TRUE tells system to set focus to the + // first control in the dialog box + return TRUE; + + default: + // for all the other ones, FALSE means that we didn't process the + // message + return FALSE; } } @@ -101,41 +113,49 @@ void wxTopLevelWindowMSW::Init() m_fsIsShowing = FALSE; } -long wxTopLevelWindowMSW::MSWGetCreateWindowFlags(long *exflags) const +WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const { - long style = GetWindowStyle(); - long msflags = 0; + // let the base class deal with the common styles but fix the ones which + // don't make sense for us (we also deal with the borders ourselves) + WXDWORD msflags = wxWindow::MSWGetStyle + ( + (style & ~wxBORDER_MASK) | wxBORDER_NONE, exflags + ) & ~WS_CHILD; // first select the kind of window being created + // + // note that if we don't set WS_POPUP, Windows assumes WS_OVERLAPPED and + // creates a window with both caption and border, hence we also test it + // below in some other cases + if ( style & wxFRAME_TOOL_WINDOW ) + msflags |= WS_POPUP; + else + msflags |= WS_OVERLAPPED; + + // border and caption styles + if ( style & wxRESIZE_BORDER ) + msflags |= WS_THICKFRAME; + else if ( !(style & wxBORDER_NONE) ) + msflags |= WS_BORDER; + else + msflags |= WS_POPUP; + if ( style & wxCAPTION ) - { - if ( style & wxFRAME_TOOL_WINDOW ) - msflags |= WS_POPUPWINDOW; - else - msflags |= WS_OVERLAPPED; - } + msflags |= WS_CAPTION; else - { msflags |= WS_POPUP; - } // next translate the individual flags if ( style & wxMINIMIZE_BOX ) msflags |= WS_MINIMIZEBOX; if ( style & wxMAXIMIZE_BOX ) msflags |= WS_MAXIMIZEBOX; - if ( style & wxTHICK_FRAME ) - msflags |= WS_THICKFRAME; if ( style & wxSYSTEM_MENU ) msflags |= WS_SYSMENU; if ( style & wxMINIMIZE ) msflags |= WS_MINIMIZE; if ( style & wxMAXIMIZE ) msflags |= WS_MAXIMIZE; - if ( style & wxCAPTION ) - msflags |= WS_CAPTION; - if ( style & wxCLIP_CHILDREN ) - msflags |= WS_CLIPCHILDREN; // Keep this here because it saves recoding this function in wxTinyFrame #if wxUSE_ITSY_BITSY && !defined(__WIN32__) @@ -150,8 +170,6 @@ long wxTopLevelWindowMSW::MSWGetCreateWindowFlags(long *exflags) const if ( exflags ) { - *exflags = MakeExtendedStyle(style); - #if !defined(__WIN16__) && !defined(__SC__) if ( !(GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) ) { @@ -170,15 +188,15 @@ long wxTopLevelWindowMSW::MSWGetCreateWindowFlags(long *exflags) const *exflags |= WS_EX_TOPMOST; #ifdef __WIN32__ - if ( m_exStyle & wxFRAME_EX_CONTEXTHELP ) - *exflags |= WS_EX_CONTEXTHELP; + if ( GetExtraStyle() & wxFRAME_EX_CONTEXTHELP ) + *exflags |= WS_EX_CONTEXTHELP; #endif // __WIN32__ } return msflags; } -bool wxTopLevelWindowMSW::CreateDialog(const wxChar *dlgTemplate, +bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate, const wxString& title, const wxPoint& pos, const wxSize& size) @@ -196,29 +214,39 @@ bool wxTopLevelWindowMSW::CreateDialog(const wxChar *dlgTemplate, { parent = wxTheApp->GetTopWindow(); - // but don't use the window which is currently hidden as then the - // dialog would be hidden as well - if ( parent && !parent->IsShown() ) + if ( parent ) { - parent = NULL; + // 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; + } } } - m_hWnd = (WXHWND)::CreateDialog(wxGetInstance(), - dlgTemplate, - parent ? GetHwndOf(parent) : NULL, - (DLGPROC)wxDlgProc); + m_hWnd = (WXHWND)::CreateDialogIndirect + ( + wxGetInstance(), + (DLGTEMPLATE*)dlgTemplate, + parent ? GetHwndOf(parent) : NULL, + (DLGPROC)wxDlgProc + ); if ( !m_hWnd ) { - wxFAIL_MSG(_("Did you forget to include wx/msw/wx.rc in your resources?")); + wxFAIL_MSG(_("Failed to create dialog. Incorrect DLGTEMPLATE?")); - wxLogSysError(_("Can't create dialog using template '%s'"), dlgTemplate); + wxLogSysError(_("Can't create dialog using memory template")); return FALSE; } - long exflags; + WXDWORD exflags; (void)MSWGetCreateWindowFlags(&exflags); if ( exflags ) @@ -301,8 +329,8 @@ bool wxTopLevelWindowMSW::CreateFrame(const wxString& title, const wxPoint& pos, const wxSize& size) { - long exflags; - long flags = MSWGetCreateWindowFlags(&exflags); + WXDWORD exflags; + WXDWORD flags = MSWGetCreateWindowFlags(&exflags); return MSWCreate(wxCanvasClassName, title, pos, size, flags, exflags); } @@ -331,28 +359,38 @@ bool wxTopLevelWindowMSW::Create(wxWindow *parent, if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG ) { - // TODO: it would be better to construct the dialog template in memory - // during run-time than to rely on the limited number of - // templates in wx.rc because: - // a) you wouldn't have to include wx.rc in all wxWin programs - // (and the number of complaints about it would dtop) - // b) we'd be able to provide more templates simply, i.e. - // we could generate the templates for all style - // combinations - // we have different dialog templates to allows creation of dialogs // with & without captions under MSWindows, resizeable or not (but a // resizeable dialog always has caption - otherwise it would look too // strange) - const wxChar *dlgTemplate; - if ( style & wxRESIZE_BORDER ) - dlgTemplate = wxT("wxResizeableDialog"); - else if ( style & wxCAPTION ) - dlgTemplate = wxT("wxCaptionDialog"); - else - dlgTemplate = wxT("wxNoCaptionDialog"); - - return CreateDialog(dlgTemplate, title, pos, size); + + // we need 3 additional WORDs for dialog menu, class and title (as we + // don't use DS_SETFONT we don't need the fourth WORD for the font) + static const int dlgsize = sizeof(DLGTEMPLATE) + (sizeof(WORD) * 3); + DLGTEMPLATE *dlgTemplate = (DLGTEMPLATE *)malloc(dlgsize); + memset(dlgTemplate, 0, dlgsize); + + // these values are arbitrary, they won't be used normally anyhow + dlgTemplate->x = 34; + dlgTemplate->y = 22; + dlgTemplate->cx = 144; + dlgTemplate->cy = 75; + + // reuse the code in MSWGetStyle() but correct the results slightly for + // the dialog + dlgTemplate->style = MSWGetStyle(style, NULL); + + // all dialogs are popups + dlgTemplate->style |= WS_POPUP; + + // force 3D-look if necessary, it looks impossibly ugly otherwise + if ( style & (wxRESIZE_BORDER | wxCAPTION) ) + dlgTemplate->style |= DS_MODALFRAME; + + bool ret = CreateDialog(dlgTemplate, title, pos, size); + free(dlgTemplate); + + return ret; } else // !dialog { @@ -379,42 +417,6 @@ wxTopLevelWindowMSW::~wxTopLevelWindowMSW() } } -// ---------------------------------------------------------------------------- -// wxTopLevelWindowMSW geometry -// ---------------------------------------------------------------------------- - -void wxTopLevelWindowMSW::DoSetClientSize(int width, int height) -{ - HWND hWnd = GetHwnd(); - - RECT rectClient; - ::GetClientRect(hWnd, &rectClient); - - RECT rectTotal; - ::GetWindowRect(hWnd, &rectTotal); - - // Find the difference between the entire window (title bar and all) - // and the client area; add this to the new client size to move the - // window - width += rectTotal.right - rectTotal.left - rectClient.right; - height += rectTotal.bottom - rectTotal.top - rectClient.bottom; - - // note that calling GetClientAreaOrigin() takes the toolbar into account - wxPoint pt = GetClientAreaOrigin(); - width += pt.x; - height += pt.y; - - if ( !::MoveWindow(hWnd, rectTotal.left, rectTotal.top, - width, height, TRUE /* redraw */) ) - { - wxLogLastError(_T("MoveWindow")); - } - - wxSizeEvent event(wxSize(width, height), m_windowId); - event.SetEventObject(this); - (void)GetEventHandler()->ProcessEvent(event); -} - // ---------------------------------------------------------------------------- // wxTopLevelWindowMSW showing // ---------------------------------------------------------------------------- @@ -594,14 +596,26 @@ bool wxTopLevelWindowMSW::ShowFullScreen(bool show, long style) void wxTopLevelWindowMSW::SetIcon(const wxIcon& icon) { - // this sets m_icon - wxTopLevelWindowBase::SetIcon(icon); + SetIcons( wxIconBundle( icon ) ); +} + +void wxTopLevelWindowMSW::SetIcons(const wxIconBundle& icons) +{ + wxTopLevelWindowBase::SetIcons(icons); #if defined(__WIN95__) && !defined(__WXMICROWIN__) - if ( m_icon.Ok() ) + 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(GetHwnd(), WM_SETICON, - (WPARAM)TRUE, (LPARAM)GetHiconOf(m_icon)); + ::SendMessage( GetHwndOf( this ), WM_SETICON, ICON_BIG, + (LPARAM)GetHiconOf(big) ); } #endif // __WIN95__ }