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 3 // found in the LICENSE file. 4 5 #include "ui/snapshot/snapshot_win.h" 6 7 #include "base/win/scoped_gdi_object.h" 8 #include "base/win/scoped_hdc.h" 9 #include "base/win/scoped_select_object.h" 10 #include "ui/gfx/codec/png_codec.h" 11 #include "ui/gfx/gdi_util.h" 12 #include "ui/gfx/rect.h" 13 #include "ui/gfx/size.h" 14 #include "ui/snapshot/snapshot.h" 15 16 namespace { 17 18 gfx::Rect GetWindowBounds(HWND window_handle) { 19 RECT content_rect = {0, 0, 0, 0}; 20 if (window_handle) { 21 ::GetWindowRect(window_handle, &content_rect); 22 } else { 23 MONITORINFO monitor_info = {}; 24 monitor_info.cbSize = sizeof(monitor_info); 25 if (GetMonitorInfo(MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY), 26 &monitor_info)) { 27 content_rect = monitor_info.rcMonitor; 28 } 29 } 30 content_rect.right++; // Match what PrintWindow wants. 31 32 return gfx::Rect(content_rect.right - content_rect.left, 33 content_rect.bottom - content_rect.top); 34 } 35 36 } // namespace 37 38 namespace ui { 39 40 namespace internal { 41 42 bool GrabHwndSnapshot(HWND window_handle, 43 const gfx::Rect& snapshot_bounds, 44 std::vector<unsigned char>* png_representation) { 45 DCHECK(snapshot_bounds.right() <= GetWindowBounds(window_handle).right()); 46 DCHECK(snapshot_bounds.bottom() <= GetWindowBounds(window_handle).bottom()); 47 48 // Create a memory DC that's compatible with the window. 49 HDC window_hdc = GetWindowDC(window_handle); 50 base::win::ScopedCreateDC mem_hdc(CreateCompatibleDC(window_hdc)); 51 52 BITMAPINFOHEADER hdr; 53 gfx::CreateBitmapHeader(snapshot_bounds.width(), 54 snapshot_bounds.height(), 55 &hdr); 56 unsigned char *bit_ptr = NULL; 57 base::win::ScopedBitmap bitmap( 58 CreateDIBSection(mem_hdc, 59 reinterpret_cast<BITMAPINFO*>(&hdr), 60 DIB_RGB_COLORS, 61 reinterpret_cast<void **>(&bit_ptr), 62 NULL, 0)); 63 64 base::win::ScopedSelectObject select_bitmap(mem_hdc, bitmap); 65 // Clear the bitmap to white (so that rounded corners on windows 66 // show up on a white background, and strangely-shaped windows 67 // look reasonable). Not capturing an alpha mask saves a 68 // bit of space. 69 PatBlt(mem_hdc, 0, 0, snapshot_bounds.width(), snapshot_bounds.height(), 70 WHITENESS); 71 // Grab a copy of the window 72 // First, see if PrintWindow is defined (it's not in Windows 2000). 73 typedef BOOL (WINAPI *PrintWindowPointer)(HWND, HDC, UINT); 74 PrintWindowPointer print_window = 75 reinterpret_cast<PrintWindowPointer>( 76 GetProcAddress(GetModuleHandle(L"User32.dll"), "PrintWindow")); 77 78 // If PrintWindow is defined, use it. It will work on partially 79 // obscured windows, and works better for out of process sub-windows. 80 // Otherwise grab the bits we can get with BitBlt; it's better 81 // than nothing and will work fine in the average case (window is 82 // completely on screen). Always BitBlt when grabbing the whole screen. 83 if (snapshot_bounds.origin() == gfx::Point() && print_window && window_handle) 84 (*print_window)(window_handle, mem_hdc, 0); 85 else 86 BitBlt(mem_hdc, 0, 0, snapshot_bounds.width(), snapshot_bounds.height(), 87 window_hdc, snapshot_bounds.x(), snapshot_bounds.y(), SRCCOPY); 88 89 // We now have a copy of the window contents in a DIB, so 90 // encode it into a useful format for posting to the bug report 91 // server. 92 gfx::PNGCodec::Encode(bit_ptr, gfx::PNGCodec::FORMAT_BGRA, 93 snapshot_bounds.size(), 94 snapshot_bounds.width() * 4, true, 95 std::vector<gfx::PNGCodec::Comment>(), 96 png_representation); 97 98 ReleaseDC(window_handle, window_hdc); 99 100 return true; 101 } 102 103 } // namespace internal 104 105 #if !defined(USE_AURA) 106 bool GrabViewSnapshot(gfx::NativeView view_handle, 107 std::vector<unsigned char>* png_representation, 108 const gfx::Rect& snapshot_bounds) { 109 return GrabWindowSnapshot(view_handle, png_representation, snapshot_bounds); 110 } 111 112 bool GrabWindowSnapshot(gfx::NativeWindow window_handle, 113 std::vector<unsigned char>* png_representation, 114 const gfx::Rect& snapshot_bounds) { 115 DCHECK(window_handle); 116 return internal::GrabHwndSnapshot(window_handle, snapshot_bounds, 117 png_representation); 118 } 119 #endif // !defined(USE_AURA) 120 121 } // namespace ui 122