Mark Needham

Thoughts on Software Development

Controlling window position with the win32 API

with one comment

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.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • HackerNews
  • StumbleUpon
  • Twitter

Written by Mark Needham

August 10th, 2008 at 3:02 am

Posted in .NET

Tagged with , ,

One Response to 'Controlling window position with the win32 API'

Subscribe to comments with RSS

  1. Good one of using Win32API is C#. I have been doing this for sometime. But I normally use AutoIT to abstract my self from the underlying C data structures and the Win32API internals…

    Sai

    12 Aug 08 at 5:28 am

Leave a Reply