home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / toplevel.cpp < prev    next >
C/C++ Source or Header  |  2002-12-22  |  36KB  |  1,119 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        msw/toplevel.cpp
  3. // Purpose:     implements wxTopLevelWindow for MSW
  4. // Author:      Vadim Zeitlin
  5. // Modified by:
  6. // Created:     30.12.01
  7. // RCS-ID:      $Id: toplevel.cpp,v 1.22.2.4 2002/12/19 23:43:32 VS Exp $
  8. // Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
  9. // License:     wxWindows license
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "toplevel.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.     #include "wx/app.h"
  33.     #include "wx/toplevel.h"
  34.     #include "wx/string.h"
  35.     #include "wx/log.h"
  36.     #include "wx/intl.h"
  37.     #include "wx/frame.h"
  38.     #include "wx/control.h"
  39.     #include "wx/containr.h"        // wxSetFocusToChild()
  40.     #include "wx/module.h"        // wxSetFocusToChild()
  41. #endif //WX_PRECOMP
  42.  
  43. #include "wx/os2/private.h"
  44.  
  45. // ----------------------------------------------------------------------------
  46. // stubs for missing functions under MicroWindows
  47. // ----------------------------------------------------------------------------
  48.  
  49.  
  50. // ----------------------------------------------------------------------------
  51. // globals
  52. // ----------------------------------------------------------------------------
  53.  
  54. // list of all frames and modeless dialogs
  55. wxWindowList wxModelessWindows;
  56.  
  57. // the name of the default wxWindows class
  58. extern void          wxAssociateWinWithHandle( HWND         hWnd
  59.                                               ,wxWindowOS2* pWin
  60.                                              );
  61. bool                 wxTopLevelWindowOS2::m_sbInitialized = FALSE;
  62. wxWindow*            wxTopLevelWindowOS2::m_spHiddenParent = NULL;
  63.  
  64. // ============================================================================
  65. // wxTopLevelWindowOS2 implementation
  66. // ============================================================================
  67.  
  68. BEGIN_EVENT_TABLE(wxTopLevelWindowOS2, wxTopLevelWindowBase)
  69.     EVT_ACTIVATE(wxTopLevelWindowOS2::OnActivate)
  70. END_EVENT_TABLE()
  71.  
  72. // ============================================================================
  73. // wxTopLevelWindowMSW implementation
  74. // ============================================================================
  75.  
  76. // Dialog window proc
  77. MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd)
  78.                            ,UINT uMessage
  79.                            ,MPARAM WXUNUSED(wParam)
  80.                            ,MPARAM WXUNUSED(lParam)
  81.                           )
  82. {
  83.     switch(uMessage)
  84.     {
  85.         case WM_INITDLG:
  86.             //
  87.             // For this message, returning TRUE tells system to set focus to
  88.             // the first control in the dialog box, but we set the focus
  89.             // ourselves, however in OS/2 we must return true to enable the dialog
  90.             //
  91.             return (MRESULT)TRUE;
  92.         default:
  93.             //
  94.             // For all the other ones, FALSE means that we didn't process the
  95.             // message
  96.             //
  97.             return (MRESULT)FALSE;
  98.     }
  99. } // end of wxDlgProc
  100.  
  101. // ----------------------------------------------------------------------------
  102. // wxTLWHiddenParentModule: used to manage the hidden parent window (we need a
  103. // module to ensure that the window is always deleted)
  104. // ----------------------------------------------------------------------------
  105.  
  106. class wxTLWHiddenParentModule : public wxModule
  107. {
  108. public:
  109.     //
  110.     // Module init/finalize
  111.     //
  112.     virtual bool OnInit(void);
  113.     virtual void OnExit(void);
  114.  
  115.     //
  116.     // Get the hidden window (creates on demand)
  117.     //
  118.     static HWND GetHWND(void);
  119.  
  120. private:
  121.     //
  122.     // The HWND of the hidden parent
  123.     //
  124.     static HWND                     m_shWnd;
  125.  
  126.     //
  127.     // The class used to create it
  128.     //
  129.     static const wxChar*            m_szClassName;
  130.     DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule)
  131. }; // end of CLASS wxTLWHiddenParentModule
  132.  
  133. IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule, wxModule)
  134.  
  135. // ----------------------------------------------------------------------------
  136. // wxTopLevelWindowOS2 creation
  137. // ----------------------------------------------------------------------------
  138.  
  139. void wxTopLevelWindowOS2::Init()
  140. {
  141.     m_bIconized = m_bMaximizeOnShow = FALSE;
  142.  
  143.     //
  144.     // Unlike (almost?) all other windows, frames are created hidden
  145.     //
  146.     m_isShown = FALSE;
  147.  
  148.     //
  149.     // Data to save/restore when calling ShowFullScreen
  150.     m_lFsStyle          = 0;
  151.     m_lFsOldWindowStyle = 0;
  152.     m_bFsIsMaximized    = FALSE;
  153.     m_bFsIsShowing      = FALSE;
  154.  
  155.     m_hFrame    = NULLHANDLE;
  156.     memset(&m_vSwp, 0, sizeof(SWP));
  157.     memset(&m_vSwpClient, 0, sizeof(SWP));
  158.     m_pWinLastFocused = (wxWindow *)NULL;
  159. } // end of wxTopLevelWindowIOS2::Init
  160.  
  161. void wxTopLevelWindowOS2::OnActivate(
  162.   wxActivateEvent&                  rEvent
  163. )
  164. {
  165.     if (rEvent.GetActive())
  166.     {
  167.         //
  168.         // Restore focus to the child which was last focused
  169.         //
  170.         wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), m_hWnd);
  171.  
  172.         wxWindow*                   pParent = m_pWinLastFocused ? m_pWinLastFocused->GetParent()
  173.                                                                 : NULL;
  174.         if (!pParent)
  175.         {
  176.             pParent = this;
  177.         }
  178.  
  179.         wxSetFocusToChild( pParent
  180.                           ,&m_pWinLastFocused
  181.                          );
  182.     }
  183.     else // deactivating
  184.     {
  185.         //
  186.         // Remember the last focused child if it is our child
  187.         //
  188.         m_pWinLastFocused = FindFocus();
  189.  
  190.         //
  191.         // So we NULL it out if it's a child from some other frame
  192.         //
  193.         wxWindow*                   pWin = m_pWinLastFocused;
  194.  
  195.         while (pWin)
  196.         {
  197.             if (pWin->IsTopLevel())
  198.             {
  199.                 if (pWin != this)
  200.                 {
  201.                     m_pWinLastFocused = NULL;
  202.                 }
  203.                 break;
  204.             }
  205.             pWin = pWin->GetParent();
  206.         }
  207.  
  208.         wxLogTrace(_T("focus"),
  209.                    _T("wxTLW %08x deactivated, last focused: %08x."),
  210.                    m_hWnd,
  211.                    m_pWinLastFocused ? GetHwndOf(m_pWinLastFocused)
  212.                                      : NULL);
  213.         rEvent.Skip();
  214.     }
  215. } // end of wxTopLevelWindowOS2::OnActivate
  216.  
  217. WXDWORD wxTopLevelWindowOS2::OS2GetStyle(
  218.   long                              lStyle
  219. , WXDWORD*                          pdwExflags
  220. ) const
  221. {
  222.     long                            lMsflags = wxWindow::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
  223.                                                                      ,pdwExflags
  224.                                                                     );
  225.  
  226.     if (lStyle == wxDEFAULT_FRAME_STYLE)
  227.         lMsflags |= FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU |
  228.                     FCF_MINMAX | FCF_TASKLIST;
  229.     else
  230.     {
  231.         if ((lStyle & wxCAPTION) == wxCAPTION)
  232.             lMsflags |= FCF_TASKLIST;
  233.         else
  234.             lMsflags |= FCF_NOMOVEWITHOWNER;
  235.  
  236.         if ((lStyle & wxVSCROLL) == wxVSCROLL)
  237.             lMsflags |= FCF_VERTSCROLL;
  238.         if ((lStyle & wxHSCROLL) == wxHSCROLL)
  239.             lMsflags |= FCF_HORZSCROLL;
  240.         if (lStyle & wxMINIMIZE_BOX)
  241.             lMsflags |= FCF_MINBUTTON;
  242.         if (lStyle & wxMAXIMIZE_BOX)
  243.             lMsflags |= FCF_MAXBUTTON;
  244.         if (lStyle & wxTHICK_FRAME)
  245.             lMsflags |= FCF_DLGBORDER;
  246.         if (lStyle & wxSYSTEM_MENU)
  247.             lMsflags |= FCF_SYSMENU;
  248.         if (lStyle & wxCAPTION)
  249.             lMsflags |= FCF_TASKLIST;
  250.         if (lStyle & wxCLIP_CHILDREN)
  251.         {
  252.             // Invalid for frame windows under PM
  253.         }
  254.  
  255.         if (lStyle & wxTINY_CAPTION_VERT)
  256.             lMsflags |= FCF_TASKLIST;
  257.         if (lStyle & wxTINY_CAPTION_HORIZ)
  258.             lMsflags |= FCF_TASKLIST;
  259.  
  260.         if ((lStyle & wxTHICK_FRAME) == 0)
  261.             lMsflags |= FCF_BORDER;
  262.         if (lStyle & wxFRAME_TOOL_WINDOW)
  263.             *pdwExflags = kFrameToolWindow;
  264.  
  265.         if (lStyle & wxSTAY_ON_TOP)
  266.             lMsflags |= FCF_SYSMODAL;
  267.     }
  268.     return lMsflags;
  269. } // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags
  270.  
  271. WXHWND wxTopLevelWindowOS2::OS2GetParent() const
  272. {
  273.     HWND                            hWndParent = NULL;
  274.  
  275.     //
  276.     // For the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL
  277.     // parent HWND or it would be always on top of its parent which is not what
  278.     // we usually want (in fact, we only want it for frames with the
  279.     // wxFRAME_FLOAT_ON_PARENT flag)
  280.     //
  281.     if (HasFlag(wxFRAME_FLOAT_ON_PARENT) )
  282.     {
  283.         const wxWindow*             pParent = GetParent();
  284.  
  285.         if (!pParent)
  286.         {
  287.             //
  288.             // This flag doesn't make sense then and will be ignored
  289.             //
  290.             wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") );
  291.         }
  292.         else
  293.         {
  294.             hWndParent = GetHwndOf(pParent);
  295.         }
  296.     }
  297.     //else: don't float on parent, must not be owned
  298.  
  299.     //
  300.     // Now deal with the 2nd taskbar-related problem (see comments above in
  301.     // OS2GetStyle())
  302.     //
  303.     if (HasFlag(wxFRAME_NO_TASKBAR) && !hWndParent)
  304.     {
  305.         //
  306.         // Use hidden parent
  307.         //
  308.         hWndParent = wxTLWHiddenParentModule::GetHWND();
  309.     }
  310.     return (WXHWND)hWndParent;
  311. } // end of wxTopLevelWindowOS2::OS2GetParent
  312.  
  313. bool wxTopLevelWindowOS2::CreateDialog(
  314.   ULONG                             ulDlgTemplate
  315. , const wxString&                   rsTitle
  316. , const wxPoint&                    rPos
  317. , const wxSize&                     rSize
  318. )
  319. {
  320.     wxWindow*                       pParent = GetParent();
  321.  
  322.     //
  323.     // For the dialogs without wxDIALOG_NO_PARENT style, use the top level
  324.     // app window as parent - this avoids creating modal dialogs without
  325.     // parent
  326.     //
  327.     if (!pParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT))
  328.     {
  329.         pParent = wxTheApp->GetTopWindow();
  330.  
  331.         if (pParent)
  332.         {
  333.             //
  334.             // Don't use transient windows as parents, this is dangerous as it
  335.             // can lead to a crash if the parent is destroyed before the child
  336.             //
  337.             // also don't use the window which is currently hidden as then the
  338.             // dialog would be hidden as well
  339.             if ((pParent->GetExtraStyle() & wxWS_EX_TRANSIENT) ||
  340.                  !pParent->IsShown())
  341.             {
  342.                 pParent = NULL;
  343.             }
  344.         }
  345.     }
  346.  
  347.     HWND                            hWndDlg;
  348.     HWND                            hWndOwner;
  349.  
  350.     if (pParent)
  351.         hWndOwner = GetHwndOf(pParent);
  352.     else
  353.         hWndOwner = HWND_DESKTOP;
  354.  
  355.     hWndDlg = ::WinLoadDlg( HWND_DESKTOP
  356.                            ,hWndOwner
  357.                            ,(PFNWP)wxDlgProc
  358.                            ,NULL
  359.                            ,(ULONG)ulDlgTemplate
  360.                            ,(PVOID)this
  361.                           );
  362.  
  363.     m_hWnd = (WXHWND) hWndDlg;
  364.  
  365.     if ( !m_hWnd )
  366.     {
  367.         wxFAIL_MSG(wxT("Did you forget to include wx/os2/wx.rc in your resources?"));
  368.  
  369.         wxLogSysError(wxT("Can't create dialog using template '%ul'"), ulDlgTemplate);
  370.  
  371.         return FALSE;
  372.     }
  373.  
  374.     //
  375.     // Move the dialog to its initial position without forcing repainting
  376.     //
  377.     int                             nX;
  378.     int                             nY;
  379.     int                             nWidth;
  380.     int                             nHeight;
  381.  
  382.     if (!OS2GetCreateWindowCoords( rPos
  383.                                   ,rSize
  384.                                   ,nX
  385.                                   ,nY
  386.                                   ,nWidth
  387.                                   ,nHeight
  388.                                  ))
  389.     {
  390.         nX = nWidth = (int)CW_USEDEFAULT;
  391.     }
  392.  
  393.     //
  394.     // We can't use CW_USEDEFAULT here as we're not calling CreateWindow()
  395.     // and passing CW_USEDEFAULT to MoveWindow() results in resizing the
  396.     // window to (0, 0) size which breaks quite a lot of things, e.g. the
  397.     // sizer calculation in wxSizer::Fit()
  398.     //
  399.     if (nWidth == (int)CW_USEDEFAULT)
  400.     {
  401.         //
  402.         // The exact number doesn't matter, the dialog will be resized
  403.         // again soon anyhow but it should be big enough to allow
  404.         // calculation relying on "totalSize - clientSize > 0" work, i.e.
  405.         // at least greater than the title bar height
  406.         //
  407.         nWidth = nHeight = 100;
  408.     }
  409.     if (nX == (int)CW_USEDEFAULT)
  410.     {
  411.         //
  412.         // Centre it on the screen - what else can we do?
  413.         //
  414.         wxSize                      vSizeDpy = wxGetDisplaySize();
  415.  
  416.         nX = (vSizeDpy.x - nWidth) / 2;
  417.         nY = (vSizeDpy.y - nHeight) / 2;
  418.     }
  419.     m_backgroundColour.Set(wxString("LIGHT GREY"));
  420.  
  421.     LONG                            lColor = (LONG)m_backgroundColour.GetPixel();
  422.  
  423.     if (!::WinSetPresParam( m_hWnd
  424.                            ,PP_BACKGROUNDCOLOR
  425.                            ,sizeof(LONG)
  426.                            ,(PVOID)&lColor
  427.                           ))
  428.     {
  429.         return FALSE;
  430.     }
  431.  
  432.     ::WinSetWindowPos( GetHwnd()
  433.                       ,HWND_TOP
  434.                       ,nX
  435.                       ,nY
  436.                       ,nWidth
  437.                       ,nHeight
  438.                       ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE
  439.                      );
  440.     ::WinQueryWindowPos(GetHwnd(), GetSwp());
  441.     m_hFrame = m_hWnd;
  442.     SubclassWin(m_hWnd);
  443.     return TRUE;
  444. } // end of wxTopLevelWindowOS2::CreateDialog
  445.  
  446. bool wxTopLevelWindowOS2::CreateFrame(
  447.   const wxString&                   rsTitle
  448. , const wxPoint&                    rPos
  449. , const wxSize&                     rSize
  450. )
  451. {
  452.     WXDWORD                         lExflags;
  453.     WXDWORD                         lFlags = OS2GetCreateWindowFlags(&lExflags);
  454.     long                            lStyle = GetWindowStyleFlag();
  455.     int                             nX = rPos.x;
  456.     int                             nY = rPos.y;
  457.     int                             nWidth = rSize.x;
  458.     int                             nHeight = rSize.y;
  459.     ULONG                           ulStyleFlags = 0L;
  460.     ERRORID                         vError;
  461.     wxString                        sError;
  462.     wxWindow*                       pParent = GetParent();
  463.     HWND                            hParent;
  464.     HWND                            hFrame;
  465.     HWND                            hClient;
  466.  
  467.     if (pParent)
  468.         hParent = GetHwndOf(pParent);
  469.     else
  470.         hParent = HWND_DESKTOP;
  471.  
  472.     if ((lStyle & wxMINIMIZE) || (lStyle & wxICONIZE))
  473.         ulStyleFlags |= WS_MINIMIZED;
  474.     if (lStyle & wxMAXIMIZE)
  475.         ulStyleFlags |= WS_MAXIMIZED;
  476.  
  477.     //
  478.     // Clear the visible flag, we always call show
  479.     //
  480.     ulStyleFlags &= (unsigned long)~WS_VISIBLE;
  481.     m_bIconized = FALSE;
  482.  
  483.     //
  484.     // Create the frame window:  We break ranks with other ports now
  485.     // and instead of calling down into the base wxWindow class' OS2Create
  486.     // we do all our own stuff here.  We will set the needed pieces
  487.     // of wxWindow manually, here.
  488.     //
  489.  
  490.      hFrame = ::WinCreateStdWindow( hParent
  491.                                    ,ulStyleFlags          // frame-window style
  492.                                    ,(PULONG)&lFlags       // window style
  493.                                    ,(PSZ)wxFrameClassName // class name
  494.                                    ,(PSZ)rsTitle.c_str()  // window title
  495.                                    ,0L                    // default client style
  496.                                    ,NULLHANDLE            // resource in executable file
  497.                                    ,0                     // resource id
  498.                                    ,&hClient              // receives client window handle
  499.                                   );
  500.     if (!hFrame)
  501.     {
  502.         vError = ::WinGetLastError(vHabmain);
  503.         sError = wxPMErrorToStr(vError);
  504.         wxLogError("Error creating frame. Error: %s\n", sError);
  505.         return FALSE;
  506.     }
  507.  
  508.     //
  509.     // wxWindow class' m_hWnd set here and needed associations
  510.     //
  511.     m_hFrame = hFrame;
  512.     m_hWnd   = hClient;
  513.     wxAssociateWinWithHandle(m_hWnd, this);
  514.     wxAssociateWinWithHandle(m_hFrame, this);
  515.  
  516.     m_backgroundColour.Set(wxString("MEDIUM GREY"));
  517.  
  518.     LONG                            lColor = (LONG)m_backgroundColour.GetPixel();
  519.  
  520.     if (!::WinSetPresParam( m_hWnd
  521.                            ,PP_BACKGROUNDCOLOR
  522.                            ,sizeof(LONG)
  523.                            ,(PVOID)&lColor
  524.                           ))
  525.     {
  526.         vError = ::WinGetLastError(vHabmain);
  527.         sError = wxPMErrorToStr(vError);
  528.         wxLogError("Error creating frame. Error: %s\n", sError);
  529.         return FALSE;
  530.     }
  531.  
  532.     //
  533.     // Now need to subclass window.  Instead of calling the SubClassWin in wxWindow
  534.     // we manually subclass here because we don't want to use the main wxWndProc
  535.     // by default
  536.     //
  537.     m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(m_hFrame, (PFNWP)wxFrameMainWndProc);
  538.  
  539.     //
  540.     // Now size everything.  If adding a menu the client will need to be resized.
  541.     //
  542.  
  543.     if (pParent)
  544.     {
  545.         nY = pParent->GetSize().y - (nY + nHeight);
  546.     }
  547.     else
  548.     {
  549.         RECTL                   vRect;
  550.  
  551.         ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
  552.         nY = vRect.yTop - (nY + nHeight);
  553.     }
  554.     if (!::WinSetWindowPos( m_hFrame
  555.                            ,HWND_TOP
  556.                            ,nX
  557.                            ,nY
  558.                            ,nWidth
  559.                            ,nHeight
  560.                            ,SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_ZORDER
  561.                           ))
  562.     {
  563.         vError = ::WinGetLastError(vHabmain);
  564.         sError = wxPMErrorToStr(vError);
  565.         wxLogError("Error sizing frame. Error: %s\n", sError);
  566.         return FALSE;
  567.     }
  568.     lStyle =  ::WinQueryWindowULong( m_hWnd
  569.                                     ,QWL_STYLE
  570.                                    );
  571.     lStyle |= WS_CLIPCHILDREN;
  572.     ::WinSetWindowULong( m_hWnd
  573.                         ,QWL_STYLE
  574.                         ,lStyle
  575.                        );
  576.     return TRUE;
  577. } // end of wxTopLevelWindowOS2::CreateFrame
  578.  
  579. bool wxTopLevelWindowOS2::Create(
  580.   wxWindow*                         pParent
  581. , wxWindowID                        vId
  582. , const wxString&                   rsTitle
  583. , const wxPoint&                    rPos
  584. , const wxSize&                     rSize
  585. , long                              lStyle
  586. , const wxString&                   rsName
  587. )
  588. {
  589.     //
  590.     // Init our fields
  591.     //
  592.     Init();
  593.     m_windowStyle = lStyle;
  594.     SetName(rsName);
  595.     m_windowId = vId == -1 ? NewControlId() : vId;
  596.     wxTopLevelWindows.Append(this);
  597.     if (pParent)
  598.         pParent->AddChild(this);
  599.  
  600.     if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG)
  601.     {
  602.         //
  603.         // We have different dialog templates to allows creation of dialogs
  604.         // with & without captions under OS2indows, resizeable or not (but a
  605.         // resizeable dialog always has caption - otherwise it would look too
  606.         // strange)
  607.         //
  608.         ULONG                       ulDlgTemplate;
  609.  
  610.         if (lStyle & wxRESIZE_BORDER)
  611.             ulDlgTemplate = (ULONG)kResizeableDialog;
  612.         else if (lStyle & wxCAPTION)
  613.             ulDlgTemplate = (ULONG)kCaptionDialog;
  614.         else
  615.             ulDlgTemplate = (ULONG)kNoCaptionDialog;
  616.         return CreateDialog( ulDlgTemplate
  617.                             ,rsTitle
  618.                             ,rPos
  619.                             ,rSize
  620.                            );
  621.     }
  622.     else // !dialog
  623.     {
  624.         return CreateFrame( rsTitle
  625.                            ,rPos
  626.                            ,rSize
  627.                           );
  628.     }
  629. } // end of wxTopLevelWindowOS2::Create
  630.  
  631. wxTopLevelWindowOS2::~wxTopLevelWindowOS2()
  632. {
  633.     if (wxModelessWindows.Find(this))
  634.         wxModelessWindows.DeleteObject(this);
  635.  
  636.     //
  637.     // After destroying an owned window, Windows activates the next top level
  638.     // window in Z order but it may be different from our owner (to reproduce
  639.     // this simply Alt-TAB to another application and back before closing the
  640.     // owned frame) whereas we always want to yield activation to our parent
  641.     //
  642.     if (HasFlag(wxFRAME_FLOAT_ON_PARENT))
  643.     {
  644.         wxWindow*                   pParent = GetParent();
  645.  
  646.         if (pParent)
  647.         {
  648.             ::WinSetWindowPos( GetHwndOf(pParent)
  649.                               ,HWND_TOP
  650.                               ,0, 0, 0, 0
  651.                               ,SWP_ZORDER
  652.                              );
  653.         }
  654.     }
  655. } // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2
  656.  
  657. // ----------------------------------------------------------------------------
  658. // wxTopLevelWindowOS2 client size
  659. // ----------------------------------------------------------------------------
  660.  
  661. void wxTopLevelWindowOS2::DoSetClientSize(
  662.   int                               nWidth
  663. , int                               nHeight
  664. )
  665. {
  666.     //
  667.     // Call GetClientAreaOrigin() to take the toolbar into account
  668.     //
  669.     wxPoint                         vPt = GetClientAreaOrigin();
  670.  
  671.     nWidth  += vPt.x;
  672.     nHeight += vPt.y;
  673.  
  674.     wxWindow::DoSetClientSize( nWidth
  675.                               ,nHeight
  676.                              );
  677. } // end of wxTopLevelWindowOS2::DoSetClientSize
  678.  
  679. void wxTopLevelWindowOS2::DoGetClientSize(
  680.   int*                              pnX
  681. , int*                              pnY
  682. ) const
  683. {
  684.     wxWindow::DoGetClientSize( pnX
  685.                               ,pnY
  686.                              );
  687.  
  688.     wxPoint                         vPt = GetClientAreaOrigin();
  689.  
  690.     if (pnX)
  691.         *pnX -= vPt.x;
  692.  
  693.     if (pnY)
  694.         *pnY += vPt.y;
  695. } // end of wxTopLevelWindowOS2::DoGetClientSize
  696.  
  697. // ----------------------------------------------------------------------------
  698. // wxTopLevelWindowOS2 showing
  699. // ----------------------------------------------------------------------------
  700.  
  701. void wxTopLevelWindowOS2::DoShowWindow(
  702.   int                               nShowCmd
  703. )
  704. {
  705.     ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW));
  706.  
  707.     //
  708.     // Need to artificially send a size event as wxApps often expect to do some
  709.     // final child control sizing
  710.     SendSizeEvent();
  711.     m_bIconized = nShowCmd == SWP_MINIMIZE;
  712. } // end of wxTopLevelWindowOS2::DoShowWindow
  713.  
  714. bool wxTopLevelWindowOS2::Show(
  715.   bool                              bShow
  716. )
  717. {
  718.     int                             nShowCmd;
  719.     SWP                             vSwp;
  720.     RECTL                           vRect;
  721.  
  722.     if (bShow != IsShown() )
  723.     {
  724.         m_isShown = bShow;
  725.     }
  726.     else
  727.     {
  728.         return FALSE;
  729.     }
  730.     if (bShow)
  731.     {
  732.         if (m_bMaximizeOnShow)
  733.         {
  734.             nShowCmd = SWP_MAXIMIZE;
  735.             m_bMaximizeOnShow = FALSE;
  736.         }
  737.         else
  738.         {
  739.             nShowCmd = SWP_SHOW;
  740.         }
  741.     }
  742.     else // hide
  743.     {
  744.         nShowCmd = SWP_HIDE;
  745.     }
  746.     DoShowWindow(nShowCmd);
  747.  
  748.     if (bShow)
  749.     {
  750.         wxActivateEvent             vEvent(wxEVT_ACTIVATE, TRUE, m_windowId);
  751.  
  752.         ::WinQueryWindowPos(m_hFrame, &vSwp);
  753.         m_bIconized = vSwp.fl & SWP_MINIMIZE;
  754.         ::WinQueryWindowPos(m_hWnd, &m_vSwpClient);
  755.         ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0);
  756.         ::WinQueryWindowPos(m_hWnd, &vSwp);
  757.         ::WinEnableWindow(m_hFrame, TRUE);
  758.  
  759.         //
  760.         // Deal with children
  761.         //
  762.         MoveChildren(m_vSwpClient.cy - vSwp.cy);
  763.         vEvent.SetEventObject(this);
  764.         GetEventHandler()->ProcessEvent(vEvent);
  765.     }
  766.     else
  767.     {
  768.         //
  769.         // Try to highlight the correct window (the parent)
  770.         //
  771.         if (GetParent())
  772.         {
  773.             HWND                    hWndParent = GetHwndOf(GetParent());
  774.  
  775.             ::WinQueryWindowPos(hWndParent, &vSwp);
  776.             m_bIconized = vSwp.fl & SWP_MINIMIZE;
  777.             ::WinEnableWindow(hWndParent, TRUE);
  778.         }
  779.     }
  780.     return TRUE;
  781. } // end of wxTopLevelWindowOS2::Show
  782.  
  783. // ----------------------------------------------------------------------------
  784. // wxTopLevelWindowOS2 maximize/minimize
  785. // ----------------------------------------------------------------------------
  786.  
  787. void wxTopLevelWindowOS2::Maximize(
  788.   bool                              bMaximize
  789. )
  790. {
  791.     if (IsShown())
  792.     {
  793.         //
  794.         // Just maximize it directly
  795.         //
  796.         DoShowWindow(bMaximize ? SWP_MAXIMIZE : SWP_RESTORE);
  797.     }
  798.     else // hidden
  799.     {
  800.         //
  801.         // We can't maximize the hidden frame because it shows it as well, so
  802.         // just remember that we should do it later in this case
  803.         //
  804.         m_bMaximizeOnShow = TRUE;
  805.     }
  806. } // end of wxTopLevelWindowOS2::Maximize
  807.  
  808. bool wxTopLevelWindowOS2::IsMaximized() const
  809. {
  810.     bool                            bIconic;
  811.  
  812.     ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
  813.     return (m_vSwp.fl & SWP_MAXIMIZE);
  814. } // end of wxTopLevelWindowOS2::IsMaximized
  815.  
  816. void wxTopLevelWindowOS2::Iconize(
  817.   bool                              bIconize
  818. )
  819. {
  820.     DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE);
  821. } // end of wxTopLevelWindowOS2::Iconize
  822.  
  823. bool wxTopLevelWindowOS2::IsIconized() const
  824. {
  825.     // also update the current state
  826.     ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp);
  827.     if (m_vSwp.fl & SWP_MINIMIZE)
  828.         ((wxTopLevelWindow*)this)->m_bIconized = TRUE;
  829.     else
  830.         ((wxTopLevelWindow*)this)->m_bIconized = FALSE;
  831.     return m_bIconized;
  832. } // end of wxTopLevelWindowOS2::IsIconized
  833.  
  834. void wxTopLevelWindowOS2::Restore()
  835. {
  836.     DoShowWindow(SWP_RESTORE);
  837. } // end of wxTopLevelWindowOS2::Restore
  838.  
  839. // generate an artificial resize event
  840. void wxTopLevelWindowOS2::SendSizeEvent()
  841. {
  842.     if (!m_bIconized)
  843.     {
  844.         RECTL                       vRect = wxGetWindowRect(GetHwnd());
  845.  
  846.         (void)::WinPostMsg( m_hFrame
  847.                            ,WM_SIZE
  848.                            ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
  849.                            ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom)
  850.                           );
  851.     }
  852. } // end of wxTopLevelWindowOS2::SendSizeEvent
  853.  
  854. // ----------------------------------------------------------------------------
  855. // wxTopLevelWindowOS2 fullscreen
  856. // ----------------------------------------------------------------------------
  857.  
  858. bool wxTopLevelWindowOS2::ShowFullScreen(
  859.   bool                              bShow
  860. , long                              lStyle
  861. )
  862. {
  863.     if (bShow)
  864.     {
  865.         if (IsFullScreen())
  866.             return FALSE;
  867.  
  868.         m_bFsIsShowing = TRUE;
  869.         m_lFsStyle = lStyle;
  870.  
  871.         //
  872.         // Zap the frame borders
  873.         //
  874.  
  875.         //
  876.         // Save the 'normal' window lStyle
  877.         //
  878.         m_lFsOldWindowStyle = ::WinQueryWindowULong( (HWND)GetHWND()
  879.                                                     ,QWL_STYLE
  880.                                                    );
  881.  
  882.         //
  883.         // Save the old position, width & height, maximize state
  884.         //
  885.         m_vFsOldSize = GetRect();
  886.         m_bFsIsMaximized = IsMaximized();
  887.  
  888.         //
  889.         // Decide which window lStyle flags to turn off
  890.         //
  891.         LONG                        lNewStyle = m_lFsOldWindowStyle;
  892.         LONG                        lOffFlags = 0;
  893.  
  894.         if (lStyle & wxFULLSCREEN_NOBORDER)
  895.             lOffFlags |= FCF_BORDER;
  896.         if (lStyle & wxFULLSCREEN_NOCAPTION)
  897.             lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU);
  898.  
  899.         lNewStyle &= (~lOffFlags);
  900.  
  901.         //
  902.         // Change our window style to be compatible with full-screen mode
  903.         //
  904.         ::WinSetWindowULong( (HWND)GetHWND()
  905.                             ,QWL_STYLE
  906.                             ,lNewStyle
  907.                            );
  908.  
  909.         //
  910.         // Resize to the size of the desktop
  911.         //
  912.         int                         nWidth;
  913.         int                         nHeight;
  914.         RECTL                       vRect = wxGetWindowRect(HWND_DESKTOP);
  915.  
  916.         nWidth = vRect.xRight - vRect.xLeft;
  917.         nHeight = vRect.yTop - vRect.yBottom;
  918.  
  919.         SetSize( nWidth
  920.                 ,nHeight
  921.                );
  922.  
  923.         //
  924.         // Now flush the window style cache and actually go full-screen
  925.         //
  926.         ::WinSetWindowPos( m_hFrame
  927.                           ,HWND_TOP
  928.                           ,0
  929.                           ,0
  930.                           ,nWidth
  931.                           ,nHeight
  932.                           ,SWP_SIZE | SWP_MOVE
  933.                          );
  934.  
  935.         wxSizeEvent                 vEvent( wxSize( nWidth
  936.                                                    ,nHeight
  937.                                                   )
  938.                                            ,GetId()
  939.                                           );
  940.  
  941.         GetEventHandler()->ProcessEvent(vEvent);
  942.         return TRUE;
  943.     }
  944.     else
  945.     {
  946.         if (!IsFullScreen())
  947.             return FALSE;
  948.  
  949.         m_bFsIsShowing = FALSE;
  950.         Maximize(m_bFsIsMaximized);
  951.         ::WinSetWindowULong( (HWND)GetHWND()
  952.                             ,QWL_STYLE
  953.                             ,m_lFsOldWindowStyle
  954.                            );
  955.         ::WinSetWindowPos( m_hFrame
  956.                           ,HWND_TOP
  957.                           ,m_vFsOldSize.x
  958.                           ,m_vFsOldSize.y
  959.                           ,m_vFsOldSize.width
  960.                           ,m_vFsOldSize.height
  961.                           ,SWP_SIZE | SWP_MOVE
  962.                          );
  963.         return TRUE;
  964.     }
  965. } // end of wxTopLevelWindowOS2::ShowFullScreen
  966.  
  967. // ----------------------------------------------------------------------------
  968. // wxTopLevelWindowOS2 misc
  969. // ----------------------------------------------------------------------------
  970.  
  971. void wxTopLevelWindowOS2::SetIcon(
  972.   const wxIcon&                     rIcon
  973. )
  974. {
  975.     SetIcons(wxIconBundle(rIcon));
  976. } // end of wxTopLevelWindowOS2::SetIcon
  977.  
  978. void wxTopLevelWindowOS2::SetIcons(
  979.   const wxIconBundle&               rIcons
  980. )
  981. {
  982.     //
  983.     // This sets m_icon
  984.     //
  985.     wxTopLevelWindowBase::SetIcons(rIcons);
  986.  
  987.     const wxIcon&                   vIcon = rIcons.GetIcon(wxSize(32, 32));
  988.  
  989.     if (vIcon.Ok() && vIcon.GetWidth() == 32 && vIcon.GetHeight() == 32)
  990.     {
  991.         ::WinSendMsg( m_hFrame
  992.                      ,WM_SETICON
  993.                      ,(MPARAM)((HPOINTER)vIcon.GetHICON())
  994.                      ,NULL
  995.                     );
  996.         ::WinSendMsg( m_hFrame
  997.                      ,WM_UPDATEFRAME
  998.                      ,(MPARAM)FCF_ICON
  999.                      ,(MPARAM)0
  1000.                     );
  1001.     }
  1002. } // end of wxTopLevelWindowOS2::SetIcon
  1003.  
  1004. bool wxTopLevelWindowOS2::EnableCloseButton(
  1005.   bool                              bEnable
  1006. )
  1007. {
  1008.     //
  1009.     // Get system (a.k.a. window) menu
  1010.     //
  1011.     HMENU                           hMenu = ::WinWindowFromID(m_hFrame, FID_SYSMENU);
  1012.  
  1013.     if (!hMenu)
  1014.     {
  1015.         wxLogLastError(_T("GetSystemMenu"));
  1016.         return FALSE;
  1017.     }
  1018.  
  1019.     //
  1020.     // Enabling/disabling the close item from it also automatically
  1021.     // disables/enables the close title bar button
  1022.     //
  1023.     if (bEnable)
  1024.         (void)::WinSendMsg( hMenu
  1025.                            ,MM_SETITEMATTR
  1026.                            ,MPFROM2SHORT(SC_CLOSE, FALSE)
  1027.                            ,MPFROM2SHORT(MIA_DISABLED, FALSE)
  1028.                           );
  1029.     else
  1030.         (void)::WinSendMsg( hMenu
  1031.                            ,MM_SETITEMATTR
  1032.                            ,MPFROM2SHORT(SC_CLOSE, FALSE)
  1033.                            ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
  1034.                           );
  1035.  
  1036.     //
  1037.     // Update appearance immediately
  1038.     //
  1039.     ::WinSendMsg( m_hFrame
  1040.                  ,WM_UPDATEFRAME
  1041.                  ,(MPARAM)FCF_MENU
  1042.                  ,(MPARAM)0
  1043.                 );
  1044.     return TRUE;
  1045. } // end of wxTopLevelWindowOS2::EnableCloseButton
  1046.  
  1047. // ============================================================================
  1048. // wxTLWHiddenParentModule implementation
  1049. // ============================================================================
  1050.  
  1051. HWND          wxTLWHiddenParentModule::m_shWnd = NULL;
  1052. const wxChar* wxTLWHiddenParentModule::m_szClassName = NULL;
  1053.  
  1054. bool wxTLWHiddenParentModule::OnInit()
  1055. {
  1056.     m_shWnd = NULL;
  1057.     m_szClassName = NULL;
  1058.     return TRUE;
  1059. } // end of wxTLWHiddenParentModule::OnInit
  1060.  
  1061. void wxTLWHiddenParentModule::OnExit()
  1062. {
  1063.     if (m_shWnd)
  1064.     {
  1065.         if (!::WinDestroyWindow(m_shWnd))
  1066.         {
  1067.             wxLogLastError(_T("DestroyWindow(hidden TLW parent)"));
  1068.         }
  1069.         m_shWnd = NULL;
  1070.     }
  1071.  
  1072.     m_szClassName = NULL;
  1073. } // end of wxTLWHiddenParentModule::OnExit
  1074.  
  1075. /* static */
  1076. HWND wxTLWHiddenParentModule::GetHWND()
  1077. {
  1078.     if (!m_shWnd)
  1079.     {
  1080.         if (!m_szClassName)
  1081.         {
  1082.             static const wxChar*    zHIDDEN_PARENT_CLASS = _T("wxTLWHiddenParent");
  1083.  
  1084.             if (!::WinRegisterClass( wxGetInstance()
  1085.                                     ,zHIDDEN_PARENT_CLASS
  1086.                                     ,NULL
  1087.                                     ,0
  1088.                                     ,sizeof(ULONG)
  1089.                                    ))
  1090.             {
  1091.                 wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")"));
  1092.             }
  1093.             else
  1094.             {
  1095.                 m_szClassName = zHIDDEN_PARENT_CLASS;
  1096.             }
  1097.         }
  1098.         m_shWnd = ::WinCreateWindow( HWND_DESKTOP
  1099.                                     ,m_szClassName
  1100.                                     ,""
  1101.                                     ,0L
  1102.                                     ,(LONG)0L
  1103.                                     ,(LONG)0L
  1104.                                     ,(LONG)0L
  1105.                                     ,(LONG)0L
  1106.                                     ,NULLHANDLE
  1107.                                     ,HWND_TOP
  1108.                                     ,0L
  1109.                                     ,NULL
  1110.                                     ,NULL
  1111.                                    );
  1112.         if (!m_shWnd)
  1113.         {
  1114.             wxLogLastError(_T("CreateWindow(hidden TLW parent)"));
  1115.         }
  1116.     }
  1117.     return m_shWnd;
  1118. } // end of wxTLWHiddenParentModule::GetHWND
  1119.