OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #include "views/controls/scrollbar/native_scroll_bar.h" | 5 #include "views/controls/scrollbar/native_scroll_bar.h" |
6 | 6 |
7 #include <atlbase.h> | 7 #include <algorithm> |
8 #include <atlapp.h> | |
9 #include <atlwin.h> | |
10 #include <atlcrack.h> | |
11 #include <atlframe.h> | |
12 #include <atlmisc.h> | |
13 #include <string> | 8 #include <string> |
14 | 9 |
15 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/window_impl.h" |
16 #include "views/controls/native/native_view_host.h" | 12 #include "views/controls/native/native_view_host.h" |
17 #include "views/widget/widget.h" | 13 #include "views/widget/widget.h" |
18 | 14 |
19 namespace views { | 15 namespace views { |
20 | 16 |
21 ///////////////////////////////////////////////////////////////////////////// | 17 ///////////////////////////////////////////////////////////////////////////// |
22 // | 18 // |
23 // ScrollBarContainer | 19 // ScrollBarContainer |
24 // | 20 // |
25 // Since windows scrollbar only send notifications to their parent hwnd, we | 21 // Since windows scrollbars only send notifications to their parent hwnd, we |
26 // use instance of this class to wrap native scrollbars. | 22 // use instances of this class to wrap native scrollbars. |
27 // | 23 // |
28 ///////////////////////////////////////////////////////////////////////////// | 24 ///////////////////////////////////////////////////////////////////////////// |
29 class ScrollBarContainer : public CWindowImpl<ScrollBarContainer, | 25 class ScrollBarContainer : public base::WindowImpl { |
30 CWindow, | |
31 CWinTraits<WS_CHILD>> { | |
32 public: | 26 public: |
33 ScrollBarContainer(ScrollBar* parent) : parent_(parent), | 27 explicit ScrollBarContainer(ScrollBar* parent) : parent_(parent), |
34 scrollbar_(NULL) { | 28 scrollbar_(NULL) { |
35 Create(parent->GetWidget()->GetNativeView()); | 29 set_window_style(WS_CHILD); |
36 ::ShowWindow(m_hWnd, SW_SHOW); | 30 Init(parent->GetWidget()->GetNativeView(), gfx::Rect()); |
| 31 ShowWindow(hwnd(), SW_SHOW); |
37 } | 32 } |
38 | 33 |
39 virtual ~ScrollBarContainer() { | 34 virtual ~ScrollBarContainer() { |
40 } | 35 } |
41 | 36 |
42 DECLARE_FRAME_WND_CLASS(L"ChromeViewsScrollBarContainer", NULL); | 37 BEGIN_MSG_MAP_EX(ScrollBarContainer); |
43 BEGIN_MSG_MAP(ScrollBarContainer); | |
44 MSG_WM_CREATE(OnCreate); | 38 MSG_WM_CREATE(OnCreate); |
45 MSG_WM_ERASEBKGND(OnEraseBkgnd); | 39 MSG_WM_ERASEBKGND(OnEraseBkgnd); |
46 MSG_WM_PAINT(OnPaint); | 40 MSG_WM_PAINT(OnPaint); |
47 MSG_WM_SIZE(OnSize); | 41 MSG_WM_SIZE(OnSize); |
48 MSG_WM_HSCROLL(OnHorizScroll); | 42 MSG_WM_HSCROLL(OnHorizScroll); |
49 MSG_WM_VSCROLL(OnVertScroll); | 43 MSG_WM_VSCROLL(OnVertScroll); |
50 END_MSG_MAP(); | 44 END_MSG_MAP(); |
51 | 45 |
52 HWND GetScrollBarHWND() { | 46 HWND GetScrollBarHWND() { |
53 return scrollbar_; | 47 return scrollbar_; |
54 } | 48 } |
55 | 49 |
56 // Invoked when the scrollwheel is used | 50 // Invoked when the scrollwheel is used |
57 void ScrollWithOffset(int o) { | 51 void ScrollWithOffset(int o) { |
58 SCROLLINFO si; | 52 SCROLLINFO si; |
59 si.cbSize = sizeof(si); | 53 si.cbSize = sizeof(si); |
60 si.fMask = SIF_POS; | 54 si.fMask = SIF_POS; |
61 ::GetScrollInfo(scrollbar_, SB_CTL, &si); | 55 GetScrollInfo(scrollbar_, SB_CTL, &si); |
62 int pos = si.nPos - o; | 56 int pos = si.nPos - o; |
63 | 57 |
64 if (pos < parent_->GetMinPosition()) | 58 if (pos < parent_->GetMinPosition()) |
65 pos = parent_->GetMinPosition(); | 59 pos = parent_->GetMinPosition(); |
66 else if (pos > parent_->GetMaxPosition()) | 60 else if (pos > parent_->GetMaxPosition()) |
67 pos = parent_->GetMaxPosition(); | 61 pos = parent_->GetMaxPosition(); |
68 | 62 |
69 ScrollBarController* sbc = parent_->GetController(); | 63 ScrollBarController* sbc = parent_->GetController(); |
70 sbc->ScrollToPosition(parent_, pos); | 64 sbc->ScrollToPosition(parent_, pos); |
71 | 65 |
72 si.nPos = pos; | 66 si.nPos = pos; |
73 si.fMask = SIF_POS; | 67 si.fMask = SIF_POS; |
74 ::SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE); | 68 SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE); |
75 } | 69 } |
76 | 70 |
77 private: | 71 private: |
78 | 72 |
79 LRESULT OnCreate(LPCREATESTRUCT create_struct) { | 73 LRESULT OnCreate(LPCREATESTRUCT create_struct) { |
80 scrollbar_ = CreateWindow(L"SCROLLBAR", | 74 scrollbar_ = CreateWindow(L"SCROLLBAR", L"", |
81 L"", | |
82 WS_CHILD | (parent_->IsHorizontal() ? | 75 WS_CHILD | (parent_->IsHorizontal() ? |
83 SBS_HORZ : SBS_VERT), | 76 SBS_HORZ : SBS_VERT), |
84 0, | 77 0, 0, parent_->width(), parent_->height(), |
85 0, | 78 hwnd(), NULL, NULL, NULL); |
86 parent_->width(), | 79 ShowWindow(scrollbar_, SW_SHOW); |
87 parent_->height(), | |
88 m_hWnd, | |
89 NULL, | |
90 NULL, | |
91 NULL); | |
92 ::ShowWindow(scrollbar_, SW_SHOW); | |
93 return 1; | 80 return 1; |
94 } | 81 } |
95 | 82 |
96 LRESULT OnEraseBkgnd(HDC dc) { | 83 LRESULT OnEraseBkgnd(HDC dc) { |
97 return 1; | 84 return 1; |
98 } | 85 } |
99 | 86 |
100 void OnPaint(HDC ignore) { | 87 void OnPaint(HDC ignore) { |
101 PAINTSTRUCT ps; | 88 PAINTSTRUCT ps; |
102 HDC dc = ::BeginPaint(*this, &ps); | 89 HDC dc = BeginPaint(hwnd(), &ps); |
103 ::EndPaint(*this, &ps); | 90 EndPaint(hwnd(), &ps); |
104 } | 91 } |
105 | 92 |
106 void OnSize(int type, const CSize& sz) { | 93 void OnSize(int type, const CSize& sz) { |
107 ::SetWindowPos(scrollbar_, | 94 SetWindowPos(scrollbar_, |
108 0, | 95 0, 0, 0, sz.cx, sz.cy, |
109 0, | 96 SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS | |
110 0, | 97 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER); |
111 sz.cx, | |
112 sz.cy, | |
113 SWP_DEFERERASE | | |
114 SWP_NOACTIVATE | | |
115 SWP_NOCOPYBITS | | |
116 SWP_NOOWNERZORDER | | |
117 SWP_NOSENDCHANGING | | |
118 SWP_NOZORDER); | |
119 } | 98 } |
120 | 99 |
121 void OnScroll(int code, HWND source, bool is_horizontal) { | 100 void OnScroll(int code, HWND source, bool is_horizontal) { |
122 int pos; | 101 int pos; |
123 | 102 |
124 if (code == SB_ENDSCROLL) { | 103 if (code == SB_ENDSCROLL) { |
125 return; | 104 return; |
126 } | 105 } |
127 | 106 |
128 // If we receive an event from the scrollbar, make the view | 107 // If we receive an event from the scrollbar, make the view |
129 // component focused so we actually get mousewheel events. | 108 // component focused so we actually get mousewheel events. |
130 if (source != NULL) { | 109 if (source != NULL) { |
131 Widget* widget = parent_->GetWidget(); | 110 Widget* widget = parent_->GetWidget(); |
132 if (widget && widget->GetNativeView() != GetFocus()) { | 111 if (widget && widget->GetNativeView() != GetFocus()) { |
133 parent_->RequestFocus(); | 112 parent_->RequestFocus(); |
134 } | 113 } |
135 } | 114 } |
136 | 115 |
137 SCROLLINFO si; | 116 SCROLLINFO si; |
138 si.cbSize = sizeof(si); | 117 si.cbSize = sizeof(si); |
139 si.fMask = SIF_POS | SIF_TRACKPOS; | 118 si.fMask = SIF_POS | SIF_TRACKPOS; |
140 ::GetScrollInfo(scrollbar_, SB_CTL, &si); | 119 GetScrollInfo(scrollbar_, SB_CTL, &si); |
141 pos = si.nPos; | 120 pos = si.nPos; |
142 | 121 |
143 ScrollBarController* sbc = parent_->GetController(); | 122 ScrollBarController* sbc = parent_->GetController(); |
144 | 123 |
145 switch (code) { | 124 switch (code) { |
146 case SB_BOTTOM: // case SB_RIGHT: | 125 case SB_BOTTOM: // case SB_RIGHT: |
147 pos = parent_->GetMaxPosition(); | 126 pos = parent_->GetMaxPosition(); |
148 break; | 127 break; |
149 case SB_TOP: // case SB_LEFT: | 128 case SB_TOP: // case SB_LEFT: |
150 pos = parent_->GetMinPosition(); | 129 pos = parent_->GetMinPosition(); |
151 break; | 130 break; |
152 case SB_LINEDOWN: // case SB_LINERIGHT: | 131 case SB_LINEDOWN: // case SB_LINERIGHT: |
153 pos += sbc->GetScrollIncrement(parent_, false, true); | 132 pos += sbc->GetScrollIncrement(parent_, false, true); |
154 pos = std::min(parent_->GetMaxPosition(), pos); | 133 pos = std::min(parent_->GetMaxPosition(), pos); |
155 break; | 134 break; |
156 case SB_LINEUP: // case SB_LINELEFT: | 135 case SB_LINEUP: // case SB_LINELEFT: |
(...skipping 17 matching lines...) Expand all Loading... |
174 pos = parent_->GetMaxPosition(); | 153 pos = parent_->GetMaxPosition(); |
175 break; | 154 break; |
176 default: | 155 default: |
177 break; | 156 break; |
178 } | 157 } |
179 | 158 |
180 sbc->ScrollToPosition(parent_, pos); | 159 sbc->ScrollToPosition(parent_, pos); |
181 | 160 |
182 si.nPos = pos; | 161 si.nPos = pos; |
183 si.fMask = SIF_POS; | 162 si.fMask = SIF_POS; |
184 ::SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE); | 163 SetScrollInfo(scrollbar_, SB_CTL, &si, TRUE); |
185 | 164 |
186 // Note: the system scrollbar modal loop doesn't give a chance | 165 // Note: the system scrollbar modal loop doesn't give a chance |
187 // to our message_loop so we need to call DidProcessMessage() | 166 // to our message_loop so we need to call DidProcessMessage() |
188 // manually. | 167 // manually. |
189 // | 168 // |
190 // Sadly, we don't know what message has been processed. We may | 169 // Sadly, we don't know what message has been processed. We may |
191 // want to remove the message from DidProcessMessage() | 170 // want to remove the message from DidProcessMessage() |
192 MSG dummy; | 171 MSG dummy; |
193 dummy.hwnd = NULL; | 172 dummy.hwnd = NULL; |
194 dummy.message = 0; | 173 dummy.message = 0; |
(...skipping 20 matching lines...) Expand all Loading... |
215 : sb_view_(NULL), | 194 : sb_view_(NULL), |
216 sb_container_(NULL), | 195 sb_container_(NULL), |
217 ScrollBar(is_horiz) { | 196 ScrollBar(is_horiz) { |
218 } | 197 } |
219 | 198 |
220 NativeScrollBar::~NativeScrollBar() { | 199 NativeScrollBar::~NativeScrollBar() { |
221 if (sb_container_) { | 200 if (sb_container_) { |
222 // We always destroy the scrollbar container explicitly to cover all | 201 // We always destroy the scrollbar container explicitly to cover all |
223 // cases including when the container is no longer connected to a | 202 // cases including when the container is no longer connected to a |
224 // widget tree. | 203 // widget tree. |
225 ::DestroyWindow(*sb_container_); | 204 DestroyWindow(sb_container_->hwnd()); |
226 delete sb_container_; | 205 delete sb_container_; |
227 } | 206 } |
228 } | 207 } |
229 | 208 |
230 void NativeScrollBar::ViewHierarchyChanged(bool is_add, View *parent, | 209 void NativeScrollBar::ViewHierarchyChanged(bool is_add, View *parent, |
231 View *child) { | 210 View *child) { |
232 Widget* widget; | 211 Widget* widget; |
233 if (is_add && (widget = GetWidget()) && !sb_view_) { | 212 if (is_add && (widget = GetWidget()) && !sb_view_) { |
234 sb_view_ = new NativeViewHost; | 213 sb_view_ = new NativeViewHost; |
235 AddChildView(sb_view_); | 214 AddChildView(sb_view_); |
236 sb_container_ = new ScrollBarContainer(this); | 215 sb_container_ = new ScrollBarContainer(this); |
237 sb_view_->Attach(*sb_container_); | 216 sb_view_->Attach(sb_container_->hwnd()); |
238 Layout(); | 217 Layout(); |
239 } | 218 } |
240 } | 219 } |
241 | 220 |
242 void NativeScrollBar::Layout() { | 221 void NativeScrollBar::Layout() { |
243 if (sb_view_) | 222 if (sb_view_) |
244 sb_view_->SetBounds(GetLocalBounds(true)); | 223 sb_view_->SetBounds(GetLocalBounds(true)); |
245 } | 224 } |
246 | 225 |
247 gfx::Size NativeScrollBar::GetPreferredSize() { | 226 gfx::Size NativeScrollBar::GetPreferredSize() { |
(...skipping 18 matching lines...) Expand all Loading... |
266 if (current_pos > content_size) | 245 if (current_pos > content_size) |
267 current_pos = content_size; | 246 current_pos = content_size; |
268 | 247 |
269 SCROLLINFO si; | 248 SCROLLINFO si; |
270 si.cbSize = sizeof(si); | 249 si.cbSize = sizeof(si); |
271 si.fMask = SIF_DISABLENOSCROLL | SIF_POS | SIF_RANGE | SIF_PAGE; | 250 si.fMask = SIF_DISABLENOSCROLL | SIF_POS | SIF_RANGE | SIF_PAGE; |
272 si.nMin = 0; | 251 si.nMin = 0; |
273 si.nMax = content_size; | 252 si.nMax = content_size; |
274 si.nPos = current_pos; | 253 si.nPos = current_pos; |
275 si.nPage = viewport_size; | 254 si.nPage = viewport_size; |
276 ::SetScrollInfo(sb_container_->GetScrollBarHWND(), | 255 SetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si, TRUE); |
277 SB_CTL, | |
278 &si, | |
279 TRUE); | |
280 } | 256 } |
281 | 257 |
282 int NativeScrollBar::GetLayoutSize() const { | 258 int NativeScrollBar::GetLayoutSize() const { |
283 return ::GetSystemMetrics(IsHorizontal() ? SM_CYHSCROLL : SM_CYVSCROLL); | 259 return GetSystemMetrics(IsHorizontal() ? SM_CYHSCROLL : SM_CYVSCROLL); |
284 } | 260 } |
285 | 261 |
286 int NativeScrollBar::GetPosition() const { | 262 int NativeScrollBar::GetPosition() const { |
287 SCROLLINFO si; | 263 SCROLLINFO si; |
288 si.cbSize = sizeof(si); | 264 si.cbSize = sizeof(si); |
289 si.fMask = SIF_POS; | 265 si.fMask = SIF_POS; |
290 GetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si); | 266 GetScrollInfo(sb_container_->GetScrollBarHWND(), SB_CTL, &si); |
291 return si.nPos; | 267 return si.nPos; |
292 } | 268 } |
293 | 269 |
294 bool NativeScrollBar::OnMouseWheel(const MouseWheelEvent& e) { | 270 bool NativeScrollBar::OnMouseWheel(const MouseWheelEvent& e) { |
295 if (!sb_container_) { | 271 if (!sb_container_) { |
296 return false; | 272 return false; |
297 } | 273 } |
298 | 274 |
299 sb_container_->ScrollWithOffset(e.GetOffset()); | 275 sb_container_->ScrollWithOffset(e.GetOffset()); |
300 return true; | 276 return true; |
301 } | 277 } |
302 | 278 |
303 bool NativeScrollBar::OnKeyPressed(const KeyEvent& event) { | 279 bool NativeScrollBar::OnKeyPressed(const KeyEvent& event) { |
304 if (!sb_container_) { | 280 if (!sb_container_) { |
305 return false; | 281 return false; |
306 } | 282 } |
307 int code = -1; | 283 int code = -1; |
308 switch(event.GetCharacter()) { | 284 switch (event.GetCharacter()) { |
309 case VK_UP: | 285 case VK_UP: |
310 if (!IsHorizontal()) | 286 if (!IsHorizontal()) |
311 code = SB_LINEUP; | 287 code = SB_LINEUP; |
312 break; | 288 break; |
313 case VK_PRIOR: | 289 case VK_PRIOR: |
314 code = SB_PAGEUP; | 290 code = SB_PAGEUP; |
315 break; | 291 break; |
316 case VK_NEXT: | 292 case VK_NEXT: |
317 code = SB_PAGEDOWN; | 293 code = SB_PAGEDOWN; |
318 break; | 294 break; |
(...skipping 10 matching lines...) Expand all Loading... |
329 case VK_LEFT: | 305 case VK_LEFT: |
330 if (IsHorizontal()) | 306 if (IsHorizontal()) |
331 code = SB_LINELEFT; | 307 code = SB_LINELEFT; |
332 break; | 308 break; |
333 case VK_RIGHT: | 309 case VK_RIGHT: |
334 if (IsHorizontal()) | 310 if (IsHorizontal()) |
335 code = SB_LINERIGHT; | 311 code = SB_LINERIGHT; |
336 break; | 312 break; |
337 } | 313 } |
338 if (code != -1) { | 314 if (code != -1) { |
339 ::SendMessage(*sb_container_, | 315 SendMessage(sb_container_->hwnd(), |
340 IsHorizontal() ? WM_HSCROLL : WM_VSCROLL, | 316 IsHorizontal() ? WM_HSCROLL : WM_VSCROLL, |
341 MAKELONG(static_cast<WORD>(code), 0), 0L); | 317 MAKELONG(static_cast<WORD>(code), 0), 0L); |
342 return true; | 318 return true; |
343 } | 319 } |
344 return false; | 320 return false; |
345 } | 321 } |
346 | 322 |
347 //static | 323 // static |
348 int NativeScrollBar::GetHorizontalScrollBarHeight() { | 324 int NativeScrollBar::GetHorizontalScrollBarHeight() { |
349 return ::GetSystemMetrics(SM_CYHSCROLL); | 325 return GetSystemMetrics(SM_CYHSCROLL); |
350 } | 326 } |
351 | 327 |
352 //static | 328 // static |
353 int NativeScrollBar::GetVerticalScrollBarWidth() { | 329 int NativeScrollBar::GetVerticalScrollBarWidth() { |
354 return ::GetSystemMetrics(SM_CXVSCROLL); | 330 return GetSystemMetrics(SM_CXVSCROLL); |
355 } | 331 } |
356 | 332 |
357 } // namespace views | 333 } // namespace views |
OLD | NEW |