Samstag, 20. September 2014

[WoW v1.12.1 / C#] A basic window mover

Hello fellow readers,
instead of beginning with the bot tutorial I will first of all explain and post some easier and more tiny tools. That way I try to progress slowly towards our goal instead of just going for the big fish.

Today we will program a window mover in C# for World of Warcraft (or any other game). This tiny tool was always a nice help when i had to deal with multiple WoW windows:


1: Gather all processes relevant to the windows you want to move

 List<Process> WoW = new List<Process>();  
 foreach (Process p in Process.GetProcessesByName("WoW"))  
 {  
      WoW.Add(p);  
 }  

2: Obtain the window handles from the process.
What is a handle?
A HANDLE in Win32 programming is a token that represents a resource that is managed by the Windows kernel. A handle can be to a window, a file, etc.
Handles are simply a way of identifying a particulate resource that you want to work with using the Win32 APIs.

Conclusion: We need the handles pointing to our WoW windows.
 IntPtr[] Handle = new IntPtr[WoW.Count];  
 for (int i = 0; i < WoW.Count; i++)  
 {  
      Handle[i] = WoW[i].MainWindowHandle;  
      WoW[i].PriorityClass = ProcessPriorityClass.Normal;  
 }  

3: After obtaining the handles to our WoW windows we need to obtain the following:
Screenwidth aswell screenheight.
 int GlobalHeight = SystemInformation.VirtualScreen.Height;  
 int GlobalWidth = SystemInformation.VirtualScreen.Width;  

Before we continue we need to realise the following
The coordinate system for a window is based on the coordinate system of the display device. The basic unit of measure is the device unit (typically, the pixel). Points on the screen are described by x- and y-coordinate pairs. The x-coordinates increase to the right; y-coordinates increase from top to bottom. The origin (0,0) for the system depends on the type of coordinates being used.

The system and applications specify the position of a window on the screen in screen coordinates. For screen coordinates, the origin is the upper-left corner of the screen. The full position of a window is often described by a RECT structure containing the screen coordinates of two points that define the upper-left and lower-right corners of the window.

Short version: The point (0/0) is the top left corner of our monitor.

4: Before we can move the window we need to learn about dllimportant:
With dllimport we can call functions provided by a dll that is written in unmanaged code (C++, C etc.). Windows is providing a lot of functions to interact with the system and the processes running on it. To call those we need to define a prototype of a function and "assign" it to a function of an unmanaged dll.
The whole topic a bit better explained: http://msdn.microsoft.com/en-us/library/aa984739(v=vs.71).aspx

To move another process window we need the function "SetWindowPos" provided by the "user32.dll". With the help of PInvoke we can get pretty good infos about all WinAPI functions and how we are supposed to call them in any .net language: http://www.pinvoke.net/default.aspx/user32.setwindowpos

 [DllImport("user32.dll")]  
 private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,  
      int x, int y, int width, int height, uint uFlags);  

After defining the prototype of SetWindowPos and creating the handle list of windows we can go on with step 5.

5: Before we learned that the very top left point of our screen is 0/0. If we move our point to the right the X-coordinate increases. If we move our point towards the bottom our Y-coordinate increases.

Since we want to start repositioning our windows at the top right of the screen we will start with the following set of coordinates:
(GlobalWidth - x / 0)
In this case x is representing the width of our wow window since it would otherwise be moved outside the screen boundaries.

 int Schieber = 0;  
 int Row = 1;  
 foreach (IntPtr p in Handle)  
 {  
      // 310 241  
      SetWindowPos(p, IntPtr.Zero, GlobalWidth - (x * Row), 0 + (y * Schieber), x, y, SHOWWINDOW);  
      Schieber++;  
      if (Schieber > 2)  
      {  
           Row++;  
           Schieber = 0;  
      }  
 }  

As you can see we iterate over our array of handles repositioning and resizing each of them. After each repositioned window the Y-coordinate will be increased to move the next window in line below the previous window.
If there are are 3 windows placed over each other it will move one window width to the left and start the next column.


The full source code can be viewed here: https://github.com/Zz9uk3/WoWMover (a pre-compiled binary is also included)

If you have problems, questions or suggestions for further posts I would be glad to have a chat over skype (cmwts9) or IRC (#FeenixED on quakenet).

1 Kommentar: