window.cs
上传用户:hbhltzc
上传日期:2022-06-04
资源大小:1925k
文件大小:22k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using System.Text;
  5. using System.Windows.Forms;
  6. using System.Threading;
  7. using System.Drawing;
  8. using System.Reflection;
  9. using System.Diagnostics;
  10. namespace UnitTests {
  11.     public class Window : IDisposable {
  12.         Process p;
  13.         IntPtr handle;
  14.         bool closed;
  15.         TestBase test;
  16.         SystemAccessible acc;
  17.         Dictionary<string, SystemAccessible> map;
  18.         Window parent;
  19.         bool disposed;
  20.         static int delay = 100;
  21.         public Window(Window parent, IntPtr handle) {
  22.             this.parent = parent;
  23.             this.handle = handle;
  24.             this.acc = SystemAccessible.AccessibleObjectForWindow(handle);
  25.         }
  26.         public Window(Process p) {
  27.             this.p = p;
  28.             IntPtr h = p.Handle;
  29.             while (h == IntPtr.Zero || !p.Responding) {
  30.                 Sleep(1000);
  31.                 p.WaitForInputIdle();
  32.                 h = p.Handle;
  33.                 if (p.HasExited) {
  34.                     throw new InvalidOperationException(string.Format("Process '{0}' has exited!", p.StartInfo.FileName));
  35.                 }
  36.             }
  37.             p.Exited += new EventHandler(OnExited);
  38.             int id = p.Id;
  39.             if (handle == IntPtr.Zero) {
  40.                 // p.MainWindowHandle always returns 0 for some unknown reason...
  41.                 int retries = 20;
  42.                 while (retries-- > 0 && handle == IntPtr.Zero) {
  43.                     handle = FindWindowForProcessId(id);
  44.                     Sleep(1000);
  45.                 }
  46.                 if (handle == IntPtr.Zero) {
  47.                     throw new Exception("Process as no window handle");
  48.                 }
  49.             }
  50.             this.acc = SystemAccessible.AccessibleObjectForWindow(handle);
  51.         }
  52.         void OnExited(object sender, EventArgs e) {
  53.             if (!disposed) {
  54.                 throw new Exception("Process exited.");
  55.             }
  56.         }
  57.         private static IntPtr FindWindowForProcessId(int id) {
  58.             // Hmmm, try and find window for this process then.
  59.             IntPtr hwnd = GetWindow(GetDesktopWindow(), GetWindowOptions.Child);
  60.             while (hwnd != IntPtr.Zero) {
  61.                 int procid;
  62.                 int thread = GetWindowThreadProcessId(hwnd, out procid);
  63.                 if (procid == id && IsWindowVisible(hwnd)) {
  64.                     SystemAccessible acc = SystemAccessible.AccessibleObjectForWindow(hwnd);
  65.                     if (acc.Role == AccessibleRole.Client && 
  66.                         (acc.State & AccessibleStates.Invisible) == 0 &&
  67.                         !string.IsNullOrEmpty(acc.Name)) {
  68.                         // found it!
  69.                         return hwnd;
  70.                     }
  71.                 }
  72.                 hwnd = GetWindow(hwnd, GetWindowOptions.Next);
  73.             }
  74.             return IntPtr.Zero;
  75.         }
  76.         public Window WaitForPopup() {
  77.             Thread.Sleep(500);
  78.             IntPtr h = this.Handle;
  79.             int retries = 20;
  80.             while (retries-- > 0) {
  81.                 IntPtr hwnd = GetForegroundWindow();
  82.                 if (hwnd != h) {
  83.                     Trace.WriteLine("WindowChanged:" + GetForegroundWindowText());
  84.                     Sleep(500); // give it time to get keystrokes!
  85.                     return new Window(this, hwnd);
  86.                 }
  87.                 Sleep(1000);                
  88.             }
  89.             throw new ApplicationException("Window is not appearing!");
  90.         }
  91.         public void WaitForNewWindow() {
  92.             int retries = 20;
  93.             while (retries-- > 0) {
  94.                 IntPtr hwnd = GetForegroundWindow();
  95.                 if (hwnd != this.Handle) {
  96.                     Trace.WriteLine("NewWindowOpened");
  97.                     Sleep(1000); // give it time to get keystrokes!
  98.                     return;
  99.                 }
  100.                 Sleep(1000);
  101.             }
  102.             throw new ApplicationException("Window is not appearing!");
  103.         }
  104.         public static IntPtr GetForegroundWindowHandle() {
  105.             return GetForegroundWindow();
  106.         }
  107.         public static string GetForegroundWindowText() {
  108.             IntPtr hwnd = GetForegroundWindow();
  109.             if (hwnd == IntPtr.Zero)
  110.                 return "";
  111.             return GetWindowText(hwnd);
  112.         }
  113.         public static string GetWindowText(IntPtr hwnd) {
  114.             int len = GetWindowTextLength(hwnd);
  115.             if (len <= 0) return "";
  116.             len++; // include space for the null terminator.
  117.             IntPtr buffer = Marshal.AllocCoTaskMem(len * 2);
  118.             GetWindowText(hwnd, buffer, len);
  119.             string s = Marshal.PtrToStringUni(buffer, len - 1);
  120.             Marshal.FreeCoTaskMem(buffer);
  121.             return s;
  122.         }
  123.         public void DismissPopUp(string keys) {
  124.             Trace.WriteLine("Dismissing: " + GetForegroundWindowText());
  125.             System.Windows.Forms.SendKeys.SendWait(keys);
  126.             Thread.Sleep(500);
  127.             IntPtr h = this.Handle;
  128.             Sleep(1000);
  129.             int retries = 10;
  130.             while (retries-- > 0) {
  131.                 Trace.WriteLine("ForegroundWindow=" + GetForegroundWindowText());
  132.                 IntPtr hwnd = GetForegroundWindow();
  133.                 if (hwnd == h) {
  134.                     Trace.WriteLine("WindowChanged:" + GetForegroundWindowText());
  135.                     Sleep(500); // give it time to get keystrokes!
  136.                     return;
  137.                 }
  138.                 Sleep(200);
  139.             }
  140.             throw new ApplicationException("Foreground window is not changing!");
  141.         }
  142.         public Window ExpectingPopup(string name) {
  143.             Application.DoEvents();
  144.             Window popup = this.WaitForPopup();
  145.             string text = Window.GetForegroundWindowText();
  146.             if (text.ToLowerInvariant() != name.ToLowerInvariant()) {
  147.                 throw new ApplicationException(string.Format("Expecting popup '{0}'", name));
  148.             }
  149.             return popup;
  150.         }
  151.         public AccessibleObject AccessibleObject {
  152.             get {
  153.                 return this.acc;
  154.             }
  155.         }
  156.         SystemAccessible GetClient() {            
  157.             if (this.acc.Role == AccessibleRole.Client) {
  158.                 return this.acc;
  159.             } else {
  160.                 return (SystemAccessible)this.acc.FindChildByRole(AccessibleRole.Client);
  161.             }
  162.         }
  163.         public SystemAccessible FindDescendant(string name) {
  164.             ReloadMap(name);  
  165.             return map[name];
  166.         }
  167.         void ReloadMap(string name) {
  168.             if (map == null) {
  169.                 map = new Dictionary<string, SystemAccessible>();
  170.             }
  171.             if (map == null || !map.ContainsKey(name)) {
  172.                 SystemAccessible client = GetClient();
  173.                 if (client != null) {
  174.                     LoadChildren(client);
  175.                 }
  176.             }
  177.         }
  178.         void LoadChildren(SystemAccessible item) {
  179.             switch (item.Role) {
  180.                 case AccessibleRole.Alert:
  181.                     break;
  182.                 case AccessibleRole.Animation:
  183.                     break;
  184.                 case AccessibleRole.Application:
  185.                     break;
  186.                 case AccessibleRole.Border:
  187.                     break;
  188.                 case AccessibleRole.ButtonDropDown:
  189.                     break;
  190.                 case AccessibleRole.ButtonDropDownGrid:
  191.                     break;
  192.                 case AccessibleRole.ButtonMenu:
  193.                     break;
  194.                 case AccessibleRole.Caret:
  195.                     break;
  196.                 case AccessibleRole.Cell:
  197.                     break;
  198.                 case AccessibleRole.Character:
  199.                     break;
  200.                 case AccessibleRole.Chart:
  201.                     break;
  202.                 case AccessibleRole.CheckButton:
  203.                     break;
  204.                 case AccessibleRole.Client:
  205.                 case AccessibleRole.Window:
  206.                     this.LoadComplexChildren(item);
  207.                     break;
  208.                 case AccessibleRole.Clock:
  209.                     break;
  210.                 case AccessibleRole.Column:
  211.                     break;
  212.                 case AccessibleRole.ColumnHeader:
  213.                     break;
  214.                 case AccessibleRole.ComboBox:
  215.                     break;
  216.                 case AccessibleRole.Cursor:
  217.                     break;
  218.                 case AccessibleRole.Default:
  219.                     break;
  220.                 case AccessibleRole.Diagram:
  221.                     break;
  222.                 case AccessibleRole.Dial:
  223.                     break;
  224.                 case AccessibleRole.Dialog:
  225.                     break;
  226.                 case AccessibleRole.Document:
  227.                     break;
  228.                 case AccessibleRole.DropList:
  229.                     break;
  230.                 case AccessibleRole.Equation:
  231.                     break;
  232.                 case AccessibleRole.Graphic:
  233.                     break;
  234.                 case AccessibleRole.Grip:
  235.                     break;
  236.                 case AccessibleRole.Grouping:
  237.                     break;
  238.                 case AccessibleRole.HelpBalloon:
  239.                     break;
  240.                 case AccessibleRole.HotkeyField:
  241.                     break;
  242.                 case AccessibleRole.Indicator:
  243.                     break;
  244.                 case AccessibleRole.IpAddress:
  245.                     break;
  246.                 case AccessibleRole.Link:
  247.                     break;
  248.                 case AccessibleRole.List:
  249.                     break;
  250.                 case AccessibleRole.ListItem:
  251.                     break;
  252.                 case AccessibleRole.MenuBar:
  253.                 case AccessibleRole.MenuItem:
  254.                 case AccessibleRole.MenuPopup:
  255.                 case AccessibleRole.ToolBar:
  256.                     this.LoadSimpleChildren(item);
  257.                     break;
  258.                 case AccessibleRole.None:
  259.                     break;
  260.                 case AccessibleRole.Outline:
  261.                     break;
  262.                 case AccessibleRole.OutlineButton:
  263.                     break;
  264.                 case AccessibleRole.OutlineItem:
  265.                     break;
  266.                 case AccessibleRole.PageTab:
  267.                     break;
  268.                 case AccessibleRole.PageTabList:
  269.                     break;
  270.                 case AccessibleRole.Pane:
  271.                     break;
  272.                 case AccessibleRole.ProgressBar:
  273.                     break;
  274.                 case AccessibleRole.PropertyPage:
  275.                     break;
  276.                 case AccessibleRole.PushButton:
  277.                     break;
  278.                 case AccessibleRole.RadioButton:
  279.                     break;
  280.                 case AccessibleRole.Row:
  281.                     break;
  282.                 case AccessibleRole.RowHeader:
  283.                     break;
  284.                 case AccessibleRole.ScrollBar:
  285.                     break;
  286.                 case AccessibleRole.Separator:
  287.                     break;
  288.                 case AccessibleRole.Slider:
  289.                     break;
  290.                 case AccessibleRole.Sound:
  291.                     break;
  292.                 case AccessibleRole.SpinButton:
  293.                     break;
  294.                 case AccessibleRole.SplitButton:
  295.                     break;
  296.                 case AccessibleRole.StaticText:
  297.                     break;
  298.                 case AccessibleRole.StatusBar:
  299.                     break;
  300.                 case AccessibleRole.Table:
  301.                     break;
  302.                 case AccessibleRole.Text:
  303.                     break;
  304.                 case AccessibleRole.TitleBar:
  305.                     break;
  306.                 case AccessibleRole.ToolTip:
  307.                     break;
  308.                 case AccessibleRole.WhiteSpace:
  309.                     break;
  310.                 default:
  311.                     break;
  312.             }
  313.         }
  314.         void LoadComplexChildren(SystemAccessible item) {
  315.             SystemAccessible first = item.FirstChild;
  316.             if (first != null) {
  317.                 SystemAccessible last = item.LastChild;
  318.                 SystemAccessible child = first;
  319.                 while (child != null) {
  320.                     AddChild(child);
  321.                     if (child == last) break;
  322.                     child = child.NextSibling;
  323.                 }
  324.             }
  325.         }
  326.         void LoadSimpleChildren(SystemAccessible item) {
  327.             for (int i = 1, n = item.GetChildCount(); i <= n; i++) {
  328.                 SystemAccessible child = (SystemAccessible)item.GetChild(i);
  329.                 AddChild(child);
  330.             }
  331.         }
  332.         void AddChild(SystemAccessible child) {
  333.             string name = child.Name;
  334.             if (!string.IsNullOrEmpty(name) && child.Role != AccessibleRole.Window) {
  335.                 Trace.WriteLine("Found: " + name);
  336.                 if (!map.ContainsKey(name) || child.Role == AccessibleRole.Client) {
  337.                     map[name] = child;
  338.                 } else {
  339.                     Trace.WriteLine(string.Format("Ambiguous item name: '{0}'", name));
  340.                 }
  341.             }
  342.             if (child.GetChildCount() > 0) {
  343.                 LoadChildren(child);
  344.             }
  345.         }
  346.         public IntPtr Handle {
  347.             get {
  348.                 return handle; 
  349.             }
  350.         }
  351.         public TestBase TestBase {
  352.             get { return test; }
  353.             set { test = value; }
  354.         }
  355.         public void SetWindowSize(int cx, int cy) {
  356.             SetWindowPos(this.handle, IntPtr.Zero, 0, 0, cx, cy, (uint)SetWindowPosFlags.SWP_NOMOVE);
  357.         }
  358.         public void SetWindowPosition(int x, int y) {
  359.             SetWindowPos(this.handle, IntPtr.Zero, x, y, 0, 0, (uint)SetWindowPosFlags.SWP_NOSIZE);
  360.         }
  361.         public void WaitForIdle(int timeout) {
  362.             if (parent != null)
  363.                 parent.WaitForIdle(timeout);
  364.             else if (p != null) 
  365.                 p.WaitForInputIdle();
  366.         }
  367.         public bool Closed {
  368.             get { return closed; }
  369.             set { closed = value; }
  370.         }
  371.         public void Sleep(int ms) {
  372.             Thread.Sleep(ms);
  373.         }
  374.         public void Close() {
  375.             if (!closed) {
  376.                 SendMessage(this.handle, (uint)WindowsMessages.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
  377.                 Sleep(delay);
  378.             }
  379.             closed = true;
  380.         }
  381.         public Window OpenDialog(string menuCommand, string formName) {
  382.             InvokeAsyncMenuItem(menuCommand);
  383.             return this.WaitForPopup();
  384.         }
  385.         public void SendKeys(string keys) {
  386.             if (Window.GetForegroundWindow() != this.handle) {
  387.                 Activate();
  388.                 Sleep(200);
  389.             }
  390.             System.Windows.Forms.SendKeys.SendWait(keys);
  391.         }
  392.         public void Activate() {
  393.             SetForegroundWindow(this.handle);
  394.         }
  395.         const uint OBJID_CLIENT = 0xFFFFFFFC;
  396.         public void InvokeMenuItem(string menuItemName) {
  397.             this.ReloadMap(menuItemName);
  398.             Sleep(30);
  399.             this.WaitForIdle(2000);
  400.             SystemAccessible item;
  401.             if (!this.map.TryGetValue(menuItemName, out item)) {
  402.                 throw new Exception(string.Format("Menu item '{0}' not found", menuItemName));                
  403.             }
  404.             Trace.WriteLine("InvokeMenuItem(" + menuItemName + ")");
  405.             item.DoDefaultAction();
  406.         }
  407.         public void InvokeAsyncMenuItem(string menuItemName) {
  408.             this.ReloadMap(menuItemName);
  409.             Sleep(delay);
  410.             this.WaitForIdle(2000);
  411.             SystemAccessible item;
  412.             if (!this.map.TryGetValue(menuItemName, out item)) {
  413.                 throw new Exception(string.Format("Menu item '{0}' not found", menuItemName));                
  414.             }
  415.             Trace.WriteLine("InvokeAsyncMenuItem(" + menuItemName + ")");
  416.             // this is NOT async with things like SaveAs where a dialog pops up!
  417.             //item.DoDefaultAction();
  418.             this.WaitForIdle(1000);
  419.             Sleep(1000);
  420.             if (item.Role == AccessibleRole.PushButton) {
  421.                 // Toolbar buttons cannot be invoked from shortcuts.
  422.                 Mouse.MouseClick(Center(item.Bounds), MouseButtons.Left);
  423.             } else {
  424.                 TypeShortcut(item);
  425.             }
  426.         }
  427.         Point Center(Rectangle bounds) {
  428.             return new Point(bounds.Left + (bounds.Width / 2),
  429.                 bounds.Top + (bounds.Height / 2));
  430.         }
  431.         void TypeShortcut(AccessibleObject item) {
  432.             Sleep(1000);
  433.             AccessibleObject parent = item.Parent;
  434.             if (parent.Role == AccessibleRole.MenuItem) {
  435.                 TypeShortcut(parent);
  436.             }
  437.             string shortcut = item.KeyboardShortcut;
  438.             if (!string.IsNullOrEmpty(shortcut)) {
  439.                 SendShortcut(shortcut);
  440.             } else {
  441.                 throw new NotImplementedException("InvokeAsyncMenuItem can't work without menu item shortcuts");
  442.             }
  443.         }
  444.         public void SendShortcut(string shortcut) {
  445.             string keys = shortcut.Replace("Alt+", "%").Replace("Ctrl+", "^").Replace("Shift+", "+");
  446.             Sleep(200);
  447.             SendKeys(keys);
  448.         }
  449.         public Rectangle GetScreenBounds() {
  450.             WINDOWINFO wi = new WINDOWINFO();
  451.             wi.cbSize = Marshal.SizeOf(wi);
  452.             if (GetWindowInfo(this.handle, ref wi)) {
  453.                 RECT r = wi.rcWindow;
  454.                 return new Rectangle(r.left, r.top, r.right - r.left, r.bottom - r.top);
  455.             }
  456.             return Rectangle.Empty;
  457.         }
  458.         #region IDisposable Members
  459.         public void Dispose() {
  460.             disposed = true;
  461.             if (p != null && !p.HasExited) {
  462.                 this.Close();
  463.                 Sleep(1000);
  464.                 if (!p.HasExited) {
  465.                     p.Kill();
  466.                 }                
  467.             }
  468.         }
  469.         #endregion
  470.         enum GetWindowOptions {
  471.             First    = 0,
  472.             Last = 1,
  473.             Next = 2,
  474.             Previous = 3,
  475.             Owner = 5,
  476.             Child = 5
  477.         }
  478.         [DllImport("User32")]
  479.         public static extern IntPtr GetForegroundWindow();
  480.         [DllImport("User32")]
  481.         public static extern IntPtr GetTopWindow(IntPtr hwnd);
  482.         [DllImport("User32")]
  483.         public static extern IntPtr GetDesktopWindow();
  484.         [DllImport("User32")]
  485.         public static extern IntPtr GetLastActivePopup(IntPtr hWnd);
  486.         [DllImport("User32", CharSet = CharSet.Unicode)]
  487.         static extern int GetWindowTextLength(IntPtr hwnd);
  488.         [DllImport("User32", CharSet = CharSet.Unicode)]
  489.         static extern int GetWindowText(IntPtr hWnd, IntPtr lpString, int nMaxCount);
  490.         [DllImport("User32", CharSet = CharSet.Unicode)]
  491.         static extern IntPtr GetWindow(IntPtr hWnd, GetWindowOptions uCmd);
  492.         [DllImport("User32", CharSet = CharSet.Unicode)]
  493.         static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
  494.         [DllImport("User32", CharSet = CharSet.Unicode)]
  495.         static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
  496.         [DllImport("User32", CharSet = CharSet.Unicode)]
  497.         static extern bool GetWindowInfo(IntPtr hwnd, ref WINDOWINFO pwi);
  498.         [DllImport("User32", CharSet = CharSet.Unicode)]
  499.         static extern bool IsWindowVisible(IntPtr hWnd);
  500.         [DllImport("User32", CharSet = CharSet.Unicode)]
  501.         static extern bool ShowWindow(IntPtr hWnd, int nCmdShows);
  502.         [DllImport("User32", CharSet = CharSet.Unicode)]
  503.         static extern void SetForegroundWindow(IntPtr hWnd);
  504.         enum WindowsMessages {
  505.             WM_CLOSE = 0x0010
  506.         }
  507.         [DllImport("User32", CharSet = CharSet.Unicode)]
  508.         static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
  509.         [StructLayout(LayoutKind.Sequential)]
  510.         struct WINDOWINFO {
  511.             public int cbSize;
  512.             public RECT rcWindow;
  513.             public RECT rcClient;
  514.             public int dwStyle;
  515.             public int dwExStyle;
  516.             public int dwWindowStatus;
  517.             public uint cxWindowBorders;
  518.             public uint cyWindowBorders;
  519.             public IntPtr atomWindowType;
  520.             public int wCreatorVersion;
  521.         }
  522.         enum SetWindowPosFlags {
  523.             SWP_NOSIZE = 0x0001,
  524.             SWP_NOMOVE = 0x0002,
  525.             SWP_NOZORDER = 0x0004,
  526.             SWP_NOREDRAW = 0x0008,
  527.             SWP_NOACTIVATE = 0x0010,
  528.             SWP_FRAMECHANGED = 0x0020,  /* The frame changed: send WM_NCCALCSIZE */
  529.             SWP_SHOWWINDOW = 0x0040,
  530.             SWP_HIDEWINDOW = 0x0080,
  531.             SWP_NOCOPYBITS = 0x0100,
  532.             SWP_NOOWNERZORDER = 0x0200, /* Don't do owner Z ordering */
  533.             SWP_NOSENDCHANGING = 0x0400,  /* Don't send WM_WINDOWPOSCHANGING */
  534.             SWP_DRAWFRAME = SWP_FRAMECHANGED,
  535.             SWP_NOREPOSITION = SWP_NOOWNERZORDER
  536.         }
  537.         enum ShowWindowFlags {
  538.             SW_HIDE = 0,
  539.             SW_SHOWNORMAL = 1,
  540.             SW_NORMAL = 1,
  541.             SW_SHOWMINIMIZED = 2,
  542.             SW_SHOWMAXIMIZED = 3,
  543.             SW_MAXIMIZE = 3,
  544.             SW_SHOWNOACTIVATE = 4,
  545.             SW_SHOW = 5,
  546.             SW_MINIMIZE = 6,
  547.             SW_SHOWMINNOACTIVE = 7,
  548.             SW_SHOWNA = 8,
  549.             SW_RESTORE = 9,
  550.             SW_SHOWDEFAULT = 10,
  551.             SW_FORCEMINIMIZE = 11,
  552.             SW_MAX = 11
  553.         }
  554.     }
  555. }