Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: base/win/scoped_hdc.h

Issue 9212020: Make scoped dc objects smarter. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/base.gyp ('k') | base/win/scoped_hdc_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_WIN_SCOPED_HDC_H_ 5 #ifndef BASE_WIN_SCOPED_HDC_H_
6 #define BASE_WIN_SCOPED_HDC_H_ 6 #define BASE_WIN_SCOPED_HDC_H_
7 #pragma once 7 #pragma once
8 8
9 #include <windows.h> 9 #include <windows.h>
10 10
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 13
14 namespace base { 14 namespace base {
15 namespace win { 15 namespace win {
16 16
17 // Like ScopedHandle but for HDC. Only use this on HDCs returned from 17 // The ScopedGetDC and ScopedCreateDC classes manage the default GDI objects
18 // GetDC. 18 // that are initially selected into a DC. They help you avoid the following
19 class ScopedGetDC { 19 // common mistake:
20 public: 20 //
21 explicit ScopedGetDC(HWND hwnd) 21 // HDC hdc = GetDC(NULL);
22 : hwnd_(hwnd), 22 // SelectObject(hdc, new_obj);
23 hdc_(GetDC(hwnd)) { 23 // .. drawing code here ..
24 DCHECK(!hwnd_ || IsWindow(hwnd_)); 24 // ReleaseDC(hdc); <--- error: the DC has a custom object still selected!
25 DCHECK(hdc_); 25 //
26 } 26 // This code should be:
27 27 //
28 ~ScopedGetDC() { 28 // HDC hdc = GetDC(NULL);
29 if (hdc_) 29 // HGDIOBJ old_obj = SelectObject(hdc, new_obj);
30 ReleaseDC(hwnd_, hdc_); 30 // .. drawing code here ..
31 } 31 // SelectObject(hdc, old_obj);
32 32 // ReleaseDC(hdc); <--- ok to release now.
33 operator HDC() { return hdc_; } 33 //
34 34 // But why work so hard? use our handy classes:
Derek Bruening 2012/01/21 02:30:49 nit: "Use"
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Done.
35 private: 35 //
36 HWND hwnd_; 36 // ScopedGetDC dc(NULL);
37 HDC hdc_; 37 // dc.SelectObject(hdc, new_obj);
Derek Bruening 2012/01/21 02:30:49 a little misleading: there is no "SelectObject".
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Done.
38 38 // .. drawing here
Derek Bruening 2012/01/21 02:30:49 is there a nice way we can prevent someone from ac
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Let me look into that, I believe the cast to HDC i
Derek Bruening 2012/01/24 18:49:43 OK, waiting on that
39 DISALLOW_COPY_AND_ASSIGN(ScopedGetDC); 39 // .. when dc goes out of scope it will select the original object before
40 }; 40 // .. being released.
41 41 //
42 // Like ScopedHandle but for HDC. Only use this on HDCs returned from 42 template <typename Derived>
43 // CreateCompatibleDC, CreateDC and CreateIC. 43 class ScopedDC {
44 class ScopedCreateDC { 44 public:
Derek Bruening 2012/01/21 02:30:49 indentation
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Done.
45 public: 45 ~ScopedDC() {
46 ScopedCreateDC() : hdc_(NULL) { }
47 explicit ScopedCreateDC(HDC h) : hdc_(h) { }
48
49 ~ScopedCreateDC() {
50 Close(); 46 Close();
51 } 47 }
52 48
53 HDC Get() { 49 HDC Get() {
54 return hdc_; 50 return hdc_;
55 } 51 }
56 52
57 void Set(HDC h) { 53 operator HDC() {
58 Close(); 54 return hdc_;
59 hdc_ = h;
60 } 55 }
61 56
62 operator HDC() { return hdc_; } 57 void SelectBitmap(HBITMAP bitmap) {
Derek Bruening 2012/01/21 02:30:49 do callers never need to know return value of Sele
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Ideally the objects that are not the initial, will
58 Select(bitmap, &bitmap_);
59 }
60
61 void SelectFont(HFONT font) {
62 Select(font, &font_);
63 }
64
65 void SelectBrush(HBRUSH brush) {
66 Select(brush, &brush_);
67 }
68
69 void SelectPen(HPEN pen) {
70 Select(pen, &pen_);
71 }
72
73 void SelectRegion(HRGN region) {
74 Select(region, &region);
75 }
76
77 protected:
78 ScopedDC(HDC hdc)
79 : hdc_(hdc), bitmap_(0), font_(0), brush_(0), pen_(0), region_(0) {
80 }
81
82 void Close() {
83 if (!hdc_)
84 return;
85 ResetObjects();
86 static_cast<Derived*>(this)->DisposeDC(hdc_);
87 }
88
89 void Reset(HDC hdc) {
90 Close();
91 hdc_ = hdc;
92 }
63 93
64 private: 94 private:
65 void Close() { 95 void ResetObjects() {
66 #ifdef NOGDI 96 if (bitmap_) {
67 assert(false); 97 SelectObject(hdc_, bitmap_);
68 #else 98 bitmap_ = 0;
69 if (hdc_) 99 }
70 DeleteDC(hdc_); 100 if (font_) {
71 #endif // NOGDI 101 SelectObject(hdc_, font_);
102 font_ = 0;
103 }
104 if (brush_) {
105 SelectObject(hdc_, brush_);
106 brush_ = 0;
107 }
108 if (pen_) {
109 SelectObject(hdc_, pen_);
110 pen_ = 0;
111 }
112 if (region_) {
113 SelectObject(hdc_, region_);
114 region_ = 0;
115 }
116 }
117
118 void Select(HGDIOBJ object, HGDIOBJ* holder) {
119 HGDIOBJ old = SelectObject(hdc_, object);
120 DCHECK(old);
Derek Bruening 2012/01/21 02:30:49 DCHECK(holder)
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 I rather not, a null pointer is guaranteed crash i
121 if (!*holder)
Derek Bruening 2012/01/21 02:30:49 ok you're not returning the HGDIOBJ and are instea
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Done.
122 *holder = old;
72 } 123 }
73 124
74 HDC hdc_; 125 HDC hdc_;
126 HGDIOBJ bitmap_;
127 HGDIOBJ font_;
128 HGDIOBJ brush_;
129 HGDIOBJ pen_;
130 HGDIOBJ region_;
Derek Bruening 2012/01/21 02:30:49 prior_bitmap_ or old_bitmap_ or orig_bitmap_ are m
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 ugly. do you really really want me to change them?
131 };
132
133 // Creates and manages a HDC obtained by GetDC.
134 class ScopedGetDC : public ScopedDC<ScopedGetDC> {
Derek Bruening 2012/01/21 02:30:49 yeah IMHO simpler code via virtual is the way to g
cpu_(ooo_6.6-7.5) 2012/01/24 04:48:04 Ok, by popular demand changed the code to use vtab
135 public:
136 explicit ScopedGetDC(HWND hwnd)
137 : ScopedDC(GetDC(hwnd)), hwnd_(hwnd) {
138 }
139
140 private:
141 friend class ScopedDC<ScopedGetDC>;
142
143 void DisposeDC(HDC hdc) {
144 ReleaseDC(hwnd_, hdc);
145 }
146
147 HWND hwnd_;
148 DISALLOW_COPY_AND_ASSIGN(ScopedGetDC);
149 };
150
151 // Like ScopedHandle but for HDC. Only use this on HDCs returned from
152 // CreateCompatibleDC, CreateDC and CreateIC.
153 class ScopedCreateDC : public ScopedDC<ScopedCreateDC> {
154 public:
155 ScopedCreateDC()
156 : ScopedDC(0) {
157 }
158
159 explicit ScopedCreateDC(HDC hdc)
160 : ScopedDC(hdc) {
161 }
162
163 void Set(HDC hdc) {
164 Reset(hdc);
165 }
166
167 private:
168 friend class ScopedDC<ScopedCreateDC>;
169
170 void DisposeDC(HDC hdc) {
171 DeleteDC(hdc);
172 }
75 173
76 DISALLOW_COPY_AND_ASSIGN(ScopedCreateDC); 174 DISALLOW_COPY_AND_ASSIGN(ScopedCreateDC);
77 }; 175 };
78 176
79 } // namespace win 177 } // namespace win
80 } // namespace base 178 } // namespace base
81 179
82 #endif // BASE_WIN_SCOPED_HDC_H_ 180 #endif // BASE_WIN_SCOPED_HDC_H_
OLDNEW
« no previous file with comments | « base/base.gyp ('k') | base/win/scoped_hdc_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698