| 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 |