Sign in to follow this  
Followers 0
KaFu

How to check if a window has the topmost flag set?

7 posts in this topic

#1 ·  Posted (edited)

HiHo Community,

just wrote a tiny wrapper for TCP-Z. Nice program, bad window behavior ;)... the wrapper will hide the GUI if minimized (it has a tray icon to maximize again) and will set the topmost flag for the minibar (I place it on the taskbar, without the flag the minibar will go behind the taskbar, at least in Win7).

Here's the wrapper:

#NoTrayIcon

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=1_tcpz64.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

Opt("WinWaitDelay", 0)
$iPID_tcpz64 = Run("tcpz64.exe")

While ProcessExists($iPID_tcpz64)

    Sleep(100)
    $state = WinGetState("TCP-Z   (x64)   v2.6.2.75", "")
    If BitAND($state, 16) Then
        WinSetState("TCP-Z   (x64)   v2.6.2.75", "", @SW_HIDE)
    EndIf

    ;ConsoleWrite(WinGetState(_Detect_TCPZ_Minibar_hWnd()) & @crlf)
    WinSetOnTop(_Detect_TCPZ_Minibar_hWnd(), "", 1)

WEnd

Func _Detect_TCPZ_Minibar_hWnd()
    Local $hWnds
    $hWnds = WinList("[CLASS:#32770;]", "")
    For $i = 1 To $hWnds[0][0]
        If BitAND(WinGetState($hWnds[$i][1], ''), 2) Then
            $hwnd_PID = WinGetProcess(_WinAPI_GetAncestor($hWnds[$i][1], $GA_ROOTOWNER))
            $processlist = ProcessList("tcpz64.exe")
            For $y = 1 To $processlist[0][0]
                If $processlist[$y][1] = $hwnd_PID Then
                    If _WinAPI_GetWindowLong($hWnds[$i][1], $GWL_STYLE) = 0x94000046 Then Return $hWnds[$i][1]
                EndIf
            Next
        EndIf
    Next
    Return 0
EndFunc   ;==>_Detect_TCPZ_Minibar_hWnd

In the loop I constantly set WinSetOnTop() for the minibar. Is that bad bahavior? I think checking the flag and only setting it if not already set would be better...

Edited by KaFu

Share this post


Link to post
Share on other sites



Found the answer myself ;), the Ex_Style is changed, WinSetOnTop() just seems to change it.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinApi.au3>
#include <Constants.au3>

$hGUI = GUICreate("My GUI")
GUISetState(@SW_SHOW)

$i = 0

While 1

    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Sleep(200)

    WinSetOnTop($hGUI, "", $i)
    $i = Not $i

    If BitAND(_WinAPI_GetWindowLong($hGUI, $GWL_EXSTYLE), $WS_EX_TOPMOST) Then
        ConsoleWrite("TOPMOST set..." & @CRLF)
    Else
        ConsoleWrite("TOPMOST not set..." & @CRLF)
    EndIf

WEnd
GUIDelete()

Share this post


Link to post
Share on other sites

The top-most style is an extended style, so I guess it's:

;)... Thanks for taking a look m8! You were about 20 seconds faster :evil:...

Cheers and a merry Christmas!

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

  • From what I understand, you should not need to set the TopMost flag more than once. Does TCP-Z unset it periodically or something alike?
  • Checking the flag before setting it will just duplicate work where it wasn't needed it. There is no relevant performance difference that justifies the extra overhead of another function call. It's not like WinSetOnTop is expensive, specially because you already have the hWnd.
  • Speaking about hWnd, why are you retrieving it multiple times? Does TCP-Z create and destroy the window? If not, you should cache the handle and avoid all that extra work. In fact, even if you can't cache it, you can optimize your routine: you should call ProcessList once outside the loop, or maybe just use the PID you already have.
Edited by danielkza

Share this post


Link to post
Share on other sites

From what I understand, you should not need to set the TopMost flag more than once. Does TCP-Z unset it periodically or something alike?

Nope, checked, once created it just hides the window. Point take, wait for first occurence then set topmost, that's it.

Checking the flag before setting it will just duplicate work where it wasn't needed it. There is no relevant performance difference that justifies the extra overhead of another function call. It's not like WinSetOnTop is expensive, specially because you already have the hWnd.

Point taken too ;).

Speaking about hWnd, why are you retrieving it multiple times? Does TCP-Z create and destroy the window? If not, you should cache the handle and avoid all that extra work. In fact, even if you can't cache it, you can optimize your routine: you should call ProcessList once outside the loop, or maybe just use the PID you already have.

Point taken too :evil:. Will post a better wrapper version later.

Thanks!

Share this post


Link to post
Share on other sites

New version considering Daniels remarks. Had to leave the WinSetOnTop() in the loop, because every time I press something in the taskbar, the Minibar went behind it without the repeating function call.

#NoTrayIcon

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=1_tcpz64.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>

Opt("WinWaitDelay", 0)
$iPID_tcpz64 = Run("tcpz64.exe")

$timer = TimerInit()
while not WinExists("TCP-Z   (x64)   v2.6.2.75", "")
    sleep(50)
    if TimerDiff($timer) > 20000 Then
        MsgBox(0,"","TCP-Z Main Window not detected, Wrapper will exit now.")
        Exit
    endif
WEnd
$hwnd_tcpz64_Main = WinGetHandle("TCP-Z   (x64)   v2.6.2.75", "")


$timer = TimerInit()
while not _Detect_TCPZ_Minibar_hWnd()
    sleep(50)
    if TimerDiff($timer) > 20000 Then
        MsgBox(0,"","TCP-Z Minibar Window not detected, Wrapper will exit now.")
        Exit
    endif
WEnd

$hwnd_tcpz64_Minibar = _Detect_TCPZ_Minibar_hWnd()
sleep(3000)
WinSetOnTop($hwnd_tcpz64_Minibar,"",1)

While ProcessExists($iPID_tcpz64)

    Sleep(300)

    $state = WinGetState($hwnd_tcpz64_Main)
    If BitAND($state, 16) Then
        WinSetState($hwnd_tcpz64_Main, "", @SW_HIDE)
    EndIf

    WinSetOnTop($hwnd_tcpz64_Minibar,"",1)

WEnd

Func _Detect_TCPZ_Minibar_hWnd()
    Local $hWnds
    $hWnds = WinList("[CLASS:#32770;]", "")
    For $i = 1 To $hWnds[0][0]
        If BitAND(WinGetState($hWnds[$i][1], ''), 2) Then
            $hwnd_PID = WinGetProcess(_WinAPI_GetAncestor($hWnds[$i][1], $GA_ROOTOWNER))
            $processlist = ProcessList("tcpz64.exe")
            For $y = 1 To $processlist[0][0]
                If $processlist[$y][1] = $hwnd_PID Then
                    If _WinAPI_GetWindowLong($hWnds[$i][1], $GWL_STYLE) = 0x94000046 Then Return $hWnds[$i][1]
                EndIf
            Next
        EndIf
    Next
    Return 0
EndFunc   ;==>_Detect_TCPZ_Minibar_hWnd

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0