8
votes

I'm trying to write a few simple AutoHotkey scripts for moving windows around, and I'm having trouble getting the correct screen size values.

I'm trying to get the size of the usable area on the screen (generally the full screen resolution minus the taskbar, and maybe any other docked windows like the sidebar in Vista). Neither of the methods I've found for getting the screen width seems to work.

None of the 3 methods I found to get the screen size are giving me the right values. Here's the test script I'm using (running on XP with the taskbar on the bottom at its default size):

#7::
WinMove A,,0,0,A_ScreenWidth,A_ScreenHeight
return

#8::
;SM_CXMAXIMIZED and SM_CYMAXIMIZED
SysGet, ScreenWidth, 61
SysGet, ScreenHeight, 62
WinMove A,,0,0,ScreenWidth,ScreenHeight
return

#9::
;SM_CXFULLSCREEN and SM_CYFULLSCREEN
SysGet, ScreenWidth, 16
SysGet, ScreenHeight, 17
WinMove A,,0,0,ScreenWidth,ScreenHeight
return

#7 causes the window to take up the entire resolution, so it overlaps the taskbar.

#8 causes the width to be larger than the resolution (I see the window's right edge show up on my secondary monitor) and the height is slightly too large, so the window partially overlaps the taskbar area. Looks like this is correct except for not taking into account the window decorations at the edges.

#9 seems to have the correct width, but the height is too short. It looks like it's subtracting the taskbar's height from the resolution's height, but then subtracting another 30 pixels from it.

I could just use what I have in #9 and add 30 to the height I get, but that feels too much like a hack that would break in other configurations. It seems like there has to be a way to get the available screen size properly, but I can't find it in AutoHotkey.

For reference, this seems to give me what I need in Java:

Toolkit.getDefaultToolkit().getScreenSize();
2

2 Answers

5
votes

I got something working in XP. It currently only takes into consideration the taskbar, so it probably won't do the right thing in Vista when the sidebar is visible. However, it does work regardless of where the toolbar is.

Here are the methods I created, along with a simple ResizeAndCenter method that shows their use:

; Gets the edge that the taskbar is docked to.  Returns:
;   "top"
;   "right"
;   "bottom"
;   "left"
GetTaskbarEdge() {
  WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,

  if (TW = A_ScreenWidth) { ; Vertical Taskbar
    if (TY = 0) {
      return "top"
    } else {
      return "bottom"
    }
  } else { ; Horizontal Taskbar
    if (TX = 0) {
      return "left"
    } else {
      return "right"
    }
  }
}

GetScreenTop() {
  WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
  TaskbarEdge := GetTaskbarEdge()

  if (TaskbarEdge = "top") {
    return TH
  } else {
    return 0
  }
}

GetScreenLeft() {
  WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
  TaskbarEdge := GetTaskbarEdge()

  if (TaskbarEdge = "left") {
    return TW
  } else {
    return 0
  }
}

GetScreenWidth() {
  WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
  TaskbarEdge := GetTaskbarEdge()

  if (TaskbarEdge = "top" or TaskbarEdge = "bottom") {
    return A_ScreenWidth
  } else {
    return A_ScreenWidth - TW
  }
}

GetScreenHeight() {
  WinGetPos,TX,TY,TW,TH,ahk_class Shell_TrayWnd,,,
  TaskbarEdge := GetTaskbarEdge()

  if (TaskbarEdge = "top" or TaskbarEdge = "bottom") {
    return A_ScreenHeight - TH
  } else {
    return A_ScreenHeight
  }
}

ResizeAndCenter(w, h)
{
  ScreenX := GetScreenLeft()
  ScreenY := GetScreenTop()
  ScreenWidth := GetScreenWidth()
  ScreenHeight := GetScreenHeight()

  WinMove A,,ScreenX + (ScreenWidth/2)-(w/2),ScreenY + (ScreenHeight/2)-(h/2),w,h
}
3
votes

Have you tried using SysGet's MonitorWorkArea sub-command?
http://www.autohotkey.com/docs/commands/SysGet.htm