Log in

View Full Version : Window ID's



Thedonsquad
04-15-2008, 12:21 AM
My system is about to get a complete clean so I'm putting the code i've created so far up:


/*
************************************************** ***************
** AHK Script: FreeBox
** Language: English
** Author: Thedonsquad
** E-mail: thedonsquad@googlemail.com
** Created: April 15, 2008
** Edited: April 20, 2008
** Revision: .29
** Status: Untested
** Specifics: Must be on system with same resolution monitors
************************************************** ***************
************************************************** ***************
** LAYOUT THEMES:
**
** These are categorized by how many instances are on the givin
** monitor. Currently allows for 1 to 4 instances.
**
** Value 0 means nonexistant display, and will be ignored
**
** If you have 1 instance opening on a monitor the value must be
** 1 in the LTMon for the monitor it is going in.
**
** If you have 2 instances opening on a monitor the value can be
** 1 for Horizontal Split:
** +-------+
** ¦ 1 ¦
** +-------+
** ¦ 2 ¦
** +-------+
** 2 for Vertical Split:
** +---+---+
** ¦ ¦ ¦
** ¦ 1 ¦ 2 ¦
** ¦ ¦ ¦
** +---+---+
**
** If you have 3 instances opening on a monitor the value can be
** 1 for Horizontal split with two on top:
** +---+---+
** ¦ 1 ¦ 2 ¦
** +---+---+
** ¦ 3 ¦
** +-------+
** 2 for Horizontal split with two on bottom:
** +-------+
** ¦ 1 ¦
** +---+---+
** ¦ 2 ¦ 3 ¦
** +---+---+
** 3 for Vertical split with two on left:
** +---+---+
** ¦ 1 ¦ ¦
** +---+ 3 ¦
** ¦ 2 ¦ ¦
** +---+---+
** 4 for Vertical split with two on right:
** +---+---+
** ¦ ¦ 2 ¦
** ¦ 1 +---+
** ¦ ¦ 3 ¦
** +---+---+
**
** If you have 4 instances opening on a monitor the value must be
** 1 in the LTMon for the monitor it is going in.
**
** Note: You can open a notepad or web browser window in one of
** these locations as well This is done by placing the program in
** the Game5 spot, it will be borderless and titleless as well.
************************************************** ***************
*/
/*
************************************************** ***************
** Launch all instances on script start
** Comment out with ; (semicolon) to take out instances
** Delete comment to enable instance
**
** Delete the comment on line prior to ifWinNotExist to disable
** automatic launch and set to the hotkey you please
**
** Note: currently not set up for OpenGL based programs, to do
** so; change "hk_class GxWindowClassD3d" to the program name
************************************************** ***************
*/
; ^!+W::
ifWinNotExist, ahk_class GxWindowClassD3d
{
; Declare programs to be opened
; Note: Open each instance and turn on windowed mode but make
; sure maximized is unchecked.
Game1 := "C:\World of Warcraft\wow.exe"
Game2 := "C:\World of Warcraft1\wow.exe"
Game3 := "D:\World of Warcraft\wow.exe"
Game4 := "D:\World of Warcraft1\wow.exe"
; Game5 := "E:\World of Warcraft\wow.exe"
; Declare working directorys of programs
PATH1 := "C:\World of Warcraft\"
PATH2 := "C:\World of Warcraft1\"
PATH3 := "D:\World of Warcraft\"
PATH4 := "D:\World of Warcraft1\"
; PATH5 := "E:\World of Warcraft1\"
; Declare number of instances per monitor
; !!!DO NOT COMMENT THESE OUT!!!
; Set to 0 if nonexistant display
INMon1 := 3
INMon2 := 0
INMon3 := 0
INMon4 := 0
; Declare layout theme
; !!!DO NOT COMMENT THESE OUT!!!
; Set to 0 if nonexistant display
; See top for proper layout numbers
LTMon1 := 2
LTMon2 := 0
LTMon3 := 0
LTMon4 := 0
; Run each declared program and assign ID to variable
; Note: to improve load time, set the default resolution of
; the program to the minimum setting as it will be modified
; later anyway.
Run, %Game1%, %PATH1%, , instanceID1
Run, %Game2%, %PATH2%, , instanceID2
Run, %Game3%, %PATH3%, , instanceID3
; Run, %Game4%, %PATH4%, , instanceID4
; Run, %Game5%, %PATH5%, , instanceID5
; Wait 5 seconds for the instances to launch
; Adjust if necessary, 1000 = 1 sec
Sleep 5000
; Call function to select regions
RegionCreate()
return
}
/*
************************************************** ***************
** Region Creation function
************************************************** ***************
*/
RegionCreate()
{
; Pull needed global values
global INMon1 ; Instances per monitor
global INMon2
global INMon3
global INMon4
global LTMon1 ; Layout Theme for monitors
global LTMon2
global LTMon3
global LTMon4
global instanceID1 ; Game PID's
global instanceID2 ; Comment out any that aren't used above
global instanceID3
global instanceID4
; global instanceID5
MonHori := (A_ScreenHeight / 2)
MonVert := (A_ScreenWidth/ 2)
; Monitor1
if INMon1 > 0
{
if INMon1 = 1
{
; Only 1 instance, so fullscreen it
WinMove, ahk_pid %instanceID1%, , -3, -3, (A_ScreenWidth + 6), (A_ScreenHeight + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID1%
WinSet, Style, -0x40000, ahk_pid %instanceID1%
Winset, Region, 3-3 W%A_ScreenWidth% H%A_ScreenHeight%, ahk_pid %instanceID1%
}
if INMon1 = 2
{
if LTMon1 = 1
{
; 2 instances Horizontal Split
WinMove, ahk_pid %instanceID1%, , -3, -3, (A_ScreenWidth + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID1%
WinSet, Style, -0x40000, ahk_pid %instanceID1%
Winset, Region, 3-3 W%A_ScreenWidth% H%MonHori%, ahk_pid %instanceID1%
WinMove, ahk_pid %instanceID2%, , -3, ((A_ScreenHeight / 2) - 3), (A_ScreenWidth + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID2%
WinSet, Style, -0x40000, ahk_pid %instanceID2%
Winset, Region, 3-3 W%A_ScreenWidth% H%MonHori%, ahk_pid %instanceID2%
}
if LTMon1 = 2
{
; 2 instances Vertical Split
WinMove, ahk_pid %instanceID1%, , -3, -3, ((A_ScreenWidth /2) + 6), (A_ScreenHeight + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID1%
WinSet, Style, -0x40000, ahk_pid %instanceID1%
Winset, Region, 3-3 W%MonVert% H%A_ScreenHeight%, ahk_pid %instanceID1%
WinMove, ahk_pid %instanceID2%, , ((A_ScreenWidth / 2) - 3), -3, ((A_ScreenWidth / 2) + 6), (A_ScreenHeight + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID2%
WinSet, Style, -0x40000, ahk_pid %instanceID2%
Winset, Region, 3-3 W%MonVert% H%A_ScreenHeight%, ahk_pid %instanceID2%
}
}
if INMon1 = 3
{
if LTMon1 = 1
{
; 3 instances Horizontal split with two on top:
WinMove, ahk_pid %instanceID1%, , -3, -3, ((A_ScreenWidth / 2) + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID1%
WinSet, Style, -0x40000, ahk_pid %instanceID1%
Winset, Region, 3-3 W%MonVert% H%MonHori%, ahk_pid %instanceID1%
WinMove, ahk_pid %instanceID2%, , ((A_ScreenWidth / 2) - 3), -3, ((A_ScreenWidth / 2) + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID2%
WinSet, Style, -0x40000, ahk_pid %instanceID2%
Winset, Region, 3-3 W%MonVert% H%MonHori%, ahk_pid %instanceID2%
WinMove, ahk_pid %instanceID3%, , -3, ((A_ScreenHeight / 2) - 3), (A_ScreenWidth + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID3%
WinSet, Style, -0x40000, ahk_pid %instanceID3%
Winset, Region, 3-3 W%A_ScreenWidth% H%MonHori%, ahk_pid %instanceID3%
}
if LTMon1 = 2
{
; 3 instances Horizontal split with two on bottom
WinMove, ahk_pid %instanceID1%, , -3, -3, (A_ScreenWidth + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID1%
WinSet, Style, -0x40000, ahk_pid %instanceID1%
Winset, Region, 3-3 W%A_ScreenWidth% H%MonHori%, ahk_pid %instanceID1%
WinMove, ahk_pid %instanceID2%, , -3, ((A_ScreenHeight / 2) - 3), ((A_ScreenWidth / 2) + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID2%
WinSet, Style, -0x40000, ahk_pid %instanceID2%
Winset, Region, 3-3 W%MonVert% H%MonHori%, ahk_pid %instanceID2%
WinMove, ahk_pid %instanceID3%, , ((A_ScreenWidth / 2) - 3), ((A_ScreenHeight / 2) - 3), ((A_ScreenWidth / 2) + 6), ((A_ScreenHeight / 2) + 6)
WinSet, Style, -0x800000, ahk_pid %instanceID3%
WinSet, Style, -0x40000, ahk_pid %instanceID3%
Winset, Region, 3-3 W%MonVert% H%MonHori%, ahk_pid %instanceID3%
}
}
}
if INMon2 > 0
{

}
if INMon3 > 0
{

}
if INMon4 > 0
{

}
}

thinus
04-15-2008, 01:16 AM
Is it necessary to bump all of them? Can't you just switch the current main and the new main or is it crucial you maintain the order?

Chorizotarian
04-15-2008, 09:03 AM
I do it by running a PowerShell script to get the process IDs of my running instances of WoW, sorting them by exe path, and passing the pids into AHK on the command line. (AHK can also make window groups based on process ID.) Code here if you are interested:
[AutoHotKey] Sleep/Spread out formations ('http://www.dual-boxing.com/forums/index.php?page=Thread&postID=51727&highlight=powershell#post51727')

Thedonsquad
04-15-2008, 11:12 AM
Meh, I'm not trying to learn and understand 2 scripting languages. I'm about 6 hours into learning AHK and have enough funtionality to play the game viably. My goals are to create a more seamless transition from one main to another.

No, I would not have to bump all of the ID's, but that doesn't change the need to be able to do it.

Chorizotarian
04-15-2008, 02:11 PM
Yeah, it would be simpler to avoid the extra script. Post back if you get an all-AHK solution!

Thedonsquad
04-15-2008, 07:00 PM
So theres a few things that i'm discovering as i work on this little project, and most of that is the possible benfits of having the script keep track of what is active and what is not

First : allows you to be able to clean up the send to all clones part to look something like this:


SendAllClone(strKeys)
{
global WoWinId1 ; declares the WoWinID(#) as global
global WoWinId2 ; the # associated is the ahk_id
global WoWinId3 ; for the corresponding list value
global WoWinId4

ControlSend, , %strKeys%, ahk_id %WoWinId2%
ControlSend, , %strKeys%, ahk_id %WoWinId3%
ControlSend, , %strKeys%, ahk_id %woWinId4%
}

In order for the list created by WinGet function to be in the correct order at startup, have your RunWait functions call in order from last to first eg:

^!+w::
ifWinNotExist, World of Warcraft
{
; Declare programs to be opened
WOW1 := "C:\World of Warcraft\maximizer.exe"
WOW2 := "C:\World of Warcraft1\maximizer.exe"
WOW3 := "D:\World of Warcraft\maximizer.exe"
WOW4 := "D:\World of Warcraft1\maximizer.exe"

; Declare working directorys of programs
WOWPATH1 := "C:\World of Warcraft\"
WOWPATH2 := "C:\World of Warcraft1\"
WOWPATH3 := "D:\World of Warcraft\"
WOWPATH4 := "D:\World of Warcraft1\"

RunWait, %WOW4%, %WOWPATH4%
RunWait, %WOW3%, %WOWPATH3%
RunWait, %WOW2%, %WOWPATH2%
RunWait, %WOW1%, %WOWPATH1%

; get the list of WoW IDs (ordered from WOW1 to WOW4 in array WoWinID)
WinGet, WoWinId, List, World of Warcraft
return
}
This makes the values work as follows (oh and don't mess with the windows while they are loading (not even click on em))
WoWinId1 = WOW1
WoWinId2 = WOW2 and so on...

thinus
04-15-2008, 08:37 PM
I am working on a script to launch WoW directly without having to use Maximizer. I am using 2 monitors and the 4 clone sessions on the 2nd monitor is pretty small so my end goal is to be able to resize/shift my WoW windows on the fly. When I change my main I can resize and reposition the main window. I am not sure if it is even possible but it would be great if it is.



RunWait, %WOW4%, %WOWPATH4%
RunWait, %WOW3%, %WOWPATH3%
RunWait, %WOW2%, %WOWPATH2%
RunWait, %WOW1%, %WOWPATH1%

; get the list of WoW IDs (ordered from WOW1 to WOW4 in array WoWinID)
WinGet, WoWinId, List, World of Warcraft



You can also try:



global WoW1
global WoW2
global WoW3
global WoW4

RunWait, %WOW4%, %WOWPATH4%
WoW4 := ActiveWin()
RunWait, %WOW3%, %WOWPATH3%
WoW3 := ActiveWin()
RunWait, %WOW2%, %WOWPATH2%
WoW2 := ActiveWin()
RunWait, %WOW1%, %WOWPATH1%
WoW1 := ActiveWin()


This way you don't rely on WinGet to give you the correct order (not tested).

Chorizotarian
04-15-2008, 08:40 PM
With this approach do you have to shut down all of your copies of WoW if you want to make a change to your AHK script? It would be nice if the script checked to see if a given copy was already running and, if so, skipped re-launching it.

Thedonsquad
04-15-2008, 09:03 PM
i'm still trying to figure out how to get it to repop a crashed/killed wow, shouldn't be that difficult. updated first post with code so far.

and the reason i'm using maximizer is just for cleanliness, i have plenty of desktop to play with but i like it clean...
there are several reasons for using RunWait, but primarily since maximizer tends to screw up when opening multiple at once, RunWait runs maximizer, waits till it's finished and out of memory before running the next one. Also, you can declare a variable to store the PID when u run a command, but this doesn't work properly due to the fact that i'm not running wow from it. So, WinGet is a perfectly viable tool, and it just means that u wait for them all to be fully opened prior to messing with them, which is pretty easy for me since i type all the passwords in at once.

thinus
04-15-2008, 10:05 PM
i'm still trying to figure out how to get it to repop a crashed/killed wow, shouldn't be that difficult. updated first post with code so far.

and the reason i'm using maximizer is just for cleanliness, i have plenty of desktop to play with but i like it clean...
there are several reasons for using RunWait, but primarily since maximizer tends to screw up when opening multiple at once, RunWait runs maximizer, waits till it's finished and out of memory before running the next one. Also, you can declare a variable to store the PID when u run a command, but this doesn't work properly due to the fact that i'm not running wow from it. So, WinGet is a perfectly viable tool, and it just means that u wait for them all to be fully opened prior to messing with them, which is pretty easy for me since i type all the passwords in at once.

I know what Maximizer and WinGet does. Your wow launching script seems to be based on the script in the Wiki which I wrote. What I am trying to do is build the Maximizer functionality into my AHK script so I don't *need* to run Maximizer at all but achieve the same effect directly through the AHK script.

My current script also doesn't care about who is main and who is not. I have two broadcast methods, one of them will broadcast to all sessions, the other will only broadcast to the non-active sessions. In other words, I didn't care who the current main was.

However, what you are trying to do and what I am working on requires knowledge of which WoW session is the main and which are clones. The script also needs to keep track of which clone is which if you want it to affect your formations or moving/sizing of individual windows and switching mains. Even re-launching a specific session requires knowledge of which session is which. You are relying on the order of the IDs retrieved by WinGet and you are welcome to. I merely presented an alternative that does not rely on WinGet. Removing dependancies is a good thing.

The code I am working on also stores everything in arrays. In other words, people who two-box, three-box, four-box and five-box can all use the same script. They just need to edit the script header. No need to go into the broadcasting methods and modify those as they will just loop through the array essentially removing code duplication.

-

Keeping track of IDs:

If you are using the order of WowWinId and you want to shift the order then the following method should work:



ShiftWoWIDs(ShiftAmount)
{
; WoWWinId is the list of IDs that will be shifted, ShiftAmount is the amount to shift the IDs by
; assumes 5 wow sessions
global WoWWinId1
global WoWWinId2
global WoWWinId3
global WoWWinId4
global WoWWinId5

; shift WoWWinId1 by ShiftAmount
Index := Mod(ShiftAmount, 5) + 1
TempID%Index% := WoWWinId1

; shift WoWWinId2 by ShiftAmount
Index := Mod(1 + ShiftAmount, 5) + 1
TempID%Index% := WoWWinId2

; shift WoWWinId3 by ShiftAmount
Index := Mod(2 + ShiftAmount, 5) + 1
TempID%Index% := WoWWinId3

; shift WoWWinId4 by ShiftAmount
Index := Mod(3 + ShiftAmount, 5) + 1
TempID%Index% := WoWWinId4

; shift WoWWinId5 by ShiftAmount
Index := Mod(4 + ShiftAmount, 5) + 1
TempID%Index% := WoWWinId5

; now assign all the TempIDs back to the WoWWinIds
WowWinId1 := TempID1
WowWinId2 := TempID2
WowWinId3 := TempID3
WowWinId4 := TempID4
WowWinId5 := TempID5
}


So to shift by 2 you just call ShiftWoWIDs(2). I've tested it and it seems to work.

Thedonsquad
04-15-2008, 10:47 PM
With this approach do you have to shut down all of your copies of WoW if you want to make a change to your AHK script? It would be nice if the script checked to see if a given copy was already running and, if so, skipped re-launching it.

The nearest way i've figured out so far is to re-title it, and that crosses that line where you are modifying wow... i don't wan't to cross that line, so i won't... still working on a solution.


My current script also doesn't care about who is main and who is not. I have two broadcast methods, one of them will broadcast to all sessions, the other will only broadcast to the non-active sessions. In other words, I didn't care who the current main was.

However, what you are trying to do and what I am working on requires knowledge of which WoW session is the main and which are clones. The script also needs to keep track of which clone is which if you want it to affect your formations or moving/sizing of individual windows and switching mains. Even re-launching a specific session requires knowledge of which session is which. You are relying on the order of the IDs retrieved by WinGet and you are welcome to. I merely presented an alternative that does not rely on WinGet. Removing dependancies is a good thing.

So far, this is exactly what my script does; it sends to all non-active windows. It does this a different method, it does this because it's more efficient to know what ones to send to and just send it than check if it's inactive (4 times, one for each window) for every keystroke. This way you only change the way it sends if you call for it to, the inherant problem atm is that if you don't tell it to re-order the list, and you click another window and start pressing keys (other than the change commands) you will have 1 window recieve none, and another window recieve twice the ammount.

I would love to see a way to exclude maximizer, and take off the borders to the windows and place them. My problem with moving them is more that I have to move my mouse around two 28" monitors, and if they swap places (which is nice mind you) I then have to move the mouse all the way back... which tends to waste time in pvp.

I tend to differ from the idea of removing dependancies, as even if i were capable of skipping maximizer i would simply use the PID variables allowed in the run command to verify and reorg the initial list. There is a reason that DLL librarys are made, and theres a reason that wow is dependant on directX. Rewriting all the code is inefficient from a time standpoint, let alone the fact that in this case the WinGet command is compiled and probably written more efficiently than any scripting.

I don't mean to be battleing you on this, moreso you have more time and knowledge of the scripting language than I. I'm just trying to solve the problem and refine my setup to act the way I want it to. If others find it usefull (and I hope they do) great! I intend to have it fully commented and simple when i'm done, with the largest part of modification being someone commenting out the extra toons, or uncommenting the ones they need.

Theres a few other things I'm trying to put in there, specifically something I miss from AO... numpad camera control. I intend to put a small twist on it tho, by setting up a baseline placement for the cameras (one facing front, one left, one back, and one right) that would be bound to the Numpad5 key (an easy reset if things get screwy); then by using the 2,4,8,6 numpad keys be able to adjust the cameras all at once. This way a 4 boxer has 360 deg coverage and easy camera movement. Numpad - and + would be distance modifiers.



The formation movement at this point is easy. Goes something like this:

^!x down::
{
; Line Formation Downpress
ControlSend, , {q down}, ahk_id %WoWinId2% ; Move Fast Left
ControlSend, , {/ down}{/ up}{e down}, ahk_id %WoWinId3% ; Move Slow Right
ControlSend, , {/ down}{/ up}{q down}, ahk_id %WoWinId4% ; Move Slow Left
ControlSend, , {s down}, ahk_id %WoWinId1% ; Move Back
}
^!x up::
{
; Line Formation Release
ControlSend, , {q up}, ahk_id %WoWinId2% ; Move Fast Left
ControlSend, , {e up}{/ down}{/ up}, ahk_id %WoWinId3% ; Move Slow Right
ControlSend, , {q up}{/ down}{/ up}, ahk_id %WoWinId4% ; Move Slow Left
ControlSend, , {s up}, ahk_id %WoWinId1% ; Move Back
}
Edit: Oh, right and the other fun part was doing the individual movement from any window to any other... Basically, the M3 Group of keys on the G11 are now:

G1...G2...G3 = Q...W...E
G4...G5...G6 = A...S...D
All of which are modified by left ctrl, then the LCtrl Q combo sends the Q button to WoWinId2... etc...
the other groups; G7-G12 and G13-G18 send to WoWinId3 and WoWinId4 respectivly, allowing me to hit the M3 button above them and take control of any of the 4 without moving my mouse over to them, or even moving my eyes from the main screen.

thinus
04-15-2008, 11:26 PM
I am just nitpicking about WinGet. Creating 5 windows, calling WinGet and making an assumption about the order in which it returns the window IDs just makes me feel slightly uncomfortable. However, if it works it works. I just proposed a solution that does not depend on any assumptions and that I feel more comfortable with.

From the Maximizer code it looks like they manipulate the WoW window using SetWindowLong and SetWindowPos. These API methods can be called from AHK using DllCall so theoretically we should be able to do in an AHK script what Maximizer currently does.

The only "gotcha" with SetWindowLong and SetWindowPos is that it is ignored unless the windows are part of the same process which is probably why Maximizer launches your WoW for you. I am not sure if this will be an issue with AHK but I doubt it as there are numerous AHK script examples where SetWindowLong and SetWindowPos is used.

Thedonsquad
04-20-2008, 03:48 AM
Well, I figured it out. I now have an all AHK solution to retrive the PID's (without WinGet), as well as to completely avoid maximizer. All without the need for any dll calls.

the code will be put out once i clean it all up, make it able to be extremely easily adjusted for different setups. some of the features to be included:

- compatibility for different # of clones
- different regions and layout presets
- custom layouts
- PiP (overlays, though i havent decided method theres 2 different ways to do it)
- automatic send error and restart errored out wow (and correctly place it reguardless of any region swaps) (this will take a bit longer to create as i need to have wow crash on me to get all the correct information)

theres still a lot of things i want to get into it, but i hope this becomes usefull

Thedonsquad
05-07-2008, 05:13 AM
First post modified with current script, all is currently is figuring out is how many and and screen positions
this does not have the full functionality, as currently it only has ability for 1, 2, and partial 3 instance split

Chorizotarian
05-07-2008, 11:34 AM
Nice!