Can I make the Plan Box window stay above all other windows?

I really like the Plan Box window for its ‘clean’ optics (no title bar) but if the user clicks another window this window disappears behind other open windows unlike floating window for instance.
Is it possible to make it “Always on Top”?

Declares may make that possible
Or use a floating windows or global floating window type ?

Well, floating windows and global floating window both have title bar which I would prefer not to see in this case…

Declares may make that possible
Any idea how?

The answer is going to be different depending on which platform(s) you’re targeting, if you go the API route.

Targets: macOS and Windows All
I was hoping for a simple click or tick, but it sounds like it’s gonna get complicated :laughing:

For macOS I use this code:

Public Sub AlwaysOnTop(extends w as Window, assigns Value as Boolean)

//# Sets the window’s window level to floating window level.

#if TargetCocoa then
Const NSNormalWindowLevel = 0
Const NSFloatingWindowLevel = 3
Const NSModalPanelWindowLevel = 8
Const NSDockWindowLevel = 20
Const NSMainMenuWindowLevel = 24
Const NSPopUpMenuWindowLevel = 101
Const NSScreenSaverWindowLevel = 1001

declare sub NSWindowSetLevel lib "Cocoa" selector "setLevel:" (WindowRef as integer, Level as Integer)
if Value then
  NSWindowSetLevel w.Handle, NSFloatingWindowLevel
else
  NSWindowSetLevel w.Handle, NSNormalWindowLevel
end if

#else
#pragma Unused w
#pragma Unused Value
#endif
End Sub

1 Like

Wow, that’s great Carlo !
unfortunately if I only have a macOS solution I’ll have to stick with the floating window model to produce unified behavior on both platforms the app is targeting, but I much appreciate your sharing!

1 Like

Still trying to crack this as @Carlo_Rubini already posted a good macOS solution I’m trying to compile an equivalent Windows extender.
So after some searching I have found a VB code that could be useful but I’m not knowledgeable enough to complete the translation into a working Xojo window extender:

Public Sub TopMost(extends windX as Window, assigns Value as Boolean)
#if TargetWindows Then
  
  Var lFlag as long
  
  If Value then
    lFlag = HWND_TOPMOST
  else
    lFlag = HWND_NOTOPMOST
  end if
  
    Call SetWindowPos(windX.hwnd, lFlag, 0&, 0&, 0&, 0&, (SWP_NOSIZE Or SWP_NOMOVE)) ' Place your winform on top

#endif
End Sub

Anyone care to lend me a hand cracking this?

And There’s this as well: (not sure if that helpful at all)

Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, y, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOSIZE = &H1
Private Const TOPMOST_FLAGS = SWP_NOMOVE Or SWP_NOSIZE

Public Sub MakeNormal(hwnd As Long)
    SetWindowPos hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS
End Sub
Public Sub MakeTopMost(hwnd As Long)
    SetWindowPos hwnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS
End Sub

Did you search the forum? I think this question (or similar) has been asked before. I did a quick search and found the following:

Thanks @LangueR !
I did search but oddly didn’t found what you have probably because I searched Always-On-Top and not TopMost or Floating window.
I will look into it :pray:

Okay, so I tried all the above options and none of them worked or at least I couldn’t find how to adapt them to an up-to-date 64 bit Windows and current Xojo code as I’m unfamiliar with the old REAL/Xojo syntax (I started using it only two years ago).

In the meantime I built a kind of a workaround that works with Window.TheParent when I call the window to open, monitor movement in the moved event and constantly updating TheParent and in the deactivate event I put Me.Hide and call a timer set to 5 ms that pushes the window back up after it gets deactivate and hidden.
I also added a boolean so I can tel when the user really wants to hide this window and in this case the timer will not get activated, with all of the above the window stay on top of the other (main) app window and in case the user moves the main window the floating Window follows it keeping itself right in the center of the main window.

Works for now until I’ll find a better solution.

Best,
Sagi

For Windows the code is

Dim l,w,t,h As Integer

l = Self.Left
t = Self.top
h = Self.Height
w = Self.Width

Declare Function SetWindowPos Lib "User32" (ByVal hwnd As Int32, ByVal hWndInsertAfter As Int32, ByVal x As Int32, ByVal y As Int32, ByVal cx As Int32, ByVal cy As Int32, ByVal uFlags As Int32) As Int32

Const HWND_BOTTOM = 1
Const HWND_NOTOPMOST = -2
Const HWND_TOP = 0
Const HWND_TOPMOST = -1

Call SetWindowPos(Self.Handle, HWND_TOPMOST, l, t,w,h,0)

where you put this will depend - it currently assumes this is in a method or event of whatever window you want to make top most (hence the use of SELF)

You might put it in the open even of whatever window you want to make top most
and it will stay there

1 Like

Amazing @Norman_Palardy!!!
Now I see my stupid error, I copied this: “user32” and you just used “User32”
I couldn’t understand why I keep getting user32 doesn’t exist error and now I get it, it wasn’t because the 64 bit Windows, it’s simply because I used the wrong quotes :scream:
Thank you very very much, you’re my angel above :smiley:

Angel - no
Helpful - I try :slight_smile:

2 Likes

I got excited too soon…:frowning_face:
It indeed works in terms that it doesn’t produces any errors but it doesn’t do anything, not even a shred of change in behavior of the window’s (any window) topping priority, not even placing the window at the top of the Z order as far as I can tell.
Is it possible the Window.Handle passes incorrect window identifier into the argument or any other idea what can shed some light on what might be the problem?

What xojo window type are you trying this on?
What event did you put this code in?
What version of xojo are you using?

  1. I tried on Plan Box and Document.
  2. I tied directly in the window open event and as Public Sub TopMost(extends wT as Window) on a module.
  3. I tried in Xojo 2019r3.1 and Xojo 2019r3.2
  4. I also tried taking one of the simple desktop example projects to see if it changes anything because my own projects are all SingleInstanceApps and have IPCSockets on them. but that didn’t change anything for the better so I assume all of the above has nothing to do with the problem.
  5. Testing on Win10 pro v1909 64 bit and the SetWindowPos function works well when I try it not via Xojo.

When you click the button here, does the window stay on top for you?


EDIT:Link corrected

Window2 is already Top Most when I run the project and clicking the button doesn’t do anything to either one of the windows.