AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Wie mache ich einen screenshot in Z-Order mit PrintWindow-API?
Thema durchsuchen
Ansicht
Themen-Optionen

Wie mache ich einen screenshot in Z-Order mit PrintWindow-API?

Ein Thema von flashcoder · begonnen am 27. Apr 2019 · letzter Beitrag vom 28. Apr 2019
 
flashcoder

Registriert seit: 10. Nov 2013
83 Beiträge
 
#1

Wie mache ich einen screenshot in Z-Order mit PrintWindow-API?

  Alt 27. Apr 2019, 09:47
Delphi-Version: 10 Seattle
Ich versuche, einen C-Code zu übersetzen, der Screenshots in Z-Reihenfolge aufnehmen kann. Wenn ich den Delphi-Code teste, wird nur das Desktopfenster gedruckt. Wie kann das behoben werden?

C code:

Code:
#include "stdafx.h"
#include <Windows.h>
#include <gdiplus.h>
#include <conio.h>

#pragma warning(disable : 4996)

#pragma comment (lib,"Gdiplus.lib")

using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
    UINT num = 0;
    UINT size = 0;

    ImageCodecInfo* pImageCodecInfo = NULL;

    GetImageEncodersSize(&num, &size);
    if (size == 0)
        return -1;

    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    if (pImageCodecInfo == NULL)
        return -1;

    GetImageEncoders(num, size, pImageCodecInfo);

    for (UINT j = 0; j < num; ++j)
    {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
        {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;
        }
    }
    free(pImageCodecInfo);
    return -1;
}

//========================================================================================================

BOOL xPrintWindow(HWND hWnd, HDC hDc, HDC hDcScreen)
{
    BOOL ret = FALSE;
    RECT rect;
    GetWindowRect(hWnd, &rect);

    HDC    hDcWindow = CreateCompatibleDC(hDc);
    HBITMAP hBmpWindow = CreateCompatibleBitmap(hDc, rect.right - rect.left, rect.bottom - rect.top);

    SelectObject(hDcWindow, hBmpWindow);
    if (PrintWindow(hWnd, hDcWindow, 0))
    {
        BitBlt(hDcScreen,
            rect.left,
            rect.top,
            rect.right - rect.left,
            rect.bottom - rect.top,
            hDcWindow,
            0,
            0,
            SRCCOPY);

        ret = TRUE;
    }
    DeleteObject(hBmpWindow);
    DeleteDC(hDcWindow);
    return ret;
}

void EnumWindowsTopToDown(HWND owner, WNDENUMPROC proc, LPARAM param)
{
    HWND currentWindow = GetTopWindow(owner);
    if (currentWindow == NULL)
        return;
    if ((currentWindow = GetWindow(currentWindow, GW_HWNDLAST)) == NULL)
        return;
    while (proc(currentWindow, param) && (currentWindow = GetWindow(currentWindow, GW_HWNDPREV)) != NULL);
}

struct EnumHwndsPrintData
{
    HDC hDc;
    HDC hDcScreen;
};

BOOL CALLBACK EnumHwndsPrint(HWND hWnd, LPARAM lParam)
{
    EnumHwndsPrintData *data = (EnumHwndsPrintData *)lParam;

    if (!IsWindowVisible(hWnd))
        return TRUE;

    xPrintWindow(hWnd, data->hDc, data->hDcScreen);

    DWORD style = GetWindowLongA(hWnd, GWL_EXSTYLE);
    SetWindowLongA(hWnd, GWL_EXSTYLE, style | WS_EX_COMPOSITED);

    /*OSVERSIONINFOA versionInfo;
    ZeroMemory(&versionInfo, sizeof(OSVERSIONINFO));
    versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
    GetVersionExA(&versionInfo);

    if (versionInfo.dwMajorVersion < 6)
        EnumWindowsTopToDown(hWnd, EnumHwndsPrint, (LPARAM)data);*/

    return TRUE;
}

void testPrintWindow(int serverWidth, int serverHeight)
{

    RECT rect;
    HWND hWndDesktop = GetDesktopWindow();
    GetWindowRect(hWndDesktop, &rect);

    HDC    hDc = GetDC(NULL);
    HDC    hDcScreen = CreateCompatibleDC(hDc);
    HBITMAP hBmpScreen = CreateCompatibleBitmap(hDc, rect.right, rect.bottom);
    SelectObject(hDcScreen, hBmpScreen);

    EnumHwndsPrintData data;
    data.hDc = hDc;
    data.hDcScreen = hDcScreen;

    EnumWindowsTopToDown(NULL, EnumHwndsPrint, (LPARAM)&data);

    if (serverWidth > rect.right)
        serverWidth = rect.right;
    if (serverHeight > rect.bottom)
        serverHeight = rect.bottom;

    if (serverWidth != rect.right || serverHeight != rect.bottom)
    {
        HBITMAP hBmpScreenResized = CreateCompatibleBitmap(hDc, serverWidth, serverHeight);
        HDC    hDcScreenResized = CreateCompatibleDC(hDc);

        SelectObject(hDcScreenResized, hBmpScreenResized);
        SetStretchBltMode(hDcScreenResized, HALFTONE);
        StretchBlt(hDcScreenResized, 0, 0, serverWidth, serverHeight,
            hDcScreen, 0, 0, rect.right, rect.bottom, SRCCOPY);

        DeleteObject(hBmpScreen);
        DeleteDC(hDcScreen);

        hBmpScreen = hBmpScreenResized;
        hDcScreen = hDcScreenResized;
    }

//=======================================================================================================

    // ========== HBITMAP to bmp file ===========

    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    Bitmap *image = new Bitmap(hBmpScreen, NULL);

    CLSID myClsId;
    int retVal = GetEncoderClsid(L"image/bmp", &myClsId);

    image->Save(L"output.bmp", &myClsId, NULL);
    delete image;

    GdiplusShutdown(gdiplusToken);

    //=======================================================================

}

int _tmain(int argc, _TCHAR* argv[])
{
    testPrintWindow(800, 600);

    _getch();

    return 0;
}
Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Windows,
  Vcl.Graphics,
  SysUtils;

type
  PEnumHwndsPrintData = ^TEnumHwndsPrintData;

  TEnumHwndsPrintData = record
    _hDc: HDC;
    hDcScreen: HDC;
  end;

type
  TFNWndEnumProc = function(_hwnd: HWND; _lParam: LPARAM): BOOL; stdcall;

function xPrintWindow(_hwnd: HWND; _hDc, hDcScreen: HDC): BOOL;
const
  sPrintWindow = 'PrintWindow';
var
  PrintWindowAPI: function(sourceHandle: HWND; destinationHandle: HDC;
    nFlags: UINT): BOOL; stdcall;
  User32DLLHandle: THandle;
  bPrint: Boolean;
  Ret: BOOL;
  R: TRect;
  hDcWindow: HDC;
  hBmpWindow: HBITMAP;
begin
  Ret := False;

  User32DLLHandle := GetModuleHandle(user32);
  if User32DLLHandle <> 0 then
  begin
    @PrintWindowAPI := GetProcAddress(User32DLLHandle, sPrintWindow);

    if @PrintWindowAPI <> nil then
    begin
      GetWindowRect(_hwnd, R);

      hDcWindow := CreateCompatibleDC(_hDc);
      hBmpWindow := CreateCompatibleBitmap(_hDc, R.Right - R.Left,
        R.Bottom - R.Top);

      SelectObject(hDcWindow, hBmpWindow);

      bPrint := PrintWindowAPI(_hwnd, hDcWindow, 0);

      if bPrint then
      begin
        BitBlt(hDcScreen, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
          hDcWindow, 0, 0, SRCCOPY);

        Ret := True;
      end;
      DeleteObject(hBmpWindow);
      DeleteDC(hDcWindow);
    end;
  end;
  Result := Ret;
end;

function GetPrevHwnd(hWindow: HWND): HWND;
begin
  hWindow := GetWindow(hWindow, GW_HWNDPREV);
  Result := hWindow;
end;

procedure EnumWindowsTopToDown(Owner: HWND; Proc: TFNWndEnumProc;
  _Param: LPARAM);
var
  CurrentWindow, _CurrentWindow: HWND;
begin
  repeat
    CurrentWindow := GetTopWindow(Owner);
    if CurrentWindow = 0 then
      Exit;

    CurrentWindow := GetWindow(CurrentWindow, GW_HWNDLAST);
    if CurrentWindow = 0 then
      Exit;

    _CurrentWindow := GetPrevHwnd(CurrentWindow);

  until Proc(CurrentWindow, _Param) and (_CurrentWindow <> 0);
end;

function EnumHwndsPrint(wHandle: HWND; _lParam: LPARAM): BOOL; stdcall;
var
  VersionInfo: TOSVersionInfo;
  Data: PEnumHwndsPrintData;
  Style: DWORD;
begin
  Result := True;

  if not IsWindowVisible(wHandle) then
    Exit;

  Data := PEnumHwndsPrintData(_lParam);
  Writeln('oi');
  xPrintWindow(wHandle, Data._hDc, Data.hDcScreen);

  Style := GetWindowLong(wHandle, GWL_EXSTYLE);
  SetWindowLong(wHandle, GWL_EXSTYLE, Style or WS_EX_COMPOSITED);

  VersionInfo.dwOSVersionInfoSize := SizeOf(VersionInfo);
  GetVersionEx(VersionInfo);

  if (VersionInfo.dwMajorVersion < 6) then
    EnumWindowsTopToDown(wHandle, EnumHwndsPrint, LPARAM(Data));
end;

procedure testPrintWindow(Width, Height: Integer);
var
  hWndDesktop: HWND;
  Data: TEnumHwndsPrintData;
  _hDcScreen, hDc_, hDcScreenResized: HDC;
  hBmpScreen, hBmpScreenResized: HBITMAP;
  Rect: TRect;
  bmp: TBitmap;
begin
  hWndDesktop := GetDesktopWindow;
  GetWindowRect(hWndDesktop, Rect);

  hDc_ := GetDC(0);
  _hDcScreen := CreateCompatibleDC(hDc_);
  hBmpScreen := CreateCompatibleBitmap(hDc_, Rect.Right, Rect.Bottom);

  SelectObject(_hDcScreen, hBmpScreen);

  with Data do
  begin
    _hDc := hDc_;
    hDcScreen := _hDcScreen;
  end;

  EnumWindowsTopToDown(0, EnumHwndsPrint, LPARAM(@Data));

  if (Width > Rect.Right) then
    Width := Rect.Right;

  if (Height > Rect.Bottom) then
    Height := Rect.Bottom;

  if (Width <> Rect.Right) or (Height <> Rect.Bottom) then
  begin
    hBmpScreenResized := CreateCompatibleBitmap(hDc_, Width, Height);

    hDcScreenResized := CreateCompatibleDC(hDc_);

    SelectObject(hDcScreenResized, hBmpScreenResized);

    SetStretchBltMode(hDcScreenResized, HALFTONE);

    StretchBlt(hDcScreenResized, 0, 0, Width, Height, _hDcScreen, 0, 0,
      Rect.Right, Rect.Bottom, SRCCOPY);

    DeleteObject(hBmpScreen);
    DeleteDC(_hDcScreen);

    hBmpScreen := hBmpScreenResized;
    _hDcScreen := hDcScreenResized;
  end;

  bmp := TBitmap.Create;
  bmp.Handle := hBmpScreen;
  bmp.SaveToFile('output.bmp');
  bmp.Free;
end;

begin
  try
    testPrintWindow(800, 600);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

Geändert von flashcoder (27. Apr 2019 um 09:54 Uhr)
  Mit Zitat antworten Zitat
 


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz