Problem with BitBlt on Windows 2012 R2 lazarus / 39-Graphics ---------------------------------------------------------------------- gwiesenekker · 2015-10-09 09:17 I am using the following code to capture the bitmap of the front window: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.Grab(bm: TBitMap);var  hWnd: THandle;  pPid: DWORD;  hProcess: THandle;  n: Integer;  hdcSrc: THandle;  SourceRect: TRect;  //bmp: TBitmap;  //cBmp: HBITMAP;begin  hWnd := GetForeGroundWindow;  if hWnd = 0 then Exit;  try    //RedrawWindow(hWnd, nil, 0, RDW_INVALIDATE or RDW_UPDATENOW);     GetWindowThreadProcessID(hWnd, pPid);    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, pPid);    SetLength(ModuleFileName, 255);    n := GetProcessImageFileName(hProcess, PChar(ModuleFileName), 255);    //On Windows 2003 GetProcessImageFileName always returns 129?    n := Strlen(PChar(ModuleFileName));    SetLength(ModuleFileName, n);     SetLength(ClassName, 255);    n := GetClassName(hWnd, PChar(ClassName), 255);    SetLength(ClassName, n);     SetLength(WindowTitle, 255 );    n := SendMessage(hWnd, WM_GETTEXT, Length(WindowTitle), Integer(WindowTitle));    SetLength(WindowTitle, n);{$IFDEF LOGFILE}    writeln(LogFile, 'ClassName=', ClassName);    writeln(LogFile, 'ModuleFileName=', ModuleFileName);    writeln(LogFile, 'WindowTitle=', WindowTitle);{$ENDIF}     hdcSrc := GetDC(hWnd);    //hdcSrc := GetDCEx(hWnd, 0, 0);     Windows.GetClientRect(hWnd, SourceRect);{$IFDEF LOGFILE}    writeln(LogFile, 'SourceRect Top/Left/Bottom/Right=', SourceRect.Top, ' ', SourceRect.Left, ' ',      SourceRect.Bottom, ' ', SourceRect.Right);{$ENDIF}    bm.Width  := SourceRect.Right - SourceRect.Left;    bm.Height := SourceRect.Bottom - SourceRect.Top;     //bmp := Graphics.TBitmap.Create;    //cBmp := CreateCompatibleBitmap(hdcSrc, bm.Width, bm.Height);    //bmp.Handle := cBmp;    //BitBlt(bmp.Canvas.Handle, 0, 0, bm.Width, bm.Height, hdcSrc, SourceRect.Left, SourceRect.Top, SRCCOPY);    //bmp.Canvas.Changed;     //StretchBlt(bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, hdcSrc,      //0, 0, SourceRect.Right - SourceRect.Left, SourceRect.Bottom - SourceRect.Top,      //SRCCOPY);    BitBlt(bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, hdcSrc, SourceRect.Left, SourceRect.Top, SRCCOPY);    //BitBlt(bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, bmp.Canvas.Handle, SourceRect.Left, SourceRect.Top, SRCCOPY);    bm.Canvas.Changed;    Application.ProcessMessages;  finally    ReleaseDC(hWnd, hdcSrc);  end;  This code works fine on Windows XP, Windows 7, Windows 8, Windows 2003 and Windows 2008 but on Windows 2012 R2 often not and if it works it shows strange behaviour. If I take a screenshot of Firefox for example it seems to work the first time, but if I go to another page and take the screenshot again it shows the previous page, even when I re-launch the executable and take the screenshot.. As you can see from the commented-out code I already tried some of the suggestions I found on the forums, but none worked until now. Any ideas? Regards, Gijsbert ---------------------------------------------------------------------- balazsszekely · 2015-10-09 11:59 First of all when you call a winapi you should always check for function result. You did in the case of GetForeGroundwindow, you should do the same with GetDC and GetClientRect. Although I don't have have w 2012 R2 to test this, I assume GetDC fails to get the correct handle. Try to take a screenshot from the entire screen, then copy the part you need according to GetClientRect. If this works the culprit is GetDC. ---------------------------------------------------------------------- gwiesenekker · 2015-10-09 20:27 Thank you! The problem is indeed with GetDC: the function result is not 0 but invalid as your suggested workaround getting the DC from the desktop window instead works: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.Grab(bm: TBitMap);var  hWnd: THandle;  pPid: DWORD;  hProcess: THandle;  n: Integer;  hdcSrc: THandle;  SourceRect: TRect;  //bmp: TBitmap;  //cBmp: HBITMAP;  TopLeft: TPoint;begin  hWnd := GetForeGroundWindow;  if hWnd = 0 then Exit;  try    //RedrawWindow(hWnd, nil, 0, RDW_INVALIDATE or RDW_UPDATENOW);    //Application.ProcessMessages;     GetWindowThreadProcessID(hWnd, pPid);    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, pPid);    SetLength(ModuleFileName, 255);    n := GetProcessImageFileName(hProcess, PChar(ModuleFileName), 255);    //On Windows 2003 GetProcessImageFileName always returns 129?    n := Strlen(PChar(ModuleFileName));    SetLength(ModuleFileName, n);     SetLength(ClassName, 255);    n := GetClassName(hWnd, PChar(ClassName), 255);    SetLength(ClassName, n);     SetLength(WindowTitle, 255 );    n := SendMessage(hWnd, WM_GETTEXT, Length(WindowTitle), Integer(WindowTitle));    SetLength(WindowTitle, n);{$IFDEF LOGFILE}    writeln(LogFile, 'ClassName=', ClassName);    writeln(LogFile, 'ModuleFileName=', ModuleFileName);    writeln(LogFile, 'WindowTitle=', WindowTitle);{$ENDIF}     hdcSrc := GetDC(GetDesktopWindow);    if hdcSrc = 0 then      raise(CGException.Create('hdcSrc returned nil'));     Windows.GetClientRect(hWnd, SourceRect);{$IFDEF LOGFILE}    writeln(LogFile, 'SourceRect Top/Left/Bottom/Right=', SourceRect.Top, ' ', SourceRect.Left, ' ',      SourceRect.Bottom, ' ', SourceRect.Right);{$ENDIF}    bm.Width  := SourceRect.Right - SourceRect.Left;    bm.Height := SourceRect.Bottom - SourceRect.Top;     TopLeft.X := SourceRect.Left;    TopLeft.Y := SourceRect.Top;    Windows.ClientToScreen(hWnd, TopLeft);    {$IFDEF LOGFILE}    writeln(LogFile, 'TopLeft X/Y=', TopLeft.X, ' ', TopLeft.Y);    {$ENDIF}     //bmp := Graphics.TBitmap.Create;    //cBmp := CreateCompatibleBitmap(hdcSrc, bm.Width, bm.Height);    //bmp.Handle := cBmp;    //BitBlt(bmp.Canvas.Handle, 0, 0, bm.Width, bm.Height, hdcSrc, SourceRect.Left, SourceRect.Top, SRCCOPY);    //bmp.Canvas.Changed;     //StretchBlt(bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, hdcSrc,      //0, 0, SourceRect.Right - SourceRect.Left, SourceRect.Bottom - SourceRect.Top,      //SRCCOPY);    BitBlt(bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, hdcSrc, TopLeft.X, TopLeft.Y, SRCCOPY);    //BitBlt(bm.Canvas.Handle, 0, 0, bm.Width, bm.Height, bmp.Canvas.Handle, SourceRect.Left, SourceRect.Top, SRCCOPY);    bm.Canvas.Changed;  finally    ReleaseDC(GetDesktopWindow, hdcSrc);  end;  Regards, Gijsbert