Я нашел демонстрационное приложение, которое может сделать снимок экрана свернутого / скрытого окна с помощью DwmRegisterThumbnail. Он работает отлично, но результирующее изображение отрисовывается в самой форме, а не в TBitmap.
Это код:
procedure TfrmMain.PreviewWindow(const ASource, ADest: HWND; const ARect: TRect);
var
LResult: HRESULT;
LThumpProp: DWM_THUMBNAIL_PROPERTIES;
begin
if NOT DwmCompositionEnabled then begin
MessageDlg('DWM composition is NOT enabled.', mtWarning, [mbOK], 0);
Exit;
end;
PreviewDisable;
FPreviewEnabled := Succeeded(DwmRegisterThumbnail(ADest, ASource, @FTumbnail));
if FPreviewEnabled then begin
LThumpProp.dwFlags := DWM_TNP_SOURCECLIENTAREAONLY or DWM_TNP_VISIBLE or
DWM_TNP_OPACITY or DWM_TNP_RECTDESTINATION;
LThumpProp.fSourceClientAreaOnly := False;
LThumpProp.fVisible := True;
LThumpProp.opacity := 200;
LThumpProp.rcDestination := ARect;
LResult := DwmUpdateThumbnailProperties(FTumbnail, LThumpProp);
FPreviewEnabled := (LResult = S_OK);
end else
MessageDlg('Cannot link to window ' + IntToStr(ASource), mtError, [mbOK], 0);
end;
И функция вызывается следующим образом:
PreviewWindow( TargetWindow.Handle, Self.Handle, LRect);
Второй параметр - это дескриптор самой формы. Пока я пытался использовать GetFormImage, но он не захватывает область, где было нарисовано захваченное окно. Я попытался поместить изображение в TBitmap следующим образом, но у меня есть 2 проблемы:
procedure TfrmMain.PreviewWindow(const ASource, ADest: HWND; const ARect: TRect);
var
LResult: HRESULT;
LThumpProp: DWM_THUMBNAIL_PROPERTIES;
Bitmap: TBitmap;
Width, Height: integer;
begin
if NOT DwmCompositionEnabled then begin
MessageDlg('DWM composition is NOT enabled.', mtWarning, [mbOK], 0);
Exit;
end; // if NOT DwmCompositionEnabled then begin
Bitmap := TBitmap.Create;
try
Width:=500; //default size....
Height:=500;
Bitmap.SetSize(Width, Height);
PreviewDisable;
//THE FOLLOWING LINE RETURN FALSE WHEN BITMAP.HANDLE IS USED INSTEAD OF ADest
FPreviewEnabled := Succeeded(DwmRegisterThumbnail(Bitmap.Handle, ASource, @FTumbnail));
if FPreviewEnabled then begin
LThumpProp.dwFlags := DWM_TNP_SOURCECLIENTAREAONLY or DWM_TNP_VISIBLE or
DWM_TNP_OPACITY or DWM_TNP_RECTDESTINATION;
LThumpProp.fSourceClientAreaOnly := False;
LThumpProp.fVisible := True;
LThumpProp.opacity := 200;
LThumpProp.rcDestination := ARect;
LResult := DwmUpdateThumbnailProperties(FTumbnail, LThumpProp);
FPreviewEnabled := (LResult = S_OK);
BitBlt(Bitmap.Canvas.Handle, 0, 0, Width, Height, ADest, 0, 0, SRCCOPY);
Bitmap.SaveToFile('d:\test.bmp'); //Test if the image is correct
end else
MessageDlg('Cannot link to window ' + IntToStr(ASource), mtError, [mbOK], 0);
finally
Bitmap.Free;
end;
end;
1. Выберите правильный размер
2. Succeeded возвращает false, если дескриптор TBitmap используется в качестве параметра.
Можно ли поместить изображение в TBitmap? Заранее спасибо.
ИЗМЕНИТЬ:
Моя последняя попытка использовать TImage
, чтобы затем сохранить содержимое изображения в файл. Но идет белый снимок экрана.
uses
dwmapi;
private
{ Private declarations }
thumb: PHTHUMBNAIL;
function UpdateThumb(aThumb: PHTHUMBNAIL; aDestRect: TRect):boolean;
var
size: PSize;
props: PDWM_THUMBNAIL_PROPERTIES;
begin
result:=true;
if aThumb <> nil then
begin
DwmQueryThumbnailSourceSize(aThumb^, size);
props.dwFlags:=DWM_TNP_VISIBLE and DWM_TNP_RECTDESTINATION and DWM_TNP_OPACITY;
props.fVisible:=true;
props.opacity:=50;
props.fSourceClientAreaOnly:=false;
props.rcDestination:= aDestRect;
if (size.cx < aDestRect.Right - aDestRect.Left) then props.rcDestination.Right:=props.rcDestination.Left+size.cx;
if (size.cy < aDestRect.Bottom - aDestRect.Top) then props.rcDestination.Top:=props.rcDestination.Left+size.cy;
DwmUpdateThumbnailProperties(aThumb^,props^);
end;
end;
procedure TForm1.btn1Click(Sender: TObject);
var
h: Hwnd;
r: TRect;
wwidth, wheight: integer;
i: integer;
begin
h:=FindWindow(nil,'Untitled - Notepad');
if h<>0 then
begin
GetWindowRect(h,r);
wwidth:=r.Right-r.Left;
wheight:=r.Bottom-r.Top;
if thumb <> nil then
begin
DwmUnregisterThumbnail(thumb^);
thumb := nil;
end;
i:=DwmRegisterThumbnail(img1.canvas.Handle,h,thumb);
if i=0 then
UpdateThumb(thumb, Rect(0,0,Img1.Width, Img1.Height));
end;
GetFormImage()
рисует форму вHDC
в памяти, моделируя сообщенияWM_ERASEBKGND
иWM_PAINT
в форму, а затем копирует этоHDC
в окончательныйTBitmap
. Эскизы не включены в эту картину. Вы не можете поставитьHBITMAP
наDwmRegisterThumbnail()
, и вы не можетеBitBlt()
напрямую отHWND
. - person Remy Lebeau   schedule 02.03.2016DwmRegisterThumbnail()
. Он предназначен для отображения миниатюр на экране пользователю, а не для захвата изображений. - person Remy Lebeau   schedule 02.03.2016GetDC(0)
,BitBlt()
и т. Д.), А затем снова скрыть / минимизировать его при окончании. Вы можете отключить анимацию окна, чтобы ускорить эффект восстановления / минимизации, и вы можете дать окну альфа-прозрачность, равную 1, чтобы оно было технически видимым для ОС, но пользователь на самом деле не увидит его на экране . Маленькие уловки вроде этого. - person Remy Lebeau   schedule 02.03.2016TImage
для сохранения содержимого в файл, см. Выше, я обновил свой вопрос, чтобы показать это. Но идет белый снимок экрана. Итак, есть ли вероятность успеха в этой моей идее, основанной на ваших технических знаниях? - person   schedule 02.03.2016TImage
внутреннийHDC
вместоHWND
вDwmRegisterThumbnail()
. Вы понимаете разницу междуHWND
(окно),HDC
(контекст устройства),HBITMAP
(растровое изображение) и т. Д.? Они представляют собой разные вещи, они не взаимозаменяемы.DwmRegisterThumbnail()
работает только сHWND
s, больше ничего. Вы можете получитьHDC
заHWND
, используя, например,GetDC()
илиGetWindowDC()
. Но вы не можете использоватьHDC
там, где ожидаетсяHWND
, и наоборот. - person Remy Lebeau   schedule 02.03.2016DWM
api, где я могу получить снимок экрана вTBitmap
? - person   schedule 02.03.2016