1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/dcclient.cpp 
   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/dcclient.h" 
  24 #include "wx/os2/dcclient.h" 
  27     #include "wx/string.h" 
  30     #include "wx/window.h" 
  33 #include "wx/os2/private.h" 
  35 // ---------------------------------------------------------------------------- 
  37 // ---------------------------------------------------------------------------- 
  39 struct WXDLLEXPORT wxPaintDCInfo
 
  41     wxPaintDCInfo( wxWindow
* pWin
 
  45         m_hWnd 
= pWin
->GetHWND(); 
  46         m_hDC 
= pDC
->GetHDC(); 
  50     WXHWND                          m_hWnd
;   // window for this DC 
  51     WXHDC                           m_hDC
;    // the DC handle 
  52     size_t                          m_nCount
; // usage count 
  53 }; // end of wxPaintDCInfot 
  55 #include "wx/arrimpl.cpp" 
  57 WX_DEFINE_OBJARRAY(wxArrayDCInfo
); 
  59 // ---------------------------------------------------------------------------- 
  61 // ---------------------------------------------------------------------------- 
  63 static RECT        g_paintStruct
; 
  66     // a global variable which we check to verify that wxPaintDC are only 
  67     // created in resopnse to WM_PAINT message - doing this from elsewhere is a 
  68     // common programming error among wxWidgets programmers and might lead to 
  69     // very subtle and difficult to debug refresh/repaint bugs. 
  73 // =========================================================================== 
  75 // =========================================================================== 
  77 // ---------------------------------------------------------------------------- 
  79 // ---------------------------------------------------------------------------- 
  81 IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl
, wxPMDCImpl
) 
  83 wxWindowDCImpl::wxWindowDCImpl( wxDC 
*owner 
) : 
  86     m_PageSize
.cx 
= m_PageSize
.cy 
= 0; 
  89 wxWindowDCImpl::wxWindowDCImpl( wxDC 
*owner
, wxWindow
* pTheCanvas
) : 
  96     m_pCanvas 
= pTheCanvas
; 
  97     DoGetSize(&nWidth
, &nHeight
); 
  98     m_PageSize
.cx 
= nWidth
; 
  99     m_PageSize
.cy 
= nHeight
; 
 100     m_hDC 
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) ); 
 103     // default under PM is that Window and Client DC's are the same 
 104     // so we offer a separate Presentation Space to use for the 
 105     // entire window.  Otherwise, calling BeginPaint will just create 
 106     // chached-micro client presentation space 
 108      m_hPS 
= ::GpiCreatePS( vHabmain
 
 111                            ,PU_PELS 
| GPIF_LONG 
| GPIA_ASSOC
 
 115         vError 
= ::WinGetLastError(vHabmain
); 
 116         sError 
= wxPMErrorToStr(vError
); 
 117         wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError
.c_str()); 
 119     ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 120     ::GpiAssociate(m_hPS
, m_hDC
); 
 123     // Set the wxWidgets color table 
 125     if (!::GpiCreateLogColorTable( m_hPS
 
 129                                   ,(LONG
)wxTheColourDatabase
->m_nSize
 
 130                                   ,(PLONG
)wxTheColourDatabase
->m_palTable
 
 133         vError 
= ::WinGetLastError(vHabmain
); 
 134         sError 
= wxPMErrorToStr(vError
); 
 135         wxLogError(_T("Unable to set current color table (3). Error: %s\n"), sError
.c_str()); 
 137     ::GpiCreateLogColorTable( m_hPS
 
 144     ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
) 
 148 } // end of wxWindowDCImpl::wxWindowDCImpl 
 150 void wxWindowDCImpl::InitDC() 
 154     // The background mode is only used for text background and is set in 
 155     // DrawText() to OPAQUE as required, otherwise always TRANSPARENT, 
 157     ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
); 
 160     // Default bg colour is pne of the window 
 162     SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
)); 
 164     m_pen
.SetColour(*wxBLACK
); 
 165     m_brush
.SetColour(*wxWHITE
); 
 166     // since we are a window dc we need to grab the palette from the window 
 170     wxFont
* pFont 
= new wxFont( 10, wxMODERN
, wxNORMAL
, wxBOLD 
); 
 174     // OS/2 default vertical character alignment needs to match the other OS's 
 176     ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
); 
 178 } // end of wxWindowDCImpl::InitDC 
 180 void wxWindowDCImpl::DoGetSize( 
 185     wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") ); 
 186     m_pCanvas
->GetSize( pnWidth
 
 189 } // end of wxWindowDCImpl::DoGetSize 
 191 // ---------------------------------------------------------------------------- 
 193 // ---------------------------------------------------------------------------- 
 195 IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl
, wxWindowDCImpl
) 
 197 wxClientDCImpl::wxClientDCImpl( wxDC 
*owner 
) : 
 198    wxWindowDCImpl( owner 
) 
 203 wxClientDCImpl::wxClientDCImpl( wxDC 
*owner
, wxWindow 
*pTheCanvas
) : 
 204    wxWindowDCImpl( owner 
) 
 206     SIZEL                           vSizl 
= { 0,0}; 
 210     m_pCanvas 
= pTheCanvas
; 
 213     // default under PM is that Window and Client DC's are the same 
 216     m_hDC 
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
)); 
 217     printf("Got WindowDC %X for window handle %X\n", m_hDC
, pTheCanvas
); 
 219     m_hPS 
= ::GpiCreatePS( wxGetInstance() 
 222                           ,PU_PELS 
| GPIF_LONG 
| GPIA_ASSOC
 
 224     ::GpiAssociate(m_hPS
, NULLHANDLE
); 
 225     ::GpiAssociate(m_hPS
, m_hDC
); 
 227     printf("Got m_hPS %X\n", m_hPS
); 
 228     // Set the wxWidgets color table 
 229     if (!::GpiCreateLogColorTable( m_hPS
 
 233                                   ,(LONG
)wxTheColourDatabase
->m_nSize
 
 234                                   ,(PLONG
)wxTheColourDatabase
->m_palTable
 
 237         vError 
= ::WinGetLastError(vHabmain
); 
 238         sError 
= wxPMErrorToStr(vError
); 
 239         wxLogError(_T("Unable to set current color table (4). Error: %s\n"), sError
.c_str()); 
 241     ::GpiCreateLogColorTable( m_hPS
 
 249     // Set the DC/PS rectangle 
 251     ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
) 
 255 } // end of wxClientDCImpl::wxClientDCImpl 
 257 void wxClientDCImpl::InitDC() 
 259     wxWindowDCImpl::InitDC(); 
 261     // in wxUniv build we must manually do some DC adjustments usually 
 262     // performed by Windows for us 
 263 #ifdef __WXUNIVERSAL__ 
 264     wxPoint ptOrigin 
= m_pCanvas
->GetClientAreaOrigin(); 
 265     if ( ptOrigin
.x 
|| ptOrigin
.y 
) 
 267         // no need to shift DC origin if shift is null 
 268         SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
 271     // clip the DC to avoid overwriting the non client area 
 272     SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize()); 
 273 #endif // __WXUNIVERSAL__ 
 274 } // end of wxClientDCImpl::InitDC 
 276 wxClientDCImpl::~wxClientDCImpl() 
 278 } // end of wxClientDCImpl::~wxClientDCImpl 
 280 void wxClientDCImpl::DoGetSize( 
 285     wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") ); 
 286     m_pCanvas
->GetClientSize( pnWidth
 
 289 } // end of wxClientDCImpl::DoGetSize 
 291 // ---------------------------------------------------------------------------- 
 293 // ---------------------------------------------------------------------------- 
 295 IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl
, wxWindowDCImpl
) 
 297 wxArrayDCInfo 
wxPaintDCImpl::ms_cache
; 
 299 wxPaintDCImpl::wxPaintDCImpl( wxDC 
*owner 
) : 
 300    wxClientDCImpl( owner 
) 
 306 wxPaintDCImpl::wxPaintDCImpl( wxDC 
*owner
, wxWindow 
*pCanvas
) : 
 307    wxClientDCImpl( owner 
) 
 309     wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor")); 
 312     if (g_isPainting 
<= 0) 
 314         wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") ); 
 317 #endif // __WXDEBUG__ 
 322     // Do we have a DC for this window in the cache? 
 324     wxPaintDCInfo
*                  pInfo 
= FindInCache(); 
 328         m_hDC 
= pInfo
->m_hDC
; 
 331     else // not in cache, create a new one 
 335         m_hDC 
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
)); 
 336         hPS 
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
) 
 342             ::GpiAssociate(hPS
, m_hDC
); 
 345             ::GpiCreateLogColorTable( m_hPS
 
 349                                      ,(LONG
)wxTheColourDatabase
->m_nSize
 
 350                                      ,(PLONG
)wxTheColourDatabase
->m_palTable
 
 352             ::GpiCreateLogColorTable( m_hPS
 
 360             ::WinFillRect(hPS
, &g_paintStruct
,  m_pCanvas
->GetBackgroundColour().GetPixel()); 
 361             ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
) 
 366         m_bIsPaintTime   
= true; 
 367         ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this)); 
 370 } // end of wxPaintDCImpl::wxPaintDCImpl 
 372 wxPaintDCImpl::~wxPaintDCImpl() 
 376         SelectOldObjects(m_hDC
); 
 379         wxPaintDCInfo
*              pInfo 
= FindInCache(&nIndex
); 
 381         wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") ); 
 383         if ( !--pInfo
->m_nCount 
) 
 385             ::WinEndPaint(m_hPS
); 
 387             m_bIsPaintTime 
= false; 
 388             ms_cache
.RemoveAt(nIndex
); 
 390         //else: cached DC entry is still in use 
 392         // prevent the base class dtor from ReleaseDC()ing it again 
 397 wxPaintDCInfo
* wxPaintDCImpl::FindInCache( 
 401     wxPaintDCInfo
*                  pInfo 
= NULL
; 
 402     size_t                          nCache 
= ms_cache
.GetCount(); 
 404     for (size_t n 
= 0; n 
< nCache
; n
++) 
 406         pInfo 
= &ms_cache
[n
]; 
 407         if (pInfo
->m_hWnd 
== m_pCanvas
->GetHWND()) 
 415 } // end of wxPaintDCImpl::FindInCache 
 417 // find the entry for this DC in the cache (keyed by the window) 
 418 WXHDC 
wxPaintDCImpl::FindDCInCache( 
 422     wxPaintDCInfo
*                  pInfo 
= NULL
; 
 423     size_t                          nCache 
= ms_cache
.GetCount(); 
 425     for (size_t n 
= 0; n 
< nCache
; n
++) 
 427         pInfo 
= &ms_cache
[n
]; 
 428         if (pInfo
->m_hWnd 
== pWin
->GetHWND()) 
 434 } // end of wxPaintDCImpl::FindInCache