2016-03-02 9 views
2

Я нашел демонстрационное приложение, которое может получить снимок экрана сведенного минимума/скрытого окна с помощью DwmRegisterThumbnail. Он работает отлично, но изображение результата рисуется в самой форме, а не в TBitmap.Прошедший захват экрана DWM на 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); 

Reference


Вторым параметром является дескриптор формы сам. До сих пор я пытался использовать 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 возвращает ложь, когда ручка в качестве параметра используется TBitmap.

Можно ли получить изображение в виде TBitmap? Заранее спасибо.

EDITED:

Моя последняя попытка с помощью 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; 
+0

'GetFormImage()' рисует форму на встроенную память 'HDC', моделируя сообщения' WM_ERASEBKGND' и 'WM_PAINT' формы, а затем копирует этот' HDC' в окончательный 'TBitmap'. Эскизы не включены в эту картину. Вы не можете присвоить 'HBITMAP'' DwmRegisterThumbnail() ', и вы не можете' BitBlt() 'из' HWND' напрямую. –

+0

Я был бы очень удивлен, если бы DWM фактически отображал миниатюры непосредственно на фактическом HWND, а не просто отображал его как часть композитного изображения HWND, когда он отображается на экране. DWM выполняет свои расширенные визуальные эффекты и улучшения производительности, манипулируя растровыми изображениями в памяти, компонуя несколько растровых изображений источника, смешивая пиксели и т. Д., А затем, наконец, копируя только результирующее изображение на экран. Миниатюра, скорее всего, является одним из нескольких растровых изображений, которые отображаются вместе, чтобы визуализировать визуальное изображение HWND на экране. –

+0

@RemyLebeau, Другими словами, невозможно сделать это, что я хочу? –

ответ

1

DwmRegisterThumbnail создает связь между окном источника и назначения окон, так что, когда содержимое окна источника изменяется, изменение ее отражение в окне предварительного просмотра.

Если у вас есть ручка окна, вы можете захватить визуальное представление своего окна в растровое изображение, используя GetDC() и CreateCompatibleDC(), BitBlt(). См. Capturing an Image