]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
basic support for encodings for wxMSW::wxFont
[wxWidgets.git] / src / os2 / dcclient.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dcclient.cpp
3// Purpose: wxClientDC class
23e4b7d8 4// Author: Julian Smart
0e320a79
DW
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
23e4b7d8
DW
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
23e4b7d8
DW
12// ===========================================================================
13// declarations
14// ===========================================================================
0e320a79 15
23e4b7d8
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0e320a79 19
23e4b7d8
DW
20#ifdef __GNUG__
21 #pragma implementation "dcclient.h"
22#endif
0e320a79 23
23e4b7d8
DW
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
0e320a79 26
23e4b7d8
DW
27#ifdef __BORLANDC__
28 #pragma hdrstop
0e320a79
DW
29#endif
30
23e4b7d8
DW
31#include "wx/string.h"
32#include "wx/log.h"
33#include "wx/window.h"
0e320a79 34
23e4b7d8 35#include "wx/msw/private.h"
0e320a79 36
23e4b7d8 37#include "wx/dcclient.h"
0e320a79 38
23e4b7d8
DW
39// ----------------------------------------------------------------------------
40// array/list types
41// ----------------------------------------------------------------------------
0e320a79 42
23e4b7d8 43struct WXDLLEXPORT wxPaintDCInfo
0e320a79 44{
23e4b7d8
DW
45 wxPaintDCInfo(wxWindow *win, wxDC *dc)
46 {
47 hwnd = win->GetHWND();
48 hdc = dc->GetHDC();
49 count = 1;
50 }
0e320a79 51
23e4b7d8
DW
52 WXHWND hwnd; // window for this DC
53 WXHDC hdc; // the DC handle
54 size_t count; // usage count
0e320a79
DW
55};
56
23e4b7d8 57#include "wx/arrimpl.cpp"
1408104d 58
23e4b7d8 59WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 60
23e4b7d8
DW
61// ----------------------------------------------------------------------------
62// macros
63// ----------------------------------------------------------------------------
0e320a79 64
23e4b7d8
DW
65#if !USE_SHARED_LIBRARY
66 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
67 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
68 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
69#endif
0e320a79 70
23e4b7d8
DW
71// ----------------------------------------------------------------------------
72// global variables
73// ----------------------------------------------------------------------------
1408104d 74
23e4b7d8 75static PAINTSTRUCT g_paintStruct;
1408104d 76
23e4b7d8
DW
77#ifdef __WXDEBUG__
78 // a global variable which we check to verify that wxPaintDC are only
79 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
80 // common programming error among wxWindows programmers and might lead to
81 // very subtle and difficult to debug refresh/repaint bugs.
82 int g_isPainting = 0;
83#endif // __WXDEBUG__
1408104d 84
23e4b7d8
DW
85// ===========================================================================
86// implementation
87// ===========================================================================
1408104d 88
23e4b7d8
DW
89// ----------------------------------------------------------------------------
90// wxWindowDC
91// ----------------------------------------------------------------------------
0e320a79 92
23e4b7d8 93wxWindowDC::wxWindowDC()
0e320a79 94{
23e4b7d8
DW
95 m_canvas = NULL;
96}
0e320a79 97
23e4b7d8 98wxWindowDC::wxWindowDC(wxWindow *the_canvas)
0e320a79 99{
23e4b7d8
DW
100 m_canvas = the_canvas;
101 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas) );
102 m_hDCCount++;
1408104d 103
23e4b7d8
DW
104 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
105}
0e320a79 106
23e4b7d8 107wxWindowDC::~wxWindowDC()
0e320a79 108{
23e4b7d8
DW
109 if (m_canvas && m_hDC)
110 {
111 SelectOldObjects(m_hDC);
1408104d 112
23e4b7d8
DW
113 //
114 // In PM one does not explicitly close or release an open WindowDC
115 // They automatically close with the window, unless explicitly detached
116 //
117 m_hDC = 0;
118 }
1408104d 119
23e4b7d8
DW
120 m_hDCCount--;
121}
0e320a79 122
23e4b7d8
DW
123// ----------------------------------------------------------------------------
124// wxClientDC
125// ----------------------------------------------------------------------------
0e320a79 126
23e4b7d8 127wxClientDC::wxClientDC()
0e320a79 128{
23e4b7d8
DW
129 m_canvas = NULL;
130}
0e320a79 131
23e4b7d8 132wxClientDC::wxClientDC(wxWindow *the_canvas)
0e320a79 133{
23e4b7d8
DW
134 m_canvas = the_canvas;
135 m_hDC = (WXHDC) ::GetDC(GetWinHwnd(the_canvas));
0e320a79 136
23e4b7d8
DW
137 // the background mode is only used for text background
138 // and is set in DrawText() to OPAQUE as required, other-
139 // wise always TRANSPARENT, RR
140 ::SetBkMode( GetHdc(), TRANSPARENT );
1408104d 141
23e4b7d8
DW
142 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
143}
0e320a79 144
23e4b7d8 145wxClientDC::~wxClientDC()
0e320a79 146{
23e4b7d8 147 if ( m_canvas && GetHdc() )
0e320a79 148 {
23e4b7d8 149 SelectOldObjects(m_hDC);
0e320a79 150
23e4b7d8
DW
151 ::ReleaseDC(GetWinHwnd(m_canvas), GetHdc());
152 m_hDC = 0;
0e320a79 153 }
23e4b7d8 154}
0e320a79 155
23e4b7d8
DW
156// ----------------------------------------------------------------------------
157// wxPaintDC
158// ----------------------------------------------------------------------------
159
160// VZ: initial implementation (by JACS) only remembered the last wxPaintDC
161// created and tried to reuse - this was supposed to take care of a
162// situation when a derived class OnPaint() calls base class OnPaint()
163// because in this case ::BeginPaint() shouldn't be called second time.
164//
165// I'm not sure how useful this is, however we must remember the HWND
166// associated with the last HDC as well - otherwise we may (and will!) try
167// to reuse the HDC for another HWND which is a nice recipe for disaster.
168//
169// So we store a list of windows for which we already have the DC and not
170// just one single hDC. This seems to work, but I'm really not sure about
171// the usefullness of the whole idea - IMHO it's much better to not call
172// base class OnPaint() at all, or, if we really want to allow it, add a
173// "wxPaintDC *" parameter to wxPaintEvent which should be used if it's
174// !NULL instead of creating a new DC.
175
176wxArrayDCInfo wxPaintDC::ms_cache;
177
178wxPaintDC::wxPaintDC()
179{
180 m_canvas = NULL;
181 m_hDC = 0;
182}
0e320a79 183
23e4b7d8 184wxPaintDC::wxPaintDC(wxWindow *canvas)
0e320a79 185{
23e4b7d8 186 wxCHECK_RET( canvas, _T("NULL canvas in wxPaintDC ctor") );
1408104d 187
23e4b7d8
DW
188#ifdef __WXDEBUG__
189 if ( g_isPainting <= 0 )
190 {
191 wxFAIL_MSG( _T("wxPaintDC may be created only in EVT_PAINT handler!") );
1408104d 192
23e4b7d8
DW
193 return;
194 }
195#endif // __WXDEBUG__
0e320a79 196
23e4b7d8 197 m_canvas = canvas;
1408104d 198
23e4b7d8
DW
199 // do we have a DC for this window in the cache?
200 wxPaintDCInfo *info = FindInCache();
201 if ( info )
0e320a79 202 {
23e4b7d8
DW
203 m_hDC = info->hdc;
204 info->count++;
205 }
206 else // not in cache, create a new one
207 {
208 m_hDC = (WXHDC)::BeginPaint(GetWinHwnd(m_canvas), &g_paintStruct);
209 ms_cache.Add(new wxPaintDCInfo(m_canvas, this));
0e320a79 210 }
0e320a79 211
23e4b7d8
DW
212 // the background mode is only used for text background
213 // and is set in DrawText() to OPAQUE as required, other-
214 // wise always TRANSPARENT, RR
215 ::SetBkMode( GetHdc(), TRANSPARENT );
0e320a79 216
23e4b7d8 217 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
0e320a79
DW
218}
219
23e4b7d8 220wxPaintDC::~wxPaintDC()
0e320a79 221{
23e4b7d8
DW
222 if ( m_hDC )
223 {
224 SelectOldObjects(m_hDC);
0e320a79 225
23e4b7d8
DW
226 size_t index;
227 wxPaintDCInfo *info = FindInCache(&index);
0e320a79 228
23e4b7d8 229 wxCHECK_RET( info, _T("existing DC should have a cache entry") );
0e320a79 230
23e4b7d8
DW
231 if ( !--info->count )
232 {
233 ::EndPaint(GetWinHwnd(m_canvas), &g_paintStruct);
0e320a79 234
23e4b7d8
DW
235 ms_cache.Remove(index);
236 }
237 //else: cached DC entry is still in use
0e320a79 238
23e4b7d8
DW
239 // prevent the base class dtor from ReleaseDC()ing it again
240 m_hDC = 0;
0e320a79
DW
241 }
242}
243
23e4b7d8 244wxPaintDCInfo *wxPaintDC::FindInCache(size_t *index) const
0e320a79 245{
23e4b7d8
DW
246 wxPaintDCInfo *info = NULL;
247 size_t nCache = ms_cache.GetCount();
248 for ( size_t n = 0; n < nCache; n++ )
0e320a79 249 {
23e4b7d8
DW
250 info = &ms_cache[n];
251 if ( info->hwnd == m_canvas->GetHWND() )
252 {
253 if ( index )
254 *index = n;
255 break;
256 }
0e320a79
DW
257 }
258
23e4b7d8
DW
259 return info;
260}