Version 18 of always on top

Updated 2002-03-10 04:06:21

[the question of how an application can force some part of itself as the top level window is a FAQ]

Could someone please write something here about the topic?

ptk*


Win32

The API function needed is (see also [L1 ]):

  SetWindowPos(HWND hWnd,       // handle to window
               HWND hWndAfter,  // placement order handle
               int x, int y,    // position (horizontal, vertical)
               int cx, int cy,  // size (width, height) 
               UINT uFlags)     // positioning flags

The placement order handle can be either another HWND or once of the following constants:

  • HWND_BOTTOM (1) Moves to the bottom
  • HWND_NOTOPMOST (-2) Place above all non-topmost windows.
  • HWND_TOP (0) Move to the top
  • HWND_TOPMOST (-1) Move to the top and keep it there.

The Flags can be one of a number but for this page probably SWP_NOMOVE (2) and SWP_NOSIZE (1) are likely the most useful. So:

  SetWindowPos([winfo id .], HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)

which turns out to be the code used by XRaiseWindow in win/tkWinWindow.c


Melissa Schrumpf recommends the GPLed WinCtl [L2 ] utility, which makes it possible to write

    exec WinCtlW.exe -id [wm frame .] topmost &

(or might there be more punctuation in the vicinity of the id?).


Martin Lemburg - 25th February 2002, 13:16 GMT

I found the original topmost package made by John Rosauer in 12.1997. It works only with tcl/tk v.8.0.

The URL is: ftp://ftp.dcade.de/pub/ml/tcl/packages/topmost10.zip [L3 ]

I created a stubs enabled topmost package, usable with tcl/tk 8.1.1 and higher.

The URL is:

ftp://ftp.dcade.de/pub/ml/tcl/packages/topmost20.zip [L4 ]

Usage:

   package require topmost 2.0;

   topmost widget ?boolean?

Much fun!

Martin Lemburg


MPJ - March 9th 2002

Using the topmost source as a guideline I wrote this tcl proc using Ffidl its usage is similar to the topmost package execpt that it does not want a widget name but the window title.

 load ffidl05.dll
 ffidl::callout dll_SetWindowPos     {int int int int int int int} int   [ffidl::symbol user32.dll SetWindowPos]
 ffidl::callout dll_GetWindowLong    {int int} int                       [ffidl::symbol user32.dll GetWindowLongA]
 ffidl::callout dll_FindWindowTitle  {int pointer-utf8} int              [ffidl::symbol user32.dll FindWindowA]
 # windowname is based on wm title
 # state is 1 to set or anything else to reset, empty returns the current state
 proc topmost {windowname {state ""}} {
        set hwnd [dll_FindWindowTitle 0 $windowname]
        if {$hwnd == 0 } {
                return "Not a valid top window"
        }
        set WS_EX_TOPMOST 0x8
        set GWL_EXSTYLE -20
        set TOPMOST -1
        set NOTOPMOST -2
        set SWP_NOACTIVATE 0x10
        set SWP_NOMOVE 0x2
        set SWP_NOSIZE 0x1
        set screenwidth [lindex [split [wm geometry .] x+] 0]
        set screenheight [lindex [split [wm geometry .] x+] 1]
        set result [expr ([dll_GetWindowLong $hwnd $GWL_EXSTYLE] & $WS_EX_TOPMOST )>>3]
        if {$state == "" } {
                return $result
        }
        if {$state == 1} {
                dll_SetWindowPos $hwnd $TOPMOST 0 0 \
                           $screenwidth $screenheight \
                           [expr $SWP_NOACTIVATE | $SWP_NOMOVE | $SWP_NOSIZE]
        } else {
                dll_SetWindowPos $hwnd $NOTOPMOST 0 0 \
                           $screenwidth $screenheight \
                           [expr $SWP_NOACTIVATE | $SWP_NOMOVE | $SWP_NOSIZE]
        }
        return [expr ([dll_GetWindowLong $hwnd $GWL_EXSTYLE] & $WS_EX_TOPMOST )>>3]
 }        

Usage:

 topmost [wm title .] ?boolean?