Jump to content

How to Know When the TaskBar Hid Itself?


Zohar
 Share

Recommended Posts

Hi

If you set some program to be FullScreen, then after you do it,

aprox. 1-2 seconds after it, the TaskBar will hide, so you can see the full screen on the program that you wanted.

My question is:

How can I know when the TaskBar hid itself?

Currently I am using a Sleep(2000) command, but I want to improve it.

I tried a while() loop, that waits for the TaskBar ("[Class:Shell_TrayWnd]") to change from Visible=True to Visible=False.

But apparently, the TaskBar's Visible property is always True, even when it's hidden.

I tried also checking the Bounds of it, but apparently here too, it doesn't change:

Its Size and Location remain, either when it's shown, or hidden.

So the only thing left, is probably the Z-Order for the TaskBar's window.

How do I check the Z-Order value of a certain Window, in AutoIt?

BTW, I am using WindowsXP, SP3.

Thank you

Zohar

Edited by Zohar
Link to comment
Share on other sites

You could just get the position of the window and then test to see if it's in the desktop area. You have to allow for the task bar at any edge of the screen.

$TaskbarVisible = False
$setlabelVis = true

Opt("WinTitleMatchMode", 4)
Opt("WinSearchChildren", 1)
$g = GUICreate("", 170, 30)
$l = GUICtrlCreateLabel("task bar showing", 20, 10)
GUISetState()

$hWnd = WinGetHandle("classname=TrayNotifyWnd")
Do
    If GUIGetMsg() = -3 Then Exit

    $wp = WinGetPos($hWnd)
    $midx = $wp[0] + $wp[2] / 2
    $midy = $wp[1] + $wp[3] / 2

    $Xinside = $midx > 0 And $midx < @DesktopWidth
    $Yinside = $midy > 0 And $midy < @DesktopHeight

    $TaskbarVisible = $Xinside And $Yinside

    If $TaskbarVisible And Not $setlabelVis Then
        GUICtrlSetData($l, "task bar Showing")
        $setlabelVis = True
    EndIf

    If Not $TaskbarVisible And $setlabelVis Then
        GUICtrlSetData($l, "task bar Hidden")
        $setlabelVis = False
    EndIf


Until 0
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I have made something similar

$_TaskBar = WinGetHandle ( "[Class:Shell_TrayWnd]" )
$_FullSize = @DesktopWidth * @DesktopHeight

While 1
    $_Winlist = WinList ( )
    For $_I = 1 To $_Winlist[0][0]
        $_Pos = WinGetPos ( $_Winlist[$_I][1] )
        If Not @error And $_Winlist[$_I][0] <> 'Program Manager' Then
            If _IsVisible ( $_Winlist[$_I][1] ) And $_Pos[2]*$_Pos[3] = $_FullSize Then
                ConsoleWrite ( "- Title=" & $_Winlist[$_I][0] & " Handle=" & $_Winlist[$_I][1] & @Crlf )
                ToolTip ( "TaskBar is Overed" )
                ExitLoop
            Else
                ToolTip ( "" )
            EndIf
        EndIf
    Next
    Sleep ( 500 )
WEnd

Func _IsVisible ( $handle )
    If BitAND ( WinGetState ( $handle ), 2 ) Then Return 1
EndFunc ;==> _IsVisible ( )

AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Link to comment
Share on other sites

@martin, your code is interesting because if I run it as you have it, it works. But if I convert it to a boolean function using TrayNotifyWnd, it doesn't. It does work if I use Shell_TrayWnd instead. Don't know why.

Here's your code converted to a function with my test stub

If TastbarVisible() Then
    MsgBox(0x1040,"","Taskbar is Visible")
Else
    MsgBox(0x1010,"","Taskbar is Not Visible")
EndIf

Func TastbarVisible()
    $hWnd = WinGetHandle("[Class:Shell_TrayWnd]")
    Local $wp = WinGetPos($hWnd)
    Local $midx = $wp[0] + $wp[2] / 2
    Local $midy = $wp[1] + $wp[3] / 2
    Local $Xinside = $midx > 0 And $midx < @DesktopWidth
    Local $Yinside = $midy > 0 And $midy < @DesktopHeight
    Return $Xinside And $Yinside
EndFunc

If I substitute TrayNotifyWnd for the class name, it always says the taskbar is visible in my code. Weird. :)

Link to comment
Share on other sites

If _IsTaskbarVisible ( ) Then
    MsgBox(0x1040,"","Taskbar is Visible")
Else
    MsgBox(0x1010,"","Taskbar is Not Visible")
EndIf

Func _IsTaskbarVisible ( )
    Local $_TaskBar = WinGetHandle ( "[Class:Shell_TrayWnd]" )
    Local $_FullSize = @DesktopWidth * @DesktopHeight
    Local $_Winlist = WinList ( )
    For $_I = 1 To $_Winlist[0][0]
        $_Pos = WinGetPos ( $_Winlist[$_I][1] )
        If Not @error And $_Winlist[$_I][0] <> 'Program Manager' And _
            _IsVisible ( $_Winlist[$_I][1] ) And $_Pos[2]*$_Pos[3] = $_FullSize Then Return False
    Next
    Return True
EndFunc ;==> _IsTaskbarVisible  ( )

Func _IsVisible ( $handle )
    If BitAND ( WinGetState ( $handle ), 2 ) Then Return 1
EndFunc ;==> _IsVisible ( )

Edited by wakillon

AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Link to comment
Share on other sites

@MilesAhead

On the PC I use most, which is XP, the task bar is always visible but not always "can be seen" because it's outside of the desktop area. That's why my code checked the position of the task bar and not it's visible status. I haven't tried W7 but I would have guessed it was the same.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Your code does work on W7. The polling seems to make a difference for some reason. I guess a Taskbar checking function should wait some limited time for the desired state to be in effect, then return it. Just testing once doesn't seem reliable. I've seen other code that uses IsWindowVisible() but it didn't work for me. As you pointed out it probably just tests the window state, so it always shows as Visible, even if off the desktop.

I tried other code to get notification on system state change. It was pretty much useless. The only reliable info relating to Taskbar seemed to be resolution change notification. There's probably some undocumented function the pros use that MS doesn't tell mortals about. :)

Edited by MilesAhead
Link to comment
Share on other sites

  • 2 weeks later...

Hi All

First of all, thank you very much for your answers.

But I think I did not sharp enough my need.

I should differentiate between two different things:

1) How to Detect If Current Application is in FullScreen Mode

2) How to Detect If the TaskBar is Hidden

Now you must ask:

"What's the difference?

Coz If some application moves to FullScreen mode, then the TaskBar will disappear too, so it's the same no?"

And no, it's not the same, and I will explain why :oops:

Let's say you do this:

Open IE,

and then press F11 for FullScreen.

After pressing F11, you'll see 2 things happening:

1) IE will switch to full screen(instantaneously)

2) At first, the TaskBar is still visible, and still covers the current application, even tho it switched to full screen!

And only after 1-2 seconds(this varies from time to time - on the same computer) it will then animate its hiding, and hide.

So you see,

what I am trying to get, is not when an application swithced to FullScreen,

But I'm trying to get what happens 1-2 seconds after it: When the TaskBar, hid itself..

(and since the time it takes it to hide itself varies, then I cannot use a constant sleep, but I need something smarter..)

So regarding 1(How to Know If Current Application is in FullScreen Mode), I have no problem..

I use this code:

Func CheckIfFullScreen()
If _
( _
  ($CurrentWindow_Class="Progman")   Or _ ;Desktop
  ($CurrentWindow_Class="DimmedWindowClass")  _ ;Shutdown Window
) _
  Then  Return False ;Ignoring these Windows

Local $W_Bounds
Do
  $W_Bounds =WinGetPos("")
Until (@error=0) And (UBound($W_Bounds)=4)


Return _
  ( _
   ( ($W_Bounds[0]<=0) And ($W_Bounds[1]<=0) ) And _
   ( ($W_Bounds[2]>=@DesktopWidth) And ($W_Bounds[3]>=@DesktopHeight) ) _
  )
EndFunc

But regarding 2(How to know If the TaskBar is Hidden), I have a problem.

- Checking the Visible property of the TaskBar's Window("[Class:Shell_TrayWnd]") did not help, it always stays Visible, even when we can't see it.

- I then thought that maybe it is simply moved.. so I checked its Bounds. That didn't help too. It's Location and Size remains the same, both when it's seen, and when it's hidden.

So it is my assumption, that the TaskBar's window does not change its Visible property, neither its Position,

but it's simply covered by the current window, which is the FullScreen application.

And for that, I need to get the Z-Order of the TaskBar's window.. (which hopefully, will show a change - so I can then use this change, to detect what I want..)

Anyone knows how to get the Z-Order of a Window?

Edited by Zohar
Link to comment
Share on other sites

I would look at martin's code. A variation on the idea would be, poll to test if taskbar is hidden. If Hidden is indicated or the time-out expires, return. The return value indicates which happened. From what you say a time-out of 2 or 3 seconds should be enough. I suspect the reason the transition is not instantaneous is Windows thinks it's cool to display some animation during the Taskbar hide/display.

Edited by MilesAhead
Link to comment
Share on other sites

Hi MilesAhead

Regarding "poll to test if taskbar is hidden", of course - that's what I plan to do.

However I do not have a way to know if the TaskBar is Hidden or Not - so I don't have what to poll..

I tried Martin's code, and unfortunately, my TaskBar doesn't change it's location, either when it's visible, or hidden..

The Values of the WinGetPos() function, are the same in each of the 2 states of the TaskBar..

(as said, I use WindowsXP+SP3)

What can I do?

Edited by Zohar
Link to comment
Share on other sites

Hi MilesAhead

Regarding "poll to test if taskbar is hidden", of course - that's what I plan to do.

However I do not have a way to know if the TaskBar is Hidden or Not - so I don't have what to poll..

I tried Martin's code, and unfortunately, my TaskBar doesn't change it's location, either when it's visible, or hidden..

The Values of the WinGetPos() function, are the same in each of the 2 states of the TaskBar..

(as said, I use WindowsXP+SP3)

What can I do?

I didn't know that. His code worked on my machine. I would look on MSDN and maybe post a new question. I signed up for the free MSDN membership and they accepted MSN Live id and password(iow if you have a Hotmail account to use.) I don't think there's an easy answer.

edit: only thing occurs to me perhaps it's going "invisible" by becoming totally transparent? Perhaps you could do GetWindowLong to get the alpha value of the window color. 255 is totally opaque and 0 is totally invisible. Don't know if it would work. It's just an idea. I'm not sure if GetWindowLong is the right call. If you think it's going transparent then research how to get the alpha value/level of opaqueness etc..

Edited by MilesAhead
Link to comment
Share on other sites

Hi Zohar,

WinList() will return an array in order of the windows z-order.

Does this work for you?

#include <array.au3>
HotKeySet('!t', 'HotKey')
While 1
    Sleep(10)
WEnd
Func HotKey()
    If IsWinAbove(WinGetHandle(""), WinGetHandle("[Class:Shell_TrayWnd]")) Then
        MsgBox(0, 'test', 'Current window is BELOW the taskbar')
    Else
        MsgBox(0, 'test', 'Current window is ABOVE the taskbar')
    EndIf
EndFunc   ;==>HotKey
Func IsWinAbove($isthis, $abovethis)
    $array = WinList()
    For $a = 1 To $array[0][0]
        If $array[$a][1] = $abovethis Then
            Return False
        ElseIf $array[$a][1] = $isthis Then
            Return True
        EndIf
    Next
EndFunc   ;==>IsWinAbove
Link to comment
Share on other sites

Hi MilesAhead

The Transparent variable is definately an option, but I think a more logical option to try first, is the Z-Order..

And this leads us to what danwilli wrote.

danwilli, your code helped!

I changed it a bit, to work in the background and sound a beep all the time,

with a changing frequency according to the window that has a bigger Z-Order(The TaskBar, or CurrentWindow).

#include <Misc.au3>

While 1
Beep(_Iif(IsWinAbove(WinGetHandle(""), WinGetHandle("[Class:Shell_TrayWnd]")),1500,700),10)
Sleep(50)
WEnd

Func IsWinAbove($isthis, $abovethis)
    $array = WinList()

    For $a = 1 To $array[0][0]
        If $array[$a][1] = $abovethis Then
            Return False
        ElseIf $array[$a][1] = $isthis Then
            Return True
        EndIf
    Next
EndFunc

Please try it.

You will see that your code is indeed checking it,

and indeed the beep frequency changes not after the window changed to Full Screen,

but after the TaskBar hid itself(which usually takes 1-2 more seconds).

This is great! thank you for it.

I have only 2 questions regarding it:

1) Is there some "WinGetZOrder()" function? (or we have to implement it like you did here?)

2) Why does it work when I am in IE and press F11, but not in SciTe and press F11?

Is SciTe's FullScreen implementation dfferent than the standard?

Thank you

Edited by Zohar
Link to comment
Share on other sites

Hi Everyone,

There are some news with this subject!

#include <Misc.au3>



While 1
    Local $V =IsWinAbove(WinGetHandle(""), WinGetHandle("[Class:Shell_TrayWnd]"))

    Beep(_Iif($V,1500,700),10)
    Sleep(50)
WEnd


Func IsWinAbove($isthis, $abovethis)
    $array = WinList()

    For $a = 1 To $array[0][0]
        If $array[$a][1] = $abovethis Then
            Return False
        ElseIf $array[$a][1] = $isthis Then
            Return True
        EndIf
    Next
EndFunc

If you run this small program,

and then, when on IE, press F11,

you'll notice this:

After pressing F11:

1) IE's window will switch to Full Screen, but the TaskBar will still cover it

2) As we talked - After 1-2 seconds ,The TaskBar will hide itself.

The script's beep's frequency changes,

not after the window switched to full screen, but only after the TaskBar actually hid itself.

So as we can see, the Z-Order is indeeed, a good way to detect it.

(thanks to danwilli for a great code)

Now, please see this second script,

which is just slightly different from the firstone:

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


While 1
    Local $V =WinGetOnTop(WinGetHandle("[Class:Shell_TrayWnd]"))

    Beep(_Iif($V,1500,700),10)
    Sleep(50)
WEnd


Func WinGetOnTop($Win)
    Return (BitAND(_WinAPI_GetWindowLong($Win,$GWL_EXSTYLE),$WS_EX_TOPMOST)<>0)
EndFunc

In this script, the difference is that I check for the AlwaysOnTop property of the TaskBar.

It seems that indeed, the AlwaysOnTop property is changing between the 2 situations

(A window is not FullScreen, and a window is FullScreen).

So this is what Microsoft Windows uses to hide the TaskBar.

And now to my question :oops:

I want to make an application, to switch to full screen, and have the TaskBar immediately hidden.

Not after 1-2 seconds, but exactly when the Window switches to FullScreen.

Here's what I tried to do, and did not work yet:

Send("{F11}")
WinSetOnTop("[Class:Shell_TrayWnd]","",0)

I also tried this:

Send("{F11}")
WinSetOnTop("[Class:Shell_TrayWnd]","",0)
Sleep(100)
WinActivate("")

And I also tried this:

Send("{F11}")
WinSetOnTop("[Class:Shell_TrayWnd]","",0)
Sleep(100)
WinActivate("")
WinSetOnTop("","",1)
WinSetOnTop("","",0)   ;Those last 2 rows are to make current(IE) window's Z-Order to be the first one

Anyone has an idea how to improve it so it will work as needed?

I put them all as a result of a hotkey press, like this:

HotKeySet("{F8}" ,"HotKeyFunction")

While 1
    Sleep(100)
WEnd

Func HotKeyFunction()
Send("{F11}")
WinSetOnTop("[Class:Shell_TrayWnd]","",0)
EndFunc
Edited by Zohar
Link to comment
Share on other sites

I have a utility called TopmostToggle that toggles the OnTop attribute of the active window. I used it on the taskbar. If it was enabled or disabled the Taskbar still stayed on top. I think this is something that varies with the flavor of windows. I wouldn't make assumptions that what works with XP works with W7 taskbar.

There should be some definitive explanation on MSDN. I don't know why they are keeping it secret. You may have to find 3 or 4 solutions and test for the Windows flavor to pick the appropriate one.

Edited by MilesAhead
Link to comment
Share on other sites

>There should be some definitive explanation on MSDN.

I think it will be shorter to simply try several ways, until succeeding,

than looking and reading alot of text in MSDN..

I thought someone will have an idea that works..

It could be very nice

Link to comment
Share on other sites

>There should be some definitive explanation on MSDN.

I think it will be shorter to simply try several ways, until succeeding,

than looking and reading alot of text in MSDN..

I thought someone will have an idea that works..

It could be very nice

You could always post the question there. Maybe if people keep posting they will finally document how the Taskbar works.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...