1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxClientDC class 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  23 #include "wx/string.h" 
  25 #include "wx/window.h" 
  28 #include "wx/os2/private.h" 
  30 #include "wx/dcclient.h" 
  32 // ---------------------------------------------------------------------------- 
  34 // ---------------------------------------------------------------------------- 
  36 struct WXDLLEXPORT wxPaintDCInfo
 
  38     wxPaintDCInfo( wxWindow
* pWin
 
  42         m_hWnd 
= pWin
->GetHWND(); 
  43         m_hDC 
= pDC
->GetHDC(); 
  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 
  52 #include "wx/arrimpl.cpp" 
  54 WX_DEFINE_OBJARRAY(wxArrayDCInfo
); 
  56 // ---------------------------------------------------------------------------- 
  58 // ---------------------------------------------------------------------------- 
  60     IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
  61     IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
) 
  62     IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
) 
  64 // ---------------------------------------------------------------------------- 
  66 // ---------------------------------------------------------------------------- 
  68 static RECT        g_paintStruct
; 
  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 wxWidgets programmers and might lead to 
  74     // very subtle and difficult to debug refresh/repaint bugs. 
  78 // =========================================================================== 
  80 // =========================================================================== 
  82 // ---------------------------------------------------------------------------- 
  84 // ---------------------------------------------------------------------------- 
  86 wxWindowDC::wxWindowDC() 
  89     m_PageSize
.cx 
= m_PageSize
.cy 
= 0; 
  93 wxWindowDC::wxWindowDC( 
 101     m_pCanvas 
= pTheCanvas
; 
 102     DoGetSize(&nWidth
, &nHeight
); 
 103     m_PageSize
.cx 
= nWidth
; 
 104     m_PageSize
.cy 
= nHeight
; 
 105     m_hDC 
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) ); 
 108     // default under PM is that Window and Client DC's are the same 
 109     // so we offer a separate Presentation Space to use for the 
 110     // entire window.  Otherwise, calling BeginPaint will just create 
 111     // chached-micro client presentation space 
 113      m_hPS 
= ::GpiCreatePS( vHabmain
 
 116                            ,PU_PELS 
| GPIF_LONG 
| GPIA_ASSOC
 
 120         vError 
= ::WinGetLastError(vHabmain
); 
 121         sError 
= wxPMErrorToStr(vError
); 
 122         wxLogError("Unable to create presentation space. Error: %s\n", sError
.c_str()); 
 124     ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 125     ::GpiAssociate(m_hPS
, m_hDC
); 
 128     // Set the wxWidgets color table 
 130     if (!::GpiCreateLogColorTable( m_hPS
 
 134                                   ,(LONG
)wxTheColourDatabase
->m_nSize
 
 135                                   ,(PLONG
)wxTheColourDatabase
->m_palTable
 
 138         vError 
= ::WinGetLastError(vHabmain
); 
 139         sError 
= wxPMErrorToStr(vError
); 
 140         wxLogError("Unable to set current color table. Error: %s\n", sError
.c_str()); 
 142     ::GpiCreateLogColorTable( m_hPS
 
 149     ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
) 
 153 } // end of wxWindowDC::wxWindowDC 
 155 void wxWindowDC::InitDC() 
 159     // The background mode is only used for text background and is set in 
 160     // DrawText() to OPAQUE as required, otherwise always TRANSPARENT, 
 162     ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
); 
 165     // Default bg colour is pne of the window 
 167     SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
)); 
 169     wxColour 
vColor( wxT("BLACK") ); 
 170     m_pen
.SetColour(vColor
); 
 172     vColor
.Set( wxT("WHITE") ); 
 173     m_brush
.SetColour(vColor
); 
 175     wxFont
*                         pFont 
= new wxFont( 12 
 183     // OS/2 default vertical character allignment needs to match the other OS's 
 185     ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
); 
 187 } // end of wxWindowDC::InitDC 
 189 void wxWindowDC::DoGetSize( 
 194     wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") ); 
 195     m_pCanvas
->GetSize( pnWidth
 
 198 } // end of wxWindowDC::DoGetSize 
 200 // ---------------------------------------------------------------------------- 
 202 // ---------------------------------------------------------------------------- 
 204 wxClientDC::wxClientDC() 
 209 wxClientDC::wxClientDC( 
 213     SIZEL                           vSizl 
= { 0,0}; 
 217     m_pCanvas 
= pTheCanvas
; 
 220     // default under PM is that Window and Client DC's are the same 
 222     m_hDC 
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
)); 
 223     m_hPS 
= ::GpiCreatePS( wxGetInstance() 
 226                           ,PU_PELS 
| GPIF_LONG 
| GPIA_ASSOC
 
 229     // Set the wxWidgets color table 
 230     if (!::GpiCreateLogColorTable( m_hPS
 
 234                                   ,(LONG
)wxTheColourDatabase
->m_nSize
 
 235                                   ,(PLONG
)wxTheColourDatabase
->m_palTable
 
 238         vError 
= ::WinGetLastError(vHabmain
); 
 239         sError 
= wxPMErrorToStr(vError
); 
 240         wxLogError("Unable to set current color table. Error: %s\n", sError
.c_str()); 
 242     ::GpiCreateLogColorTable( m_hPS
 
 250     // Set the DC/PS rectangle 
 252     ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
) 
 256 } // end of wxClientDC::wxClientDC 
 258 void wxClientDC::InitDC() 
 260     wxWindowDC::InitDC(); 
 262     // in wxUniv build we must manually do some DC adjustments usually 
 263     // performed by Windows for us 
 264 #ifdef __WXUNIVERSAL__ 
 265     wxPoint ptOrigin 
= m_pCanvas
->GetClientAreaOrigin(); 
 266     if ( ptOrigin
.x 
|| ptOrigin
.y 
) 
 268         // no need to shift DC origin if shift is null 
 269         SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
 272     // clip the DC to avoid overwriting the non client area 
 273     SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize()); 
 274 #endif // __WXUNIVERSAL__ 
 275 } // end of wxClientDC::InitDC 
 277 wxClientDC::~wxClientDC() 
 279 } // end of wxClientDC::~wxClientDC 
 281 void wxClientDC::DoGetSize( 
 286     wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") ); 
 287     m_pCanvas
->GetClientSize( pnWidth
 
 290 } // end of wxClientDC::DoGetSize 
 292 // ---------------------------------------------------------------------------- 
 294 // ---------------------------------------------------------------------------- 
 296 wxArrayDCInfo 
wxPaintDC::ms_cache
; 
 298 wxPaintDC::wxPaintDC() 
 304 wxPaintDC::wxPaintDC( 
 308     wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor")); 
 311     if (g_isPainting 
<= 0) 
 313         wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") ); 
 316 #endif // __WXDEBUG__ 
 321     // Do we have a DC for this window in the cache? 
 323     wxPaintDCInfo
*                  pInfo 
= FindInCache(); 
 327         m_hDC 
= pInfo
->m_hDC
; 
 330     else // not in cache, create a new one 
 334         m_hDC 
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
)); 
 335         hPS 
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
) 
 341             ::GpiAssociate(hPS
, m_hDC
); 
 344             ::GpiCreateLogColorTable( m_hPS
 
 348                                      ,(LONG
)wxTheColourDatabase
->m_nSize
 
 349                                      ,(PLONG
)wxTheColourDatabase
->m_palTable
 
 351             ::GpiCreateLogColorTable( m_hPS
 
 359             ::WinFillRect(hPS
, &g_paintStruct
,  m_pCanvas
->GetBackgroundColour().GetPixel()); 
 360             ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
) 
 365         m_bIsPaintTime   
= TRUE
; 
 366         ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this)); 
 369 } // end of wxPaintDC::wxPaintDC 
 371 wxPaintDC::~wxPaintDC() 
 375         SelectOldObjects(m_hDC
); 
 378         wxPaintDCInfo
*              pInfo 
= FindInCache(&nIndex
); 
 380         wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") ); 
 382         if ( !--pInfo
->m_nCount 
) 
 384             ::WinEndPaint(m_hPS
); 
 386             m_bIsPaintTime 
= FALSE
; 
 387             ms_cache
.RemoveAt(nIndex
); 
 389         //else: cached DC entry is still in use 
 391         // prevent the base class dtor from ReleaseDC()ing it again 
 396 wxPaintDCInfo
* wxPaintDC::FindInCache( 
 400     wxPaintDCInfo
*                  pInfo 
= NULL
; 
 401     size_t                          nCache 
= ms_cache
.GetCount(); 
 403     for (size_t n 
= 0; n 
< nCache
; n
++) 
 405         pInfo 
= &ms_cache
[n
]; 
 406         if (pInfo
->m_hWnd 
== m_pCanvas
->GetHWND()) 
 414 } // end of wxPaintDC::FindInCache 
 416 // find the entry for this DC in the cache (keyed by the window) 
 417 WXHDC 
wxPaintDC::FindDCInCache( 
 421     wxPaintDCInfo
*                  pInfo 
= NULL
; 
 422     size_t                          nCache 
= ms_cache
.GetCount(); 
 424     for (size_t n 
= 0; n 
< nCache
; n
++) 
 426         pInfo 
= &ms_cache
[n
]; 
 427         if (pInfo
->m_hWnd 
== pWin
->GetHWND()) 
 433 } // end of wxPaintDC::FindInCache