diff --git a/src/TestStack.White/Configuration/CoreAppXmlConfiguration.cs b/src/TestStack.White/Configuration/CoreAppXmlConfiguration.cs
index d69d45d5..738b3d50 100644
--- a/src/TestStack.White/Configuration/CoreAppXmlConfiguration.cs
+++ b/src/TestStack.White/Configuration/CoreAppXmlConfiguration.cs
@@ -26,6 +26,7 @@ static CoreAppXmlConfiguration()
DefaultValues.Add("PopupTimeout", 5000);
DefaultValues.Add("TooltipWaitTime", 3000);
DefaultValues.Add("SuggestionListTimeout", 3000);
+ DefaultValues.Add("HighlightTimeout", 1000);
DefaultValues.Add("DefaultDateFormat", DateFormat.CultureDefault.ToString());
DefaultValues.Add("DragStepCount", 1);
DefaultValues.Add("InProc", false);
@@ -108,6 +109,12 @@ public virtual int SuggestionListTimeout
set { SetUsedValue("SuggestionListTimeout", value); }
}
+ public virtual int HighlightTimeout
+ {
+ get { return Convert.ToInt32(UsedValues["HighlightTimeout"]); }
+ set { SetUsedValue("HighlightTimeout", value); }
+ }
+
public virtual DateFormat DefaultDateFormat
{
get { return DateFormat.Parse(UsedValues["DefaultDateFormat"]); }
diff --git a/src/TestStack.White/Configuration/CoreConfiguration.cs b/src/TestStack.White/Configuration/CoreConfiguration.cs
index 17d99e11..0b29c2d1 100644
--- a/src/TestStack.White/Configuration/CoreConfiguration.cs
+++ b/src/TestStack.White/Configuration/CoreConfiguration.cs
@@ -23,6 +23,7 @@ public interface ICoreConfiguration
int PopupTimeout { get; set; }
int TooltipWaitTime { get; set; }
int SuggestionListTimeout { get; set; }
+ int HighlightTimeout { get; set; }
DateFormat DefaultDateFormat { get; set; }
int DragStepCount { get; set; }
bool InProc { get; set; }
diff --git a/src/TestStack.White/Drawing/ScreenRectangle.cs b/src/TestStack.White/Drawing/ScreenRectangle.cs
new file mode 100644
index 00000000..2e6d4e37
--- /dev/null
+++ b/src/TestStack.White/Drawing/ScreenRectangle.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Windows;
+using System.Windows.Forms;
+using TestStack.White.Configuration;
+
+namespace TestStack.White.Drawing
+{
+ internal class ScreenRectangle
+ {
+ private Form form = new Form();
+ //TODO: Think about making color configurable
+ private Color Color = Color.Red;
+
+ internal ScreenRectangle(Rect rectangle)
+ {
+ form.FormBorderStyle = FormBorderStyle.None;
+ form.ShowInTaskbar = false;
+ form.TopMost = true;
+ form.Left = 0;
+ form.Top = 0;
+ form.Width = 1;
+ form.Height = 1;
+ form.BackColor = this.Color;
+ form.Opacity = 0.8;
+ form.Visible = false;
+
+ //Set popup style
+ int num1 = TestStack.White.WindowsAPI.NativeWindow.GetWindowLong(form.Handle, -20);
+ TestStack.White.WindowsAPI.NativeWindow.SetWindowLong(form.Handle, -20, num1 | 0x80);
+
+ //Set position
+ TestStack.White.WindowsAPI.NativeWindow.SetWindowPos(form.Handle, new IntPtr(-1), Convert.ToInt32(rectangle.X), Convert.ToInt32(rectangle.Y),
+ Convert.ToInt32(rectangle.Width), Convert.ToInt32(rectangle.Height), 0x10);
+ }
+
+ internal virtual void Show()
+ {
+ TestStack.White.WindowsAPI.NativeWindow.ShowWindow(form.Handle, 8);
+ }
+
+ internal virtual void Hide()
+ {
+ form.Hide();
+ }
+ }
+
+ internal class FrameRectangle
+ {
+ //Using 4 rectangles to display each border
+ private ScreenRectangle leftBorder;
+ private ScreenRectangle topBorder;
+ private ScreenRectangle rightBorder;
+ private ScreenRectangle bottomBorder;
+
+ private ScreenRectangle[] rectangles;
+ private int width = 3;
+
+ internal FrameRectangle(Rect boundingRectangle)
+ {
+ leftBorder = new ScreenRectangle(new Rect(boundingRectangle.X - width, boundingRectangle.Y - width, width, boundingRectangle.Height + 2*width));
+ topBorder = new ScreenRectangle(new Rect(boundingRectangle.X, boundingRectangle.Y - width, boundingRectangle.Width, width));
+ rightBorder = new ScreenRectangle(new Rect(boundingRectangle.X + boundingRectangle.Width, boundingRectangle.Y - width, width, boundingRectangle.Height + 2*width));
+ bottomBorder = new ScreenRectangle(new Rect(boundingRectangle.X, boundingRectangle.Y + boundingRectangle.Height, boundingRectangle.Width, width));
+ rectangles = new ScreenRectangle[] { leftBorder, topBorder, rightBorder, bottomBorder };
+ }
+
+ internal virtual void Highlight()
+ {
+ rectangles.ToList().ForEach(x => x.Show());
+ Thread.Sleep(CoreAppXmlConfiguration.Instance.HighlightTimeout);
+ rectangles.ToList().ForEach(x => x.Hide());
+ }
+ }
+}
diff --git a/src/TestStack.White/TestStack.White.csproj b/src/TestStack.White/TestStack.White.csproj
index 1e47ec8f..8180c03b 100644
--- a/src/TestStack.White/TestStack.White.csproj
+++ b/src/TestStack.White/TestStack.White.csproj
@@ -94,6 +94,7 @@
+
diff --git a/src/TestStack.White/UIItems/IUIItem.cs b/src/TestStack.White/UIItems/IUIItem.cs
index 73b3edee..d1632e21 100644
--- a/src/TestStack.White/UIItems/IUIItem.cs
+++ b/src/TestStack.White/UIItems/IUIItem.cs
@@ -94,5 +94,7 @@ public interface IUIItem : ActionListener
AutomationElement GetElement(SearchCriteria searchCriteria);
void Enter(string value);
+
+ void DrawHighlight();
}
}
\ No newline at end of file
diff --git a/src/TestStack.White/UIItems/UIItem.cs b/src/TestStack.White/UIItems/UIItem.cs
index 36efd431..5f589131 100644
--- a/src/TestStack.White/UIItems/UIItem.cs
+++ b/src/TestStack.White/UIItems/UIItem.cs
@@ -20,6 +20,7 @@
using TestStack.White.WindowsAPI;
using Action = TestStack.White.UIItems.Actions.Action;
using Point = System.Windows.Point;
+using System.Windows.Forms;
namespace TestStack.White.UIItems
{
@@ -424,5 +425,18 @@ public virtual void RaiseClickEvent()
var invokePattern = (InvokePattern)Pattern(InvokePattern.Pattern);
if (invokePattern != null) invokePattern.Invoke();
}
+
+ ///
+ /// Highlight UIItem with red frame
+ ///
+ public virtual void DrawHighlight()
+ {
+ Rect rectangle = AutomationElement.Current.BoundingRectangle;
+
+ if (rectangle != Rect.Empty)
+ {
+ new Drawing.FrameRectangle(rectangle).Highlight();
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/TestStack.White/UIItems/WindowItems/Win32Window.cs b/src/TestStack.White/UIItems/WindowItems/Win32Window.cs
index 406b2807..feb8d73a 100644
--- a/src/TestStack.White/UIItems/WindowItems/Win32Window.cs
+++ b/src/TestStack.White/UIItems/WindowItems/Win32Window.cs
@@ -1,5 +1,8 @@
+using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
using System.Windows.Automation;
+using TestStack.White.AutomationElementSearch;
using TestStack.White.Factory;
using TestStack.White.Sessions;
using TestStack.White.UIItems.Finders;
@@ -36,6 +39,16 @@ public override Window ModalWindow(string title, InitializeOption option)
WindowSession.ModalWindowSession(option));
}
+ public override List ModalWindows()
+ {
+ var descendants = new AutomationElementFinder(automationElement)
+ .Children(new AutomationSearchConditionFactory().GetWindowSearchConditions(automationElement.Current.ProcessId).ToArray());
+
+ return descendants
+ .Select(descendant => ChildWindowFactory.Create(descendant, InitializeOption.NoCache, WindowSession.ModalWindowSession(InitializeOption.NoCache)))
+ .ToList();
+ }
+
public override Window ModalWindow(SearchCriteria searchCriteria, InitializeOption option)
{
return windowFactory.ModalWindow(searchCriteria, option, WindowSession.ModalWindowSession(option));
diff --git a/src/TestStack.White/WindowsAPI/NativeWindow.cs b/src/TestStack.White/WindowsAPI/NativeWindow.cs
index acf44b78..99900014 100644
--- a/src/TestStack.White/WindowsAPI/NativeWindow.cs
+++ b/src/TestStack.White/WindowsAPI/NativeWindow.cs
@@ -83,10 +83,24 @@ public virtual COLORREF TextColor
return GetTextColor(GetDC(handle));
}
}
-
+
public virtual void PostCloseMessage()
{
PostMessage(handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
+
+ //Native methods needed for highlighting UIItems
+ [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
+ internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hwndAfter, int x, int y, int width, int height, int flags);
+ [return: MarshalAs(UnmanagedType.Bool)]
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
+ internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
}
}
\ No newline at end of file