Autor Beitrag
HenryHux
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Fr 04.02.11 21:16 
Hi,

ich wende mich mal wieder an euch, da ich absolut nicht mehr weiter weiß.
Und zwar habe ich eine ältere Procedur, welche einen Screenshot macht, und diesen schneidet.
So sieht sie aus:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
procedure Screenshot(Bounds:TRect; Links, Rechts, Oben, Unten : Integer; var TBmp : TBitmap);
var DeskCanvas: TCanvas;
    ShotTargetBitmap : TBitmap;
    Cut : TRect;
begin
  try
    try
      Shottargetbitmap := TBitmap.create;  //Nur für den eigentlichen Screenshot
      ShotTargetbitmap.Width := (Bounds.Right - Bounds.left);
      ShotTargetbitmap.Height := (Bounds.Right - Bounds.Left);

      TBmp:=TBitmap.Create;                //Soll fertiges, geschnittenes Bmp enthalten
      TBmp.Width := Rechts - Links;
      TBmp.Height := Unten - Oben;

      DeskCanvas := TCanvas.Create;
      DeskCanvas.Handle := GetDC(0);

      Cut.Left := Links;
      Cut.Top := Oben;
      Cut.Right := Rechts;
      Cut.Bottom := Unten;

      BitBlt(ShotTargetBitmap.Canvas.Handle, 0 ,0, bounds.Right-bounds.left,
             bounds.Bottom-bounds.top, DeskCanvas.handle, bounds.Left,
             bounds.Top,SRCCOPY);
      BitBlt(TBmp.Canvas.Handle, 00, Cut.Right, Cut.Bottom,
             ShotTargetBitmap.Canvas.Handle, Cut.Left, Cut.Top, SRCCOPY);


      TBmp.savetofile('C:\TBmp2 '+inttostr(Random(50000))+'.bmp');                //Testweise speichern
      ShotTargetBitmap.savetofile('C:\TBmp1 '+inttostr(Random(50000))+'.bmp');


    finally
      ReleaseDC(0,DeskCanvas.Handle);
      FreeAndNil(deskcanvas);
      FreeAndNil(ShotTargetBitmap);
    end;
  except
    on E : Exception do
    begin
      showmessage('Exception in Screenshot : ' + E.Message);
      FreeAndNil(TBmp);
    end;
  end;
end;


Das Problem, welches ich erst kürzlich bemerkt habe ist, dass das fertig geschnittene Bitmap, einfach nur weiß ist.
Zwar richtig geschnitten, aber 0 Inhalt.
Bei ca jedem 6ten bis 7ten Bmp, hat er es aber genau so gemacht wie gewollt, sprich mir Inhalt.
Meiner Meinung nach, müsste es an dem letzten BitBlt liegen, denn alle! abgespeicherten ShotTargetBmps sind richtig.
Zu sagen bleibt, dass keine einzige Exception ausgelöst wurde.
Habe noch ein paar mal sleep() eingebaut, was aber das gleiche, ist also nicht weil die Prozedur zu schnell läuft.
Vielleicht wisst ihr ja was.

Lg
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Fr 04.02.11 21:25 
Was sagt GetLastError?

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.

Für diesen Beitrag haben gedankt: HenryHux
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Fr 04.02.11 21:39 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Was sagt GetLastError?


Der sagt bei jedem mal wo das Bild weiß bleibt 87.
Nur kann ich damit nichts anfangen, laut msdn.microsoft.com/en-us/library/ms681382 ist es ein falcher Parameter.
Doch ich rufe immer die gleichen auf, also wodran könnte es liegen?

lg
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 04.02.11 21:43 
Naja, fällt dir hier nicht etwas auf... ;-)
user profile iconHenryHux hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
      ShotTargetbitmap.Width := (Bounds.Right - Bounds.left);
      ShotTargetbitmap.Height := (Bounds.Right - Bounds.Left);
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Fr 04.02.11 21:55 
Ok, danke wahr denke auch noch ein Fehler, aber nicht der, den ich suche..
ausblenden Delphi-Quelltext
1:
2:
      ShotTargetbitmap.Width := (Bounds.Right - Bounds.left);
      ShotTargetbitmap.Height := (Bounds.Bottom - Bounds.Top);

Damit ist es genau das gleiche.
Der Aufruf sieht so aus :
ausblenden Delphi-Quelltext
1:
Screenshot(Rect(Links,Oben,Links+100,Oben+100),32,43,64,90, TBmp);					


Wobei TBmp dort wo es aufgerufne wird nur lokal deklariert ist und noch nicht mit create erzeugt ist.
Es wird lediglich mit .free am Ende beendet.

Sonst ne Idee wodran es liegen könnte?

Lg
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 04.02.11 22:00 
Kann es sein, dass du das fälschlicherweise in einem Thread aufrufst?

Und wozu brauchst du überhaupt DeskCanvas? :gruebel:

Für diesen Beitrag haben gedankt: HenryHux
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Fr 04.02.11 22:06 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Kann es sein, dass du das fälschlicherweise in einem Thread aufrufst?

Und wozu brauchst du überhaupt DeskCanvas? :gruebel:


Gehts auch ohne? o.O

Aber vermutung ist richtig, ist eine Klasse, deren Instanz in einem Thread aufgerufen wird.
Ist dasn Problem?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 04.02.11 22:20 
user profile iconHenryHux hat folgendes geschrieben Zum zitierten Posting springen:
Wobei TBmp dort wo es aufgerufne wird nur lokal deklariert ist und noch nicht mit create erzeugt ist.
Es wird lediglich mit .free am Ende beendet.
Äußerst schlechter Stil. Ressourcen sollten immer dort freigegeben werden, wo sie reserviert werden. Und schon gar nicht innerhalb einer Prozedur erzeugt und nach außen gegeben werden.
Und auch die Fehlerbehandlung gehört nach draußen, nicht in die Prozedur.
Außerdem hast du die Ressourcenschutzblöcke falsch angewendet.
Außerdem brauchst du kein var, da eine Bitmap ohnehin schon eine Objektreferenz ist, wenn du es außen erzeugst.
Und zu deinem Cut-Rect: Variablen so im Grunde nur durch andersnamige zu ersetzen, führt höchstens zu Verwirrung...

user profile iconHenryHux hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Und wozu brauchst du überhaupt DeskCanvas? :gruebel:
Gehts auch ohne? o.O
Ja, denn du benutzt ja nur den HDC, nicht das Canvas Objekt...

Korrigiert also so ca.:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
procedure Screenshot(Bounds:TRect; Links, Rechts, Oben, Unten : Integer; TargetBmp : TBitmap);
var
  DesktopHandle: HDC;
  ShotTargetBitmap: TBitmap;
begin
  if not Assigned(TargetBmp) then
    Exit;
  Shottargetbitmap := TBitmap.Create;  //Nur für den eigentlichen Screenshot
  try
    ShotTargetbitmap.Width := Bounds.Right - Bounds.Left;
    ShotTargetbitmap.Height := Bounds.Bottom - Bounds.Top;
    TargetBmp.Width := Rechts - Links;
    TargetBmp.Height := Unten - Oben;

    DesktopHandle := GetDC(0);
    try
      BitBlt(ShotTargetBitmap.Canvas.Handle, 0 ,0, bounds.Right-bounds.left,
        bounds.Bottom - bounds.top, DesktopHandle, bounds.Left,
        bounds.Top,SRCCOPY);
      BitBlt(TargetBmp.Canvas.Handle, 00, Rechts, Unten,
        ShotTargetBitmap.Canvas.Handle, Links, Oben, SRCCOPY);

      TargetBmp.savetofile('K:\TBmp2 '+inttostr(Random(50000))+'.bmp');                //Testweise speichern
      ShotTargetBitmap.savetofile('K:\TBmp1 '+inttostr(Random(50000))+'.bmp');
    finally
      ReleaseDC(0, DesktopHandle);
    end;
  finally
    FreeAndNil(ShotTargetBitmap);
  end;
end;


user profile iconHenryHux hat folgendes geschrieben Zum zitierten Posting springen:
Aber vermutung ist richtig, ist eine Klasse, deren Instanz in einem Thread aufgerufen wird.
Ist dasn Problem?
Ja, denn du benutzt eine Leinwand zum Zeichnen. Das geht nicht in einem Thread, sondern nur synchronisiert mit dem Hauptthread.

Für diesen Beitrag haben gedankt: HenryHux
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Fr 04.02.11 23:22 
Ok, danke habe jetzt einiges verändert.
Doch habe ich das mit dem Synchronisieren noch nicht ganz hinbekommen.
Ich kenne nur Synchronize und TCriticalSection, muss aber zugeben, dass ich noch nie damit gearbeitet habe.
Mit Synchronize sollte ich die Prozedur ja aufrufen können, aber er macht es nur, wenn ich keine Parameter übergebe.
Muss ich aber. Zumindest kenne ich keinen anderen Weg.
ausblenden Delphi-Quelltext
1:
SYNCHRONIZE(Screenshot(Rect(Links,Oben,Links+100,Oben+100),32,43,64,90, TBmp));					

Das klappt nicht, wäre auch zu einfach gewesen :D
Wie synchronisiere ich sowas am Besten?
Vielleicht ein paar gute Tipps? =)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 04.02.11 23:25 
Du musst die Daten unter private als Feld speichern. Dann kannst du eine Methode ohne Parameter synchronisiert aufrufen und darin diese Daten wiederum verwenden um die Screenshot-Prozedur aufzurufen.
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Fr 04.02.11 23:41 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Du musst die Daten unter private als Feld speichern. Dann kannst du eine Methode ohne Parameter synchronisiert aufrufen und darin diese Daten wiederum verwenden um die Screenshot-Prozedur aufzurufen.

:autsch: :autsch:

Da hätte ich selber drauf kommen müssten... Naja
Habe aber noch ein Problem:
ausblenden Delphi-Quelltext
1:
Synchronize(Screenshot);					

Wird zu [DCC Fehler] UnCardScanning.pas(158): E2066 Operator oder Semikolon fehlt .
Ich denke, dass ich noch die Instanz oder Ähnliches angeben muss.
Doch TThread.Synchronize(Screenshot)
[DCC Fehler] UnCardScanning.pas(159): E2389 Auf Protected-Element 'TThread.Synchronize' kann hier nicht zugegriffen werden
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 04.02.11 23:58 
Eigentlich ist das so schon richtig, schließlich bist du ja schon im Thread. Mich irritiert, dass du die Methode Screenshot synchronisieren willst, obwohl so ja schon die Prozedur eben hieß. Bist du da durcheinander gekommen?

Ich vermute jedenfalls, dass da irgendetwas anderes noch Screenshot heißt als deine Methode...

Sonst: Wie sieht denn der Quelltext dort sonst aus?
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Sa 05.02.11 00:06 
Ich bin immoment viel am basteln.
Die Procedure Screenshot ist lokal in einer Funktion, die ReadIn heißt.
Und diese ist Bestand von einer Klasse, welche dann in einem Thread aufgerufen wird.
Ist das vlt ein Problem?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 05.02.11 00:11 
Das Synchronize gehört in das Execute des Threads.

Theoretisch kannst du die Instanz des Threads mitgeben, aber das wäre nicht gerade sauber...

In neueren Delphiversionen kann man auch außerhalb eines Threads synchronisieren. Aber am besten pack das ins Execute, da gehört es hin. Mit dem private meinte ich das des Threads.

Für diesen Beitrag haben gedankt: HenryHux
HenryHux Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 542
Erhaltene Danke: 33

Windows 7 Premium
Delphi XE, Eclipse
BeitragVerfasst: Sa 05.02.11 00:52 
Ok, habe es jetzt hinbekommen.
Zwar etwas hässlich, aber es klappt.
Habe einfach die ganze Klasse in den Thread gesteckt, wusste einfach nicht wie ich es sonst machen sollte.
Werde mich dann in nächster Zeit öfter damit beschäftigen müssen, mit Zeit kommt Rat =)

Vielen Dank, jaenicke!

Lg