[gelöst]GetDesktopWindow

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
atroesch
Beiträge: 71
Registriert: Mo 7. Jul 2025, 10:05

[gelöst]GetDesktopWindow

Beitrag von atroesch »

ich versuche einen rechteckigen bereich vom desktop (wallpaper) zu kopieren.
mit getDC(0) oder getDC(GetdesktopWindow) geht es nur wenn kein fenster diesen
Bereich überlagert, ebenso BGRA takeScreenShoot(). gibt es einen weg, das das auch bei überlagernden Fenstern funktioniert?
Irgendeinen Zeiger auf wallpaper / Desktopfarbe?
Form2 ist eine transparente form...

Code: Alles auswählen

Ba_img:=TBgraBitmap.Create();
 Ba_img.SetSize(Form2.width,form2.height);
 ScreenDC := GetDC(0);   // oder GetDesktopWindow
 try
    BitBlt(Ba_img.Canvas.Handle, 0, 0, Ba_img.Width, Ba_img.Height, ScreenDC, form2.left, form2.top, cmSrcCopy);
  finally
    ReleaseDC(0, ScreenDC);
  end;
 //Ba_img.TakeScreenShot(Ba_rect); 
 Ba_img.SaveToFile(ts);
 Ba_img.Free;    
 
Zuletzt geändert von atroesch am Mo 17. Nov 2025, 15:22, insgesamt 1-mal geändert.

Mathias
Beiträge: 7125
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: GetDesktopWindow

Beitrag von Mathias »

Ich denke kaum, das dies geht, ich kenne kein PrintScreen Programm, welches dies kann.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Zvoni
Beiträge: 470
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: GetDesktopWindow

Beitrag von Zvoni »

Stimme Mathias zu: Alle Hinweise die ich finden konnte, sagten, dass immer das ganze Brett kommt.

Es gab aber Workarounds.
1) Per Message alle Fenster minimieren, mach deinen Screenshot, restore die Fenster
2) Mach den Screenshot mit allen Fenstern, enumeriere durch die Fenster, hol dir die Handles, und dann "maskiere" die Fenster gegenüber dem Desktop.
3) Direkten Zugriff auf den Window-Manager (weil der ja die Fenster verwaltet)

Keine Ahnung ob es funktioniert
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

atroesch
Beiträge: 71
Registriert: Mo 7. Jul 2025, 10:05

Re: GetDesktopWindow

Beitrag von atroesch »

funny, bei minimieren und danach maximieren war ich auch gerade..
so gehts, allerdings auch nur mit nem sleep();

Code: Alles auswählen

hndl := FindWindow('Shell_TrayWnd', '');
 SendMessage(hndl, WM_COMMAND, 419, 0);
 sleep(500);     
 Ba_img:=TBgraBitmap.Create();
 Ba_img.SetSize(Form2.width,form2.height);
 ScreenDC := GetDC(0);   // oder GetDesktopWindow
 try
    BitBlt(Ba_img.Canvas.Handle, 0, 0, Ba_img.Width, Ba_img.Height, ScreenDC, form2.left, form2.top, cmSrcCopy);
  finally
    ReleaseDC(0, ScreenDC);
  end;
SendMessage(hndl, WM_COMMAND, 416, 0);    
 Ba_img.SaveToFile(ts);
 Ba_img.Free; 

atroesch
Beiträge: 71
Registriert: Mo 7. Jul 2025, 10:05

Re: GetDesktopWindow

Beitrag von atroesch »

ich habs fast.....
bitte kann hier mal jemand drüber sehen ob das ok ist?

Wenn das noch jemand hin bekommt das das "child window " workerW von
FolderView als handle zurück gegeben wird, habe ich ein supi wochennende 8)

Das ist der 'Draw behing the desktop-Icons' hack (also zeichnen auf dem Desktop. hinter den Icons)
Ich weiss leider zu wenig über callback function und IntPtr....
Das child-fenster wird wohl irgendwie mit IntPtr.zero erreicht?

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private

  public
   png1 : TportableNetworkGraphic;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

type
  TMyData = record
    Handle: HWND;
    Pid: DWORD;
    Caption: String;
    ClassName: String;
  end;
  PMyData = ^TMyData;

function GetWindowClass(const Handle: HWND): String;
begin
  SetLength(Result, MAX_PATH);
  SetLength(Result, GetClassName(Handle, PChar(Result), Length(Result)));
end;

function GetWindowCaption(const Handle: HWND): String;
 begin
  SetLength(Result, MAX_PATH);
  SetLength(Result, GetWindowText(Handle, PChar(Result), Length(Result)));
end;

function EnumChildWindowsProc(Handle: THandle; MyData: LParam): BOOL; stdcall;
var
  ClassName: String;
  Caption: String;
  Pid: DWORD;
begin
  ClassName := GetWindowClass(Handle);
  Caption := GetWindowCaption(Handle);

  Result := (ClassName = 'SysListView32') and (Caption = 'FolderView');
  if Result then
  begin
    PmyData(MyData)^.Handle := Handle;
    GetWindowThreadProcessId(Handle, PmyData(MyData)^.Pid);
    PmyData(MyData)^.Caption := Caption;
    PmyData(MyData)^.ClassName := ClassName;
  end;

  // To continue enumeration, the callback function must return TRUE;
  // to stop enumeration, it must return FALSE
  Result := not Result;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyData  : TMyData;
  P       : IntPtr;
  DC      : HDC;
begin
  ZeroMemory(@MyData, SizeOf(MyData));
  EnumChildWindows(GetDesktopWindow, @EnumChildWindowsProc, NativeInt(@MyData));
  if MyData.Handle > 0 then
  begin
    ShowMessageFmt('Found Window in Pid %d '+MyData.caption, [MyData.Pid]);
    png1:=TportableNetworkGraphic.Create;
    DC:=getDC(MyData.handle);
    if(DC = 0 ) then
     showmessage('no');
    png1.LoadFromDevice(DC);
    releaseDC(MyData.handle,DC);
    png1.SaveToFile(getuserdir+'Pictures\test.png');
    png1.Free;
  end
  else begin
    ShowMessage('Window not found!');
  end;
end;

end.   

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1709
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: GetDesktopWindow

Beitrag von fliegermichl »

Also ich hab's mal getestet.
Das Programmelchen speichert ein Png mit dem Inhalt des Desktops in C:\users\user\pictures\test.png

Was genau ist jetzt Deine Frage?

atroesch
Beiträge: 71
Registriert: Mo 7. Jul 2025, 10:05

Re: GetDesktopWindow

Beitrag von atroesch »

Das Teilchen speichert nicht einfach den Desktop sondern den Desktop hinter allen anderen fenstern...
aber eben mit den Icons.
das interessante ist das man
erstens:
auf den desktop hinter den icons zeichnen kann
zweitens:
einen zugriff auf das Wallpaper (oder den hintergrund) als HDC erhalten kann

was mir noch fehlt ist:
send message an Progman mit

Code: Alles auswählen

W32.SendMessageTimeout(progman, 
                       0x052C, 
                       new IntPtr(0), 
                       IntPtr.Zero, 
                       W32.SendMessageTimeoutFlags.SMTO_NORMAL, 
                       1000, 
                       out result);

das ist C#

zugriff auf das dadurch erzeugte Fenster mit der Class WorkerW

https://www.codeproject.com/articles/Dr ... ts-section

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1709
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: GetDesktopWindow

Beitrag von fliegermichl »

So wie ich das sehe, wird dort ein Fenster erzeugt und als Child vom Desktopwindow hinter den Desktop Icons gezeichnet. Das mit dem SendMessage dient dann nur der Kommunikation mit diesem Fenster, da das Desktopfenster nicht dafür ausgelegt ist, Children zu verwalten. Aus dem Grund kommen ansonsten keinerlei Messages bei dem Fenster an.

atroesch
Beiträge: 71
Registriert: Mo 7. Jul 2025, 10:05

Re: GetDesktopWindow

Beitrag von atroesch »

nö.
die message erzeugt das fenster. mit der class WorkerW
wenn ich dieses handle bekomme (workerW), hab ich was ich will.. 8)

Antworten