VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename) { HBITMAP hBmp; if ((hBmp = CaptureWindow(hWnd)) == NULL) { return; } RECT client; GetClientRect(hWnd, &client); UINT uiBytesPerRow = 3 * client.right; // RGB takes 24 bits UINT uiRemainderForPadding; if ((uiRemainderForPadding = uiBytesPerRow % sizeof(DWORD)) > 0) uiBytesPerRow += (sizeof(DWORD) - uiRemainderForPadding); UINT uiBytesPerAllRows = uiBytesPerRow * client.bottom; PBYTE pDataBits; if ((pDataBits = new BYTE[uiBytesPerAllRows]) != NULL) { BITMAPINFOHEADER bmi = {0}; BITMAPFILEHEADER bmf = {0}; // Prepare to get the data out of HBITMAP: bmi.biSize = sizeof(bmi); bmi.biPlanes = 1; bmi.biBitCount = 24; bmi.biHeight = client.bottom; bmi.biWidth = client.right; // Get it: HDC hDC = GetDC(hWnd); GetDIBits(hDC, hBmp, 0, client.bottom, pDataBits, (BITMAPINFO*) &bmi, DIB_RGB_COLORS); ReleaseDC(hWnd, hDC); // Fill the file header: bmf.bfOffBits = sizeof(bmf) + sizeof(bmi); bmf.bfSize = bmf.bfOffBits + uiBytesPerAllRows; bmf.bfType = 0x4D42; // Writing: FILE* pFile; int err = fopen_s(&pFile, filename, "wb"); if (err == 0) { fwrite(&bmf, sizeof(bmf), 1, pFile); fwrite(&bmi, sizeof(bmi), 1, pFile); fwrite(pDataBits, sizeof(BYTE), uiBytesPerAllRows, pFile); fclose(pFile); } delete [] pDataBits; } DeleteObject(hBmp); }
HRESULT ScreenshotCommandHandler::CaptureViewport(BrowserHandle browser) { LOG(TRACE) << "Entering ScreenshotCommandHandler::CaptureViewport"; HWND content_window_handle = browser->GetContentWindowHandle(); int content_width = 0, content_height = 0; this->GetWindowDimensions(content_window_handle, &content_width, &content_height); CaptureWindow(content_window_handle, content_width, content_height); return S_OK; }
void SaveWindowToDIB(HWND hWnd, int nBitCount, int nCompression) { HBITMAP hBmp = CaptureWindow(hWnd); if ( hBmp ) { BITMAPINFO * pDIB = BitmapToDIB(NULL, hBmp, nBitCount, nCompression); if ( pDIB ) { SaveDIBToFile(NULL, pDIB, NULL); delete [] (BYTE *) pDIB; } DeleteObject(hBmp); } }
//--------------------------------------------------------------------------- void TfrmMain::btnCaptureClick() { m_bFormEdit = false; //until UEditForm is includet if(m_opt_tabCapture==1) m_hTargetWindow=GetDesktopWindow(); else if(!m_hTargetWindow) { TCHAR *err = TranslateT("Select a target window."); MessageBox(m_hWnd,err,ERROR_TITLE,MB_OK|MB_ICONWARNING); return; } TfrmMain::Hide(); if (m_opt_chkTimed) { SetTimer(m_hWnd, ID_chkTimed, m_opt_edtTimed ? m_opt_edtTimed*1000 : 500, NULL); } else if (m_opt_tabCapture == 1) { //desktop need always time to update from TfrmMain::Hide() SetTimer(m_hWnd, ID_chkTimed, 500, NULL); } else { m_Screenshot = CaptureWindow(m_hTargetWindow, m_opt_chkClientArea); SendMessage(m_hWnd,UM_EVENT, 0, (LPARAM)EVT_CaptureDone); } }
// Keyboard hook for the Finder Tool. // This hook just monitors the ESCAPE key static LRESULT CALLBACK draghookproc(int code, WPARAM wParam, LPARAM lParam) { ULONG state = (ULONG)lParam; static int count; if(code < 0) return CallNextHookEx(draghook, code, wParam, lParam); switch(wParam) { case VK_ESCAPE: if(!(state & 0x80000000)) { //don't let the current window procedure process a VK_ESCAPE, //because we want it to cancel the mouse capture PostMessage(draghookhwnd, WM_CANCELMODE, 0, 0); return -1; } break; case VK_SHIFT: if(state & 0x80000000) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_SHIFT_UP, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } else { if(!(state & 0x40000000)) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_SHIFT_DOWN, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } } return -1; case VK_CONTROL: if(state & 0x80000000) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_CTRL_UP, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } else { if(!(state & 0x40000000)) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_CTRL_DOWN, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } } return -1; } // Test to see if a key is pressed for first time if(!(state & 0xC0000000)) { // Find ASCII character UINT ch = MapVirtualKey((UINT)wParam, 2); if(ch == _T('c') || ch == _T('C')) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); CaptureWindow(GetParent(draghookhwnd), hwndCurrent); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); return -1; } } return CallNextHookEx(draghook, code, wParam, lParam); }
HRESULT ScreenshotCommandHandler::CaptureFullPage(BrowserHandle browser) { LOG(TRACE) << "Entering ScreenshotCommandHandler::CaptureFullPage"; HWND ie_window_handle = browser->GetTopLevelWindowHandle(); HWND content_window_handle = browser->GetContentWindowHandle(); CComPtr<IHTMLDocument2> document; browser->GetDocument(true, &document); if (!document) { LOG(WARN) << "Unable to get document from browser. Are you viewing a non-HTML document?"; return E_ABORT; } LocationInfo document_info; bool result = DocumentHost::GetDocumentDimensions(document, &document_info); if (!result) { LOG(DEBUG) << "Unable to get document dimensions"; return E_FAIL; } LOG(DEBUG) << "Initial document sizes (scrollWidth, scrollHeight) are (w, h): " << document_info.width << ", " << document_info.height; int chrome_width(0); int chrome_height(0); this->GetBrowserChromeDimensions(ie_window_handle, content_window_handle, &chrome_width, &chrome_height); LOG(DEBUG) << "Initial chrome sizes are (w, h): " << chrome_width << ", " << chrome_height; int target_window_width = document_info.width + chrome_width; int target_window_height = document_info.height + chrome_height; // For some reason, this technique does not allow the user to resize // the browser window to greater than SIZE_LIMIT x SIZE_LIMIT. This is // pretty big, so we'll cap the allowable screenshot size to that. // // GDI+ limit after which it may report Generic error for some image types int SIZE_LIMIT = 65534; if (target_window_height > SIZE_LIMIT) { LOG(WARN) << "Required height is greater than limit. Truncating screenshot height."; target_window_height = SIZE_LIMIT; document_info.height = target_window_height - chrome_height; } if (target_window_width > SIZE_LIMIT) { LOG(WARN) << "Required width is greater than limit. Truncating screenshot width."; target_window_width = SIZE_LIMIT; document_info.width = target_window_width - chrome_width; } long original_width = browser->GetWidth(); long original_height = browser->GetHeight(); LOG(DEBUG) << "Initial browser window sizes are (w, h): " << original_width << ", " << original_height; // If the window is already wide enough to accomodate // the document, don't resize that dimension. Otherwise, // the window will display a horizontal scroll bar, and // we need to retain the scrollbar to avoid rerendering // during the resize, so reduce the target window width // by two pixels. if (original_width > target_window_width) { target_window_width = original_width; } else { target_window_width -= 2; } // If the window is already tall enough to accomodate // the document, don't resize that dimension. Otherwise, // the window will display a vertical scroll bar, and // we need to retain the scrollbar to avoid rerendering // during the resize, so reduce the target window height // by two pixels. if (original_height > target_window_height) { target_window_height = original_height; } else { target_window_height -= 2; } BOOL is_maximized = ::IsZoomed(ie_window_handle); bool requires_resize = original_width < target_window_width || original_height < target_window_height; if (requires_resize) { // The resize message is being ignored if the window appears to be // maximized. There's likely a way to bypass that. The kludgy way // is to unmaximize the window, then move on with setting the window // to the dimensions we really want. This is okay because we revert // back to the original dimensions afterward. if (is_maximized) { LOG(DEBUG) << "Window is maximized currently. Demaximizing."; ::ShowWindow(ie_window_handle, SW_SHOWNORMAL); } // NOTE: There is a *very* slight chance that resizing the window // so there are no longer scroll bars to be displayed *might* cause // layout redraws such that the screenshot does not show the entire // DOM after the resize. Since we should always be expanding the // window size, never contracting it, this is a corner case that // explicitly will *not* be fixed. Any issue reports describing this // corner case will be closed without action. RECT ie_window_rect; ::GetWindowRect(ie_window_handle, &ie_window_rect); ::SetWindowPos(ie_window_handle, NULL, ie_window_rect.left, ie_window_rect.top, target_window_width, target_window_height, SWP_NOSENDCHANGING); } CaptureWindow(content_window_handle, document_info.width, document_info.height); if (requires_resize) { // Restore the browser to the original dimensions. if (is_maximized) { ::ShowWindow(ie_window_handle, SW_MAXIMIZE); } else { browser->SetHeight(original_height); browser->SetWidth(original_width); } } return S_OK; }
void TfrmMain::wmTimer(WPARAM wParam, LPARAM lParam) { if (wParam == ID_bvlTarget) { // Timer for Target selector static int primarymouse; if(!m_hTargetHighlighter) { primarymouse=GetSystemMetrics(SM_SWAPBUTTON)?VK_RBUTTON:VK_LBUTTON; m_hTargetHighlighter=CreateWindowEx(WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW,(LPTSTR)g_clsTargetHighlighter,NULL,WS_POPUP,0,0,0,0,NULL,NULL,hInst,NULL); if(!m_hTargetHighlighter) return; SetLayeredWindowAttributes(m_hTargetHighlighter,0,123,LWA_ALPHA); SetSystemCursor(CopyCursor(IcoLib_GetIcon(ICO_PLUG_SSTARGET)),OCR_NORMAL); Hide(); } if(!(GetAsyncKeyState(primarymouse)&0x8000)) { KillTimer(m_hWnd,ID_bvlTarget); SystemParametersInfo(SPI_SETCURSORS,0,NULL,0); DestroyWindow(m_hTargetHighlighter),m_hTargetHighlighter=NULL; SetTargetWindow(m_hTargetWindow); Show(); return; } POINT point; GetCursorPos(&point); m_hTargetWindow=WindowFromPoint(point); if(!((GetAsyncKeyState(VK_SHIFT)|GetAsyncKeyState(VK_MENU))&0x8000)) for(HWND hTMP; (hTMP=GetParent(m_hTargetWindow)); m_hTargetWindow=hTMP); if(m_hTargetWindow!=m_hLastWin) { m_hLastWin=m_hTargetWindow; RECT rect; GetWindowRect(m_hLastWin,&rect); int width=rect.right-rect.left; int height=rect.bottom-rect.top; if(g_iTargetBorder) { SetWindowPos(m_hTargetHighlighter,NULL,0,0,0,0,SWP_HIDEWINDOW|SWP_NOMOVE|SWP_NOSIZE); if(width>g_iTargetBorder*2 && height>g_iTargetBorder*2) { HRGN hRegnNew=CreateRectRgn(0,0,width,height); HRGN hRgnHole=CreateRectRgn(g_iTargetBorder,g_iTargetBorder,width-g_iTargetBorder,height-g_iTargetBorder); CombineRgn(hRegnNew,hRegnNew,hRgnHole,RGN_XOR); DeleteObject(hRgnHole); SetWindowRgn(m_hTargetHighlighter,hRegnNew,FALSE);//cleans up hRegnNew } else SetWindowRgn(m_hTargetHighlighter,NULL,FALSE); } SetWindowPos(m_hTargetHighlighter,HWND_TOPMOST,rect.left,rect.top,width,height,SWP_SHOWWINDOW|SWP_NOACTIVATE); } return; } if (wParam == ID_chkTimed) { // Timer for Screenshot #ifdef _DEBUG OutputDebugStringA("SS Bitmap Timer Start\r\n" ); #endif if(!m_bCapture) { //only start once if (m_Screenshot) { FIP->FI_Unload(m_Screenshot); m_Screenshot = NULL; } m_bCapture = true; switch (m_opt_tabCapture) { case 0: m_Screenshot = CaptureWindow(m_hTargetWindow, m_opt_chkClientArea); break; case 1: m_Screenshot = CaptureMonitor((m_opt_cboxDesktop > 0) ? m_Monitors[m_opt_cboxDesktop-1].szDevice : NULL); break; default: KillTimer(m_hWnd,ID_chkTimed); m_bCapture = false; #ifdef _DEBUG OutputDebugStringA("SS Bitmap Timer Stop (no tabCapture)\r\n" ); #endif return; } if (!m_Screenshot) m_bCapture = false; } if (m_Screenshot) { KillTimer(m_hWnd,ID_chkTimed); m_bCapture = false; #ifdef _DEBUG OutputDebugStringA("SS Bitmap Timer Stop (CaptureDone)\r\n" ); #endif SendMessage(m_hWnd,UM_EVENT, 0, (LPARAM)EVT_CaptureDone); } } }