Autor |
Beitrag |
HenryHux
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: 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:
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; ShotTargetbitmap.Width := (Bounds.Right - Bounds.left); ShotTargetbitmap.Height := (Bounds.Right - Bounds.Left);
TBmp:=TBitmap.Create; 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, 0, 0, Cut.Right, Cut.Bottom, ShotTargetBitmap.Canvas.Handle, Cut.Left, Cut.Top, SRCCOPY);
TBmp.savetofile('C:\TBmp2 '+inttostr(Random(50000))+'.bmp'); 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
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: 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 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 04.02.11 21:39
BenBE hat folgendes geschrieben : | 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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 04.02.11 21:43
|
|
HenryHux 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 04.02.11 21:55
Ok, danke wahr denke auch noch ein Fehler, aber nicht der, den ich suche..
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 :
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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 04.02.11 22:00
Kann es sein, dass du das fälschlicherweise in einem Thread aufrufst?
Und wozu brauchst du überhaupt DeskCanvas? 
Für diesen Beitrag haben gedankt: HenryHux
|
|
HenryHux 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 04.02.11 22:06
jaenicke hat folgendes geschrieben : | Kann es sein, dass du das fälschlicherweise in einem Thread aufrufst?
Und wozu brauchst du überhaupt DeskCanvas?  |
Gehts auch ohne? o.O
Aber vermutung ist richtig, ist eine Klasse, deren Instanz in einem Thread aufgerufen wird.
Ist dasn Problem?
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 04.02.11 22:20
HenryHux hat folgendes geschrieben : | 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...
HenryHux hat folgendes geschrieben : | jaenicke hat folgendes geschrieben : | Und wozu brauchst du überhaupt DeskCanvas?  | Gehts auch ohne? o.O |
Ja, denn du benutzt ja nur den HDC, nicht das Canvas Objekt...
Korrigiert also so ca.: 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; 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, 0, 0, Rechts, Unten, ShotTargetBitmap.Canvas.Handle, Links, Oben, SRCCOPY);
TargetBmp.savetofile('K:\TBmp2 '+inttostr(Random(50000))+'.bmp'); ShotTargetBitmap.savetofile('K:\TBmp1 '+inttostr(Random(50000))+'.bmp'); finally ReleaseDC(0, DesktopHandle); end; finally FreeAndNil(ShotTargetBitmap); end; end; |
HenryHux hat folgendes geschrieben : | 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 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: 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.
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
Wie synchronisiere ich sowas am Besten?
Vielleicht ein paar gute Tipps? =)
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 04.02.11 23:41
jaenicke hat folgendes geschrieben : | 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. |
Da hätte ich selber drauf kommen müssten... Naja
Habe aber noch ein Problem:
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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: 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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: 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
|
|
|