Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Forum dedicato ai programmatori di X# in lingua italiana – Italian language forum

Moderator: wriedmann

Post Reply
User avatar
claudiocarletta
Posts: 101
Joined: Sat Sep 05, 2020 8:56 am

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by claudiocarletta »

Salve a tutti.
Ho creato un'applicazione MDI, dallo standardmenu richiamo una DATAWINDOW ma voglio che non possa essere aperta un'altra istanza della stessa DATAWINDOW.
Come faccio?
Ho provato a creare una variabile globale LOGIC lNewPermessi e nel PreInit() la controllo...

Code: Select all

method PreInit(oWindow,iCtlID,oServer,uExtra)
	//Put your PreInit additions here
	if lNewPermessi
		self:EndWindow()
    else
	    lNewPermessi = true
    endif
return NIL
e poi nel QueryClose rimetto la variabile a false

Code: Select all

method QueryClose(oEvent)
	local lAllowClose as logic
	lAllowClose := super:QueryClose(oEvent)
	lNewPermessi = false
return lAllowClose
Ho provato anche con Destroy()
NULLA

Qualcuno può aiutarmi?
Grazie mille
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by ic2 »

Hello Claudio,

I assume you can translate my reply. I do it as follows. It's a bit of work but very flexible. You decide if you want to prevent a 2nd instantiation of our window to open, or just give focus to the requested window if open.

I run this function:

Code: Select all

IF !CheckOpenChildWindow(#SomeWindow,FALSE,TRUE,FALSE)   // See this function below
// do something
endif
It does require you to store and remove open window names. I use this:

Code: Select all

FUNCTION IC2GetAppObject()
//#s Returns application object and thus gives access to 'global' variables from any place 28-2-2003
RETURN GetAppObject()
(but you could do it with globals, but these are better avoided normally).


Now when I call the opening of the window I do something like this:

Code: Select all

oSomeWindow := SomeWindow(SELF,,oMyDBF,{""} 
AddChildWindow( oSomeWindow)

Code: Select all

FUNCTION AddChildWindow(oChild) 
//#s Source: SSA. Adds window to array array

IF ALen(IC2GetAppObject ():aOpenWindows) == 0
	IC2GetAppObject ():aOpenWindows := {}
ENDIF	
AAdd( IC2GetAppObject ():aOpenWindows, oChild )
RETURN NIL


In the queryclose of oSomeWindow add:

Code: Select all

DeleteChildWindow(SELF)

Code: Select all

FUNCTION DeleteChildWindow(oChild AS OBJECT) AS LOGIC PASCAL
//#s Source: SSA. removes window from array
	
LOCAL nChild	AS DWORD
LOCAL dwIndex	AS DWORD

LOCAL oObject	AS OBJECT
nChild := 0
FOR dwIndex := 1 UPTO ALen (IC2GetAppObject():aOpenWindows)
	oObject := IC2GetAppObject ():aOpenWindows[dwIndex]
	IF oObject <> NULL_OBJECT
		IF oChild:Handle() == oObject:Handle()
			nChild := dwIndex
			EXIT
		ENDIF
	ENDIF
NEXT

IF nChild > 0
	IC2GetAppObject():aOpenWindows[nChild] := NULL_OBJECT
ENDIF
RETURN TRUE

Code: Select all

FUNCTION  CheckOpenChildWindow( sObject AS SYMBOL,lClose AS LOGIC ,lFocus AS LOGIC ,lReturnWindow AS LOGIC) AS USUAL PASCAL // CLASS Window	// IC2DW
//#s Checks if sObject is open 6-7-2001
//#s
//#x
//#l Paramater lClose: if true, close window as well 8-1-2003 lReturnWindow (element of aChildWindows) instead of true/false 2-7-2008
//#l
//#l
//#l
//#p sObject=symbolic name of datawindow lClose= true if we want to close the window lfocus=true if we want to select the window  lReturnWindow =return array element nr instead of logic 
//#p
//#r false if not, true if open or array element number of aChildWindows when lReturnWindow is true
//#e
//#e
LOCAL NI AS DWORD
LOCAL nWindow AS DWORD
LOCAL lFound AS LOGIC
LOCAL oObject AS OBJECT

nWindow:=0																// Default: window not found 19-7-2008
lFound:=FALSE															// Default: not open 5-2-2009

FOR NI:= 1 UPTO ALen(IC2GetAppObject ():aOpenWindows)
	oObject := IC2GetAppObject ():aOpenWindows [NI]
	IF oObject <> NULL_OBJECT
		IF IsInstanceOf (oObject,sObject)
			lFound:=TRUE
			nWindow:=NI														// Assign to LATEST window
			IF lClose
				oObject:ENDwindow()											// Instead of close Close()
				IC2GetAppObject ():aOpenWindows [NI] := NULL_OBJECT
			ENDIF
			IF lFocus
				oObject:SetFocus()											//Show current window 17-8-2007
			ENDIF	
		ENDIF
	ENDIF
NEXT
IF lReturnWindow
	RETURN nWindow
ELSE
	RETURN lFound
ENDIF

RETURN lFound

Dick
User avatar
claudiocarletta
Posts: 101
Joined: Sat Sep 05, 2020 8:56 am

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by claudiocarletta »

Grazie
Ciao
User avatar
wriedmann
Posts: 3644
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by wriedmann »

Ciao Claudio,
personalmente non chiuderei la seconda istanza, ma non la farei aprire.
Visto che probabilmente la DataWindow viene aperta tramite il menu, crea semplicemente una metodo della ShellWindow con il nome della DataWindow:

Code: Select all

method PermessiWindow() class StandardShellWindow
if lNewPermessi
  InfoMessage{ self, "Permessi", "la finestra è già aperta" }:Show()
else
  PermessiWindow{ self }:Show()
endif
Saluti
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Jamal
Posts: 314
Joined: Mon Jul 03, 2017 7:02 pm

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by Jamal »

Ciao Claudio,

You can try to override the Show() method of the datawindow.

Code: Select all

method Show(kStyle) Class YourWindow

    if !lNewPermessi	 
	    lNewPermessi = true
            Super:Show(kStyle)
    endif
return self
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by Karl-Heinz »

Hi Claudio,

Maybe the translation from ITA to GER missed something important ?,

ma perché non disabilitare semplicemente la voce di menu tramite <oMenu>:DisableItem(<nItemID>) quando la finestra viene aperta, in modo che l'utente veda che una seconda istanza non può essere aperta. Quando la finestra viene chiusa, abilita nuovamente la voce di menu tramite <oMenu>:EnableItem(<nItemID>).

tradotto via deepl.com da GER a ITA

regards
Karl-Heinz
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by robert »

Dick,

PMFJI

Code: Select all

FUNCTION  CheckOpenChildWindow( sObject AS SYMBOL,lClose AS LOGIC ,lFocus AS LOGIC ,lReturnWindow AS LOGIC) AS USUAL PASCAL
Really?
One function that either closes a window, sets focus or returns a window ?
I don't want to be arrogant, but this is a really bad example.
Have you guys ever heard of "The Single Responsibility Principle".
I would split this in:
FindOpenWindow() -> returns the Window object or NULL_OBJECT
CloseWindow() : uses FindOpenWindow() to find the window and when it is found then it closes the window with EndWindow() and removes it from the array by calling DeleteChildWindow .
Can return TRUE when found and FALSE when not found.
FocusWindow(): uses FindOpenWindow() to find the window and when it is found then it sets the focus to the window.
Can return TRUE when found and FALSE when not found.

And why are you returning the nWindow of the window when you are returning a value and not the object itself ?

Something else:
Your aOpenWindows array keeps growing (based on the code that you have shared)

AddChildWindow() always uses AAdd()
DeleteChildWindow and CheckOpenChildWindow with lClose parameter sets the element to NIL.
After you have opened and closed 100 windows you will have an array of 100 elements with 100 x NIL.
Opening the 101st window adds another element to that array.
I understand that the position in the array is important (because you are returning nWindow
from CheckOpenChildWindow) but normally you would ADel() the element where the object is and
shrink the array with one element ASize(aOpenWindows , ALen(aOpenWindows )-1).

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
ic2
Posts: 1798
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by ic2 »

Hello Robert,

I don't know why anymore why we have modified the DeleteChildWindow to not remove the object from the array, but have modified the (original) method from the South Sea Adventures and no doubt we had a good reason for that. That a user can end up with 100's of null_object array elements doesn't bother me at all. If a user wants to concentrate to only open and close windows until the program crashes he will probably see that happen after a few days of unceasingly doing that and nothing else. Very unlikely behaviour I'd say..

This part of the program has served us well during 20 years, without any issues and I am not going to modify it because it can be done differently with, basically, only an advantage for the user who never closes the program. We actually discourage that (by emphasizing that users should sign off from RD sessions which some clients do well and others don't).

If our program crashes because of someone neglected this and has collected several 10.000's of array elements (because that's were we are talking about, at least) causing the program to crash, then this is a very good reason to keep it that way.

In the meantime I will concentrate on more useful changes in our programs than code which has worked well despite being "a bad example" according to you.

Dick
User avatar
claudiocarletta
Posts: 101
Joined: Sat Sep 05, 2020 8:56 am

Forzare la chiusura di una DATAWINDOW in un'applicazione MDI di VisualObject

Post by claudiocarletta »

Ciao Wolfgang,
Scusa per il ritardo ma sono stato fuori sede e non ho potuto dedicarmi al progetto (fuori sede).
Appena ho letto sullo smartphone il tuo consiglio ho pensato che fosse quello giusto, solo oggi l'ho potuto provare.
Tutto perfetto.
Grazie sempre
Saluti
Claudio
Post Reply