Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
setting program to display always on top of other windows without having the focus?
#1
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
Reply
#2
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
Reply
#3
(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!
Reply
#4
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.
grymmjack (gj!)
GitHubYouTube | Soundcloud | 16colo.rs
Reply
#5
(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!   Smile
Reply
#6
(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
Reply
#7
(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.
Reply
#8
@madscijr It works as expected on my PC. Smile

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. Smile
Reply
#9
(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.
Reply
#10
(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.  Smile
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.  Smile
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
Reply




Users browsing this thread: 2 Guest(s)