· win32 c net

Controlling window position with the win32 API

We’ve been doing a bit of work around controlling the state of the windows of applications launched programmatically.

The problem we were trying to solve is to launch an arbitrary application, move it around the screen and then save its window position on the screen so that next time it’s launched it loads in the same position.

There are some win32 APIs designed to do just this, although it took a fair bit of searching and trial and error to work out exactly how to use them.

Since the application we wrote to do this is in C# it was fairly easy to import the win32 APIs, the main method call being GetWindowInfo, which is imported like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
~~~
   [DllImport(user32.dll)]
   private static extern bool GetWindowInfo(IntPtr hwnd, ref tagWINDOWINFO pwi); 

   [StructLayout(LayoutKind.Sequential)]
    public struct tagRECT
    {
        /// LONG->int
        public int left;

        /// LONG->int
        public int top;

        /// LONG->int
        public int right;

        /// LONG->int
        public int bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct tagWINDOWINFO
    {
        /// DWORD->unsigned int
        public uint cbSize;

        /// RECT->tagRECT
        public tagRECT rcWindow;

        /// RECT->tagRECT
        public tagRECT rcClient;

        /// DWORD->unsigned int
        public uint dwStyle;

        /// DWORD->unsigned int
        public uint dwExStyle;

        /// DWORD->unsigned int
        public uint dwWindowStatus;

        /// UINT->unsigned int
        public uint cxWindowBorders;

        /// UINT->unsigned int
        public uint cyWindowBorders;

        /// ATOM->WORD->unsigned short
        public ushort atomWindowType;

        /// WORD->unsigned short
        public ushort wCreatorVersion;
    }~~~
We found out how to do this from here, but for the sake of explaining how it works I’ll keep it here too.

The GetWindowInfo’s first argument is a window handler. We launched our application using the .NET Process class so we can access this using the MainWindowHandle property. Don’t use WindowHandle as this doesn’t get the handle to the window itself - I think it gets the handle to the process which launched the window which is not what we want.

Therefore, to get the position of the window on the screen we can use the following code:

1
2
3
~~~
tagWINDOWINFO info = new tagWINDOWINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
GetWindowInfo(process.MainWindowHandle, ref info);~~~
To put the window back in this position we first need to include the following API calls:
1
2
3
4
5
~~~
[DllImport(user32.dll)]
private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

[DllImport(user32.dll)]
private static extern bool UpdateWindow(IntPtr hWnd);~~~
Then call both of these methods like so:
1
2
3
4
5
~~~
process.Start();
process.ForceWaitForInputIdle();

MoveWindow(process.MainWindowHandle, left, top, width, height, true);
UpdateWindow(process.MainWindowHandle);~~~
UpdateWindow needs to be called otherwise the window will remain in its previous position.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket