[Done] CanvasOutput(0) per Parameter an Proc = IMA

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
Kurzer
Beiträge: 1614
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

[Done] CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von Kurzer »

Hallo,

die Überschrift beschreibt es nicht ganz, aber irgendwas ist hier faul.

Testet bitte mal folgenden Code.
1) Zeile 15 auskommentiert und Zeile 16 einkommentiert = alles OK
2) Zeile 16 auskommentiert und Zeile 15 einkommentiert = IMA Fehler
3) Zeile 16 auskommentiert und Zeile 15 einkommentiert und Zeile 5 bis 13 auskommentiert = alles OK

Hier scheint es ein Problem zu geben, wenn ich CanvasOutput() als Parameter an die Prozedur übergebe und gleichzeitig zwei StartDrawing() / StopDrawing() - Abschnitte darin enthalten sind.

Vermutlich habe ich mal wieder nur was übersehen, aber ich finde die Ursache nicht.

Code: Alles auswählen

Procedure Test (OutID.i)
	
	iTempImage1 =CreateImage(#PB_Any, 1800, 1800)
	
	iDC = StartDrawing(ImageOutput(iTempImage1))
	If iDC = 0
		; Device Context ist nicht für Zeichenoperationen gültig
	Else
		Debug iDC
		Debug OutputWidth()
		Debug OutputHeight()
		StopDrawing()
	EndIf
	
	;iDC = StartDrawing(OutID)	; Das hier bringt einen Fehler
	iDC = StartDrawing(CanvasOutput(0)) ; Das hier funktioniert
	If iDC = 0
		; Device Context ist nicht für Zeichenoperationen gültig
	Else
		Debug iDC
		Debug OutputWidth()
		Debug OutputHeight()
		StopDrawing()
	EndIf 
	
	FreeImage(iTempImage1)
EndProcedure	

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 120, 120, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
	CanvasGadget(0, 10, 10, 100, 100)
	Test (CanvasOutput(0))
	
	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Zuletzt geändert von Kurzer am 09.10.2016 09:54, insgesamt 2-mal geändert.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2023: 56 Jahre.
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von RSBasic »

Hallo Kurzer,

es hat anscheinend wirklich damit zu tun, dass du dazwischen eine andere Zeichenoperation durchführst und dann ist die übergebene Output-Nummer ungültig.
Wenn du diesen Code ausführst, dann klappt es wieder (wie du ja auch schon festgestellt hast):

Code: Alles auswählen

Procedure Test (OutID.i)
   
   iTempImage1 =CreateImage(#PB_Any, 1800, 1800)
   
;    iDC = StartDrawing(ImageOutput(iTempImage1))
;    If iDC = 0
;       ; Device Context ist nicht für Zeichenoperationen gültig
;    Else
;       Debug iDC
;       Debug OutputWidth()
;       Debug OutputHeight()
;       StopDrawing()
;    EndIf
   
   iDC = StartDrawing(OutID)   ; Das hier bringt einen Fehler
   ;iDC = StartDrawing(CanvasOutput(0)) ; Das hier funktioniert
   If iDC = 0
      ; Device Context ist nicht für Zeichenoperationen gültig
   Else
      Debug iDC
      Debug OutputWidth()
      Debug OutputHeight()
      StopDrawing()
   EndIf
   
   FreeImage(iTempImage1)
EndProcedure   

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 120, 120, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
   CanvasGadget(0, 10, 10, 100, 100)
   Test (CanvasOutput(0))
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Warum das so ist, weiß ich leider nicht.
Interessant ist auch, dass sich die Output-Nummer jedes Mal ändert, wenn man diese Nummer ermitteln möchte:

Code: Alles auswählen

Procedure Test (OutID.i)
   
   iTempImage1 =CreateImage(#PB_Any, 1800, 1800)
   
;    iDC = StartDrawing(ImageOutput(iTempImage1))
;    If iDC = 0
;       ; Device Context ist nicht für Zeichenoperationen gültig
;    Else
;       Debug iDC
;       Debug OutputWidth()
;       Debug OutputHeight()
;       StopDrawing()
;    EndIf
   
   Debug CanvasOutput(0)
   Debug CanvasOutput(0)
   Debug CanvasOutput(0)
   Debug CanvasOutput(0)
   Debug CanvasOutput(0)
   
;    iDC = StartDrawing(OutID)   ; Das hier bringt einen Fehler
;    iDC = StartDrawing(CanvasOutput(0)) ; Das hier funktioniert
;    If iDC = 0
;       ; Device Context ist nicht für Zeichenoperationen gültig
;    Else
;       Debug iDC
;       Debug OutputWidth()
;       Debug OutputHeight()
;       StopDrawing()
;    EndIf
   
   FreeImage(iTempImage1)
EndProcedure   

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 120, 120, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
   CanvasGadget(0, 10, 10, 100, 100)
   Test (CanvasOutput(0))
   
   Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von Bisonte »

Jeder "...Output()" erstellt einen eigenen DeviceContext.... der sofort bei StopDrawing() seine berechtigung verliert (gelöscht und freigegeben)

ist wie bei API mit GetDC_() und CloseHandle_()

Daher ist es sinnlos die Nummern zu speichern.
Sie sind definitiv nicht wiederverwendbar.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von STARGÅTE »

Kurzer hat geschrieben:Vermutlich habe ich mal wieder nur was übersehen, aber ich finde die Ursache nicht.
PureBasic Hilfe hat geschrieben:Gibt die AusgabeID zurück, oder Null, wenn Zeichnen nicht möglich ist. Dieser Wert sollte direkt an die Funktion StartDrawing() übergeben werden, um die Zeichenoperation zu starten. Der Rückgabewert ist nur für eine Zeichenoperation gültig und kann nicht wiederverwendet werden.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Kurzer
Beiträge: 1614
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: [Done] CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von Kurzer »

Vielen Dank Euch allen. :allright:

Ich werde die Prozedur so umschreiben, dass die ImageID übergeben werden muss, statt der AusgabeID, dann kann ich das ImageOutput() direkt innerhalb der Prozedur anwenden.
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2023: 56 Jahre.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: [Done] CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von Bisonte »

Bedenke, das man ALLE Zeichenoperationen für einen "Output" in einem Rutsch machen sollte und nicht mehrere StartDrawing() StopDrawing() Blöcke.
StartDrawing verlangsamt dein Programm... je weniger, desto besser ...
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
Kurzer
Beiträge: 1614
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Re: [Done] CanvasOutput(0) per Parameter an Proc = IMA

Beitrag von Kurzer »

Ich habe das ganze jetzt anders geregelt, so dass ich nur einen StartDrawing-Block benötige.
Es ging hier um eine "Windows XP-sichere" Version einer Screenshotfunktion (mit Ausschnittwahl) von verdeckten Fenstern. Codebeispiel unten.

Dabei ist folgende, weitere Frage aufgekommen: Zeigt der PB-LibraryViewer gar keine Images an, die für eine Imagegadget verwendet werden? Im Beispiel unten ist nach Aufruf von ShowLibraryViewer("Image") zwar kein eigenständiges Image mehr aktiv, aber zumidndest das Image, welches im ImageGadget gesetzt worden ist.

Edit: Aha, offenbar benötigt das ImageGadget eh immer ein separates Image. Demzufolge darf ich das FreeImage() auch erst bei Programmende ausführen. Ich hatte mich nämlich gewundert, dass das Imagegadget zwar einmalig den Screenshot anzeigt, aber das Bild nicht redrawed, wenn man andere Fenstern drüber zieht. Verschiebt man FreeImage(iImage) an das Ende des Programms, dann läuft es wie erwartet.

Edit 2: Aha2, wenn ich ein CanvasGadget nehme und dem das Image via "SetGadgetAttribute(MyCanvasGadget, #PB_Canvas_Image, ImageID(iImage))" zuweise, dann kann ich es auch sofort nach der Zuweisung wieder löschen. Offenbar legt das CanvasGadget eine interne Kopie davon an.

Code: Alles auswählen

EnableExplicit
#ImageGadget = 0

Prototype.i PrintWindow(iHandle.i, iDC.i, iFlags.i)
Global.i PrintWindow_.PrintWindow, iImage, iCalc

Procedure.i CreateImageFromScreenshot(sWindowTitel.s, x.i, y.i, iWidth, iHeight.i)
	; +-----------------------------------------------------------------
	; |Description  : Grabbt den Inhalt eines Fensters oder einen Ausschnitt davon und erzeugt daraus ein neues Image
	; |Arguments    : sWindowTitel: Kompletter Titel des Fensters das abfotografiert werden soll
	; |             : x						: X-Position des auszuschneidenden Screenshot-Bereichs
	; |             : y						: Y-Position des auszuschneidenden Screenshot-Bereichs
	; |             : iWidth			: Breite des auszuschneidenden Screenshot-Bereichs
	; |             : iHeight			: Höhe des auszuschneidenden Screenshot-Bereichs
	; |Results      : Image-Nummer des neuen Images oder 0, wenn eine Fehler aufgetreten ist
	; |Remarks      : -
	; +-----------------------------------------------------------------
	Protected.i iImage1, iImage2, iWindowHandle, iImageDC
	Protected.RECT stWindowRect
	
	If iWidth < 1 Or iHeight < 1
		; Die Screenshot-Ausmaße sind ungültig
		Goto ErrorExit
	EndIf
	
	If OpenLibrary(0, "user32.dll") = 0
		; Library konnte nicht geöffnet werden
		Goto ErrorExit
	EndIf
	
	; Das Fenster anhand des kompletten Titels finden
	PrintWindow_ = GetFunction(0, "PrintWindow")
	iWindowHandle = FindWindow_(0, sWindowTitel)
	If iWindowHandle = 0
		; Das Fenster wurde nicht gefunden
		Goto ErrorExitCloseLib
	EndIf
	
	; Ermitteln der Ausmaße des zu grabbenden Fensters
	GetWindowRect_(iWindowHandle, @stWindowRect)
	If stWindowRect\right < 1 Or stWindowRect\bottom < 1
		; Die Ausmaße des zu grabbenden Fensters sind nicht gültig
		Goto ErrorExitCloseLib
	EndIf						
	
	; Erstellen eines temporären Images in der Größe des Screenshots
	iImage1 =CreateImage(#PB_Any, stWindowRect\right, stWindowRect\bottom)
	If iImage1 < 0
		; Das Image konnte nicht erstellt werden
		Goto ErrorExitCloseLib
	EndIf
	
	; Kopieren des Screenshots in ein temporäres Image
	iImageDC = StartDrawing(ImageOutput(iImage1))
	If iImageDC = 0
		; Device Context ist nicht für Zeichenoperationen gültig
		Goto ErrorExitCloseLib
	EndIf
	
	Printwindow_(iWindowHandle, iImageDC, 0)
	StopDrawing()
	
	iImage2 = GrabImage(iImage1, #PB_Any, x, y, iWidth, iHeight)
	If iImage2 = 0
		; Device Context ist nicht für Zeichenoperationen gültig
		Goto ErrorExitFreeImage:
	EndIf
	
	FreeImage(iImage1)
	CloseLibrary(0)
	ProcedureReturn iImage2
	
	ErrorExitFreeImage:
	FreeImage(iImage1)
	ErrorExitCloseLib:
	CloseLibrary(0)
	ErrorExit:
	ProcedureReturn 0
	
EndProcedure

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 120, 120, "Test", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
	ImageGadget(#ImageGadget, 10, 10, 100, 100, 0, #PB_Image_Border)
	
	iCalc = RunProgram("calc.exe","","",#PB_Program_Open)
	Delay(1000)
	
	iImage = CreateImageFromScreenshot("Rechner", 0, 0, 100, 100)
	SetGadgetState(#ImageGadget, ImageID(iImage))
	Debug iImage
	FreeImage(iImage)
	ShowLibraryViewer("Image")
	
	Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
	
	KillProgram(iCalc)
	CloseProgram(iCalc)
EndIf
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.02 x64, OS: Win 7 Pro x64 & Win 11 x64, Desktopscaling: 125%, CPU: I7 6500, RAM: 16 GB, GPU: Intel Graphics HD 520
Useralter in 2023: 56 Jahre.
Antworten