34

I'd like to know any sort of API or workaround (e.g., script or registry) to move (or resize) Windows taskbar to another position including another monitor (if dual monitors). Definitely, we can move task bar by using mouse, but I want to move it by a program, or a sort of automated way.

I tried to find Win32 API, but it seems no one does this job.

EDIT: I was surprised by many people's opinion. Let me explain why I wanted it. In my workplace, I'm using dual monitors (resolutions are different), and the taskbar is placed on the left monitor while the primary monitor is the right monitor. However, I often connect to my workplace computer via remote desktop. After the remote connection, the taskbar position is switched. That's why I wanted to make a simple program that can save/restore taskbar's position. Everyday I have to rearrange my taskbar. That's it. I just want it for me.

minjang
  • 8,860
  • 9
  • 42
  • 61
  • Well, Thomas, the argument could be made that the question isn't useful since it's not a task that programs should be doing. However, we don't really know the intent of Minjang's program, so let's all give the benefit of the doubt, shall we? – Rob Kennedy Jan 14 '10 at 21:34
  • 14
    "Not a task that programs should be doing" - Really? How do you arrive at that conclusion Rob? If you've ever worked in a multi-monitor environment then you'd know that these types of apps (like UltraMon - http://www.realtimesoft.com/ultramon/) are almost essential. Who appointed you God of what programs should be doing? This is a perfectly good question; +1 from me. –  Jan 14 '10 at 21:47
  • Personally, I've often worked in multi-monitor environments, with no additional utility programs. I'll also say my personal concern isn't with utility programs (note I first asked if it was moving the taskbar where the user wanted it). My concern was programs taking the choice away from the user. – John Saunders Jan 14 '10 at 23:07
  • 1
    That type of concern can be pitched at any application. There is nothing in this question suggesting a motive such as that which you are concerned about. –  Jan 15 '10 at 00:44
  • @Gerard: note how in my answer, I said, "are you moving the taskbar because the user asked you to?" I didn't make an assumption - I asked. Maybe the answer is, "yes, the user specifies top/bottom/left/right and I move the taskbar to stretch across that side across all monitors". That would be a good thing. Or maybe the answer is that there's a corporate or government mandate to put the task bar in a particular place and keep it there. That would _not_ be a good thing, in my opinion, subject to someone telling me why it's a good thing. – John Saunders Jan 15 '10 at 03:18
  • Answering a question with another question should be done in the comments section, not as a posted "Answer". "Answers" are for Answers, not more questions. Get with the program that's clearly documented in the SO FAQ. If you really want a hot topic to get your teeth into then try this one - "Can i programatically change the keyboard-layout in Windows" http://stackoverflow.com/questions/2069469/can-i-programatically-change-the-keyboard-layout-in-windows –  Jan 15 '10 at 04:50
  • @Gerard: having a bad day? Getting tired yet of telling me what to do and having me ignore you? Is there some reason I should not ignore you? Are you my new manager and i didn't know that? Are you so obviously correct that I should acknowledge the fact? Let me know, because the default answer is to ignore you, and I wouldn't want to miss paying attention if I need to. – John Saunders Jan 15 '10 at 05:12
  • @minjang: I occasionally had the same thing happen to me, but I didn't realize it was Remote Desktop making the change. BTW, I also sometimes had primary and secondary monitors switch, and maybe that's due to Remote Desktop as well. – John Saunders Jan 15 '10 at 05:14
  • 2
    Gerard, you've misinterpreted what I wrote. I was giving Thomas a reason someone *might* use to justify voting against this question. I didn't say I voted it down, I didn't say it would have been my reason if I had, and I didn't say it was true. It's clearly something *some* people think a program shouldn't do. People who believe it shouldn't be done could therefore believe that a question asking how to do it is not a useful question. (BTW, I'm using a multi-monitor setup right now, and I don't see such programs as essential at all. I can't see myself using any of Ultramon's features.) – Rob Kennedy Jan 15 '10 at 17:28

8 Answers8

8

I also have this need on Windows 7. Here is my take to do this using autohotkey script:

; This script will try to drag and move the taskbar to where the *current* mouse
; cursor is

; 0x111: WM_COMMAND, 424: lock/unlock taskbar, http://www.codeproject.com/KB/miscctrl/Taskbar_Manipulation.aspx
RegRead, TaskbarLocked, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced, TaskbarSizeMove
If TaskbarLocked = 0
  SendMessage 0x111, 424, , , ahk_class Shell_TrayWnd   

WinActivate ahk_class Shell_TrayWnd
MouseGetPos targetX, targetY
ControlGetPos x, y, w, h, MSTaskListWClass1, ahk_class Shell_TrayWnd
MouseMove x+1, y+1
MouseClickDrag Left, x+1, y+1, targetX, targetY, 10

; often after dragging the taskbar to left or right side of a monitor, even though
; there are enough room to show two columns of icons, it will only show one column,
; it seems showing or hiding an icon will fix this
Menu, Tray, NoIcon
Menu, Tray, Icon

; lock the taskbar if it was previously locked
If TaskbarLocked = 0
  SendMessage 0x111, 424, , , ahk_class Shell_TrayWnd   

I have tested this on Windows 7 with classic window theme. To use this, assign a hotkey to call this script, then position mouse cursor to where you want to drag the taskbar to, then press the hotkey.

Zusukar
  • 382
  • 2
  • 8
wangzq
  • 896
  • 8
  • 17
  • works perfectly! thank you! (i had to tweak the exact coordinates to x+10, y-35 for my resolution and theme) – staafl Feb 13 '13 at 09:12
  • Exactly what I needed, this was driving me crazy. Thanks! Note: I had to use the w and h variables to define separate offsets for different taskbar starting positions. – Another Code Mar 13 '13 at 20:32
  • Works on Windows 10. I've modified it slightly to make the taskbar always the same size and added it to the scheduler to run on workstation unlock. – Yuriy Faktorovich Dec 03 '16 at 17:56
5

The taskbar is a window. Use SetWindowPos() to move it. See also SHAppBarMessage() and ABM_WINDOWPOSCHANGED.

Though the taskbar may be special and Windows may not like you moving it around. There are a lot of special cases in the Shell appbar API implementation for the taskbar.

To move to another monitor, use EnumDisplayMonitors() with GetMonitorInfo(). Some monitors may have negative coordinates.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
  • 2
    This is an awful idea. Please don't do that to your customers. – Ana Betts Jan 15 '10 at 02:59
  • 9
    Until OP tells us why he wants to do it, we don't know. There are two things to consider: is it possible and is it a good idea. We are only here to consider the former and not the later. Though I agree in general it's not good to move the users task bar around, I also can see at least two valid cases for moving it at the users request. Since we don't know, lets try not to judge too much. – i_am_jorf Jan 15 '10 at 03:10
  • @jeffamaphone: we're here because we choose to be here. Who are you to say we're only here for one and not the other? – John Saunders Jan 15 '10 at 03:14
4

I've had some luck with this task in an AutoHotkey script, just in case you don't care about the language used. It uses simulated keystrokes and mouse movements to move your taskbar. I stopped short of automatically unlocking/locking the taskbar.

The hard part was getting it to work reliably. A lot of the code is dedicated to making sure that the taskbar moved. It still doesn't work 100%... it fails like 10% of the time from what I've seen. However, it should be good enough to get you started!

If I ever come back to this script to make it work perfectly, I'll repost here.

Here is the example script (highlighting is a bit odd here, as the language is AHK):

F3::
    reload
return

F5::
    MoveTaskbar(2,"bottom")
return

F6::
    MoveTaskbar(2,"left")
return

F7::
    MoveTaskbar(1,"top")
return

; Move the taskbar
; dspNumber:    number.  device number (primary display is 1, secondary display is 2...)
; edge:         string.  Top, Right, Bottom, or Left
MoveTaskbar(dspNumber, edge)
{
    Critical 
    OutputDebug MoveTaskbar - called to move taskbar to display #%dspNumber% ("%edge%" edge)

    ; absolute coordinate system
    CoordMode, Mouse, Screen

    ; error checking for dspNumber
    SysGet, numMonitors, MonitorCount
    if (numMonitors<dspNumber)
    {
        OutputDebug MoveTaskbar - [ERROR] target monitor does not exist (dspNumber = "%dspNumber%")
        return
    }

    ; get screen position for target monitor
    SysGet, target, Monitor, %dspNumber%

    oX := 7
    oY := 7

    ; get coordinates for where to move the taskbar
    if (edge = "Top")
    {
        oX := (targetRight-targetLeft)/2
        trgX := oX+targetLeft
        trgY := targetTop+15
    }
    else if (edge = "Right")
    {
        oY := -(targetBottom-targetTop)/2
        trgX := targetRight-15
        trgY := -oY + targetTop
    }
    else if (edge = "Bottom")
    {
        oX := -(targetRight-targetLeft)/2
        trgX := -oX+targetLeft
        trgY := targetBottom-15
    }
    else if (edge = "Left")
    {
        oY := (targetBottom-targetTop)/2
        trgX := targetLeft+15
        trgY := oY+targetTop
    }
    else
    {
        OutputDebug MoveTaskbar - [ERROR] target edge was improperly specified (edge = "%edge%")
        return
    }
    trgX := round(trgX)
    trgY := round(trgY)
    oX := round(oX)
    oY := round(oY)

    OutputDebug MoveTaskbar - target location is (%trgX%,%trgY%)
    MouseGetPos, startX, startY
    OutputDebug MoveTaskbar - mouse is currently at (%startX%,%startY%)

    ; request the move mode (via context menu)
    SendInput #b
    SendInput !+{Space}
    SendInput m

    ; wait for the move mode to be ready
    Loop 
    {
        if A_Cursor = SizeAll
            break
    }
    OutputDebug MoveTaskbar - move mode is ready

    ; start the move mode
    SendInput {Right}   

    ; wait for the move mode to become active for mouse control
    Loop 
    {
        if A_Cursor = Arrow
            break
    }
    OutputDebug MoveTaskbar - move mode is active for mouse control

    ; move taskbar (and making sure it actually does move)
    offset := 7
    count := 0
    Loop
    {
        ; move the taskbar to the desired location
        OutputDebug MoveTaskbar - attempting to move mouse to (%trgX%,%trgY%)
        MouseMove, %trgX%, %trgY%, 0
        MouseGetPos, mX, mY, win_id
        WinGetClass, win_class, ahk_id %win_id%

        count += 1

        ; if the mouse didn't get where it was supposed to, try again
        If ((mX != trgX) or (mY != trgY))
        {
            OutputDebug MoveTaskbar - mouse didn't get to its destination (currently at (%mX%,%mY%)).  Trying the move again...
            continue
        }

        ; if the taskbar hasn't followed yet, wiggle the mouse!
        if (win_class != "Shell_TrayWnd")
        {
            OutputDebug MoveTaskbar - window with class "%win_class%" is under the mouse... wiggling the mouse until the taskbar gets over here

            ;offset := - offset
            trgX -= round(oX/2)
            trgY -= round(oY/2)
            oX := -oX
            oY := -oY
            if count = 50
            {
                OutputDebug, MoveTaskbar - wiggling isn't working, so I'm giving up.
                return
            }
        }
        else
            break
    }

    OutputDebug MoveTaskbar - taskbar successfully moved
    SendInput {Enter}
}
Josh
  • 173
  • 3
  • 7
4

Thank you for asking this question!

Its Windows 10 now and i got the same kind of problem where i made a script to switch between a 2 screens setup and only the tv for movies. After switching back to the 2 screens setup, the taskbar is back on the right monitor, just like you experienced.

I found a solution involving modifying the registry key that defines the taskbar location.

This is the said key: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3

Open the regisrty editor while your taskbar is at the right spot and size (Win+R, type regedit", the enter), then navigate to the key path above. You should find a binary value named "Settings" that looks like this:

30 00 00 00 fe ff ff ff 02 00 00 00 03 00 00 00 4e 00 00 00 32 00 00 00 80 f8 ff ff b2 01 00 00 be f8 ff ff ea 05 00 00 60 00 00 00 01 00 00 00

Your numbers may vary, but it doesn't matter. Simply click on file>export action in the menu once you navigated to the value, then use the file->export option from the top menu, and and save the .reg file in your system forlder (C:\Windows\System32). Make sure the export range is set to "Selected Branch" so only this value is affected. This will create a registry script that will restore the exact position of your taskbar.

However, if you just use the "merge" option on your script, you won't see the change since you will need to restart the explorer.exe process. To achieve this, you can simply make a batch script in noptepad looking like this:

@echo off
%windir%\system32\regedit.exe /s file.reg
taskkill /f /im explorer.exe
start explorer.exe
end

Simply replace in the 2nd line the "file.reg" by the complete file name of the .reg script you previously created, then save the file as a ".bat".

Running this script as an admin will reset the taskbar to where it should be. You will see the ui flashing briefly, since the taskbar and desktop will reset.

You could call this script from a Task, or make a shortcut that is set to run as admin to make it even easier!

I hope this answer reaches you, even if is is a "little" late XD

Your Welcome!

  • Thank you for saving me the hassle to find the correct reg key :D I combined this with taskschd in order to not get an UAC prompt (without deactivating it completely). You have to specifically use it to call regedit, starting a bat this way will prompt UAC for regedit https://www.winhelponline.com/blog/run-programs-elevated-without-getting-the-uac-prompt/ – 2called-chaos Feb 20 '21 at 17:31
3

As far as I can tell, Vista and onwards ignore any program trying to move the taskbar. The old method was ABM_SETPOS + MoveWindow, and this no longer works on the taskbar. The only way that I am aware of that still works is simulating a mouse move (click-move-release). I've read about that method, but I've never done it myself.

Bob Moore
  • 6,788
  • 3
  • 29
  • 42
1

Here is a solution with PowerShell. My code is based on the solutions presented in the answers here:

2,3 | ForEach-Object {
    $local:regPath = "HKCU:\$(
        )SOFTWARE\Microsoft\Windows\$(
            )CurrentVersion\Explorer\StuckRects$_"
    $s = Get-ItemProperty $regPath |
        Select-Object -ExpandProperty Settings
    $s[12] = 2
    Set-ItemProperty -Path $regPath -Name Settings -Value $s
}

# Restart the Explorer process so that registry is read again
Get-Process Explorer | Stop-Process
$local:stop = $false
do {
    Start-Sleep -Seconds 5
    $stop = Get-Process Explorer -ErrorAction SilentlyContinue
    if( $stop ) { continue }
    Write-Host -ForegroundColor Yellow "$(
        )Explorer hasn't auto-started, attempting to restart..."
    Start-Process Explorer
} until ( $stop )

The code will change to 2 (right-side) the 13th position of the Settings registry stream at the following keys:

HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StuckRects2
HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3

Afterwards, it kills the explorer.exe process, waits around for 5 seconds and if explorer hasn't started again, it will start a new instance.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Lockszmith
  • 2,173
  • 1
  • 29
  • 43
0

SHAppBarMessage(ABM_SETPOS,...)

Anders
  • 97,548
  • 12
  • 110
  • 164
  • 1
    `ABM_GETTASKBARPOS` retrieves the position of taskbar. But, ABM_SETPOS isn't working well. I've obtained taskbar's hWnd by looking up "Shell_TrayWnd". (I'm using Windows 7) But, no luck. MoveWindow/SetWindowPos and any other ABM_* are not working. But, thanks. – minjang Jan 15 '10 at 05:26
0

In my experience the task bar on the left and right side clash unworkably with the rest of the experience. Even top has the problem that Preview appear outside the screen at the top.

For me this works in windows 11 to toggle task bar between top and bottom.

$RegistryPath =  'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3'
$Name = "Settings"

$NewValue = Get-ItemProperty -Path $RegistryPath
$NewValue.Settings[12] = 4-$NewValue.Settings[12]

Set-ItemProperty -Path $RegistryPath -Name $Name -Value $NewValue.Settings
Stop-Process -Name "Explorer"

Explorer is autmatically started when it is killed so there is no need to start it manually.

theking2
  • 2,174
  • 1
  • 27
  • 36