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

Side by Side Diff: ui/gfx/native_theme_win.cc

Issue 8139022: Rename ScopedHDC to ScopedCreateDC (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update a comment of ScopedCreateDC Created 9 years, 2 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
« base/win/scoped_hdc.h ('K') | « printing/emf_win_unittest.cc ('k') | no next file » | 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) 2011 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 "ui/gfx/native_theme_win.h" 5 #include "ui/gfx/native_theme_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <uxtheme.h> 8 #include <uxtheme.h>
9 #include <vsstyle.h> 9 #include <vsstyle.h>
10 #include <vssym32.h> 10 #include <vssym32.h>
11 11
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_handle.h" 13 #include "base/memory/scoped_handle.h"
14 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "base/win/scoped_gdi_object.h" 15 #include "base/win/scoped_gdi_object.h"
16 #include "base/win/scoped_hdc.h" 16 #include "base/win/scoped_hdc.h"
17 #include "base/win/scoped_select_object.h"
17 #include "base/win/windows_version.h" 18 #include "base/win/windows_version.h"
18 #include "skia/ext/platform_canvas.h" 19 #include "skia/ext/platform_canvas.h"
19 #include "skia/ext/skia_utils_win.h" 20 #include "skia/ext/skia_utils_win.h"
20 #include "third_party/skia/include/core/SkCanvas.h" 21 #include "third_party/skia/include/core/SkCanvas.h"
21 #include "third_party/skia/include/core/SkColorPriv.h" 22 #include "third_party/skia/include/core/SkColorPriv.h"
22 #include "third_party/skia/include/core/SkShader.h" 23 #include "third_party/skia/include/core/SkShader.h"
23 #include "ui/gfx/gdi_util.h" 24 #include "ui/gfx/gdi_util.h"
24 #include "ui/gfx/rect.h" 25 #include "ui/gfx/rect.h"
25 26
26 namespace { 27 namespace {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 get_theme_int_ = reinterpret_cast<GetThemeIntPtr>( 104 get_theme_int_ = reinterpret_cast<GetThemeIntPtr>(
104 GetProcAddress(theme_dll_, "GetThemeInt")); 105 GetProcAddress(theme_dll_, "GetThemeInt"));
105 } 106 }
106 memset(theme_handles_, 0, sizeof(theme_handles_)); 107 memset(theme_handles_, 0, sizeof(theme_handles_));
107 } 108 }
108 109
109 NativeThemeWin::~NativeThemeWin() { 110 NativeThemeWin::~NativeThemeWin() {
110 if (theme_dll_) { 111 if (theme_dll_) {
111 // todo (cpu): fix this soon. Making a call to CloseHandles() here breaks 112 // todo (cpu): fix this soon. Making a call to CloseHandles() here breaks
112 // certain tests and the reliability bots. 113 // certain tests and the reliability bots.
113 //CloseHandles(); 114 // CloseHandles();
114 FreeLibrary(theme_dll_); 115 FreeLibrary(theme_dll_);
115 } 116 }
116 } 117 }
117 118
118 gfx::Size NativeThemeWin::GetPartSize(Part part, 119 gfx::Size NativeThemeWin::GetPartSize(Part part,
119 State state, 120 State state,
120 const ExtraParams& extra) const { 121 const ExtraParams& extra) const {
121 SIZE size; 122 SIZE size;
122 int part_id = GetWindowsPart(part, state, extra); 123 int part_id = GetWindowsPart(part, state, extra);
123 int state_id = GetWindowsState(part, state, extra); 124 int state_id = GetWindowsState(part, state, extra);
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 RECT rect_win = rect.ToRECT(); 331 RECT rect_win = rect.ToRECT();
331 if (handle && draw_theme_) { 332 if (handle && draw_theme_) {
332 int index = part - kScrollbarDownArrow; 333 int index = part - kScrollbarDownArrow;
333 DCHECK(index >=0 && index < 4); 334 DCHECK(index >=0 && index < 4);
334 int state_id = state_id_matrix[index][state]; 335 int state_id = state_id_matrix[index][state];
335 336
336 // Hovering means that the cursor is over the scroolbar, but not over the 337 // Hovering means that the cursor is over the scroolbar, but not over the
337 // specific arrow itself. We don't want to show it "hot" mode, but only 338 // specific arrow itself. We don't want to show it "hot" mode, but only
338 // in "hover" mode. 339 // in "hover" mode.
339 if (state == kHovered && extra.is_hovering) { 340 if (state == kHovered && extra.is_hovering) {
340 switch(part) { 341 switch (part) {
341 case kScrollbarDownArrow: 342 case kScrollbarDownArrow:
342 state_id = ABS_DOWNHOVER; 343 state_id = ABS_DOWNHOVER;
343 break; 344 break;
344 case kScrollbarLeftArrow: 345 case kScrollbarLeftArrow:
345 state_id = ABS_LEFTHOVER; 346 state_id = ABS_LEFTHOVER;
346 break; 347 break;
347 case kScrollbarRightArrow: 348 case kScrollbarRightArrow:
348 state_id = ABS_RIGHTHOVER; 349 state_id = ABS_RIGHTHOVER;
349 break; 350 break;
350 case kScrollbarUpArrow: 351 case kScrollbarUpArrow:
351 state_id = ABS_UPHOVER; 352 state_id = ABS_UPHOVER;
352 break; 353 break;
353 default: 354 default:
354 NOTREACHED() << "Invalid part: " << part; 355 NOTREACHED() << "Invalid part: " << part;
355 break; 356 break;
356 } 357 }
357 } 358 }
358 359
359 return draw_theme_(handle, hdc, SBP_ARROWBTN, state_id, &rect_win, NULL); 360 return draw_theme_(handle, hdc, SBP_ARROWBTN, state_id, &rect_win, NULL);
360 } 361 }
361 362
362 int classic_state = DFCS_SCROLLDOWN; 363 int classic_state = DFCS_SCROLLDOWN;
363 switch(part) { 364 switch (part) {
364 case kScrollbarDownArrow: 365 case kScrollbarDownArrow:
365 classic_state = DFCS_SCROLLDOWN; 366 classic_state = DFCS_SCROLLDOWN;
366 break; 367 break;
367 case kScrollbarLeftArrow: 368 case kScrollbarLeftArrow:
368 classic_state = DFCS_SCROLLLEFT; 369 classic_state = DFCS_SCROLLLEFT;
369 break; 370 break;
370 case kScrollbarRightArrow: 371 case kScrollbarRightArrow:
371 classic_state = DFCS_SCROLLRIGHT; 372 classic_state = DFCS_SCROLLRIGHT;
372 break; 373 break;
373 case kScrollbarUpArrow: 374 case kScrollbarUpArrow:
374 classic_state = DFCS_SCROLLUP; 375 classic_state = DFCS_SCROLLUP;
375 break; 376 break;
376 default: 377 default:
377 NOTREACHED() << "Invalid part: " << part; 378 NOTREACHED() << "Invalid part: " << part;
378 break; 379 break;
379 } 380 }
380 switch(state) { 381 switch (state) {
381 case kDisabled: 382 case kDisabled:
382 classic_state |= DFCS_INACTIVE; 383 classic_state |= DFCS_INACTIVE;
383 break; 384 break;
384 case kHovered: 385 case kHovered:
385 classic_state |= DFCS_HOT; 386 classic_state |= DFCS_HOT;
386 break; 387 break;
387 case kNormal: 388 case kNormal:
388 break; 389 break;
389 case kPressed: 390 case kPressed:
390 classic_state |= DFCS_PUSHED; 391 classic_state |= DFCS_PUSHED;
(...skipping 11 matching lines...) Expand all
402 HDC hdc, 403 HDC hdc,
403 Part part, 404 Part part,
404 State state, 405 State state,
405 const gfx::Rect& rect, 406 const gfx::Rect& rect,
406 const ScrollbarTrackExtraParams& extra) const { 407 const ScrollbarTrackExtraParams& extra) const {
407 HANDLE handle = GetThemeHandle(SCROLLBAR); 408 HANDLE handle = GetThemeHandle(SCROLLBAR);
408 RECT rect_win = rect.ToRECT(); 409 RECT rect_win = rect.ToRECT();
409 int part_id; 410 int part_id;
410 int state_id; 411 int state_id;
411 412
412 switch(part) { 413 switch (part) {
413 case gfx::NativeTheme::kScrollbarHorizontalTrack: 414 case gfx::NativeTheme::kScrollbarHorizontalTrack:
414 part_id = extra.is_upper ? SBP_UPPERTRACKHORZ : SBP_LOWERTRACKHORZ; 415 part_id = extra.is_upper ? SBP_UPPERTRACKHORZ : SBP_LOWERTRACKHORZ;
415 break; 416 break;
416 case gfx::NativeTheme::kScrollbarVerticalTrack: 417 case gfx::NativeTheme::kScrollbarVerticalTrack:
417 part_id = extra.is_upper ? SBP_UPPERTRACKVERT : SBP_LOWERTRACKVERT; 418 part_id = extra.is_upper ? SBP_UPPERTRACKVERT : SBP_LOWERTRACKVERT;
418 break; 419 break;
419 default: 420 default:
420 NOTREACHED() << "Invalid part: " << part; 421 NOTREACHED() << "Invalid part: " << part;
421 break; 422 break;
422 } 423 }
423 424
424 switch(state) { 425 switch (state) {
425 case kDisabled: 426 case kDisabled:
426 state_id = SCRBS_DISABLED; 427 state_id = SCRBS_DISABLED;
427 break; 428 break;
428 case kHovered: 429 case kHovered:
429 state_id = SCRBS_HOVER; 430 state_id = SCRBS_HOVER;
430 break; 431 break;
431 case kNormal: 432 case kNormal:
432 state_id = SCRBS_NORMAL; 433 state_id = SCRBS_NORMAL;
433 break; 434 break;
434 case kPressed: 435 case kPressed:
(...skipping 29 matching lines...) Expand all
464 HDC hdc, 465 HDC hdc,
465 Part part, 466 Part part,
466 State state, 467 State state,
467 const gfx::Rect& rect, 468 const gfx::Rect& rect,
468 const ScrollbarThumbExtraParams& extra) const { 469 const ScrollbarThumbExtraParams& extra) const {
469 HANDLE handle = GetThemeHandle(SCROLLBAR); 470 HANDLE handle = GetThemeHandle(SCROLLBAR);
470 RECT rect_win = rect.ToRECT(); 471 RECT rect_win = rect.ToRECT();
471 int part_id; 472 int part_id;
472 int state_id; 473 int state_id;
473 474
474 switch(part) { 475 switch (part) {
475 case gfx::NativeTheme::kScrollbarHorizontalThumb: 476 case gfx::NativeTheme::kScrollbarHorizontalThumb:
476 part_id = SBP_THUMBBTNHORZ; 477 part_id = SBP_THUMBBTNHORZ;
477 break; 478 break;
478 case gfx::NativeTheme::kScrollbarVerticalThumb: 479 case gfx::NativeTheme::kScrollbarVerticalThumb:
479 part_id = SBP_THUMBBTNVERT; 480 part_id = SBP_THUMBBTNVERT;
480 break; 481 break;
481 case gfx::NativeTheme::kScrollbarHorizontalGripper: 482 case gfx::NativeTheme::kScrollbarHorizontalGripper:
482 part_id = SBP_GRIPPERHORZ; 483 part_id = SBP_GRIPPERHORZ;
483 break; 484 break;
484 case gfx::NativeTheme::kScrollbarVerticalGripper: 485 case gfx::NativeTheme::kScrollbarVerticalGripper:
485 part_id = SBP_GRIPPERVERT; 486 part_id = SBP_GRIPPERVERT;
486 break; 487 break;
487 default: 488 default:
488 NOTREACHED() << "Invalid part: " << part; 489 NOTREACHED() << "Invalid part: " << part;
489 break; 490 break;
490 } 491 }
491 492
492 switch(state) { 493 switch (state) {
493 case kDisabled: 494 case kDisabled:
494 state_id = SCRBS_DISABLED; 495 state_id = SCRBS_DISABLED;
495 break; 496 break;
496 case kHovered: 497 case kHovered:
497 state_id = extra.is_hovering ? SCRBS_HOVER : SCRBS_HOT; 498 state_id = extra.is_hovering ? SCRBS_HOVER : SCRBS_HOT;
498 break; 499 break;
499 case kNormal: 500 case kNormal:
500 state_id = SCRBS_NORMAL; 501 state_id = SCRBS_NORMAL;
501 break; 502 break;
502 case kPressed: 503 case kPressed:
(...skipping 13 matching lines...) Expand all
516 // Classic mode doesn't have a gripper. 517 // Classic mode doesn't have a gripper.
517 return S_OK; 518 return S_OK;
518 } 519 }
519 520
520 HRESULT NativeThemeWin::PaintPushButton(HDC hdc, 521 HRESULT NativeThemeWin::PaintPushButton(HDC hdc,
521 Part part, 522 Part part,
522 State state, 523 State state,
523 const gfx::Rect& rect, 524 const gfx::Rect& rect,
524 const ButtonExtraParams& extra) const { 525 const ButtonExtraParams& extra) const {
525 int state_id; 526 int state_id;
526 switch(state) { 527 switch (state) {
527 case kDisabled: 528 case kDisabled:
528 state_id = PBS_DISABLED; 529 state_id = PBS_DISABLED;
529 break; 530 break;
530 case kHovered: 531 case kHovered:
531 state_id = PBS_HOT; 532 state_id = PBS_HOT;
532 break; 533 break;
533 case kNormal: 534 case kNormal:
534 state_id = extra.is_default ? PBS_DEFAULTED : PBS_NORMAL; 535 state_id = extra.is_default ? PBS_DEFAULTED : PBS_NORMAL;
535 break; 536 break;
536 case kPressed: 537 case kPressed:
537 state_id = PBS_PRESSED; 538 state_id = PBS_PRESSED;
538 break; 539 break;
539 default: 540 default:
540 NOTREACHED() << "Invalid state: " << state; 541 NOTREACHED() << "Invalid state: " << state;
541 break; 542 break;
542 } 543 }
543 544
544 RECT rect_win = rect.ToRECT(); 545 RECT rect_win = rect.ToRECT();
545 return PaintButton(hdc, state, extra, BP_PUSHBUTTON, state_id, &rect_win); 546 return PaintButton(hdc, state, extra, BP_PUSHBUTTON, state_id, &rect_win);
546 } 547 }
547 548
548 HRESULT NativeThemeWin::PaintRadioButton(HDC hdc, 549 HRESULT NativeThemeWin::PaintRadioButton(HDC hdc,
549 Part part, 550 Part part,
550 State state, 551 State state,
551 const gfx::Rect& rect, 552 const gfx::Rect& rect,
552 const ButtonExtraParams& extra) const { 553 const ButtonExtraParams& extra) const {
553 int state_id; 554 int state_id;
554 switch(state) { 555 switch (state) {
555 case kDisabled: 556 case kDisabled:
556 state_id = extra.checked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED; 557 state_id = extra.checked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
557 break; 558 break;
558 case kHovered: 559 case kHovered:
559 state_id = extra.checked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT; 560 state_id = extra.checked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
560 break; 561 break;
561 case kNormal: 562 case kNormal:
562 state_id = extra.checked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL; 563 state_id = extra.checked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
563 break; 564 break;
564 case kPressed: 565 case kPressed:
565 state_id = extra.checked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED; 566 state_id = extra.checked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
566 break; 567 break;
567 default: 568 default:
568 NOTREACHED() << "Invalid state: " << state; 569 NOTREACHED() << "Invalid state: " << state;
569 break; 570 break;
570 } 571 }
571 572
572 RECT rect_win = rect.ToRECT(); 573 RECT rect_win = rect.ToRECT();
573 return PaintButton(hdc, state, extra, BP_RADIOBUTTON, state_id, &rect_win); 574 return PaintButton(hdc, state, extra, BP_RADIOBUTTON, state_id, &rect_win);
574 } 575 }
575 576
576 HRESULT NativeThemeWin::PaintCheckbox(HDC hdc, 577 HRESULT NativeThemeWin::PaintCheckbox(HDC hdc,
577 Part part, 578 Part part,
578 State state, 579 State state,
579 const gfx::Rect& rect, 580 const gfx::Rect& rect,
580 const ButtonExtraParams& extra) const { 581 const ButtonExtraParams& extra) const {
581 int state_id; 582 int state_id;
582 switch(state) { 583 switch (state) {
583 case kDisabled: 584 case kDisabled:
584 state_id = extra.checked ? CBS_CHECKEDDISABLED : 585 state_id = extra.checked ? CBS_CHECKEDDISABLED :
585 extra.indeterminate ? CBS_MIXEDDISABLED : 586 extra.indeterminate ? CBS_MIXEDDISABLED :
586 CBS_UNCHECKEDDISABLED; 587 CBS_UNCHECKEDDISABLED;
587 break; 588 break;
588 case kHovered: 589 case kHovered:
589 state_id = extra.checked ? CBS_CHECKEDHOT : 590 state_id = extra.checked ? CBS_CHECKEDHOT :
590 extra.indeterminate ? CBS_MIXEDHOT : 591 extra.indeterminate ? CBS_MIXEDHOT :
591 CBS_UNCHECKEDHOT; 592 CBS_UNCHECKEDHOT;
592 break; 593 break;
(...skipping 21 matching lines...) Expand all
614 const ButtonExtraParams& extra, 615 const ButtonExtraParams& extra,
615 int part_id, 616 int part_id,
616 int state_id, 617 int state_id,
617 RECT* rect) const { 618 RECT* rect) const {
618 HANDLE handle = GetThemeHandle(BUTTON); 619 HANDLE handle = GetThemeHandle(BUTTON);
619 if (handle && draw_theme_) 620 if (handle && draw_theme_)
620 return draw_theme_(handle, hdc, part_id, state_id, rect, NULL); 621 return draw_theme_(handle, hdc, part_id, state_id, rect, NULL);
621 622
622 // Adjust classic_state based on part, state, and extras. 623 // Adjust classic_state based on part, state, and extras.
623 int classic_state = extra.classic_state; 624 int classic_state = extra.classic_state;
624 switch(part_id) { 625 switch (part_id) {
625 case BP_CHECKBOX: 626 case BP_CHECKBOX:
626 classic_state |= DFCS_BUTTONCHECK; 627 classic_state |= DFCS_BUTTONCHECK;
627 break; 628 break;
628 case BP_RADIOBUTTON: 629 case BP_RADIOBUTTON:
629 classic_state |= DFCS_BUTTONRADIO; 630 classic_state |= DFCS_BUTTONRADIO;
630 break; 631 break;
631 case BP_PUSHBUTTON: 632 case BP_PUSHBUTTON:
632 classic_state |= DFCS_BUTTONPUSH; 633 classic_state |= DFCS_BUTTONPUSH;
633 break; 634 break;
634 default: 635 default:
635 NOTREACHED() << "Unknown part_id: " << part_id; 636 NOTREACHED() << "Unknown part_id: " << part_id;
636 break; 637 break;
637 } 638 }
638 639
639 switch(state) { 640 switch (state) {
640 case kDisabled: 641 case kDisabled:
641 classic_state |= DFCS_INACTIVE; 642 classic_state |= DFCS_INACTIVE;
642 break; 643 break;
643 case kPressed: 644 case kPressed:
644 classic_state |= DFCS_PUSHED; 645 classic_state |= DFCS_PUSHED;
645 break; 646 break;
646 case kNormal: 647 case kNormal:
647 case kHovered: 648 case kHovered:
648 break; 649 break;
649 default: 650 default:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 if (handle && draw_theme_) { 701 if (handle && draw_theme_) {
701 if (extra.pointing_right) { 702 if (extra.pointing_right) {
702 return draw_theme_(handle, hdc, MENU_POPUPSUBMENU, state_id, &rect_win, 703 return draw_theme_(handle, hdc, MENU_POPUPSUBMENU, state_id, &rect_win,
703 NULL); 704 NULL);
704 } else { 705 } else {
705 // There is no way to tell the uxtheme API to draw a left pointing arrow; 706 // There is no way to tell the uxtheme API to draw a left pointing arrow;
706 // it doesn't have a flag equivalent to DFCS_MENUARROWRIGHT. But they 707 // it doesn't have a flag equivalent to DFCS_MENUARROWRIGHT. But they
707 // are needed for RTL locales on Vista. So use a memory DC and mirror 708 // are needed for RTL locales on Vista. So use a memory DC and mirror
708 // the region with GDI's StretchBlt. 709 // the region with GDI's StretchBlt.
709 Rect r(rect); 710 Rect r(rect);
710 base::win::ScopedHDC mem_dc(CreateCompatibleDC(hdc)); 711 base::win::ScopedCreateDC mem_dc(CreateCompatibleDC(hdc));
711 base::win::ScopedBitmap mem_bitmap(CreateCompatibleBitmap(hdc, r.width(), 712 base::win::ScopedBitmap mem_bitmap(CreateCompatibleBitmap(hdc, r.width(),
712 r.height())); 713 r.height()));
713 HGDIOBJ old_bitmap = SelectObject(mem_dc, mem_bitmap); 714 base::win::ScopedSelectObject select_bitmap(mem_dc, mem_bitmap);
714 // Copy and horizontally mirror the background from hdc into mem_dc. Use 715 // Copy and horizontally mirror the background from hdc into mem_dc. Use
715 // a negative-width source rect, starting at the rightmost pixel. 716 // a negative-width source rect, starting at the rightmost pixel.
716 StretchBlt(mem_dc, 0, 0, r.width(), r.height(), 717 StretchBlt(mem_dc, 0, 0, r.width(), r.height(),
717 hdc, r.right()-1, r.y(), -r.width(), r.height(), SRCCOPY); 718 hdc, r.right()-1, r.y(), -r.width(), r.height(), SRCCOPY);
718 // Draw the arrow. 719 // Draw the arrow.
719 RECT theme_rect = {0, 0, r.width(), r.height()}; 720 RECT theme_rect = {0, 0, r.width(), r.height()};
720 HRESULT result = draw_theme_(handle, mem_dc, MENU_POPUPSUBMENU, 721 HRESULT result = draw_theme_(handle, mem_dc, MENU_POPUPSUBMENU,
721 state_id, &theme_rect, NULL); 722 state_id, &theme_rect, NULL);
722 // Copy and mirror the result back into mem_dc. 723 // Copy and mirror the result back into mem_dc.
723 StretchBlt(hdc, r.x(), r.y(), r.width(), r.height(), 724 StretchBlt(hdc, r.x(), r.y(), r.width(), r.height(),
724 mem_dc, r.width()-1, 0, -r.width(), r.height(), SRCCOPY); 725 mem_dc, r.width()-1, 0, -r.width(), r.height(), SRCCOPY);
725 SelectObject(mem_dc, old_bitmap);
726 return result; 726 return result;
727 } 727 }
728 } 728 }
729 729
730 // For some reason, Windows uses the name DFCS_MENUARROWRIGHT to indicate a 730 // For some reason, Windows uses the name DFCS_MENUARROWRIGHT to indicate a
731 // left pointing arrow. This makes the following 'if' statement slightly 731 // left pointing arrow. This makes the following 'if' statement slightly
732 // counterintuitive. 732 // counterintuitive.
733 UINT pfc_state; 733 UINT pfc_state;
734 if (extra.pointing_right) 734 if (extra.pointing_right)
735 pfc_state = DFCS_MENUARROW; 735 pfc_state = DFCS_MENUARROW;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 } 801 }
802 802
803 HRESULT NativeThemeWin::PaintMenuItemBackground( 803 HRESULT NativeThemeWin::PaintMenuItemBackground(
804 HDC hdc, 804 HDC hdc,
805 State state, 805 State state,
806 const gfx::Rect& rect, 806 const gfx::Rect& rect,
807 const MenuItemExtraParams& extra) const { 807 const MenuItemExtraParams& extra) const {
808 HANDLE handle = GetThemeHandle(MENU); 808 HANDLE handle = GetThemeHandle(MENU);
809 RECT rect_win = rect.ToRECT(); 809 RECT rect_win = rect.ToRECT();
810 int state_id; 810 int state_id;
811 switch(state) { 811 switch (state) {
812 case kNormal: 812 case kNormal:
813 state_id = MPI_NORMAL; 813 state_id = MPI_NORMAL;
814 break; 814 break;
815 case kDisabled: 815 case kDisabled:
816 state_id = extra.is_selected ? MPI_DISABLEDHOT : MPI_DISABLED; 816 state_id = extra.is_selected ? MPI_DISABLEDHOT : MPI_DISABLED;
817 break; 817 break;
818 case kHovered: 818 case kHovered:
819 state_id = MPI_HOT; 819 state_id = MPI_HOT;
820 break; 820 break;
821 default: 821 default:
822 NOTREACHED() << "Invalid state " << state; 822 NOTREACHED() << "Invalid state " << state;
823 break; 823 break;
824 } 824 }
825 825
826 if (handle && draw_theme_) 826 if (handle && draw_theme_)
827 return draw_theme_(handle, hdc, MENU_POPUPITEM, state_id, &rect_win, NULL); 827 return draw_theme_(handle, hdc, MENU_POPUPITEM, state_id, &rect_win, NULL);
828 828
829 if (extra.is_selected) 829 if (extra.is_selected)
830 FillRect(hdc, &rect_win, GetSysColorBrush(COLOR_HIGHLIGHT)); 830 FillRect(hdc, &rect_win, GetSysColorBrush(COLOR_HIGHLIGHT));
831 return S_OK; 831 return S_OK;
832 } 832 }
833 833
834 HRESULT NativeThemeWin::PaintMenuList(HDC hdc, 834 HRESULT NativeThemeWin::PaintMenuList(HDC hdc,
835 State state, 835 State state,
836 const gfx::Rect& rect, 836 const gfx::Rect& rect,
837 const MenuListExtraParams& extra) const { 837 const MenuListExtraParams& extra) const {
838 HANDLE handle = GetThemeHandle(MENULIST); 838 HANDLE handle = GetThemeHandle(MENULIST);
839 RECT rect_win = rect.ToRECT(); 839 RECT rect_win = rect.ToRECT();
840 int state_id; 840 int state_id;
841 switch(state) { 841 switch (state) {
842 case kNormal: 842 case kNormal:
843 state_id = CBXS_NORMAL; 843 state_id = CBXS_NORMAL;
844 break; 844 break;
845 case kDisabled: 845 case kDisabled:
846 state_id = CBXS_DISABLED; 846 state_id = CBXS_DISABLED;
847 break; 847 break;
848 case kHovered: 848 case kHovered:
849 state_id = CBXS_HOT; 849 state_id = CBXS_HOT;
850 break; 850 break;
851 case kPressed: 851 case kPressed:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 HRESULT NativeThemeWin::PaintSpinButton( 890 HRESULT NativeThemeWin::PaintSpinButton(
891 HDC hdc, 891 HDC hdc,
892 Part part, 892 Part part,
893 State state, 893 State state,
894 const gfx::Rect& rect, 894 const gfx::Rect& rect,
895 const InnerSpinButtonExtraParams& extra) const { 895 const InnerSpinButtonExtraParams& extra) const {
896 HANDLE handle = GetThemeHandle(SPIN); 896 HANDLE handle = GetThemeHandle(SPIN);
897 RECT rect_win = rect.ToRECT(); 897 RECT rect_win = rect.ToRECT();
898 int part_id = extra.spin_up ? SPNP_UP : SPNP_DOWN; 898 int part_id = extra.spin_up ? SPNP_UP : SPNP_DOWN;
899 int state_id; 899 int state_id;
900 switch(state) { 900 switch (state) {
901 case kDisabled: 901 case kDisabled:
902 state_id = extra.spin_up ? UPS_DISABLED : DNS_DISABLED; 902 state_id = extra.spin_up ? UPS_DISABLED : DNS_DISABLED;
903 break; 903 break;
904 case kHovered: 904 case kHovered:
905 state_id = extra.spin_up ? UPS_HOT : DNS_HOT; 905 state_id = extra.spin_up ? UPS_HOT : DNS_HOT;
906 break; 906 break;
907 case kNormal: 907 case kNormal:
908 state_id = extra.spin_up ? UPS_NORMAL : DNS_NORMAL; 908 state_id = extra.spin_up ? UPS_NORMAL : DNS_NORMAL;
909 break; 909 break;
910 case kPressed: 910 case kPressed:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 HDC hdc, 955 HDC hdc,
956 Part part, 956 Part part,
957 State state, 957 State state,
958 const gfx::Rect& rect, 958 const gfx::Rect& rect,
959 const TrackbarExtraParams& extra) const { 959 const TrackbarExtraParams& extra) const {
960 int part_id = part == kTrackbarTrack ? TKP_TRACK : TKP_THUMBBOTTOM; 960 int part_id = part == kTrackbarTrack ? TKP_TRACK : TKP_THUMBBOTTOM;
961 if (extra.vertical) 961 if (extra.vertical)
962 part_id = part == kTrackbarTrack ? TKP_TRACKVERT : TKP_THUMBVERT; 962 part_id = part == kTrackbarTrack ? TKP_TRACKVERT : TKP_THUMBVERT;
963 963
964 int state_id = 0; 964 int state_id = 0;
965 switch(state) { 965 switch (state) {
966 case kDisabled: 966 case kDisabled:
967 state_id = TUS_DISABLED; 967 state_id = TUS_DISABLED;
968 break; 968 break;
969 case kHovered: 969 case kHovered:
970 state_id = TUS_HOT; 970 state_id = TUS_HOT;
971 break; 971 break;
972 case kNormal: 972 case kNormal:
973 state_id = TUS_NORMAL; 973 state_id = TUS_NORMAL;
974 break; 974 break;
975 case kPressed: 975 case kPressed:
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 } 1182 }
1183 1183
1184 HRESULT NativeThemeWin::PaintTextField( 1184 HRESULT NativeThemeWin::PaintTextField(
1185 HDC hdc, 1185 HDC hdc,
1186 Part part, 1186 Part part,
1187 State state, 1187 State state,
1188 const gfx::Rect& rect, 1188 const gfx::Rect& rect,
1189 const TextFieldExtraParams& extra) const { 1189 const TextFieldExtraParams& extra) const {
1190 int part_id = EP_EDITTEXT; 1190 int part_id = EP_EDITTEXT;
1191 int state_id = ETS_NORMAL; 1191 int state_id = ETS_NORMAL;
1192 switch(state) { 1192 switch (state) {
1193 case kNormal: 1193 case kNormal:
1194 if (extra.is_read_only) { 1194 if (extra.is_read_only) {
1195 state_id = ETS_READONLY; 1195 state_id = ETS_READONLY;
1196 } else if (extra.is_focused) { 1196 } else if (extra.is_focused) {
1197 state_id = ETS_FOCUSED; 1197 state_id = ETS_FOCUSED;
1198 } else { 1198 } else {
1199 state_id = ETS_NORMAL; 1199 state_id = ETS_NORMAL;
1200 } 1200 }
1201 break; 1201 break;
1202 case kHovered: 1202 case kHovered:
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 // CreateSolidBrush() accepts a RGB value but alpha must be 0. 1237 // CreateSolidBrush() accepts a RGB value but alpha must be 0.
1238 HBRUSH bg_brush = CreateSolidBrush(color); 1238 HBRUSH bg_brush = CreateSolidBrush(color);
1239 HRESULT hr; 1239 HRESULT hr;
1240 // DrawThemeBackgroundEx was introduced in XP SP2, so that it's possible 1240 // DrawThemeBackgroundEx was introduced in XP SP2, so that it's possible
1241 // draw_theme_ex_ is NULL and draw_theme_ is non-null. 1241 // draw_theme_ex_ is NULL and draw_theme_ is non-null.
1242 if (handle && (draw_theme_ex_ || (draw_theme_ && draw_edges))) { 1242 if (handle && (draw_theme_ex_ || (draw_theme_ && draw_edges))) {
1243 if (draw_theme_ex_) { 1243 if (draw_theme_ex_) {
1244 static DTBGOPTS omit_border_options = { 1244 static DTBGOPTS omit_border_options = {
1245 sizeof(DTBGOPTS), 1245 sizeof(DTBGOPTS),
1246 DTBG_OMITBORDER, 1246 DTBG_OMITBORDER,
1247 {0,0,0,0} 1247 { 0, 0, 0, 0 }
1248 }; 1248 };
1249 DTBGOPTS* draw_opts = draw_edges ? NULL : &omit_border_options; 1249 DTBGOPTS* draw_opts = draw_edges ? NULL : &omit_border_options;
1250 hr = draw_theme_ex_(handle, hdc, part_id, state_id, rect, draw_opts); 1250 hr = draw_theme_ex_(handle, hdc, part_id, state_id, rect, draw_opts);
1251 } else { 1251 } else {
1252 hr = draw_theme_(handle, hdc, part_id, state_id, rect, NULL); 1252 hr = draw_theme_(handle, hdc, part_id, state_id, rect, NULL);
1253 } 1253 }
1254 1254
1255 // TODO(maruel): Need to be fixed if get_theme_content_rect_ is NULL. 1255 // TODO(maruel): Need to be fixed if get_theme_content_rect_ is NULL.
1256 if (fill_content_area && get_theme_content_rect_) { 1256 if (fill_content_area && get_theme_content_rect_) {
1257 RECT content_rect; 1257 RECT content_rect;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1358 State control_state) const { 1358 State control_state) const {
1359 const int width = rect.width(); 1359 const int width = rect.width();
1360 const int height = rect.height(); 1360 const int height = rect.height();
1361 1361
1362 // DrawFrameControl for menu arrow/check wants a monochrome bitmap. 1362 // DrawFrameControl for menu arrow/check wants a monochrome bitmap.
1363 base::win::ScopedBitmap mask_bitmap(CreateBitmap(width, height, 1, 1, NULL)); 1363 base::win::ScopedBitmap mask_bitmap(CreateBitmap(width, height, 1, 1, NULL));
1364 1364
1365 if (mask_bitmap == NULL) 1365 if (mask_bitmap == NULL)
1366 return E_OUTOFMEMORY; 1366 return E_OUTOFMEMORY;
1367 1367
1368 base::win::ScopedHDC bitmap_dc(CreateCompatibleDC(NULL)); 1368 base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(NULL));
1369 HGDIOBJ org_bitmap = SelectObject(bitmap_dc, mask_bitmap); 1369 base::win::ScopedSelectObject select_bitmap(bitmap_dc, mask_bitmap);
1370 RECT local_rect = { 0, 0, width, height }; 1370 RECT local_rect = { 0, 0, width, height };
1371 DrawFrameControl(bitmap_dc, &local_rect, type, state); 1371 DrawFrameControl(bitmap_dc, &local_rect, type, state);
1372 1372
1373 // We're going to use BitBlt with a b&w mask. This results in using the dest 1373 // We're going to use BitBlt with a b&w mask. This results in using the dest
1374 // dc's text color for the black bits in the mask, and the dest dc's 1374 // dc's text color for the black bits in the mask, and the dest dc's
1375 // background color for the white bits in the mask. DrawFrameControl draws the 1375 // background color for the white bits in the mask. DrawFrameControl draws the
1376 // check in black, and the background in white. 1376 // check in black, and the background in white.
1377 int bg_color_key; 1377 int bg_color_key;
1378 int text_color_key; 1378 int text_color_key;
1379 switch (control_state) { 1379 switch (control_state) {
(...skipping 14 matching lines...) Expand all
1394 bg_color_key = COLOR_MENU; 1394 bg_color_key = COLOR_MENU;
1395 text_color_key = COLOR_MENUTEXT; 1395 text_color_key = COLOR_MENUTEXT;
1396 break; 1396 break;
1397 } 1397 }
1398 COLORREF old_bg_color = SetBkColor(hdc, GetSysColor(bg_color_key)); 1398 COLORREF old_bg_color = SetBkColor(hdc, GetSysColor(bg_color_key));
1399 COLORREF old_text_color = SetTextColor(hdc, GetSysColor(text_color_key)); 1399 COLORREF old_text_color = SetTextColor(hdc, GetSysColor(text_color_key));
1400 BitBlt(hdc, rect.x(), rect.y(), width, height, bitmap_dc, 0, 0, SRCCOPY); 1400 BitBlt(hdc, rect.x(), rect.y(), width, height, bitmap_dc, 0, 0, SRCCOPY);
1401 SetBkColor(hdc, old_bg_color); 1401 SetBkColor(hdc, old_bg_color);
1402 SetTextColor(hdc, old_text_color); 1402 SetTextColor(hdc, old_text_color);
1403 1403
1404 SelectObject(bitmap_dc, org_bitmap);
1405
1406 return S_OK; 1404 return S_OK;
1407 } 1405 }
1408 1406
1409 void NativeThemeWin::CloseHandles() const { 1407 void NativeThemeWin::CloseHandles() const {
1410 if (!close_theme_) 1408 if (!close_theme_)
1411 return; 1409 return;
1412 1410
1413 for (int i = 0; i < LAST; ++i) { 1411 for (int i = 0; i < LAST; ++i) {
1414 if (theme_handles_[i]) { 1412 if (theme_handles_[i]) {
1415 close_theme_(theme_handles_[i]); 1413 close_theme_(theme_handles_[i]);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 default: 1472 default:
1475 NOTREACHED(); 1473 NOTREACHED();
1476 } 1474 }
1477 theme_handles_[theme_name] = handle; 1475 theme_handles_[theme_name] = handle;
1478 return handle; 1476 return handle;
1479 } 1477 }
1480 1478
1481 // static 1479 // static
1482 NativeThemeWin::ThemeName NativeThemeWin::GetThemeName(Part part) { 1480 NativeThemeWin::ThemeName NativeThemeWin::GetThemeName(Part part) {
1483 ThemeName name; 1481 ThemeName name;
1484 switch(part) { 1482 switch (part) {
1485 case kCheckbox: 1483 case kCheckbox:
1486 case kRadio: 1484 case kRadio:
1487 case kPushButton: 1485 case kPushButton:
1488 name = BUTTON; 1486 name = BUTTON;
1489 break; 1487 break;
1490 case kInnerSpinButton: 1488 case kInnerSpinButton:
1491 name = SPIN; 1489 name = SPIN;
1492 break; 1490 break;
1493 case kMenuCheck: 1491 case kMenuCheck:
1494 case kMenuPopupGutter: 1492 case kMenuPopupGutter:
(...skipping 30 matching lines...) Expand all
1525 break; 1523 break;
1526 } 1524 }
1527 return name; 1525 return name;
1528 } 1526 }
1529 1527
1530 // static 1528 // static
1531 int NativeThemeWin::GetWindowsPart(Part part, 1529 int NativeThemeWin::GetWindowsPart(Part part,
1532 State state, 1530 State state,
1533 const ExtraParams& extra) { 1531 const ExtraParams& extra) {
1534 int part_id; 1532 int part_id;
1535 switch(part) { 1533 switch (part) {
1536 case kCheckbox: 1534 case kCheckbox:
1537 part_id = BP_CHECKBOX; 1535 part_id = BP_CHECKBOX;
1538 break; 1536 break;
1539 case kMenuCheck: 1537 case kMenuCheck:
1540 part_id = MENU_POPUPCHECK; 1538 part_id = MENU_POPUPCHECK;
1541 break; 1539 break;
1542 case kMenuPopupArrow: 1540 case kMenuPopupArrow:
1543 part_id = MENU_POPUPSUBMENU; 1541 part_id = MENU_POPUPSUBMENU;
1544 break; 1542 break;
1545 case kMenuPopupGutter: 1543 case kMenuPopupGutter:
(...skipping 15 matching lines...) Expand all
1561 NOTREACHED() << "Invalid part: " << part; 1559 NOTREACHED() << "Invalid part: " << part;
1562 break; 1560 break;
1563 } 1561 }
1564 return part_id; 1562 return part_id;
1565 } 1563 }
1566 1564
1567 int NativeThemeWin::GetWindowsState(Part part, 1565 int NativeThemeWin::GetWindowsState(Part part,
1568 State state, 1566 State state,
1569 const ExtraParams& extra) { 1567 const ExtraParams& extra) {
1570 int state_id; 1568 int state_id;
1571 switch(part) { 1569 switch (part) {
1572 case kCheckbox: 1570 case kCheckbox:
1573 switch(state) { 1571 switch (state) {
1574 case kNormal: 1572 case kNormal:
1575 state_id = CBS_UNCHECKEDNORMAL; 1573 state_id = CBS_UNCHECKEDNORMAL;
1576 break; 1574 break;
1577 case kHovered: 1575 case kHovered:
1578 state_id = CBS_UNCHECKEDHOT; 1576 state_id = CBS_UNCHECKEDHOT;
1579 break; 1577 break;
1580 case kPressed: 1578 case kPressed:
1581 state_id = CBS_UNCHECKEDPRESSED; 1579 state_id = CBS_UNCHECKEDPRESSED;
1582 break; 1580 break;
1583 case kDisabled: 1581 case kDisabled:
1584 state_id = CBS_UNCHECKEDDISABLED; 1582 state_id = CBS_UNCHECKEDDISABLED;
1585 break; 1583 break;
1586 default: 1584 default:
1587 NOTREACHED() << "Invalid state: " << state; 1585 NOTREACHED() << "Invalid state: " << state;
1588 break; 1586 break;
1589 } 1587 }
1590 break; 1588 break;
1591 case kMenuCheck: 1589 case kMenuCheck:
1592 switch(state) { 1590 switch (state) {
1593 case kNormal: 1591 case kNormal:
1594 case kHovered: 1592 case kHovered:
1595 case kPressed: 1593 case kPressed:
1596 state_id = extra.menu_check.is_radio ? MC_BULLETNORMAL 1594 state_id = extra.menu_check.is_radio ? MC_BULLETNORMAL
1597 : MC_CHECKMARKNORMAL; 1595 : MC_CHECKMARKNORMAL;
1598 break; 1596 break;
1599 case kDisabled: 1597 case kDisabled:
1600 state_id = extra.menu_check.is_radio ? MC_BULLETDISABLED 1598 state_id = extra.menu_check.is_radio ? MC_BULLETDISABLED
1601 : MC_CHECKMARKDISABLED; 1599 : MC_CHECKMARKDISABLED;
1602 break; 1600 break;
1603 default: 1601 default:
1604 NOTREACHED() << "Invalid state: " << state; 1602 NOTREACHED() << "Invalid state: " << state;
1605 break; 1603 break;
1606 } 1604 }
1607 break; 1605 break;
1608 case kMenuPopupArrow: 1606 case kMenuPopupArrow:
1609 case kMenuPopupGutter: 1607 case kMenuPopupGutter:
1610 case kMenuPopupSeparator: 1608 case kMenuPopupSeparator:
1611 switch(state) { 1609 switch (state) {
1612 case kNormal: 1610 case kNormal:
1613 state_id = MBI_NORMAL; 1611 state_id = MBI_NORMAL;
1614 break; 1612 break;
1615 case kHovered: 1613 case kHovered:
1616 state_id = MBI_HOT; 1614 state_id = MBI_HOT;
1617 break; 1615 break;
1618 case kPressed: 1616 case kPressed:
1619 state_id = MBI_PUSHED; 1617 state_id = MBI_PUSHED;
1620 break; 1618 break;
1621 case kDisabled: 1619 case kDisabled:
1622 state_id = MBI_DISABLED; 1620 state_id = MBI_DISABLED;
1623 break; 1621 break;
1624 default: 1622 default:
1625 NOTREACHED() << "Invalid state: " << state; 1623 NOTREACHED() << "Invalid state: " << state;
1626 break; 1624 break;
1627 } 1625 }
1628 break; 1626 break;
1629 case kPushButton: 1627 case kPushButton:
1630 switch(state) { 1628 switch (state) {
1631 case kNormal: 1629 case kNormal:
1632 state_id = PBS_NORMAL; 1630 state_id = PBS_NORMAL;
1633 break; 1631 break;
1634 case kHovered: 1632 case kHovered:
1635 state_id = PBS_HOT; 1633 state_id = PBS_HOT;
1636 break; 1634 break;
1637 case kPressed: 1635 case kPressed:
1638 state_id = PBS_PRESSED; 1636 state_id = PBS_PRESSED;
1639 break; 1637 break;
1640 case kDisabled: 1638 case kDisabled:
1641 state_id = PBS_DISABLED; 1639 state_id = PBS_DISABLED;
1642 break; 1640 break;
1643 default: 1641 default:
1644 NOTREACHED() << "Invalid state: " << state; 1642 NOTREACHED() << "Invalid state: " << state;
1645 break; 1643 break;
1646 } 1644 }
1647 break; 1645 break;
1648 case kRadio: 1646 case kRadio:
1649 switch(state) { 1647 switch (state) {
1650 case kNormal: 1648 case kNormal:
1651 state_id = RBS_UNCHECKEDNORMAL; 1649 state_id = RBS_UNCHECKEDNORMAL;
1652 break; 1650 break;
1653 case kHovered: 1651 case kHovered:
1654 state_id = RBS_UNCHECKEDHOT; 1652 state_id = RBS_UNCHECKEDHOT;
1655 break; 1653 break;
1656 case kPressed: 1654 case kPressed:
1657 state_id = RBS_UNCHECKEDPRESSED; 1655 state_id = RBS_UNCHECKEDPRESSED;
1658 break; 1656 break;
1659 case kDisabled: 1657 case kDisabled:
1660 state_id = RBS_UNCHECKEDDISABLED; 1658 state_id = RBS_UNCHECKEDDISABLED;
1661 break; 1659 break;
1662 default: 1660 default:
1663 NOTREACHED() << "Invalid state: " << state; 1661 NOTREACHED() << "Invalid state: " << state;
1664 break; 1662 break;
1665 } 1663 }
1666 break; 1664 break;
1667 case kWindowResizeGripper: 1665 case kWindowResizeGripper:
1668 switch(state) { 1666 switch (state) {
1669 case kNormal: 1667 case kNormal:
1670 case kHovered: 1668 case kHovered:
1671 case kPressed: 1669 case kPressed:
1672 case kDisabled: 1670 case kDisabled:
1673 state_id = 1; // gripper has no windows state 1671 state_id = 1; // gripper has no windows state
1674 break; 1672 break;
1675 default: 1673 default:
1676 NOTREACHED() << "Invalid state: " << state; 1674 NOTREACHED() << "Invalid state: " << state;
1677 break; 1675 break;
1678 } 1676 }
1679 break; 1677 break;
1680 default: 1678 default:
1681 NOTREACHED() << "Invalid part: " << part; 1679 NOTREACHED() << "Invalid part: " << part;
1682 break; 1680 break;
1683 } 1681 }
1684 return state_id; 1682 return state_id;
1685 } 1683 }
1686 1684
1687 } // namespace gfx 1685 } // namespace gfx
OLDNEW
« base/win/scoped_hdc.h ('K') | « printing/emf_win_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698