Posts: 733
Threads: 103
Joined: Apr 2022
Reputation:
14
Is there a command or way to set your program to stay on top of other windows (and keep running), even if it doesn't have the focus?
If there is, then I want to make line 31 enable always on top in the programs below, and line 34 disable always on top.
Is this possible? Any info appreciated!
Program #1:
Code: (Select All) Const cProgName = "Program #1": _Title cProgName
Const FALSE = 0: Const TRUE = Not FALSE
' TEXT MODE COLORS:
Const cBlack = 0: Const cBlue = 1: Const cGreen = 2: Const cLtBlue = 3
Const cRed = 4: Const cPurple = 5: Const cOrange = 6: Const cWhite = 7
Const cGray = 8: Const cPeriwinkle = 9: Const cLtGreen = 10: Const cCyan = 11
Const cLtRed = 12: Const cPink = 13: Const cYellow = 14: Const cLtGray = 15
' COUNT UNTIL USER HITS ESC
Screen 12 ' SCREEN 12 can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
Cls , cBlue
Color cWhite, cBlue
Dim iLoop As Integer
Dim bOnTop As Integer: bOnTop = FALSE
Locate 5, 20 ' y,x where 1,1 = top left
Print cProgName
Locate 10, 20
Print "Press A to stay on top, B for background"
Locate 25, 20 ' y,x where 1,1 = top left
Print "Hold down ESC to exit."
For iLoop = 0 To 10000
Locate 15, 20
Print IIFSTR$(bOnTop, "STAY ON TOP", "BACKGROUND ")
Locate 20, 20 ' y,x where 1,1 = top left
Print _Trim$(Str$(iLoop)) + " "
While _DeviceInput(1): Wend ' clear and update the keyboard buffer
If _KeyDown(Asc("a")) Or _KeyDown(Asc("A")) Then
bOnTop = TRUE
'(ENABLE ALWAYS STAY ON TOP)
ElseIf _KeyDown(Asc("b")) Or _KeyDown(Asc("B")) Then
bOnTop = FALSE
'(DISABLE ALWAYS STAY ON TOP)
End If
If _KeyDown(27) Then Exit For ' leave loop when ESC key pressed
_Limit 4 ' keep loop at 4 frames per second
Next iLoop
End
Function IIF (Condition, IfTrue, IfFalse)
If Condition Then IIF = IfTrue Else IIF = IfFalse
End Function
Function IIFSTR$ (Condition, IfTrue$, IfFalse$)
If Condition Then IIFSTR$ = IfTrue$ Else IIFSTR$ = IfFalse$
End Function
Program #2:
Code: (Select All) Const cProgName = "Program #2": _Title cProgName
Const FALSE = 0: Const TRUE = Not FALSE
' TEXT MODE COLORS:
Const cBlack = 0: Const cBlue = 1: Const cGreen = 2: Const cLtBlue = 3
Const cRed = 4: Const cPurple = 5: Const cOrange = 6: Const cWhite = 7
Const cGray = 8: Const cPeriwinkle = 9: Const cLtGreen = 10: Const cCyan = 11
Const cLtRed = 12: Const cPink = 13: Const cYellow = 14: Const cLtGray = 15
' COUNT UNTIL USER HITS ESC
Screen 12 ' SCREEN 12 can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
Cls , cRed
Color cWhite, cRed
Dim iLoop As Integer
Dim bOnTop As Integer: bOnTop = FALSE
Locate 5, 20 ' y,x where 1,1 = top left
Print cProgName
Locate 10, 20
Print "Press A to stay on top, B for background"
Locate 25, 20 ' y,x where 1,1 = top left
Print "Hold down ESC to exit."
For iLoop = 10000 To 0 Step -1
Locate 15, 20
Print IIFSTR$(bOnTop, "STAY ON TOP", "BACKGROUND ")
Locate 20, 20 ' y,x where 1,1 = top left
Print _Trim$(Str$(iLoop)) + " "
While _DeviceInput(1): Wend ' clear and update the keyboard buffer
If _KeyDown(Asc("a")) Or _KeyDown(Asc("A")) Then
bOnTop = TRUE
'(ENABLE ALWAYS STAY ON TOP)
ElseIf _KeyDown(Asc("b")) Or _KeyDown(Asc("B")) Then
bOnTop = FALSE
'(DISABLE ALWAYS STAY ON TOP)
End If
If _KeyDown(27) Then Exit For ' leave loop when ESC key pressed
_Limit 4 ' keep loop at 4 frames per second
Next iLoop
End
Function IIF (Condition, IfTrue, IfFalse)
If Condition Then IIF = IfTrue Else IIF = IfFalse
End Function
Function IIFSTR$ (Condition, IfTrue$, IfFalse$)
If Condition Then IIFSTR$ = IfTrue$ Else IIFSTR$ = IfFalse$
End Function
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
05-17-2024, 11:27 PM
(This post was last modified: 05-17-2024, 11:28 PM by SMcNeill.)
https://qb64phoenix.com/qb64wiki/index.p...ost_Window
Code: (Select All) 'public domain
CONST SWP_NOSIZE = &H0001 'ignores cx and cy size parameters
CONST SWP_NOMOVE = &H0002 'ignores x and y position parameters
CONST SWP_NOZORDER = &H0004 'keeps z order and ignores hWndInsertAfter parameter
CONST SWP_NOREDRAW = &H0008 'does not redraw window changes
CONST SWP_NOACTIVATE = &H0010 'does not activate window
CONST SWP_FRAMECHANGED = &H0020
CONST SWP_SHOWWINDOW = &H0040
CONST SWP_HIDEWINDOW = &H0080
CONST SWP_NOCOPYBITS = &H0100
CONST SWP_NOOWNERZORDER = &H0200
CONST SWP_NOSENDCHANGING = &H0400
CONST SWP_DRAWFRAME = SWP_FRAMECHANGED
CONST SWP_NOREPOSITION = SWP_NOOWNERZORDER
CONST SWP_DEFERERASE = &H2000
CONST SWP_ASYNCWINDOWPOS = &H4000
CONST HWND_TOP = 0 'window at top of z order no focus
CONST HWND_BOTTOM = 1 'window at bottom of z order no focus
CONST HWND_TOPMOST = -1 'window above all others no focus unless active
CONST HWND_NOTOPMOST = -2 'window below active no focus
DECLARE DYNAMIC LIBRARY "user32"
FUNCTION FindWindowA%& (BYVAL lpClassName%&, BYVAL lpWindowName%&)
FUNCTION SetWindowPos& (BYVAL hWnd%&, BYVAL hWndInsertAfter%&, BYVAL X&, BYVAL Y&, BYVAL cx&, BYVAL cy&, BYVAL uFlags~&)
FUNCTION GetForegroundWindow%&
END DECLARE
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION GetLastError~& ()
END DECLARE
DIM t AS STRING
DIM hWnd AS _OFFSET
RANDOMIZE TIMER
t = HEX$(RND * &H1000000) 'random title for FindWindowA
_TITLE t
t = t + CHR$(0)
hWnd = _WINDOWHANDLE 'FindWindowA(0, _OFFSET(t))
_TITLE "This Window will always be on Top" 'any title
_DELAY 4 'delay allows user to click focus on other windows
'set as topmost window and move without sizing or activation
IF 0 = SetWindowPos(hWnd, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE OR SWP_NOACTIVATE) THEN
PRINT "SetWindowPos failed. 0x" + LCASE$(HEX$(GetLastError))
END IF
x%& = GetForegroundWindow%& 'find currently focused process handle
PRINT "Program handle:"; hWnd; "Focus handle:"; x%&
IF hWnd <> x%& THEN _SCREENCLICK 240, 240 'add 40 to x and y to focus on positioned window
END
Posts: 733
Threads: 103
Joined: Apr 2022
Reputation:
14
(05-17-2024, 11:27 PM)SMcNeill Wrote: https://qb64phoenix.com/qb64wiki/index.p...ost_Window
Interesting - I'll give this a try when back at the PC. Thanks!
Posts: 476
Threads: 25
Joined: Nov 2022
Reputation:
45
I wonder if it's possible to do this on Mac and Linux? If so, maybe we could add a $WINDOW_ONTOP:ON or something?
How difficult is it to add new things to the QB64PE sourcecode?
Has anyone ever documented that, or the steps required in a tutorial? We might be able to cast a wider net of PRs if we did.
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
(05-18-2024, 04:20 PM)grymmjack Wrote: I wonder if it's possible to do this on Mac and Linux? If so, maybe we could add a $WINDOW_ONTOP:ON or something?
How difficult is it to add new things to the QB64PE sourcecode?
Has anyone ever documented that, or the steps required in a tutorial? We might be able to cast a wider net of PRs if we did.
https://qb64forum.alephc.xyz/index.php?t...#msg108485 <-- There's my original guide to adding/altering QB64. Things may have been shuffled a bit (as we expand, we've restructured the folders a bit), but it's still the same basic process as it was back when I wrote that oh-so-many-moons-ago!
Posts: 733
Threads: 103
Joined: Apr 2022
Reputation:
14
05-19-2024, 03:24 PM
(This post was last modified: 05-19-2024, 03:45 PM by madscijr.
Edit Reason: fixed sample code again
)
(05-17-2024, 11:27 PM)SMcNeill Wrote: https://qb64phoenix.com/qb64wiki/index.p...ost_Window Fantastic!
Now once the program window is set to always be in the foreground, how would you change it back to a normal window?
I tried modifying my programs so
a window stays on top (HWND_TOPMOST) when the user presses the "a" key,
and goes back to normal (HWND_NOTOPMOST) when they press "b",
but it doesn't seem to be working...
Program #1 (blue):
Code: (Select All) ' McNeill - Super Moderator
' #2
' 05-17-2024, 07:27 PM (This post was last modified: 05-17-2024, 07:28 PM by SMcNeill.)
' https://qb64phoenix.com/qb64wiki/index.php/Windows_Libraries#Top_Most_Window
' public domain
Const cProgName = "Program #1": _Title cProgName
Const FALSE = 0: Const TRUE = Not FALSE
' TEXT MODE COLORS:
Const cBlack = 0: Const cBlue = 1: Const cGreen = 2: Const cLtBlue = 3
Const cRed = 4: Const cPurple = 5: Const cOrange = 6: Const cWhite = 7
Const cGray = 8: Const cPeriwinkle = 9: Const cLtGreen = 10: Const cCyan = 11
Const cLtRed = 12: Const cPink = 13: Const cYellow = 14: Const cLtGray = 15
Const SWP_NOSIZE = &H0001 'ignores cx and cy size parameters
Const SWP_NOMOVE = &H0002 'ignores x and y position parameters
Const SWP_NOZORDER = &H0004 'keeps z order and ignores hWndInsertAfter parameter
Const SWP_NOREDRAW = &H0008 'does not redraw window changes
Const SWP_NOACTIVATE = &H0010 'does not activate window
Const SWP_FRAMECHANGED = &H0020
Const SWP_SHOWWINDOW = &H0040
Const SWP_HIDEWINDOW = &H0080
Const SWP_NOCOPYBITS = &H0100
Const SWP_NOOWNERZORDER = &H0200
Const SWP_NOSENDCHANGING = &H0400
Const SWP_DRAWFRAME = SWP_FRAMECHANGED
Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
Const SWP_DEFERERASE = &H2000
Const SWP_ASYNCWINDOWPOS = &H4000
Const HWND_TOP = 0 'window at top of z order no focus
Const HWND_BOTTOM = 1 'window at bottom of z order no focus
Const HWND_TOPMOST = -1 'window above all others no focus unless active
Const HWND_NOTOPMOST = -2 'window below active no focus
Declare Dynamic Library "user32"
Function FindWindowA%& (ByVal lpClassName%&, Byval lpWindowName%&)
Function SetWindowPos& (ByVal hWnd%&, Byval hWndInsertAfter%&, Byval X&, Byval Y&, Byval cx&, Byval cy&, Byval uFlags~&)
Function GetForegroundWindow%&
End Declare
Declare Dynamic Library "kernel32"
Function GetLastError~& ()
End Declare
Dim t As String
Dim hWnd As _Offset
Dim iLoop As Integer
Dim bOnTop As Integer: bOnTop = FALSE
Screen 12 ' SCREEN 12 can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
Cls , cBlue
Color cWhite, cBlue
Randomize Timer
t = Hex$(Rnd * &H1000000) ' random title for FindWindowA
_Title cProgName + t ' _Trim$(Str$(t))
t = t + Chr$(0)
hWnd = _WindowHandle ' FindWindowA(0, _OFFSET(t))
_Title cProgName + t + ": This Window will always be on Top" ' any title
_Delay 4 ' delay allows user to click focus on other windows
' set as topmost window and move without sizing or activation
If 0 = SetWindowPos(hWnd, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) Then
Print "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
x%& = GetForegroundWindow%& ' find currently focused process handle
Print "Program handle:"; hWnd; "Focus handle:"; x%&
If hWnd <> x%& Then
_ScreenClick 240, 240 ' add 40 to x and y to focus on positioned window
End If
Locate 5, 20 ' y,x where 1,1 = top left
Print cProgName
Locate 10, 20
Print "Press A to stay on top, B for background"
Locate 25, 20 ' y,x where 1,1 = top left
Print "Hold down ESC to exit."
For iLoop = 10000 To 0 Step -1
Locate 15, 20
Print IIFSTR$(bOnTop, "STAY ON TOP", "BACKGROUND ")
Locate 20, 20 ' y,x where 1,1 = top left
Print _Trim$(Str$(iLoop)) + " "
While _DeviceInput(1): Wend ' clear and update the keyboard buffer
If _KeyDown(Asc("a")) Or _KeyDown(Asc("A")) Then
bOnTop = TRUE
'(ENABLE ALWAYS STAY ON TOP)
' set as topmost window and move without sizing or activation
If 0 = SetWindowPos(hWnd, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) Then
Locate 1, 1
Print "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
ElseIf _KeyDown(Asc("b")) Or _KeyDown(Asc("B")) Then
bOnTop = FALSE
'(DISABLE ALWAYS STAY ON TOP)
' set as topmost window and move without sizing or activation
If 0 = SetWindowPos(hWnd, HWND_NOTOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) Then
Locate 1, 1
Print "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
End If
If _KeyDown(27) Then Exit For ' leave loop when ESC key pressed
_Limit 4 ' keep loop at 4 frames per second
Next iLoop
End
Function IIF (Condition, IfTrue, IfFalse)
If Condition Then IIF = IfTrue Else IIF = IfFalse
End Function
Function IIFSTR$ (Condition, IfTrue$, IfFalse$)
If Condition Then IIFSTR$ = IfTrue$ Else IIFSTR$ = IfFalse$
End Function
Program #2 (red):
Code: (Select All) ' McNeill - Super Moderator
' #2
' 05-17-2024, 07:27 PM (This post was last modified: 05-17-2024, 07:28 PM by SMcNeill.)
' https://qb64phoenix.com/qb64wiki/index.php/Windows_Libraries#Top_Most_Window
' public domain
Const cProgName = "Program #2": _Title cProgName
Const FALSE = 0: Const TRUE = Not FALSE
' TEXT MODE COLORS:
Const cBlack = 0: Const cBlue = 1: Const cGreen = 2: Const cLtBlue = 3
Const cRed = 4: Const cPurple = 5: Const cOrange = 6: Const cWhite = 7
Const cGray = 8: Const cPeriwinkle = 9: Const cLtGreen = 10: Const cCyan = 11
Const cLtRed = 12: Const cPink = 13: Const cYellow = 14: Const cLtGray = 15
Const SWP_NOSIZE = &H0001 'ignores cx and cy size parameters
Const SWP_NOMOVE = &H0002 'ignores x and y position parameters
Const SWP_NOZORDER = &H0004 'keeps z order and ignores hWndInsertAfter parameter
Const SWP_NOREDRAW = &H0008 'does not redraw window changes
Const SWP_NOACTIVATE = &H0010 'does not activate window
Const SWP_FRAMECHANGED = &H0020
Const SWP_SHOWWINDOW = &H0040
Const SWP_HIDEWINDOW = &H0080
Const SWP_NOCOPYBITS = &H0100
Const SWP_NOOWNERZORDER = &H0200
Const SWP_NOSENDCHANGING = &H0400
Const SWP_DRAWFRAME = SWP_FRAMECHANGED
Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
Const SWP_DEFERERASE = &H2000
Const SWP_ASYNCWINDOWPOS = &H4000
Const HWND_TOP = 0 'window at top of z order no focus
Const HWND_BOTTOM = 1 'window at bottom of z order no focus
Const HWND_TOPMOST = -1 'window above all others no focus unless active
Const HWND_NOTOPMOST = -2 'window below active no focus
Declare Dynamic Library "user32"
Function FindWindowA%& (ByVal lpClassName%&, Byval lpWindowName%&)
Function SetWindowPos& (ByVal hWnd%&, Byval hWndInsertAfter%&, Byval X&, Byval Y&, Byval cx&, Byval cy&, Byval uFlags~&)
Function GetForegroundWindow%&
End Declare
Declare Dynamic Library "kernel32"
Function GetLastError~& ()
End Declare
Dim t As String
Dim hWnd As _Offset
Dim iLoop As Integer
Dim bOnTop As Integer: bOnTop = FALSE
Screen 12 ' SCREEN 12 can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
Cls , cRed
Color cWhite, cRed
Randomize Timer
t = Hex$(Rnd * &H1000000) ' random title for FindWindowA
_Title cProgName + t ' _Trim$(Str$(t))
t = t + Chr$(0)
hWnd = _WindowHandle ' FindWindowA(0, _OFFSET(t))
_Title cProgName + t + ": This Window will always be on Top" ' any title
_Delay 4 ' delay allows user to click focus on other windows
' set as topmost window and move without sizing or activation
If 0 = SetWindowPos(hWnd, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) Then
Print "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
x%& = GetForegroundWindow%& ' find currently focused process handle
Print "Program handle:"; hWnd; "Focus handle:"; x%&
If hWnd <> x%& Then
_ScreenClick 240, 240 ' add 40 to x and y to focus on positioned window
End If
Locate 5, 20 ' y,x where 1,1 = top left
Print cProgName
Locate 10, 20
Print "Press A to stay on top, B for background"
Locate 25, 20 ' y,x where 1,1 = top left
Print "Hold down ESC to exit."
For iLoop = 10000 To 0 Step -1
Locate 15, 20
Print IIFSTR$(bOnTop, "STAY ON TOP", "BACKGROUND ")
Locate 20, 20 ' y,x where 1,1 = top left
Print _Trim$(Str$(iLoop)) + " "
While _DeviceInput(1): Wend ' clear and update the keyboard buffer
If _KeyDown(Asc("a")) Or _KeyDown(Asc("A")) Then
bOnTop = TRUE
'(ENABLE ALWAYS STAY ON TOP)
' set as topmost window and move without sizing or activation
If 0 = SetWindowPos(hWnd, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) Then
Locate 1, 1
Print "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
ElseIf _KeyDown(Asc("b")) Or _KeyDown(Asc("B")) Then
bOnTop = FALSE
'(DISABLE ALWAYS STAY ON TOP)
' set as topmost window and move without sizing or activation
If 0 = SetWindowPos(hWnd, HWND_NOTOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) Then
Locate 1, 1
Print "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
End If
If _KeyDown(27) Then Exit For ' leave loop when ESC key pressed
_Limit 4 ' keep loop at 4 frames per second
Next iLoop
End
Function IIF (Condition, IfTrue, IfFalse)
If Condition Then IIF = IfTrue Else IIF = IfFalse
End Function
Function IIFSTR$ (Condition, IfTrue$, IfFalse$)
If Condition Then IIFSTR$ = IfTrue$ Else IIFSTR$ = IfFalse$
End Function
Posts: 73
Threads: 3
Joined: Apr 2022
Reputation:
14
(05-19-2024, 03:24 PM)madscijr Wrote: (05-17-2024, 11:27 PM)SMcNeill Wrote: https://qb64phoenix.com/qb64wiki/index.p...ost_Window Fantastic!
Now once the program window is set to always be in the foreground, how would you change it back to a normal window?
I tried modifying my programs so
a window stays on top (HWND_TOPMOST) when the user presses the "a" key,
and goes back to normal (HWND_NOTOPMOST) when they press "b",
but it doesn't seem to be working...
But your programs are fine.
If you press key B the window is no longer in the foreground and with A it is in the front again.
All you have to do is click on it with the mouse to give the program focus again, and then press the corresponding keys.
And the second program should not be in the same place as the first.
The function brings the window to the foreground, but does not hold the focus.
Posts: 2,698
Threads: 327
Joined: Apr 2022
Reputation:
217
@madscijr It works as expected on my PC.
I think the problem is you're clicking "b" while the program doesn't have focus, so it's not going to read that input and change modes on you.
Run the second program as you have it written, and click "a" to make it stay on top. Then click anywhere else you want and watch as that window remains on top of everything else.
Now open notepad, or your browser, or whatever, and hit "b".... Notice how you just typed a "b" on that newly opened app? It's where your input is being directed to.
Click back on the "always on top" program and hit "b". Maybe hit it twice for good measure to make certain that it catches that input. Watch the status change to "BACKGROUND".
At least, that's how it's working for me on Win 11.
Posts: 733
Threads: 103
Joined: Apr 2022
Reputation:
14
(05-19-2024, 04:35 PM)Steffan-68 Wrote: (05-19-2024, 03:24 PM)madscijr Wrote: (05-17-2024, 11:27 PM)SMcNeill Wrote: https://qb64phoenix.com/qb64wiki/index.p...ost_Window Fantastic!
Now once the program window is set to always be in the foreground, how would you change it back to a normal window?
I tried modifying my programs so
a window stays on top (HWND_TOPMOST) when the user presses the "a" key,
and goes back to normal (HWND_NOTOPMOST) when they press "b",
but it doesn't seem to be working...
But your programs are fine.
If you press key B the window is no longer in the foreground and with A it is in the front again.
All you have to do is click on it with the mouse to give the program focus again, and then press the corresponding keys.
And the second program should not be in the same place as the first.
The function brings the window to the foreground, but does not hold the focus. Thanks for your reply - I'm away from my PC now but what I was seeing (in Windows 11)
was that alt-tabbing to the program not set to "top" (or even clicking it), it moved to the top. I would expect the one not on top to stay underneath. I'll give it a look when I'm back at the computer - thanks again.
Posts: 733
Threads: 103
Joined: Apr 2022
Reputation:
14
05-20-2024, 05:57 PM
(This post was last modified: 05-20-2024, 06:02 PM by madscijr.)
(05-19-2024, 04:35 PM)Steffan-68 Wrote: But your programs are fine.
If you press key B the window is no longer in the foreground and with A it is in the front again.
All you have to do is click on it with the mouse to give the program focus again, and then press the corresponding keys.
And the second program should not be in the same place as the first.
The function brings the window to the foreground, but does not hold the focus. (05-19-2024, 04:36 PM)SMcNeill Wrote: @madscijr It works as expected on my PC.
I think the problem is you're clicking "b" while the program doesn't have focus, so it's not going to read that input and change modes on you.
...
At least, that's how it's working for me on Win 11. Thank you both for your replies.
I see what was happening - both were initializing as "top" so whichever one got the focus went to top.
I fixed that and now it's working, just one problem now, which is that when you press "a" or "b" and the program changes the "always on top" state, the window moves.
I see that lines 81 and 87 are calling SetWindowPos with X& and Y& hardcoded to 200:
Code: (Select All) Function SetWindowPos& (ByVal hWnd%&, Byval hWndInsertAfter%&, Byval X&, Byval Y&, Byval cx&, Byval cy&, Byval uFlags~&)
...
If SetWindowPos(hWndThis, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) = 0 Then
Is there a way to get the current window x, y position to pass to SetWindowPos so the window stays at its current position?
Thanks again!
Program #1
Code: (Select All) ' McNeill - Super Moderator
' #2
' 05-17-2024, 07:27 PM (This post was last modified: 05-17-2024, 07:28 PM by SMcNeill.)
' https://qb64phoenix.com/qb64wiki/index.php/Windows_Libraries#Top_Most_Window
Const cProgName = "Program #1"
Const FALSE = 0
Const TRUE = Not FALSE
' TEXT MODE COLORS:
Const cBlack = 0: Const cBlue = 1: Const cGreen = 2: Const cLtBlue = 3
Const cRed = 4: Const cPurple = 5: Const cOrange = 6: Const cWhite = 7
Const cGray = 8: Const cPeriwinkle = 9: Const cLtGreen = 10: Const cCyan = 11
Const cLtRed = 12: Const cPink = 13: Const cYellow = 14: Const cLtGray = 15
Const SWP_NOSIZE = &H0001 'ignores cx and cy size parameters
Const SWP_NOMOVE = &H0002 'ignores x and y position parameters
Const SWP_NOZORDER = &H0004 'keeps z order and ignores hWndInsertAfter parameter
Const SWP_NOREDRAW = &H0008 'does not redraw window changes
Const SWP_NOACTIVATE = &H0010 'does not activate window
Const SWP_FRAMECHANGED = &H0020
Const SWP_SHOWWINDOW = &H0040
Const SWP_HIDEWINDOW = &H0080
Const SWP_NOCOPYBITS = &H0100
Const SWP_NOOWNERZORDER = &H0200
Const SWP_NOSENDCHANGING = &H0400
Const SWP_DRAWFRAME = SWP_FRAMECHANGED
Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
Const SWP_DEFERERASE = &H2000
Const SWP_ASYNCWINDOWPOS = &H4000
Const HWND_TOP = 0 'window at top of z order no focus
Const HWND_BOTTOM = 1 'window at bottom of z order no focus
Const HWND_TOPMOST = -1 'window above all others no focus unless active
Const HWND_NOTOPMOST = -2 'window below active no focus
Declare Dynamic Library "user32"
Function FindWindowA%& (ByVal lpClassName%&, Byval lpWindowName%&)
Function SetWindowPos& (ByVal hWnd%&, Byval hWndInsertAfter%&, Byval X&, Byval Y&, Byval cx&, Byval cy&, Byval uFlags~&)
Function GetForegroundWindow%&
End Declare
Declare Dynamic Library "kernel32"
Function GetLastError~& ()
End Declare
Dim hWndThis As _Offset ' hWndThis%&
Dim hWndTop As _Offset ' x%&
Dim iLoop As Integer
Dim bOnTop As Integer: bOnTop = FALSE
Dim sError As String: sError = ""
_Title cProgName
Screen 12 ' SCREEN 12 can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
Cls , cBlue
Color cWhite, cBlue: Locate 5, 20: Print cProgName
For iLoop = 10000 To 0 Step -1
' GET WINDOW HANDLES
hWndThis = _WindowHandle ' FindWindowA(0, _OFFSET(t))
hWndTop = GetForegroundWindow%& ' find currently focused process handle
'If hWndThis <> hWndTop Then
' _ScreenClick 240, 240 ' add 40 to x and y to focus on positioned window
'End If
' UPDATE SCREEN y,x where 1,1 = top left
Locate 10, 20: Print "Program handle: " + _Trim$(Str$(hWndThis))
Locate 12, 20: Print "Focus handle: " + _Trim$(Str$(hWndTop))
Locate 14, 20: Print _Trim$(Str$(iLoop)) + " "
Locate 16, 20: Print "Press A to stay on top, B for background"
Locate 18, 20: If bOnTop = TRUE Then Print "STAY ON TOP" Else Print "NORMAL"
Locate 20, 20: If Len(sError) > 0 Then Print sError Else Print " "
Locate 25, 20: Print "Hold down ESC to exit."
' -----------------------------------------------------------------------------
' GET KEYBOARD INPUT
While _DeviceInput(1): Wend ' clear and update the keyboard buffer
If _KeyDown(Asc("a")) Or _KeyDown(Asc("A")) Then
' SET AS TOPMOST WINDOW AND MOVE WITHOUT SIZING OR ACTIVATION
If SetWindowPos(hWndThis, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) = 0 Then
sError = "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
bOnTop = TRUE ' FLAG ALWAYS STAY ON TOP
ElseIf _KeyDown(Asc("b")) Or _KeyDown(Asc("B")) Then
' SET AS TOPMOST WINDOW AND MOVE WITHOUT SIZING OR ACTIVATION
If SetWindowPos(hWndThis, HWND_NOTOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) = 0 Then
sError = "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
bOnTop = FALSE ' UN-FLAG ALWAYS STAY ON TOP
ElseIf _KeyDown(27) Then
Exit For ' leave loop when ESC key pressed
End If
_Limit 4 ' keep loop at 4 frames per second
Next iLoop
End
Program #2
Code: (Select All) ' McNeill - Super Moderator
' #2
' 05-17-2024, 07:27 PM (This post was last modified: 05-17-2024, 07:28 PM by SMcNeill.)
' https://qb64phoenix.com/qb64wiki/index.php/Windows_Libraries#Top_Most_Window
Const cProgName = "Program #2"
Const FALSE = 0
Const TRUE = Not FALSE
' TEXT MODE COLORS:
Const cBlack = 0: Const cBlue = 1: Const cGreen = 2: Const cLtBlue = 3
Const cRed = 4: Const cPurple = 5: Const cOrange = 6: Const cWhite = 7
Const cGray = 8: Const cPeriwinkle = 9: Const cLtGreen = 10: Const cCyan = 11
Const cLtRed = 12: Const cPink = 13: Const cYellow = 14: Const cLtGray = 15
Const SWP_NOSIZE = &H0001 'ignores cx and cy size parameters
Const SWP_NOMOVE = &H0002 'ignores x and y position parameters
Const SWP_NOZORDER = &H0004 'keeps z order and ignores hWndInsertAfter parameter
Const SWP_NOREDRAW = &H0008 'does not redraw window changes
Const SWP_NOACTIVATE = &H0010 'does not activate window
Const SWP_FRAMECHANGED = &H0020
Const SWP_SHOWWINDOW = &H0040
Const SWP_HIDEWINDOW = &H0080
Const SWP_NOCOPYBITS = &H0100
Const SWP_NOOWNERZORDER = &H0200
Const SWP_NOSENDCHANGING = &H0400
Const SWP_DRAWFRAME = SWP_FRAMECHANGED
Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
Const SWP_DEFERERASE = &H2000
Const SWP_ASYNCWINDOWPOS = &H4000
Const HWND_TOP = 0 'window at top of z order no focus
Const HWND_BOTTOM = 1 'window at bottom of z order no focus
Const HWND_TOPMOST = -1 'window above all others no focus unless active
Const HWND_NOTOPMOST = -2 'window below active no focus
Declare Dynamic Library "user32"
Function FindWindowA%& (ByVal lpClassName%&, Byval lpWindowName%&)
Function SetWindowPos& (ByVal hWnd%&, Byval hWndInsertAfter%&, Byval X&, Byval Y&, Byval cx&, Byval cy&, Byval uFlags~&)
Function GetForegroundWindow%&
End Declare
Declare Dynamic Library "kernel32"
Function GetLastError~& ()
End Declare
Dim hWndThis As _Offset ' hWndThis%&
Dim hWndTop As _Offset ' x%&
Dim iLoop As Integer
Dim bOnTop As Integer: bOnTop = FALSE
Dim sError As String: sError = ""
_Title cProgName
Screen 12 ' SCREEN 12 can use 16 color attributes with a black background. 256K possible RGB color hues. Background colors can be used with QB64.
Cls , cRed
Color cWhite, cRed: Locate 5, 20: Print cProgName
For iLoop = 10000 To 0 Step -1
' GET WINDOW HANDLES
hWndThis = _WindowHandle ' FindWindowA(0, _OFFSET(t))
hWndTop = GetForegroundWindow%& ' find currently focused process handle
'If hWndThis <> hWndTop Then
' _ScreenClick 240, 240 ' add 40 to x and y to focus on positioned window
'End If
' UPDATE SCREEN y,x where 1,1 = top left
Locate 10, 20: Print "Program handle: " + _Trim$(Str$(hWndThis))
Locate 12, 20: Print "Focus handle: " + _Trim$(Str$(hWndTop))
Locate 14, 20: Print _Trim$(Str$(iLoop)) + " "
Locate 16, 20: Print "Press A to stay on top, B for background"
Locate 18, 20: If bOnTop = TRUE Then Print "STAY ON TOP" Else Print "NORMAL"
Locate 20, 20: If Len(sError) > 0 Then Print sError Else Print " "
Locate 25, 20: Print "Hold down ESC to exit."
' -----------------------------------------------------------------------------
' GET KEYBOARD INPUT
While _DeviceInput(1): Wend ' clear and update the keyboard buffer
If _KeyDown(Asc("a")) Or _KeyDown(Asc("A")) Then
' SET AS TOPMOST WINDOW AND MOVE WITHOUT SIZING OR ACTIVATION
If SetWindowPos(hWndThis, HWND_TOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) = 0 Then
sError = "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
bOnTop = TRUE ' FLAG ALWAYS STAY ON TOP
ElseIf _KeyDown(Asc("b")) Or _KeyDown(Asc("B")) Then
' SET AS TOPMOST WINDOW AND MOVE WITHOUT SIZING OR ACTIVATION
If SetWindowPos(hWndThis, HWND_NOTOPMOST, 200, 200, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE) = 0 Then
sError = "SetWindowPos failed. 0x" + LCase$(Hex$(GetLastError))
End If
bOnTop = FALSE ' UN-FLAG ALWAYS STAY ON TOP
ElseIf _KeyDown(27) Then
Exit For ' leave loop when ESC key pressed
End If
_Limit 4 ' keep loop at 4 frames per second
Next iLoop
End
|