朋友,
需要在没有MY FORM的情况下截取所有桌面并在TImage中加载。 在Windows XP 7中取得成功 - 仅使用ALPHABLEND = TRUE + SCREENSHOT程序。
但是相同的代码在Windows 8中不起作用 - 捕获所有屏幕,包括表格。
我知道问题与AERO - DWM.EXE有关 - 使用pssuspend.exe(sysinternals)成功 - 暂停winlogon.exe并杀死dwm.exe
有人可以告诉我如何在Windows 8中没有我的表格捕获所有桌面吗?
prntscr.com/314rix - WIN7中的成功
prntscr.com/314tj7 - 在WIN8中失败
prntscr com / 31502u - 在WIN8中暂停WINLOGON.EXE和KILL DWM.EXE
www sentpace com / file / b5oxhb - SOURCE CODE
// FORM -> ALPHABLEND -> TRUE
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,
Clipbrd;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
ScrollBox1: TScrollBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure ScreenShot(DestBitmap: TBitmap);
var
DC: HDC;
begin
DC:=GetDC(GetDesktopWindow);
try
DestBitmap.Width:=GetDeviceCaps(DC, HORZRES);
DestBitmap.Height:=GetDeviceCaps(DC, VERTRES);
BitBlt(DestBitmap.Canvas.Handle,0,0,DestBitmap.Width,DestBitmap.Height,DC,0,0,SRCCOPY);
finally
ReleaseDC(GetDesktopWindow, DC);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ScreenShot(Image1.Picture.Bitmap);
end;
end.
答案 0 :(得分:2)
如果你想在没有出现窗口的情况下拍摄截图:在截取屏幕截图之前隐藏窗口:
procedure TForm1.Button1Click(Sender: TObject);
var
desktop: TGraphic;
fDisable: BOOL;
begin
{
Capture a screenshot without this window showing
}
//Disable DWM transactions so the window hides immediately
if DwmApi.DwmCompositionEnabled then
begin
fDisable := True;
OleCheck(DwmSetWindowAttribute(Self.Handle, DWMWA_TRANSITIONS_FORCEDISABLED, @fDisable, sizeof(fDisable)));
end;
try
//Hide the window
Self.Hide;
try
//Capture the desktop
desktop := CaptureDesktop;
finally
//Re-show our window
Self.Show;
end;
finally
//Restore animation transitions
if DwmApi.DwmCompositionEnabled then
begin
fDisable := False;
DwmSetWindowAttribute(Self.Handle, DWMWA_TRANSITIONS_FORCEDISABLED, @fDisable, sizeof(fDisable));
end;
end;
//Save the screenshot somewhere
desktop.SaveToFile('d:\temp\ss.bmp');
end;
随着魔法的发生:
function CaptureDesktop: TGraphic;
const
CAPTUREBLT = $40000000;
SM_XVIRTUALSCREEN = 76;
SM_YVIRTUALSCREEN = 77;
SM_CXVIRTUALSCREEN = 78;
SM_CYVIRTUALSCREEN = 79;
var
nDesktopWidth, nDesktopHeight: Integer;
tmpBmp: TBitmap;
hwndDesktop: HWND;
dcDesktop: HDC;
begin
Result := nil;
{
GetWindowRect(GetDesktopWindow)
is completely wrong. It will intentionally return only the rectangle of the primary monotor. See MSDN.
}
{ Cannot handle dpi virtualization
//Get the rect of the entire desktop; not just the primary monitor
ZeroMemory(@desktopRect, SizeOf(desktopRect));
for i := 0 to Screen.MonitorCount-1 do
begin
desktopRect.Top := Min(desktopRect.Top, Screen.Monitors[i].Top);
desktopRect.Bottom := Max(desktopRect.Bottom, Screen.Monitors[i].Top + Screen.Monitors[i].Height);
desktopRect.Left := Min(desktopRect.Left, Screen.Monitors[i].Left);
desktopRect.Right := Max(desktopRect.Right, Screen.Monitors[i].Left + Screen.Monitors[i].Width);
end;
//Get the size of the entire desktop
nDesktopWidth := (desktopRect.Right - desktopRect.Left);
nDesktopHeight := (desktopRect.Bottom - desktopRect.Top);
}
//Also doesn't handle dpi virtualization; but is shorter and unioning rects
nDesktopWidth := GetSystemMetrics(SM_CXVIRTUALSCREEN);
nDesktopHeight := GetSystemMetrics(SM_CYVIRTUALSCREEN);
tmpBmp:= TBitmap.Create;
try
tmpBmp.Width := nDesktopWidth;
tmpBmp.Height := nDesktopHeight;
//dcDesktop := GetDC(0); //
hwndDesktop := GetDesktopWindow;
dcDesktop := GetDC(hwndDesktop); //GetWindowDC(0) returns the DC of the primary monitor (not what we want)
if dcDesktop = 0 then
Exit;
try
if not BitBlt(tmpBmp.Canvas.Handle, 0, 0, nDesktopWidth, nDesktopHeight, dcDesktop, 0, 0, SRCCOPY or CAPTUREBLT) then
Exit;
finally
ReleaseDC(0, dcDesktop);
end;
except
tmpBmp.Free;
raise;
end;
// CaptureScreenShot(GetDesktopWindow, Image, false);
Result := tmpBmp;
end;
应用运行的屏幕:
保存的屏幕截图:
注意:任何已发布到公共领域的代码。无需归属。