Page 1 of 1
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 7:09 am
by Frank Müßner
Hello,
I try to display a splash screen at startup. The SplashScreen is a DevExpress component.
So that the SplashSreen is updated, I think it has to be started in a separate task.
Unfortunately I get this error:
Code: Select all
System.ArgumentNullException: Der Wert darf nicht NULL sein.
Parametername: start
bei System.Threading.Thread..ctor(ThreadStart start)
bei XApp.Start(__Usual[] Xs$Args) in F:VSVisual Studio 2017XSWinQuickDev20VOMDIApp1Start.prg:Zeile 21.
bei VOMDIApp.Exe.Functions.Start() in F:VSVisual Studio 2017XSWinQuickDev20VOMDIApp1Start.prg:Zeile 8.
But the SplashSreen is Show.
My code is:
Code: Select all
USING System
USING System.Threading.Tasks
[STAThread];
FUNCTION Start() AS INT
LOCAL oXApp AS XApp
TRY
oXApp:=XApp{}
oXApp:Start()
CATCH oException AS Exception
ErrorDialog(oException)
END TRY
RETURN 0
CLASS XApp INHERIT App
METHOD Start()
LOCAL oMainWindow AS StandardShellWindow
local i AS DWORD
local thread1 as System.Threading.Thread
thread1:=System.Threading.Thread{XApp:ShowSreen()}
thread1:Start()
//Do Some Start routine
For I:=1 to 100
sleep(50)
NEXT
//how to close the SplashSreen Form? Kill the Task?
thread1:Abort()
oMainWindow:Show(SHOWCENTERED)
local Nw1 as Window1
Nw1:=Window1{oMainWindow}
Nw1:Show()
SELF:Exec()
RETURN NIL
Static method ShowSreen() as System.Threading.ThreadStart
Local sp as AuftragSQLKasseCSWinForms.SplashScreen1
sp:=AuftragSQLKasseCSWinForms.SplashScreen1{}
sp:Show()
return
END CLASS
What am i thinking wrong?
VS2019 / X#2.4a
Regards, Frank
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 7:17 am
by SHirsch
Hallo Frank,
try this:
Code: Select all
thread1:=System.Threading.Thread{ThreadStart{ShowSreen}}
...
method ShowSreen() as void
Local sp as AuftragSQLKasseCSWinForms.SplashScreen1
sp:=AuftragSQLKasseCSWinForms.SplashScreen1{}
sp:Show()
return
Stefan
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 7:34 am
by Frank Müßner
Hi Stefan,
Thanks for your two examples.
I have change:
Code: Select all
thread1:=System.Threading.Thread{ShowSreen}
...
Static method ShowSreen() as void
Local sp as AuftragSQLKasseCSWinForms.SplashScreen1
sp:=AuftragSQLKasseCSWinForms.SplashScreen1{}
sp:Show()
Error:
Code: Select all
XS1503 Argument 1: cannot convert from 'method' to 'System.Threading.ThreadStart'
Code: Select all
thread1:=System.Threading.Thread{ThreadStart{ShowSreen}}
...
method ShowSreen() as void
Local sp as AuftragSQLKasseCSWinForms.SplashScreen1
sp:=AuftragSQLKasseCSWinForms.SplashScreen1{}
sp:Show()
Error:
Code: Select all
XS0123 No overload for 'ShowSreen' matches delegate 'System.Threading.ThreadStart'
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 9:19 am
by Chris
Hi Frank,
Most likely you have the /vo5 compiler option enabled, and this options makes methods without parameters to be emitted as CLIPPER methods, which are indeed incompatible with the ThreadStart delegate and this is why you get that error message.
Please add the STRICT clause to the method declaration and it should work fine:
Static method ShowSreen() as void STRICT
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 9:39 am
by Frank Müßner
Hi Chris,
you are right, the option /VO5 is activated.
I no longer get an error message, and the method ShowSreen() is called , but the SplashSreen is not displayed either. Another tip on what I'm doing wrong?
My final Code:
Code: Select all
CLASS XApp INHERIT App
METHOD Start()
LOCAL oMainWindow AS StandardShellWindow
local i AS DWORD
oMainWindow := StandardShellWindow{}
local thread1 as System.Threading.Thread
thread1:=System.Threading.Thread{ThreadStart{ShowSreen}}
thread1:Start()
//Do Some Start routine
For I:=1 to 100
sleep(50)
NEXT
thread1:Abort()
oMainWindow:Show(SHOWCENTERED)
local Nw1 as Window1
Nw1:=Window1{oMainWindow}
Nw1:Show()
SELF:Exec()
RETURN NIL
Static method ShowSreen() as void STRICT
Local sp as AuftragSQLKasseCSWinForms.SplashScreen1
sp:=AuftragSQLKasseCSWinForms.SplashScreen1{}
sp:Show()
return
return
END CLASS
FRank
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 1:15 pm
by Chris
Hi Frank,
Maybe you need to use ShowDialog() instead of Show()? At least for regular forms, you'd need to use ShowDialog(), not sure how this particular component works.
If that still doesn't work, try using a simple regular (empty) Form instead, does it work with that? If yes, then we need to find what is special about this component.
But a general comment, I do not think you need a thread anyway. You'd need a thread in order to do things in parallel, but when you just want to show a splash screen for a while, you can simply do it in the Start() function. Or maybe I did not understand correctly how you plan to use this?
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 2:25 pm
by Frank Müßner
Hi Chris,
normal Winforms work with Show() That i have tested.
I can not use ShowDialog() this is modal. So the Program Stop at ShowDialog().
I think the Problem is the DexExpress Control.
i am looking for another solution, need more time
Thanks, Frank
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 3:07 pm
by Chris
Hi Frank,
You do not have a message loop running when you are showing the window, so I believe a simple Show() will just show the window for a brief moment and it will close right after. Did you have success using the exact same code with a regular windows forms Form?
Btw, another thing that you need to pay attention when using threads and GUI, is that you need to make sure you have included a STAThread attribute on your Start() funcntion:
[STAThread];
FUNCTION Start() AS VOID
How can I display a SplashSreen?
Posted: Mon Jul 13, 2020 4:53 pm
by Karl-Heinz
Hi Frank,
When you build with VO a StandardMDI app there´s also a splash window included. The splash window is created at the beginning of the VO App Start() and it´s destroyed via a timer. That´s the content of the SplashScreen Show() method.
Code: Select all
METHOD Show(kShowState) CLASS SplashScreen
SUPER:show(kShowState)
// Make window topmost
SetWindowPos(SELF:handle(), HWND_TOPMOST, 0, 0, 0, 0, DWORD(_OR(SWP_NOSIZE, SWP_NOMOVE)))
// Register Timer
SELF:RegisterTimer(3, TRUE)
// Remove the following two lines if you don't want to show the Splashscreen separatly
GetAppObject():Exec(EXECWHILEEVENT)
Sleep(1000)
RETURN NIL
METHOD Timer() CLASS SplashScreen
SELF:Destroy()
RETURN SELF
But you don´t really need a timer. Just paint a centered and *
modeless* DialogWindow. Now your X# Start() method might look like:
Code: Select all
METHOD Start()
LOCAL oMainWindow AS StandardShellWindow
// ------------------
LOCAL oSplashScreen := DlgSplash{SELF}
oSplashScreen:Show()
// Make window topmost
// SetWindowPos(SELF:handle(), HWND_TOPMOST, 0, 0, 0, 0, DWORD(_OR(SWP_NOSIZE, SWP_NOMOVE)))
DoEvents() // ensures that the content of the splash window is drawn !
Sleep(1000)
// -----------
oMainWindow := StandardShellWindow{}
oMainWindow:Show(SHOWCENTERED)
local Nw1 as Window1
Nw1:=Window1{oMainWindow}
Nw1:Show()
oSplashScreen:Destroy() // <---------
SELF:Exec()
RETURN NIL
Regards
Karl-Heinz
How can I display a SplashSreen?
Posted: Tue Jul 14, 2020 7:04 am
by Frank Müßner
@ Chris,
Regular windows forms Form is show normal. The DevExpress SplashScreen need DoEvents() to show correctly.
I have [STAThread];
but not work.
@Karl-Heinz,
the normal *modeless* DialogWindow. is not nice as the DevExpress Control
Fadein Fadeout .
I have now this working code:
Code: Select all
CLASS XApp INHERIT App
METHOD Start()
LOCAL oMainWindow AS StandardShellWindow
LOCAL I as DWORD
local SplashScreenHelper AS AuftragSQLKasseCSWinForms.XSTools
SplashScreenHelper:=AuftragSQLKasseCSWinForms.XSTools{}
SplashScreenHelper:TestAsyncWaitForm()
For I:=1 to 100
sleep(50)
NEXT
SplashScreenHelper:nStatus=1 //Close
For I:=1 to 20
sleep(50)
DoEvents()
if SplashScreenHelper:nStatus=0 //is Closed
Exit
endif
next
SplashScreenHelper:=NULL_OBJECT
oMainWindow := StandardShellWindow{SELF}
oMainWindow:Show(SHOWCENTERED)
SELF:Exec()
RETURN NIL
END CLASS
Code: Select all
public class XSTools
{
public Int16 nStatus;
public async void TestAsyncWaitForm()
{
SplashScreenManager.ShowForm(typeof(SplashScreen1), true, false);
await Task.Run(() =>
{
for (int i = 0; i < 200; i++)
{
System.Threading.Thread.Sleep(100);
if (nStatus == 1)
{
i = 300;
}
}
});
SplashScreenManager.CloseForm();
nStatus = 0;
}
}
This work and I hope there are no side effects.
Frank