Screenshot einer nicht sichtbaren Form erzeugen

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
ArchChem
Beiträge: 83
Registriert: Mo 11. Jul 2022, 10:41

Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von ArchChem »

Hallo allerseits,

für ein Präsentationsprogramm möchte ich die Möglichkeit bieten, anstatt die Präsentation zu zeigen, diese als Graphik zu exportieren. Dazu möchte ich gerne eine Form erzeugen, diese ggf. verändern und dann das Canvas von ihr erhalten, ohne sie zu zeigen (also Show() zu verwenden).

Folgendes habe ich probiert:

Code: Alles auswählen

PreviewPresentationForm := TFrmPresent.Create(frmSettings);
// ein paar Aktionen auf der Form vornehmen
PreviewPresentationForm.Refresh;
  PreviewPresentationForm.Repaint;
  PreviewPresentationForm.Update;
  PreviewPresentationForm.Invalidate;
  PreviewPresentationForm.Canvas.Refresh;
  imgWidth := PreviewPresentationForm.Width;
  imgHeight:= PreviewPresentationForm.Height;
  Rectangle:= Rect(0, 0, imgWidth, imgHeight);
  ImagePresentationPreview.Picture.Bitmap.Width := imgWidth;
  ImagePresentationPreview.Picture.Bitmap.Height:= imgHeight;
  ImagePresentationPreview.Picture.Bitmap.Canvas.CopyRect(Rectangle, PreviewPresentationForm.Canvas, Rectangle); 
Ich habe alle Repaint,Update, etc. Methoden mal "reingehauen", trotzdem wird am Ende auf dem ImagePresentationPreview (ein TImage) nur ein schwarzes Bild angezeigt. Hat jemand eine Idee?

Vielen Dank euch!

Benutzeravatar
theo
Beiträge: 10498
Registriert: Mo 11. Sep 2006, 19:01

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von theo »

Ehrlich gesagt, verstehe ich nicht was du meinst.
Der Titel klingt für mich wie ein Widerspruch in sich.
Etwa wie "Ich möchte mit dem Mikrofon eine nicht hörbare Musik aufnehmen". :wink:

ArchChem
Beiträge: 83
Registriert: Mo 11. Jul 2022, 10:41

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von ArchChem »

Hallo Theo,
theo hat geschrieben:
Fr 19. Mai 2023, 15:02
Ehrlich gesagt, verstehe ich nicht was du meinst.
Der Titel klingt für mich wie ein Widerspruch in sich.
Ich habe eine Form, welche eine Präsentation anzeigen kann, die aus verschiedenen Komponenten (hauptsächlich Labels) zusammengesetzt ist. Nun möchte ich aber diese Anzeige – anstatt sie am Bildschirm auszugeben – als Bild exportieren (das TImage ist nur für Testzwecke, später wird es direkt als Bilddatei exportiert).
theo hat geschrieben:
Fr 19. Mai 2023, 15:02
Etwa wie "Ich möchte mit dem Mikrofon eine nicht hörbare Musik aufnehmen". :wink:
Eher: Ich möchte Audio aufzeichnen, welches auf meinem PC wiedergeben wird, ohne es dabei über die Lautsprecher auszugeben :-)

Benutzeravatar
theo
Beiträge: 10498
Registriert: Mo 11. Sep 2006, 19:01

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von theo »

ArchChem hat geschrieben:
Fr 19. Mai 2023, 16:43
Ich habe eine Form, welche eine Präsentation anzeigen kann, die aus verschiedenen Komponenten (hauptsächlich Labels) zusammengesetzt ist. Nun möchte ich aber diese Anzeige – anstatt sie am Bildschirm auszugeben – als Bild exportieren (das TImage ist nur für Testzwecke, später wird es direkt als Bilddatei exportiert).
Das geht so meines Wissens nicht, aber sicher kann man sich nie sein, wenn man so etwas sagt! :wink:
Du kannst einen Screenshot machen:
https://wiki.freepascal.org/Developing_ ... the_screen
https://wiki.freepascal.org/Screenshot
aber dazu muss das Formular mindestens kurz sichtbar sein.

ArchChem
Beiträge: 83
Registriert: Mo 11. Jul 2022, 10:41

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von ArchChem »

Alles klar, danke! Leider ist das kurze Sichtbarsein für mich keine Option... Welche Alternativen gäbe es denn? Könnte ein Frame sowas eventuell schaffen?

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 170
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von Jorg3000 »

Hi!
Ich habe früher mal Folgendes gebastelt. Ich glaube es funzt auch ohne Sichtbarkeit (nicht ausprobiert) ...

Code: Alles auswählen

type THackWinControl = class(TWinControl);  

procedure ImageOfWinControl(aWinControl: TWinControl);
var cv: TCanvas;
    Src: THackWinControl;
    Img: TImage;
    ImgBmp: TBitmap;
    notUsed: HWND;
    SrcR, DestR: TRect;
begin
  notUsed:=0;
  cv:=TCanvas.Create;
  Img:=TImage.Create(nil);
  ImgBmp:=Img.Picture.Bitmap;
  Src:=THackWinControl(aWinControl);  // damit .GetDeviceContext() sichtbar wird
  try
    cv.Handle:=Src.GetDeviceContext({var}notUsed);  // wäre in Windows gleichbedeutend mit: cv.Handle:=GetDC(self.PageControl.Handle);
    SrcR:=Rect(0,0,Src.Width,Src.Height);
    DestR:=SrcR;
    ImgBmp.PixelFormat:=pf24Bit;
    ImgBmp.Width:=Src.Width;
    ImgBmp.Height:=Src.Height;
    Img.Canvas.CopyRect(DestR,cv,SrcR);
    FreeAndNIL(cv);
    
    // *** hier ImgBmp speichern
    
  finally
    Img.Free;
    cv.Free;
  end;
end;

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von af0815 »

Was du willst, ist ganz einfach ein Form auf einen anderen Kontext rendern. Das kenne ich von einem Reprotingsystem

Was mir dazu einfällt, wieso verwendest du nicht einen Report wie fpreport dafür. Und ersetzt deine verwendeten Komponenten durch die des Reports.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

ArchChem
Beiträge: 83
Registriert: Mo 11. Jul 2022, 10:41

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von ArchChem »

Hallo Jorg und af0815,

vielen Dank für eure Antworten und Vorschläge!
Jorg3000 hat geschrieben:
Fr 19. Mai 2023, 18:03
Ich habe früher mal Folgendes gebastelt. Ich glaube es funzt auch ohne Sichtbarkeit (nicht ausprobiert) ...
Danke für den Ansatz! Hier kommt es bei mir bei der Ausführung allerdings zu einem Type Cast Fehler (Illegal Type Conversion). Ich übergebe die Form als TWinControl, bei der Zeile

Code: Alles auswählen

Src:=THackWinControl(aWinControl);
schlägt die Umwandlung jedoch fehl. Weißt du, woran das liegen könnte?
af0815 hat geschrieben:
Fr 19. Mai 2023, 20:46
Was mir dazu einfällt, wieso verwendest du nicht einen Report wie fpreport dafür. Und ersetzt deine verwendeten Komponenten durch die des Reports.
Meinst du die Labels auf der Form sollten alle durch fpreport ersetzt werden?

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 170
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von Jorg3000 »

Moin!
Ich hatte gerade Zeit, mein Beispiel von gestern zu testen.
Eine Fehlermeldung wie "Illegal Type Conversion" bekomme ich nicht.

Habe die Procedure aufgerufen mit: ImageOfWinControl(Form1);
und zum Speichern darin eingebaut: ImgBmp.SaveToFile( ExtractFilePath(ParamStr(0))+'Test.bmp' );

Schlechte Nachricht: Es funktioniert doch nur, wenn das Fenster sichtbar ist! :cry:
Wenn es unsichtbar ist, erhält man nur ein schwarzes Bild. Ach menno.
Grüße, Jörg

ArchChem
Beiträge: 83
Registriert: Mo 11. Jul 2022, 10:41

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von ArchChem »

Guten Morgen Jorg,
Jorg3000 hat geschrieben:
Sa 20. Mai 2023, 07:20
Schlechte Nachricht: Es funktioniert doch nur, wenn das Fenster sichtbar ist! :cry:
Wenn es unsichtbar ist, erhält man nur ein schwarzes Bild. Ach menno.
Trotzdem vielen Dank für den Tipp und deine Hilfe!

Benutzeravatar
theo
Beiträge: 10498
Registriert: Mo 11. Sep 2006, 19:01

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von theo »

ArchChem hat geschrieben:
Sa 20. Mai 2023, 07:50
Guten Morgen Jorg,
Jorg3000 hat geschrieben:
Sa 20. Mai 2023, 07:20
Schlechte Nachricht: Es funktioniert doch nur, wenn das Fenster sichtbar ist! :cry:
Wenn es unsichtbar ist, erhält man nur ein schwarzes Bild. Ach menno.
Trotzdem vielen Dank für den Tipp und deine Hilfe!
Ich bleibe dabei, dass man etwas was nicht da ist nicht fotografieren kann. :lol:
Aber vielleicht kann man es für den Screenhot irgendwo hin verschieben, wo man es nicht sieht?
Auf Linux geht so etwas:.

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var OrigLeft:integer;
begin
  OrigLeft:=Left;
  Left:=3000; //Kommt halt auf das Display an.
  Show;
  Application.ProcessMessages;   
  ImageOfWinControl(Self);
  Hide;
  Left:=OrigLeft;
end;  
Nur so als Idee. Auf Windows weiss ich's nicht.

Benutzeravatar
kupferstecher
Beiträge: 422
Registriert: Do 17. Nov 2016, 11:52

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von kupferstecher »

Es gibt schon Möglichkeiten, z.B. mit TWinControl.PaintTo. Allerdings geht das so viel ich weiß unter Linux nicht mit dem GTK-Widgetset (dort dann schwarz, was nicht auch auf dem Bildschirm sichtbar ist), sondern nur mit QT. Windows funktioniert auch. Auch über LM_Paint und BitBLT lässt sich was machen, jede Variante hat so ihre Eigenheit, also einfach ausprobieren.

Code: Alles auswählen

    ////PAINTTO
    vControl.PaintTo(aImage.Canvas,0,0);

    ////LM_PAINT
    SendMessage(vControl.Handle, LM_Paint, aImage.Canvas.Handle, 0);

    ////BITBLT
    BitBLT(aImage.Canvas.Handle,0,0,aImage.Width,aImage.Height,
                                          GetDC(vControl.Handle),0,0,SRCCOPY);

Benutzeravatar
KodeZwerg
Beiträge: 98
Registriert: Mo 6. Feb 2023, 11:04

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von KodeZwerg »

Ich habs noch nicht so ganz verstanden aber hier wäre eine möglichkeit unter windows:

Code: Alles auswählen

  Self.AlphaBlend := True;
  Self.AlphaBlendValue := 1; // nun ist die form sogut wie unsichtbar
  Image1.Picture.Assign(GetFormImage); // nun ist ein bild der form im image1
  Self.AlphaBlend := False;
Zuletzt geändert von KodeZwerg am Sa 39. Okt 6043, 29:87, insgesamt 43-mal geändert.

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

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von Mathias »

Ich habs noch nicht so ganz verstanden aber hier wäre eine möglichkeit unter windows:
An dies habe ich auch schon gedacht, aber was passiert, wen dieses unsichtbare Fenster etwas anderes überdeckt ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
KodeZwerg
Beiträge: 98
Registriert: Mo 6. Feb 2023, 11:04

Re: Screenshot einer nicht sichtbaren Form erzeugen

Beitrag von KodeZwerg »

Mathias hat geschrieben:
Sa 20. Mai 2023, 17:35
Ich habs noch nicht so ganz verstanden aber hier wäre eine möglichkeit unter windows:
An dies habe ich auch schon gedacht, aber was passiert, wen dieses unsichtbare Fenster etwas anderes überdeckt ?
Das sollte egal sein da eine Kopie vom canvas erstellt wird ohne hacks etc...

Code: Alles auswählen

function TCustomForm.GetFormImage: TBitmap;
var
  ARect: TRect;
begin
  Result := TBitmap.Create;
  try
    Result.SetSize(ClientWidth, ClientHeight);
    LCLIntf.GetWindowRect(Handle, ARect);
    with GetClientOrigin do
      PaintTo(Result.Canvas, ARect.Left - X, ARect.Top - Y);
  except
    Result.Free;
    raise;
  end;
end;
Wichtig ist halt das das Fenster nicht "Self.Hide;" ist, da dann das canvas leer bleibt.
Zuletzt geändert von KodeZwerg am Sa 39. Okt 6043, 29:87, insgesamt 43-mal geändert.

Antworten