How to set Taskbar to Auto Hide programmatically?

Windows specific forum
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

How to set Taskbar to Auto Hide programmatically?

Post by TerryHough »

Is it possible with PB to set the Taskbar to Auto Hide?

I have a program that needs the entire screen. This is fine on systems that have the Taskbar settings set to Auto Hide. However, some users do not have their systems set this way and lose the bottom line to the Taskbar.

How can I temporarily change that setting so that the Taskbar does Auto Hide while my program is running and then reset it to the user's original setting when my program exits?

A search on the forum yields a couple of clues. One allowed me to query the Taskbar settings and display them (fsw), modifying another allowed me to modify the setting to Auto Hide, but then it doesn't actually auto hide the task bar. Another example causes the taskbar to be "hidden" but it doesn't reapper as it does in Auto Hide until the program "unhides" it.

Any suggestions or code examples appreciated.

Terry
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Here you go Terry:

Code: Select all

#ABM_SETSTATE = 10
aBdata.AppBarData
aBdata\cbsize = SizeOf(AppBarData)

aBdata\lparam = #ABS_AUTOHIDE
SHAppBarMessage_(#ABM_SETSTATE, @aBdata)

Delay(5000) ;during this time, hover mouse over taskbar to test

aBdata\lparam = #ABS_ALWAYSONTOP
SHAppBarMessage_(#ABM_SETSTATE, @aBdata)
BERESHEIT
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

Thanks for the reply, netmaestro!

But, it doesn't really seem to do anything here (Win98SE, PB 4.0)

Try my modification of your code:

Code: Select all

;#ABS_ALWAYSONTOP = 2
;#ABS_AUTOHIDE = 1

#ABM_SETSTATE = 10 
aBdata.AppBarData 
aBdata\cbsize = SizeOf(AppBarData) 

Explanation$ =  #LF$ + #LF$ + "0 = Neither AutoHide or AlwaysOnTop" + #LF$ + "1 = AutoHide" + #LF$ + "2 = AlwaysOnTop" + #LF$ + "3 = AutoHide and AlwaysOnTop"
MessageRequester("Taskbar Starting Status", "Taskbar Status is: " + Str(SHAppBarMessage_(#ABM_GETSTATE, @aBdata)) + Explanation$)

aBdata\lparam = #ABS_AUTOHIDE 
SHAppBarMessage_(#ABM_SETSTATE, @aBdata) 

aBdata\lparam = #ABS_ALWAYSONTOP 
SHAppBarMessage_(#ABM_SETSTATE, @aBdata)

MessageRequester("Taskbar Adjusted Status", "Taskbar Status is: " + Str(SHAppBarMessage_(#ABM_GETSTATE, @aBdata)) + Explanation$)
I don't get any change in the Auto Hide or Always On Top status.

Terry
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Your snippet does:

1. display the status
2. change to autohide
3. change to alwaysontop
4. display the status

With that, I don't see a change. I modified it to:

1. change to autohide
2. display the status
3. change to alwaysontop
4. display the status

Using that order, the mb reports 1=autohide first, and testing it works, then after replying to the mb, it reports 2=alwaysontop. MSDN's doc for this command says it's applicable all the way back to W95, so it really should work in W98SE. If it doesn't, I'm mystified.

Code: Select all

;#ABS_ALWAYSONTOP = 2 
;#ABS_AUTOHIDE = 1 

#ABM_SETSTATE = 10 
aBdata.AppBarData 
aBdata\cbsize = SizeOf(AppBarData) 

aBdata\lparam = #ABS_AUTOHIDE 
SHAppBarMessage_(#ABM_SETSTATE, @aBdata) 

Explanation$ =  #LF$ + #LF$ + "0 = Neither AutoHide or AlwaysOnTop" + #LF$ + "1 = AutoHide" + #LF$ + "2 = AlwaysOnTop" + #LF$ + "3 = AutoHide and AlwaysOnTop" 
MessageRequester("Taskbar Starting Status", "Taskbar Status is: " + Str(SHAppBarMessage_(#ABM_GETSTATE, @aBdata)) + Explanation$) 

aBdata\lparam = #ABS_ALWAYSONTOP 
SHAppBarMessage_(#ABM_SETSTATE, @aBdata) 

MessageRequester("Taskbar Adjusted Status", "Taskbar Status is: " + Str(SHAppBarMessage_(#ABM_GETSTATE, @aBdata)) + Explanation$) 
BERESHEIT
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

@netmaestro

Must be a problem with my Win98SE. I will try another Win98SE box.

Just tried a WinXP box with both options turned off intitially. Both are
turned on by the following code as expected.

Code: Select all

#ABM_SETSTATE = 10 
aBdata.AppBarData 
aBdata\cbsize = SizeOf(AppBarData) 

Explanation$ =  #LF$ + #LF$ + "0 = Neither AutoHide or AlwaysOnTop" + #LF$ + "1 = AutoHide" + #LF$ + "2 = AlwaysOnTop" + #LF$ + "3 = AutoHide and AlwaysOnTop" 
MessageRequester("Taskbar Starting Status", "Taskbar Status is: " + Str(SHAppBarMessage_(#ABM_GETSTATE, @aBdata)) + Explanation$) 

aBdata\lparam = #ABS_ALWAYSONTOP | #ABS_AUTOHIDE 
SHAppBarMessage_(#ABM_SETSTATE, @aBdata) 

MessageRequester("Taskbar Adjusted Status", "Taskbar Status is: " + Str(SHAppBarMessage_(#ABM_GETSTATE, @aBdata)) + Explanation$) 
Thanks for your help.
Terry
User avatar
Shardik
Addict
Addict
Posts: 2069
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

I have also tried the different code examples under WinNT 4 SP6 and they also didn't work, but worked fine under WinXP SP2. Further investigation revealed that the constant ABM_SETSTATE is only supported beginning with WinXP:
http://msdn.microsoft.com/library/defau ... tstate.asp
Minimum operating systems Windows XP
Therefore in Win9x/ME/2000 it is only possible to query the taskbar state but not to change it, because the function ABM_SETSTATE is not supported. For those interested in a VisualBASIC 6 example for querying the taskbar state:
http://support.microsoft.com/kb/143117/en-us
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Well there has to be something else that'll set it for OS's other than XP, I can't believe it wouldn't be possible. Surely programs were doing it long before XP turned up. Back to the docs I go...
BERESHEIT
User avatar
Shardik
Addict
Addict
Posts: 2069
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

Of course it is possible to hide and show the taskbar also in older Windows versions (but only with a brutal :wink: and not very elegant approach):

Code: Select all

TrayHandle = FindWindow_("Shell_TrayWnd", #NULL$)

MessageRequester("Info", "Press OK to hide Taskbar")

If TrayHandle <> 0
  SetWindowPos_(TrayHandle, 0, 0, 0, 0, 0, #SWP_HIDEWINDOW)
EndIf

MessageRequester("Info", "Press OK to show Taskbar")

If TrayHandle <> 0
  SetWindowPos_(TrayHandle, 0, 0, 0, 0, 0, #SWP_SHOWWINDOW)
EndIf
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

It would be much better to do a fullscreen window!

Here is an example (full screen directx window with)
same method can be used with a normal fullscreen window.
http://www.purebasic.fr/english/viewtopic.php?t=21211

Windows will basicaly turn any window (with no border) that is the size of the full screen into a fullscreen window, covering the taskbar.

That way the user can have their desktop whatever way they want.
This is the prefered way of full screen window applications.
Messing with hiding and showing the taskbar is bad you should always avoid changing the user system settings.

Here is a skeleton example for ya,
I use something very similar in my applications. usually offering a F4 or similar key to toggle fullscreen app and normal (I also keep track of the user maximized state too)

Code: Select all

Macro MakeWindowTopmost(window)
 SetWindowPos_(WindowID(window),#HWND_TOPMOST,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_FRAMECHANGED)
EndMacro

#Flags=#PB_Window_Invisible|#PB_Window_Maximize|#PB_Window_BorderLess
OpenWindow(0,0,0,800,600,"our screen",#Flags)
HideWindow(0,#False)
SmartWindowRefresh(0,#True)

#Flags2=#PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_WindowCentered|#PB_Window_BorderLess
OpenWindow(1,0,0,200,200,"screen "+Str(WindowWidth(0))+"x"+Str(WindowHeight(0)),#Flags2,WindowID(0))
MakeWindowTopmost(1)
CreateGadgetList(WindowID(1))

WebGadget(1,0,20,WindowWidth(1),WindowHeight(1)-20,"http://www.purebasic.com")
HideWindow(1,#False)
SmartWindowRefresh(1,#True)

Repeat
 Event=WaitWindowEvent(1)
Until Event=#PB_Event_CloseWindow
EDIT you said "I have a program that needs the entire screen."
That can be a pain to handle. What if someone only has a 800x600 resolution?
What if they have something other than 1024x768 (even though the majority do these days) there is a lot of odd sizes not all got 4:3 screens.
And what about those with larger resolutions?

If you app really need the whole screen and is resolution locked,
my suggestion would be to either 1. use my example above and make your layout slightly dynamic so that it looks "ok" from 800x600 to 1600x1200 and base it around your 1024x768 sweetspot.
Or 2. put all the stuff inside a container and make sure the user can scroll everything if they do not happen to have the proper resolution.
Or even a mix of these two methods!
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

@Rescator
Thanks for your reply, comments, and the nifty example code.

Unfortunately, it does not solve my problem. Making the window

Code: Select all

SetWindowPos_(WindowID(window),#HWND_TOPMOST,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_FRAMECHANGED)
prevents the Taskbar (Appbar) from displaying or activating.

I don't want it disabled. I just want it to Auto Hide while my program is active regardless of the user's actual settings for the Taskbar. If the user moves his cursor to the Taskbar's normal position, I want it to unHide and be responsive as normal.
... the user can have their desktop whatever way they want. ...
Messing with hiding and showing the taskbar is bad you should always avoid changing the user system settings.
:) Yes, I want the user to have their desktop however they want it, just not have the Taskbar overlaying part of my screen unnecessarily. So, I set it to Auto Hide after capturing their settings and restore those settings upon my programs exit. A variation of the code offered by netmaestro above works perfectly on WinXP. Unfortunately, I have been unable to accomplish this on Win98SE as of yet (my users have 100s of Win98SE machines still in use.)

So, I will have to keep searching for a way to set the Auto Hide on Win98SE. Certainly it is possible!

Your comments regarding resolution are well taken. Fortunately, all of my users have 1024 x 768 capabilities so that is not a concern at the moment. Currently, the higher resolutions present no problem as the application is written, although we are not taking advantage of the higher resolution.

Thanks again.
Terry
User avatar
Shardik
Addict
Addict
Posts: 2069
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Post by Shardik »

Terry,

as I tried to explain in my previous post the Win-API function #ABM_SETSTATE is implemented by Microsoft only for operating systems beginning with WinXP. So there exists no "easy" way to implement an autohide function for Win9x/NT/2000 though it might of course be possible. Therefore I have written an "emulation" of the autohide function for non-XP systems in PureBASIC code (tested with WinNT 4 SP6, since I am at work and have no possibility to test it under Win98SE, but in the evening at home I will try it there also):

Code: Select all

AppBarDataStructure.APPBARDATA
InitialTaskbarState.L
TaskbarIsHidden.L
TrayHandle.L
WindowEventID.L
yPosTaskbarBottom.L

InitialTaskbarState = SHAppBarMessage_(#ABM_GETSTATE, @AppBarDataStructure)
TrayHandle = FindWindow_("Shell_TrayWnd", #NULL$)

SHAppBarMessage_(#ABM_GETTASKBARPOS, @AppBarDataStructure)

yPosTaskbarBottom = AppBarDataStructure\rc\bottom - 3

If InitialTaskbarState = #ABS_ALWAYSONTOP
  SetWindowPos_(TrayHandle, 0, 0, 0, 0, 0, #SWP_HIDEWINDOW)
  TaskbarIsHidden = #True
EndIf

OpenWindow(1, 0, 0, 205, 100, "Non-XP Hide Taskbar Demo", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

Repeat
  WindowEventID = WaitWindowEvent(1)

  If InitialTaskbarState = #ABS_ALWAYSONTOP

    ; ----- Show Taskbar if ALWAYSONTOP and yPos Cursor >= yPosTaskbarBottom and Taskbar is currently hidden

    If DesktopMouseY() >= yPosTaskbarBottom
      If TaskbarIsHidden = #True
        SetWindowPos_(TrayHandle, 0, 0, 0, 0, 0, #SWP_SHOWWINDOW)
        TaskbarIsHidden = #False
      EndIf
    Else

    ; ----- Hide Taskbar if ALWAYSONTOP and yPos Cursor < yPosTaskbarBottom and Taskbar is currently shown

      If TaskbarIsHidden = #False
        SetWindowPos_(TrayHandle, 0, 0, 0, 0, 0, #SWP_HIDEWINDOW)
        TaskbarIsHidden = #True
      EndIf
    EndIf
  EndIf
Until WindowEventID = #PB_Event_CloseWindow

If InitialTaskbarState = #ABS_ALWAYSONTOP
  SetWindowPos_(TrayHandle, 0, 0, 0, 0, 0, #SWP_SHOWWINDOW)
EndIf
If the example code detects that taskbar ALWAYSONTOP is activated it hides the taskbar until the end of the program. If the cursor reaches the bottom of the screen the taskbar is shown again. If the cursor leaves the bottom position the taskbar is again hidden.

I hope you can find some use in that code and that it solves your problem. :D
Post Reply