如何以编程方式移动Windows任务栏?

时间:2010-01-14 20:58:03

标签: c++ windows winapi

我想知道任何类型的API或解决方法(例如,脚本或注册表)将Windows任务栏移动(或调整大小)到另一个位置,包括另一个监视器(如果是双监视器)。当然,我们可以使用鼠标移动任务栏,但我想通过程序或某种自动方式移动任务栏。

我试图找到Win32 API,但似乎没人做这个工作。

编辑:很多人的意见让我感到惊讶。让我解释为什么我想要它。在我的工作场所,我使用的是双显示器(分辨率不同),任务栏放在左侧显示器上,而主显示器是正确的显示器。但是,我经常通过远程桌面连接到我的工作场所计算机。远程连接后,任务栏位置被切换。这就是为什么我想制作一个可以保存/恢复任务栏位置的简单程序。每天我都要重新安排我的任务栏。而已。我只想要

6 个答案:

答案 0 :(得分:7)

我在Windows 7上也有此需求。以下是使用autohotkey脚本执行此操作的方法:

; 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   

我在Windows 7上使用经典窗口主题对此进行了测试。要使用此功能,请指定一个热键来调用此脚本,然后将鼠标光标定位到要将任务栏拖动到的位置,然后按热键。

答案 1 :(得分:5)

任务栏是一个窗口。使用SetWindowPos()移动它。另请参见SHAppBarMessage()和ABM_WINDOWPOSCHANGED。

虽然任务栏可能很特殊,但Windows可能不喜欢你移动它。任务栏的Shell appbar API实现中有很多特殊情况。

要移至其他监视器,请将EnumDisplayMonitors()GetMonitorInfo()一起使用。有些显示器可能有负坐标。

答案 2 :(得分:4)

我已经在AutoHotkey脚本中运行了这个任务,以防万一你不关心使用的语言。它使用模拟击键和鼠标移动来移动任务栏。我没有自动解锁/锁定任务栏。

困难的部分是让它可靠地运作。许多代码专门用于确保任务栏移动。它仍然不能100%工作......它从我看到的10%的时间失败了。但是,它应该足以让你开始!

如果我回到这个剧本以使其完美运作,我会转发到这里。

以下是示例脚本(此处突出显示有点奇怪,因为语言是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}
}

答案 3 :(得分:3)

据我所知,Vista和以后版本忽略了任何试图移动任务栏的程序。旧方法是ABM_SETPOS + MoveWindow,这不再适用于任务栏。我所知道的唯一方法仍然是模拟鼠标移动(点击 - 移动 - 释放)。我已经读过这个方法了,但我自己从来没有这样做过。

答案 4 :(得分:0)

SHAppBarMessage(ABM_SETPOS,...)

答案 5 :(得分:0)

谢谢你问这个问题!

现在是Windows 10,我遇到了同样的问题,我制作了一个脚本来在2屏幕设置和仅电视电影之间切换。切换回2个屏幕设置后,就像您所经历的一样,任务栏又回到了右侧的监视器上。

我找到了一种解决方案,其中涉及修改注册表项,该解决方案定义了任务栏的位置。

这是所述键: HKEY_CURRENT_USER \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Explorer \ StuckRects3

在任务栏位于正确的位置和大小上时打开注册表编辑器 (Win + R,输入regedit”,然后按Enter),然后导航到上面的关键路径。您应该找到一个二进制文件名为“ Settings”的值,如下所示:

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

您的电话号码可能会有所不同,但这并不重要。导航到该值后,只需单击菜单中的file> export操作,然后使用顶部菜单中的file-> export选项,然后将.reg文件保存在您的系统中(C:\ Windows \ System32)。确保导出范围设置为“选定分支”,以便仅此值受到影响。这将创建一个注册脚本,该脚本将还原任务栏的确切位置。

但是,如果仅在脚本上使用“合并”选项,则不会看到更改,因为您需要重新启动explorer.exe进程。为此,您只需在noptepad中制作一个批处理脚本,如下所示:

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

只需在第二行中用先前创建的.reg脚本的完整文件名替换“ file.reg”,然后将该文件另存为“ .bat”。

以管理员身份运行此脚本会将任务栏重置为应有的位置。 您会看到ui短暂闪烁,因为任务栏和桌面将重置

您可以从“任务”中调用此脚本,或创建快捷方式,该快捷方式被设置为以管理员身份运行,从而使其变得更加简单!

我希望这个答案能到达您,即使它是XD的“小”晚期

您的欢迎!