xsharp.eu • RedimDataWindow
Page 1 of 3

RedimDataWindow

Posted: Wed Feb 05, 2020 9:29 am
by lagraf
Ich verwende in meinen Kassenprogrammen die Klasse RedimDataWindow, welche alle Controls an die Bildschirmgröße anpasst. Mein Kassenfenster leite ich von RedimDataWindow ab. In einer For ... Next Schleife werden die Controls abgearbeitet, ControlFont, Origin und Size zugeordnet. Wenn ich das Programm ein paar Mal hintereinander starte, funktioniert es manchmal und dann wieder nicht!!! Die Zuordnung des ControlFonts ist dann das Problem, im Error Objekt steht dann "Konvertierungsfehler von USUAL (FLOAT) oin PTR".

Code: Select all

CLASS RedimDataWindow INHERIT DataWindow
METHOD ResizeWindow( oDimension ) 	// Methode gekürzt!
	LOCAL nWidth		AS INT
	LOCAL nHeight		AS INT
	LOCAL nLen		AS DWORD
	LOCAL nI, nJ		AS DWORD
	LOCAL nPos		AS DWORD
	LOCAL nHorFaktor	AS FLOAT
	LOCAL nVerFaktor	AS FLOAT
	LOCAL aC			AS ARRAY
	LOCAL symName	AS SYMBOL
	LOCAL oSize		AS Dimension
	LOCAL oOrigin		AS Point
	LOCAL uError		AS USUAL

	BEGIN SEQUENCE
	IF ! IsInstanceOf( oDimension, #Dimension )
		oDimension			:= SELF:Size
	ENDIF

	nWidth				:= oDimension:Width
	nHeight				:= oDimension:Height
	nHorFaktor			:= Round( FLOAT( nWidth ) / FLOAT( _nSizeWidth ), 2 )	
	nVerFaktor			:= Round( FLOAT( nHeight ) / FLOAT( _nSizeHeight ), 2 )

	IF _oFont != NULL_OBJECT
		_oFont:Destroy()
		_oFont			:= NULL_OBJECT
	ENDIF
	_oFont				:= Font{ , Integer( FLOAT( _nFontSize ) * nVerFaktor ), _cFontName }
	IF _lFontBold
		_oFont:Bold		:= TRUE
	ENDIF

	aC					:= SELF:GetControls( #Control )
	nLen				:= ALen( aC )
	FOR nI := 1 UPTO nLen
		symName		:= aC[nI]:NameSym
		nPos			:= AScan( _aControls, {|a| a[1] == symName } )
		IF nPos > 0
			oSize	:= Dimension{ Integer( FLOAT( _aControls[nPos,3]:Width ) * nHorFaktor ), ;
						Integer( FLOAT( _aControls[nPos,3]:Height ) * nVerFaktor )}
			oOrigin	:= Point{ Integer( FLOAT( _aControls[nPos,2]:X ) * nHorFaktor ), ;
						Integer( FLOAT( _aControls[nPos,2]:Y ) * nVerFaktor ) }
// Wenn die Zuordnung von ControlFont auskommentiert wird funktionierts immer!
// Mit der Zuordnung funktionierts manchmal und dann wieder nicht!
			aC[nI]:ControlFont	:= _oFont
			aC[nI]:Origin			:= oOrigin
			aC[nI]:Size			:= oSize
		ENDIF
	NEXT

	RECOVER USING uError
		IF IsInstanceOf(uError, #Error)
			ErrorBox{, uError:Description}:Show()
		ENDIF
	END SEQUENCE
	RETURN NIL
Mal vom Begriff "oin" :) in der Fehlermeldung abgesehen:
-> Wie kann das Programm mit dem gleichen Fenster 1x funktionieren und dann wieder nicht?
-> Was ist an der Zuordnung des ControlsFonts eines Controls falsch?

RedimDataWindow

Posted: Wed Feb 05, 2020 9:46 am
by robert
Franz,
I am not sure what the exact reason for the problem is but I do see that your code is doing all kind of operations on array elements (Visual Arrays ?) which is late bound by nature so I would suggest:
1) Create a local variable oControl of type Control inside the loop and assign aC[nI] to this variable
2) Assign the size and dimension from the array to a local as well: oSize := _aControls[nPos,3] and oOrigin := _aControls[nPos,2]
3) Then use these oSize and oOrigin in the calculation:
oSize := Dimension{ Integer( FLOAT( oSize:Width ) * nHorFaktor ), Integer( FLOAT( oSize:Height ) * nVerFaktor )}
oOrigin := Point{ Integer( FLOAT( oOrigin:X ) * nHorFaktor ), Integer( FLOAT( oOrigin:Y ) * nVerFaktor ) }

4) assign to the local control:
oControl:ControlFont := _oFont
oControl:Origin := oOrigin
oControl:Size := oSize

This should help to make the code "early bound" in stead of "late bound" and may help to reveal the cause of the problem.

Robert

RedimDataWindow

Posted: Wed Feb 05, 2020 10:03 am
by lagraf
Hi Robert,
if I do this and define LOCAL oControl AS Control, I get an error

Code: Select all

error XS1061: 'VO.Control' does not contain a definition for 'ControlFont' and no accessible extension method 'ControlFont' accepting a first argument of type 'VO.Control' could be found (are you missing a using directive or an assembly reference?)
If it brings the error, it's always at the 2nd Control, the first Control is resized!
Maybe this info helps.

RedimDataWindow

Posted: Wed Feb 05, 2020 10:29 am
by robert
Franz,
The ControlFont is a property of the TextControl class.
What kind of controls do you have in the array. Are there controls in there that are not a TextControl (like DataBrowser, CustomControl, AnimationControl etc). When not then you should declare the local as TextControl.
If there is an object in there that does is not a TextControl you will find out quickly enough at runtime.

Robert

RedimDataWindow

Posted: Wed Feb 05, 2020 10:42 am
by lagraf
Hi Robert,
I filter the controls and use BUTTON, BASELISTBOX and EDIT, so I define oControl as TextControl. It compiles with no errors but at runtime the problem still appears!

RedimDataWindow

Posted: Wed Feb 05, 2020 4:43 pm
by g.bunzel@domonet.de
Franz,

...ich würde die Controls auch nicht bei jedem Resize als Array lesen.
Die Controls werden wohl im geöffneten Fenster nicht verändert.
Deshalb:
PROTECT aC AS ARRAY

und z.B. in PostInit() nur einmal:
SELF:aC := SELF:GetControls( #Control )

In der Methode ResizeWindow() dann mit SELF:aC arbeiten.

Wie kann diese Methode dann aufgerufen werden, damit oDimension nicht ein Object #Dimension ist?
Deshalb hast Du ja diese Prüfung:

IF ! IsInstanceOf( oDimension, #Dimension )
oDimension := SELF:Size
ENDIF


Die Methode ResizeWindow() sollte nur mit einer Dimension als Parameter aufgerufen werden - dann würde ich die Methode typisieren:

METHOD ResizeWindow( oDimension AS DIMENSION ) AS VOID PASCAL CLASS RedimDataWindow

HTH

Gerhard Bunzel

RedimDataWindow

Posted: Wed Feb 05, 2020 6:04 pm
by lagraf
Hallo Gerhard,
aC als Protect und die Typisierung habe ich eingebaut, hat aber nichts geholfen. ResizeWindow wird aufgerufen aus

Code: Select all

CLASS RedimDataWindow INHERIT DataWindow
...
METHOD ResizeWindow( oDimension AS dimension) AS VOID PASCAL
...
RETURN

METHOD Resize( oEvent )
SUPER:Resize( oEvent )
IF _aControls != NULL_ARRAY  .AND. ALen( _aControls ) > 1
	SELF:ResizeWindow( Dimension{ oEvent:Width, oEvent:Height } )
ENDIF
RETURN NIL
Die Prüfung sollte eigentlich überflüssig sein?

RedimDataWindow

Posted: Wed Feb 05, 2020 7:10 pm
by g.bunzel@domonet.de
Hallo Franz,

...hast Du mal geprüft, ob die Methode mehrfach aufgerufen wird - also während die Berechnung läuft nochmal?
Um da zu verhindern am Anfang der Methode:

IF SELF:_lInResize
RETURN
ENDIF


SELF:_lInResize := TRUE

....die Berechnung der Controls


SELF:_lInResize := FALSE

RETURN

HTH

Gerhard Bunzel

RedimDataWindow

Posted: Thu Feb 06, 2020 6:35 am
by lagraf
Hallo Gerhard,
die Abfrage ist drin damit nicht mehrfach aufgerufen werden kann!
Ich habe jetzt das RedimDataWindow mit ein paar Controls in eine MDI Testapp eingebaut und dabei festgestellt, dass das Problem bei den Fonts der MultiHoverButtons liegen muss:
-> Wenn ich die Zuordnung von ControlFont auskommentiere gehts
-> Wenn ich den MultiHoverButton von PushButton ableite gehts auch
Es scheint also die Umstellung der HoverButtonLib nicht ganz sauber zu sein!
Ich habe die Testapp und die HoverButtonLib beigelegt, vielleicht hat mal jemand Lust!
Das DataWindow dtaKassa einfach ein paar Mal starten, bis der Fehler auftritt!
LG Franz

RedimDataWindow

Posted: Thu Feb 06, 2020 6:56 am
by Karl-Heinz
Hallo Franz,

warum verwendest Du eigentlich 2 arrays ?

aC := SELF:GetControls( #Control )

und

_aControls - wie wird das gefüllt, per self:GetAllChildren() ?

Sinn macht doch wohl eher einmalig ein Array mit den controls der Klasse #TextControl zu füllen ?

Gruß
Karl-Heinz