xsharp.eu • Bringing a VO window to the top
Page 1 of 2

Bringing a VO window to the top

Posted: Wed Nov 09, 2022 3:14 am
by JohnBonnett88
Hi All,

I have another VO GUI problem.

The VO application I have converted to X# starts with a main shell window with a number of buttons. Clicking on one of those brings up various MDI shell windows for different application areas in the system.

When it was running in VO, clicking one of those buttons, pushed the main shell into the background and brought the newly opened window to the top. This does not happen in the X# version.

The relevant code, exported from VO, seems to be

oWin := CreateInstance(symShell, SELF)
BringWindowToTop(oWin:Handle())

That BringWindowToTop doesn't, and on searching for ideas I see other people have this problem too, completely outside of VO.

I have also tried replacing BringWindowToTop with SetForegroundWindow, as suggested in other forums, but that does not work either.
Even just having a way to minimise the initial window would be a solution.
Any ideas about what I should try?

Is there a source of VO GUI documentation about this sort of thing? I also have some differences from VO in which control receives focus when a form opens that I need to resolve.

Best Regards,
John Bonnett

Bringing a VO window to the top

Posted: Wed Nov 09, 2022 7:40 am
by Chris
Hi John,

Not aware of anything like this, can you please create and send a small sample showing how this works as you expect in VO, but not in X#?

Bringing a VO window to the top

Posted: Wed Nov 09, 2022 10:28 am
by FFF
John,
i can't remember ever having seen a "Shellwindow" with buttons, always thought it can contain only Datawindows, dialogs, menu and toolbar. Equally, didn't know a shellwindow can hold other shellwindows. So, as Chris said, give us a minimal sample, pls.

Bringing a VO window to the top

Posted: Wed Nov 09, 2022 5:34 pm
by Karl-Heinz
JohnBonnett88 post=24376 userid=6661 wrote:
The relevant code, exported from VO, seems to be

oWin := CreateInstance(symShell, SELF)
BringWindowToTop(oWin:Handle())
I doubt that the window becomes visibel if you´re running such code with VO . You don´t need BringWindowToTop(oWin:Handle()) or SetForegroundWindow(oWin:Handle()). What´s missing is a Show().

Code: Select all

oWin := CreateInstance(symShell, SELF)
oWin:Show()


regards
Karl-Heinz

Bringing a VO window to the top

Posted: Wed Nov 09, 2022 11:29 pm
by JohnBonnett88
Thanks to all who replied, I will reply to each of you.

Firstly to Chris,
I will try to make a small sample, but I don't have VO, and never have. I am working totally in X# in VS. The creators of the system are effectively defunct now, so I got the AEF files, ran the Xporter and have been working in X# since. It's a big system and we now have lots working. We are now cleaning up details like which window is on top, which control has focus etc.

To FFF,
You are right, on closer inspection the initial window inherits from DATAWINDOW, and so can have buttons. I was misled by the fact that the window class in the code is called WholeShell2.
The sub-windows that get opened from this startup window do inherit from ShellWindow and are MDI windows. What I am trying to achieve is that, when a sub-window is opened, it becomes the top window. Currently the startup window stays on top.

To Karl-Heinz,
I did not show the full story. Here is more complete code

oWin := CreateInstance(symShell, SELF)
BringWindowToTop(oWin:Handle())
AAdd(SELF:aWindowsUp,{Upper(cName), oWIn:Handle(), oWin:Caption})
oWin:Show(iif(lZoomed,SHOWZOOMED,NIL))

That AAdd is about keeping track of which sub-windows are currently open. The Show is there, but it occurred to me that perhaps I should only try bring to top after the Show, so one variation I tried was this

oWin := CreateInstance(symShell, SELF)
AAdd(SELF:aWindowsUp,{Upper(cName), oWIn:Handle(), oWin:Caption})
oWin:Show(iif(lZoomed,SHOWZOOMED,NIL))
SetForegroundWindow(oWin:Handle())

This uses that alternate way of making a top window, but it did not work either.

In my researches I discovered there are lots of rules in Windows about who can bring windows to the top, so perhaps I am still doing something wrong. I will keep trying.

Best Regards,
John

Bringing a VO window to the top

Posted: Thu Nov 10, 2022 7:20 am
by jonhn
I use this in my app to check if the window class is already open, and check if it is for the same job, or a different one and bring it to the top if

Code: Select all

correct. It works like magic.

  //   See if the JobPlanWindow is open and if so, bring it to top and focus!
  aBrse:={}
  aBrse:=SELF:Owner:GetAllChildren()
   FOR i:=1 TO ALen(aBrse)
         IF ClassName (aBrse [i]) = #JobPlanWindow2
              	TheWindow :=aBrse[i]:oDCsleHireNo:TextValue
         	IF AllTrim(TheWindow) = AllTrim(TheHireNo)
         	     * Then it is open on this very machine, already...
                       GotIt:=TRUE
                       aBrse[i]:show()
                      aBrse[i]:ToTop()
         	      aBrse[i]:SetFocus()
         	      EXIT
         	ENDIF  //  It is the actual matching window
         ENDIF  //   If you actually found a JobPlanWindow
   NEXT i

HTH. Jonathan

Bringing a VO window to the top

Posted: Thu Nov 10, 2022 2:51 pm
by Karl-Heinz
Hi John,

There must be something else going wrong on your side. As a test i created a Datawindow with two Pushbuttons. Each time i open a new Shell window.the window becomes the Top window - no matter if i´m using VO or X#.

Code: Select all

oWin := CreateInstance(symShell, SELF)
oWin:Show()

To see what i did extract the attached WinShell.zip and then doubleclick the WinShell.gif

btw. What happens when you try SetWindowPos() ?

Code: Select all

oWin := CreateInstance(symShell, SELF) 
SetWindowPos(oWin:Handle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE  | SWP_SHOWWINDOW )	
regards
Karl-Heinz

Bringing a VO window to the top

Posted: Fri Nov 11, 2022 4:24 am
by JohnBonnett88
Hi Karl-Heinz,

Thanks for your reply. Your suggestion about SetWindowPos fixed it for me.

By the way, that example you sent was neat. I had never seen a GIF used to make a short animation like that!

Thanks again,
John

Bringing a VO window to the top

Posted: Fri Nov 11, 2022 6:53 am
by FFF
John,
I think he used screen2gif, it's free and very simple to use. Hint: you have to hide the gif into a zip, if you want to use it on this site, if you post directly, somehow the animation gets lost...

Bringing a VO window to the top

Posted: Tue Nov 29, 2022 12:06 am
by JohnBonnett88
Hi All,
Karl-Heinz suggestion certainly got the window to the top for me but it had the undesirable property of wanting to stay on top regardless of anything else. I guess that's what TOPMOST means! I first encountered this when debugging, the window had become TOPMOST and VS had stopped at a breakpoint but VS was behind the window so I could not access it. Various tricks of moving things to other monitors got me untangled but I also got feedback from users of the application that these TOPMOST windows were a pain.

I chatted with one of my C++ colleagues and he said that he had also encountered this sort of thing. He had got around it by making the window TOPMOST, but also setting a timer to make the window only TOP shortly after. I set about implementing that using the VO SetTimer function. I stumbled a bit with this because, although there were SetTimer calls already in the app I am working on, none of them called a timer function, and I could not find an example anywhere else where the TimerFunc was anything but NULL_PTR.

Since I am running in X# and have all the .NET environment with other timers available, I switched to using System.Threading.Timer. Curiously I had a similar problem with getting the syntax of the parameter that specified the timer function, even though I had good documentation and examples to follow, but not in X#. I got another colleague to look over my code and he made one suggestion that fixed it. In X# you learn to treat USUAL as the equivalent of OBJECT in .NET, and notionally it is, but apparently not quite equivalent enough for function signatures to match.

Here is the code I came up with in case it helps someone else.
The following code creates the window I want to come up on top, adds it to an array of currently open windows, sets it TOPMOST, sets up the timer and shows the window.

oWin := CreateInstance(symShell, SELF)
AAdd(SELF:aWindowsUp,{Upper(cName), oWIn:Handle(), oWin:Caption})
SetWindowPos(oWin:Handle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW )
// Set timer to stop window being TOPMOST after a half second
System.Threading.Timer{TimerCallback{oWin:ShownTopMost}, null, 500, Timeout.Infinite}
oWin:Show(iif(lZoomed,SHOWZOOMED,NIL))

Here is the function that executes when the the timer elapses after half a second. That "As Object" in the parameter is the last thing I fixed to make it work. I previously had "AS Usual". This method is in the base class of the family of windows I need to go to the top

/// <summary>
/// Sets window shown as TOPMOST back to just TOP
/// </summary>
/// <param name="stateInfo">Unused, but needed to match Delegate System.Threading.TimerCallback</param>
METHOD ShownTopMost(stateInfo AS Object) AS VOID
SetWindowPos(SELF:Handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW )
RETURN NIL

Best Regards,
John