172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// found in the LICENSE file. 472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/window_snapshot/window_snapshot.h" 672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/win/scoped_gdi_object.h" 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/win/scoped_hdc.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/codec/png_codec.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gdi_util.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/rect.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "ui/gfx/size.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace browser { 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<unsigned char>* png_representation) { 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Create a memory DC that's compatible with the window. 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HDC window_hdc = GetWindowDC(window_handle); 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::win::ScopedHDC mem_hdc(CreateCompatibleDC(window_hdc)); 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Create a DIB that's the same size as the window. 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen RECT content_rect = {0, 0, 0, 0}; 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ::GetWindowRect(window_handle, &content_rect); 2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen content_rect.right++; // Match what PrintWindow wants. 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int width = content_rect.right - content_rect.left; 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int height = content_rect.bottom - content_rect.top; 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BITMAPINFOHEADER hdr; 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::CreateBitmapHeader(width, height, &hdr); 3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen unsigned char *bit_ptr = NULL; 3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::win::ScopedBitmap bitmap( 3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CreateDIBSection(mem_hdc, 3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<BITMAPINFO*>(&hdr), 3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DIB_RGB_COLORS, 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<void **>(&bit_ptr), 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NULL, 0)); 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SelectObject(mem_hdc, bitmap); 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Clear the bitmap to white (so that rounded corners on windows 4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // show up on a white background, and strangely-shaped windows 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // look reasonable). Not capturing an alpha mask saves a 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // bit of space. 4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PatBlt(mem_hdc, 0, 0, width, height, WHITENESS); 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Grab a copy of the window 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // First, see if PrintWindow is defined (it's not in Windows 2000). 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen typedef BOOL (WINAPI *PrintWindowPointer)(HWND, HDC, UINT); 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen PrintWindowPointer print_window = 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<PrintWindowPointer>( 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetProcAddress(GetModuleHandle(L"User32.dll"), "PrintWindow")); 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If PrintWindow is defined, use it. It will work on partially 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // obscured windows, and works better for out of process sub-windows. 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Otherwise grab the bits we can get with BitBlt; it's better 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // than nothing and will work fine in the average case (window is 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // completely on screen). 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (print_window) 5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (*print_window)(window_handle, mem_hdc, 0); 5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BitBlt(mem_hdc, 0, 0, width, height, window_hdc, 0, 0, SRCCOPY); 6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We now have a copy of the window contents in a DIB, so 6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // encode it into a useful format for posting to the bug report 6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // server. 6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen gfx::PNGCodec::Encode(bit_ptr, gfx::PNGCodec::FORMAT_BGRA, 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen gfx::Size(width, height), width * 4, true, 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<gfx::PNGCodec::Comment>(), 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen png_representation); 6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReleaseDC(window_handle, window_hdc); 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return gfx::Rect(width, height); 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} // namespace browser 75