aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/VSIX/Tango.BuildExtensions/WindowInfo.cs
blob: f9681ea312dfa7b461b80038894d168bdad277e8 (plain)
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TestStack.White.InputDevices;
using TestStack.White.WindowsAPI;

namespace Tango.BuildExtensions
{
    public class WindowInfo
    {
        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        static extern IntPtr GetDesktopWindow();

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        static extern int SendMessage(IntPtr hwndControl, uint Msg, int wParam, StringBuilder strBuffer); // get text

        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        static extern int SendMessage(IntPtr hwndControl, uint Msg, int wParam, int lParam);  // text length

        [DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out IntPtr result);

        [Flags]
        enum SendMessageTimeoutFlags : uint
        {
            SMTO_NORMAL = 0x0,
            SMTO_BLOCK = 0x1,
            SMTO_ABORTIFHUNG = 0x2,
            SMTO_NOTIMEOUTIFNOTHUNG = 0x8,
            SMTO_ERRORONEXIT = 0x20
        }

        private static List<IntPtr> GetAllChildrenHandles(IntPtr hParent, int maxCount)
        {
            List<IntPtr> result = new List<IntPtr>();
            int ct = 0;
            IntPtr prevChild = IntPtr.Zero;
            IntPtr currChild = IntPtr.Zero;
            while (true && ct < maxCount)
            {
                Debug.WriteLine("FindWindowEx: " + hParent);
                currChild = FindWindowEx(hParent, prevChild, null, null);
                if (currChild == IntPtr.Zero) break;
                result.Add(currChild);
                prevChild = currChild;
                ++ct;
            }
            return result;
        }

        private static int GetCaptionTextLength(IntPtr hTextBox)
        {
            // helper for GetCaptionText
            uint WM_GETTEXTLENGTH = 0x000E;
            IntPtr result = IntPtr.Zero;
            SendMessageTimeout(hTextBox, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 1000, out result);
            return (int)result;
        }

        private static string GetCaptionText(IntPtr hTextBox)
        {
            uint WM_GETTEXT = 0x000D;
            int len = GetCaptionTextLength(hTextBox);
            if (len <= 0) return null;  // no text. consider empty string instead.
            StringBuilder sb = new StringBuilder(len + 1);
            SendMessage(hTextBox, WM_GETTEXT, len + 1, sb);
            return sb.ToString();
        }

        public IntPtr Handle { get; set; }
        public int Level { get; set; }
        public String Caption { get; set; }
        public WindowInfo Parent { get; set; }
        public List<WindowInfo> Children { get; set; }

        public WindowInfo()
        {
            Children = new List<WindowInfo>();
        }

        public void SetActive()
        {
            SetForegroundWindow(Handle);
        }

        public void PressKey(KeyboardInput.SpecialKeys key)
        {
            SetActive();
            Keyboard.Instance.PressSpecialKey(key);
        }

        public override string ToString()
        {
            return Caption;
        }

        public static List<WindowInfo> GetAllWindows()
        {
            List<WindowInfo> windows = new List<WindowInfo>();

            IntPtr hDesktop = GetDesktopWindow();
            WindowInfo desktop = new WindowInfo();
            desktop.Handle = hDesktop;
            desktop.Level = 0;
            desktop.Caption = "(Desktop)";
            desktop.Parent = null;
            windows.Add(desktop);

            try
            {
                FillWindows(desktop, desktop.Children);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }

            return windows;
        }

        private static void FlattenWindows(WindowInfo parent, List<WindowInfo> windows)
        {
            windows.Add(parent);

            foreach (var window in parent.Children)
            {
                windows.Add(window);
                FlattenWindows(window, windows);
            }
        }

        public static WindowInfo GetWindow(String title)
        {
            var windows = GetAllWindows();

            List<WindowInfo> flatList = new List<WindowInfo>();
            FlattenWindows(windows.First(), flatList);

            return flatList.FirstOrDefault(x => x.Caption == title);
        }

        private static void FillWindows(WindowInfo parent, List<WindowInfo> windows)
        {
            foreach (var handle in GetAllChildrenHandles(parent.Handle, 5000))
            {
                WindowInfo child = new WindowInfo();
                child.Handle = handle;
                child.Level = parent.Level + 1;
                child.Caption = GetCaptionText(handle);
                child.Parent = parent;

                if (child.Caption != null)
                {
                    Debug.WriteLine(parent.Caption + " | " + child.Caption);
                    windows.Add(child);
                }

                FillWindows(child, child.Children);
            }
        }
    }
}