home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / os2 / dcclient.cpp < prev    next >
C/C++ Source or Header  |  2002-05-05  |  13KB  |  423 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        dcclient.cpp
  3. // Purpose:     wxClientDC class
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     09/21/99
  7. // RCS-ID:      $Id: DCCLIENT.CPP,v 1.30 2002/04/30 22:31:01 DW Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ===========================================================================
  13. // declarations
  14. // ===========================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. // For compilers that support precompilation, includes "wx.h".
  21. #include "wx/wxprec.h"
  22.  
  23. #include "wx/string.h"
  24. #include "wx/log.h"
  25. #include "wx/window.h"
  26. #include "wx/app.h"
  27.  
  28. #include "wx/os2/private.h"
  29.  
  30. #include "wx/dcclient.h"
  31.  
  32. // ----------------------------------------------------------------------------
  33. // array/list types
  34. // ----------------------------------------------------------------------------
  35.  
  36. struct WXDLLEXPORT wxPaintDCInfo
  37. {
  38.     wxPaintDCInfo( wxWindow* pWin
  39.                   ,wxDC*     pDC
  40.                  )
  41.     {
  42.         m_hWnd = pWin->GetHWND();
  43.         m_hDC = pDC->GetHDC();
  44.         m_nCount = 1;
  45.     }
  46.  
  47.     WXHWND                          m_hWnd;   // window for this DC
  48.     WXHDC                           m_hDC;    // the DC handle
  49.     size_t                          m_nCount; // usage count
  50. }; // end of wxPaintDCInfot
  51.  
  52. #include "wx/arrimpl.cpp"
  53.  
  54. WX_DEFINE_OBJARRAY(wxArrayDCInfo);
  55.  
  56. // ----------------------------------------------------------------------------
  57. // macros
  58. // ----------------------------------------------------------------------------
  59.  
  60.     IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
  61.     IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
  62.     IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
  63.  
  64. // ----------------------------------------------------------------------------
  65. // global variables
  66. // ----------------------------------------------------------------------------
  67.  
  68. static RECT        g_paintStruct;
  69.  
  70. #ifdef __WXDEBUG__
  71.     // a global variable which we check to verify that wxPaintDC are only
  72.     // created in resopnse to WM_PAINT message - doing this from elsewhere is a
  73.     // common programming error among wxWindows programmers and might lead to
  74.     // very subtle and difficult to debug refresh/repaint bugs.
  75.     int g_isPainting = 0;
  76. #endif // __WXDEBUG__
  77.  
  78. // ===========================================================================
  79. // implementation
  80. // ===========================================================================
  81.  
  82. // ----------------------------------------------------------------------------
  83. // wxWindowDC
  84. // ----------------------------------------------------------------------------
  85.  
  86. wxWindowDC::wxWindowDC()
  87. {
  88.     m_pCanvas = NULL;
  89. }
  90.  
  91. wxWindowDC::wxWindowDC(
  92.   wxWindow*                         pTheCanvas
  93. )
  94. {
  95.     ERRORID                         vError;
  96.     wxString                        sError;
  97.  
  98.     m_pCanvas = pTheCanvas;
  99.     m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
  100.  
  101.     //
  102.     // default under PM is that Window and Client DC's are the same
  103.     // so we offer a separate Presentation Space to use for the
  104.     // entire window.  Otherwise, calling BeginPaint will just create
  105.     // chached-micro client presentation space
  106.     //
  107.      m_hPS = ::GpiCreatePS( vHabmain
  108.                            ,m_hDC
  109.                            ,&m_PageSize
  110.                            ,PU_PELS | GPIF_LONG | GPIA_ASSOC
  111.                           );
  112.     ::GpiAssociate(m_hPS, NULLHANDLE);
  113.     ::GpiAssociate(m_hPS, m_hDC);
  114.  
  115.     //
  116.     // Set the wxWindows color table
  117.     //
  118.     if (!::GpiCreateLogColorTable( m_hPS
  119.                                   ,0L
  120.                                   ,LCOLF_CONSECRGB
  121.                                   ,0L
  122.                                   ,(LONG)wxTheColourDatabase->m_nSize
  123.                                   ,(PLONG)wxTheColourDatabase->m_palTable
  124.                                  ))
  125.     {
  126.         vError = ::WinGetLastError(vHabmain);
  127.         sError = wxPMErrorToStr(vError);
  128.         wxLogError("Unable to set current color table. Error: %s\n", sError);
  129.     }
  130.     ::GpiCreateLogColorTable( m_hPS
  131.                              ,0L
  132.                              ,LCOLF_RGB
  133.                              ,0L
  134.                              ,0L
  135.                              ,NULL
  136.                             );
  137.     ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
  138.                          ,&m_vRclPaint
  139.                         );
  140.     InitDC();
  141. } // end of wxWindowDC::wxWindowDC
  142.  
  143. void wxWindowDC::InitDC()
  144. {
  145.     wxColour                        vColor;
  146.  
  147.     //
  148.     // The background mode is only used for text background and is set in
  149.     // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
  150.     //
  151.     ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
  152.  
  153.     //
  154.     // Default bg colour is pne of the window
  155.     //
  156.     SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
  157.  
  158.     vColor.InitFromName("BLACK");
  159.     m_pen.SetColour(vColor);
  160.     vColor.Set("WHITE");
  161.     m_brush.SetColour(vColor);
  162.     InitializePalette();
  163.     wxFont*                         pFont = new wxFont( 12
  164.                                                        ,wxNORMAL
  165.                                                        ,wxNORMAL
  166.                                                        ,wxBOLD
  167.                                                       );
  168.     SetFont(*pFont);
  169.     delete pFont;
  170.     //
  171.     // OS/2 default vertical character allignment needs to match the other OS's
  172.     //
  173.     ::GpiSetTextAlignment((HPS)GetHPS(), TA_NORMAL_HORIZ, TA_BOTTOM);
  174.  
  175. } // end of wxWindowDC::InitDC
  176.  
  177. void wxWindowDC::DoGetSize(
  178.   int*                              pnWidth
  179. , int*                              pnHeight
  180. ) const
  181. {
  182.     wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
  183.     m_pCanvas->GetSize( pnWidth
  184.                        ,pnHeight
  185.                       );
  186. } // end of wxWindowDC::DoGetSize
  187.  
  188. // ----------------------------------------------------------------------------
  189. // wxClientDC
  190. // ----------------------------------------------------------------------------
  191.  
  192. wxClientDC::wxClientDC()
  193. {
  194.     m_pCanvas = NULL;
  195. }
  196.  
  197. wxClientDC::wxClientDC(
  198.   wxWindow*                         pTheCanvas
  199. )
  200. {
  201.     SIZEL                           vSizl = { 0,0};
  202.     ERRORID                         vError;
  203.     wxString                        sError;
  204.  
  205.     m_pCanvas = pTheCanvas;
  206.  
  207.     //
  208.     // default under PM is that Window and Client DC's are the same
  209.     //
  210.     m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
  211.     m_hPS = ::GpiCreatePS( wxGetInstance()
  212.                           ,m_hDC
  213.                           ,&vSizl
  214.                           ,PU_PELS | GPIF_LONG | GPIA_ASSOC
  215.                          );
  216.  
  217.     // Set the wxWindows color table
  218.     if (!::GpiCreateLogColorTable( m_hPS
  219.                                   ,0L
  220.                                   ,LCOLF_CONSECRGB
  221.                                   ,0L
  222.                                   ,(LONG)wxTheColourDatabase->m_nSize
  223.                                   ,(PLONG)wxTheColourDatabase->m_palTable
  224.                                  ))
  225.     {
  226.         vError = ::WinGetLastError(vHabmain);
  227.         sError = wxPMErrorToStr(vError);
  228.         wxLogError("Unable to set current color table. Error: %s\n", sError);
  229.     }
  230.     ::GpiCreateLogColorTable( m_hPS
  231.                              ,0L
  232.                              ,LCOLF_RGB
  233.                              ,0L
  234.                              ,0L
  235.                              ,NULL
  236.                             );
  237.     //
  238.     // Set the DC/PS rectangle
  239.     //
  240.     ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
  241.                          ,&m_vRclPaint
  242.                         );
  243.     InitDC();
  244. } // end of wxClientDC::wxClientDC
  245.  
  246. void wxClientDC::InitDC()
  247. {
  248.     wxWindowDC::InitDC();
  249.  
  250.     // in wxUniv build we must manually do some DC adjustments usually
  251.     // performed by Windows for us
  252. #ifdef __WXUNIVERSAL__
  253.     wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
  254.     if ( ptOrigin.x || ptOrigin.y )
  255.     {
  256.         // no need to shift DC origin if shift is null
  257.         SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
  258.     }
  259.  
  260.     // clip the DC to avoid overwriting the non client area
  261.     SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
  262. #endif // __WXUNIVERSAL__
  263. } // end of wxClientDC::InitDC
  264.  
  265. wxClientDC::~wxClientDC()
  266. {
  267. } // end of wxClientDC::~wxClientDC
  268.  
  269. void wxClientDC::DoGetSize(
  270.   int*                              pnWidth
  271. , int*                              pnHeight
  272. ) const
  273. {
  274.     wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
  275.     m_pCanvas->GetClientSize( pnWidth
  276.                              ,pnHeight
  277.                             );
  278. } // end of wxClientDC::DoGetSize
  279.  
  280. // ----------------------------------------------------------------------------
  281. // wxPaintDC
  282. // ----------------------------------------------------------------------------
  283.  
  284. wxArrayDCInfo wxPaintDC::ms_cache;
  285.  
  286. wxPaintDC::wxPaintDC()
  287. {
  288.     m_pCanvas = NULL;
  289.     m_hDC = 0;
  290. }
  291.  
  292. wxPaintDC::wxPaintDC(
  293.   wxWindow*                         pCanvas
  294. )
  295. {
  296.     wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
  297.  
  298. #ifdef __WXDEBUG__
  299.     if (g_isPainting <= 0)
  300.     {
  301.         wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
  302.         return;
  303.     }
  304. #endif // __WXDEBUG__
  305.  
  306.     m_pCanvas = pCanvas;
  307.  
  308.     //
  309.     // Do we have a DC for this window in the cache?
  310.     //
  311.     wxPaintDCInfo*                  pInfo = FindInCache();
  312.  
  313.     if (pInfo)
  314.     {
  315.         m_hDC = pInfo->m_hDC;
  316.         pInfo->m_nCount++;
  317.     }
  318.     else // not in cache, create a new one
  319.     {
  320.         HPS                         hPS;
  321.  
  322.         m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
  323.         hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
  324.                               ,NULLHANDLE
  325.                               ,&g_paintStruct
  326.                              );
  327.         if(hPS)
  328.         {
  329.             ::GpiAssociate(hPS, m_hDC);
  330.             m_hOldPS = m_hPS;
  331.             m_hPS = hPS;
  332.             ::GpiCreateLogColorTable( m_hPS
  333.                                      ,0L
  334.                                      ,LCOLF_CONSECRGB
  335.                                      ,0L
  336.                                      ,(LONG)wxTheColourDatabase->m_nSize
  337.                                      ,(PLONG)wxTheColourDatabase->m_palTable
  338.                                     );
  339.             ::GpiCreateLogColorTable( m_hPS
  340.                                      ,0L
  341.                                      ,LCOLF_RGB
  342.                                      ,0L
  343.                                      ,0L
  344.                                      ,NULL
  345.                                     );
  346.  
  347.             ::WinFillRect(hPS, &g_paintStruct,  m_pCanvas->GetBackgroundColour().GetPixel());
  348.             ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
  349.                                  ,&m_vRclPaint
  350.                                 );
  351.         }
  352.  
  353.         m_bIsPaintTime   = TRUE;
  354.         ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
  355.     }
  356.     InitDC();
  357. } // end of wxPaintDC::wxPaintDC
  358.  
  359. wxPaintDC::~wxPaintDC()
  360. {
  361.     if ( m_hDC )
  362.     {
  363.         SelectOldObjects(m_hDC);
  364.  
  365.         size_t                      nIndex;
  366.         wxPaintDCInfo*              pInfo = FindInCache(&nIndex);
  367.  
  368.         wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
  369.  
  370.         if ( !--pInfo->m_nCount )
  371.         {
  372.             ::WinEndPaint(m_hPS);
  373.             m_hPS          = m_hOldPS;
  374.             m_bIsPaintTime = FALSE;
  375.             ms_cache.RemoveAt(nIndex);
  376.         }
  377.         //else: cached DC entry is still in use
  378.  
  379.         // prevent the base class dtor from ReleaseDC()ing it again
  380.         m_hDC = 0;
  381.     }
  382. }
  383.  
  384. wxPaintDCInfo* wxPaintDC::FindInCache(
  385.   size_t*                           pIndex
  386. ) const
  387. {
  388.     wxPaintDCInfo*                  pInfo = NULL;
  389.     size_t                          nCache = ms_cache.GetCount();
  390.  
  391.     for (size_t n = 0; n < nCache; n++)
  392.     {
  393.         pInfo = &ms_cache[n];
  394.         if (pInfo->m_hWnd == m_pCanvas->GetHWND())
  395.         {
  396.             if (pIndex)
  397.                 *pIndex = n;
  398.             break;
  399.         }
  400.     }
  401.     return pInfo;
  402. } // end of wxPaintDC::FindInCache
  403.  
  404. // find the entry for this DC in the cache (keyed by the window)
  405. WXHDC wxPaintDC::FindDCInCache(
  406.   wxWindow*                         pWin
  407. )
  408. {
  409.     wxPaintDCInfo*                  pInfo = NULL;
  410.     size_t                          nCache = ms_cache.GetCount();
  411.  
  412.     for (size_t n = 0; n < nCache; n++)
  413.     {
  414.         pInfo = &ms_cache[n];
  415.         if (pInfo->m_hWnd == pWin->GetHWND())
  416.         {
  417.             return pInfo->m_hDC;
  418.         }
  419.     }
  420.     return 0;
  421. } // end of wxPaintDC::FindInCache
  422.  
  423.