Targets: macOS and Windows All
I was hoping for a simple click or tick, but it sounds like it’s gonna get complicated
Targets: macOS and Windows All
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
#pragma Unused w
#pragma Unused Value
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!
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
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.
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
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
Thank you very very much, you’re my angel above
Angel - no
Helpful - I try
I got excited too soon…
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?
- I tried on Plan Box and Document.
- I tied directly in the window open event and as Public Sub TopMost(extends wT as Window) on a module.
- I tried in Xojo 2019r3.1 and Xojo 2019r3.2
- 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.
- 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?
Window2 is already Top Most when I run the project and clicking the button doesn’t do anything to either one of the windows.
Re-download the project. But the window does stay topmost? Is that not what you’re seeing when you try?
I don’t need to re-download I already fixed the button action to show/hide window2 and it works as it should, but when I copy paste this exact code into a new window in my project and set a button just like your example it doesn’t work… any idea what can interfere with that?
The window you create in your existing project, does it have a Super of Window or something else?
Do you have any other declares in your project?
Does your code have a WindowProc callback?
Here you have one of my projects, you can try using it and see: