Skip to content

Commit 68e7f7c

Browse files
authored
Merge pull request #42 from FlaUI/open-for-application
New 3.0.0 version
2 parents 66d15c2 + 9c5c6b1 commit 68e7f7c

File tree

76 files changed

+4357
-1306
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+4357
-1306
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ obj/
1010

1111
# Artifacts
1212
artifacts/
13+
src/.idea/
14+
*.user
15+
desktop.ini

README.md

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,89 @@
11
# FlaUInspect
2+
23
![FlaUInspect](/FlaUInspect.png?raw=true)
34

4-
### New 2.0.0
5-
New has been [released](https://github.com/FlaUI/FlaUInspect/releases/tag/v2.0.0)!
5+
## NEW 3.0.0
6+
7+
New version released! Download it [here](https://github.com/FlaUI/FlaUInspect/releases/tag/v3.0.0)
68

79
This is a major update with a lot of changes:
10+
- using separated window for process
11+
- new UI
12+
- Dark and Light theme support
13+
- implement settings
14+
- new icons
15+
- new application selection bounding
16+
- redesigned:
17+
- property grid
18+
- control tree
19+
- menu buttons
20+
- mouse hover control selection
21+
- improved performance
22+
- fixed and redesigned 3-state highlight of selected control
23+
24+
#### Screenshot of new UI:
25+
26+
Main window and selection application highlights.
27+
28+
<img width="600" alt="Image" src="https://github.com/user-attachments/assets/f0a23f20-f994-4a17-b83b-3da6c96e337f" />
29+
30+
Main window display application and allow user to select it from list or press and hold Find window button and drag mouse over applications. The FlaUinspect will highlight the application under mouse cursor and select id in the list.
31+
32+
Hover mode
33+
34+
<img width="600" alt="Image" src="https://github.com/user-attachments/assets/53fbcd61-cd93-4f09-9962-13be900f4c95" />
35+
36+
Select Hover mode button and hold Ctrl key and move mouse over application windows. The FlaUInspect will highlight the control under mouse cursor and select it in the tree.
37+
38+
Highlight selection
39+
40+
<img width="600" alt="Image" src="https://github.com/user-attachments/assets/7e5c8767-e75f-449b-adb5-cbd55522f405" />
41+
42+
Select Selection Mode button and click on any control in the application. The FlaUInspect will highlight the selected control in the application.
43+
44+
Highlight selectin and Dark theme
45+
46+
<img width="600" alt="Image" src="https://github.com/user-attachments/assets/7b9db566-6e3b-459d-bc49-1715a172a189" />
47+
48+
FlaUinspect supports Light and Dark theme currently.
49+
50+
### 2.0.0
51+
52+
Download it [here](https://github.com/FlaUI/FlaUInspect/releases/tag/v2.0.0)
53+
54+
This is a major update with a lot of changes:
55+
856
* Complete rewrite of the application
957
* New UI
1058
* New features
1159
* Much more stable
1260
* Based on .NET 8
1361
* Three separate versions for UIA2 and UIA3 and default with choosing on startup
1462

15-
1663
### Installation
17-
To install FlaUInspect, either build it yourself or get the zip from the releases page here on GitHub (https://github.com/FlaUI/FlaUInspect/releases).
64+
65+
To install FlaUInspect, either build it yourself or get the zip from the releases page here on
66+
GitHub (https://github.com/FlaUI/FlaUInspect/releases).
1867

1968
### Description
20-
There are various tools around which help inspecting application that should be ui tested or automated. Some of them are:
69+
70+
There are various tools around which help inspecting application that should be ui tested or automated. Some of them
71+
are:
72+
2173
* VisualUIAVerify
2274
* Inspect
2375
* UISpy
2476
* and probably others
25-
Most of them are old and sometimes not very stable and (if open source), a code mess to maintain.
77+
Most of them are old and sometimes not very stable and (if open source), a code mess to maintain.
2678

2779
FlaUInspect is supposed to be a modern alternative, based on [FlaUI](https://github.com/Roemer/FlaUI).
2880

29-
On startup of FlaUInspect, you can choose if you want to use UIA2 or UIA3 (see [FAQ](https://github.com/Roemer/FlaUI/wiki/FAQ) why you can't use both at the same time).
81+
On startup of FlaUInspect, you can choose if you want to use UIA2 or UIA3 (
82+
see [FAQ](https://github.com/Roemer/FlaUI/wiki/FAQ) why you can't use both at the same time).
3083
You can use pre-built versions of FlaUInspect.UIA2 and FlaUInspect.UIA3 if you want to use a version of UIA.
3184

32-
3385
###### Main Screen
86+
3487
![Main Screen](https://github.com/user-attachments/assets/6212341b-9776-4907-9edc-acc00073c92e)
3588

3689
##### Tool buttons
@@ -43,10 +96,11 @@ You can use pre-built versions of FlaUInspect.UIA2 and FlaUInspect.UIA3 if you w
4396
| Show XPath | Enable this option to show a simple XPath to the current selected element in the StatusBar of FlaUInspect |
4497

4598
### Release Notes 2.0.0
99+
46100
* Deployed FlaUInspect, FlaUInspect.UIA2, and FlaUInspect.UIA3 applications with hardcoded UI2 or UI3 selection.
47101
* Refactored code and implemented asynchronous operations.
48102
* Redesigned the property grid; collapsed groups remain collapsed after selecting another control.
49103
* Added a third selection state: highlighting the selected control in an application.
50104
* Included a refresh button for each item in the tree.
51-
*Refined icons.
105+
*Refined icons.
52106

src/FlaUInspect/App.xaml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
<Application x:Class="FlaUInspect.App"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4-
Startup="ApplicationStart">
5-
<Application.Resources />
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
4+
<Application.Resources>
5+
<ResourceDictionary>
6+
<ResourceDictionary.MergedDictionaries>
7+
<ResourceDictionary Source="Themes/LightTheme.xaml" />
8+
</ResourceDictionary.MergedDictionaries>
9+
</ResourceDictionary>
10+
</Application.Resources>
611
</Application>

src/FlaUInspect/App.xaml.cs

Lines changed: 121 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,153 @@
1-
using System.Reflection;
1+
using System.Drawing;
2+
using System.IO;
3+
using System.Reflection;
24
using System.Windows;
3-
using FlaUI.Core;
5+
using FlaUInspect.Core;
46
using FlaUInspect.Core.Logger;
7+
using FlaUInspect.Settings;
58
using FlaUInspect.ViewModels;
69
using FlaUInspect.Views;
10+
using Microsoft.Extensions.DependencyInjection;
711

812
namespace FlaUInspect;
913

1014
public partial class App {
11-
private void ApplicationStart(object sender, StartupEventArgs e) {
15+
16+
public static IServiceProvider Services { get; private set; } = null!;
17+
public static FlaUiAppOptions FlaUiAppOptions { get; } = new ();
18+
19+
public static InternalLogger Logger { get; } = new ();
20+
21+
protected override void OnStartup(StartupEventArgs e) {
22+
base.OnStartup(e);
23+
24+
ServiceCollection services = new ();
25+
services.AddSingleton<ISettingsService<FlaUiAppSettings>>(_ => new JsonSettingsService<FlaUiAppSettings>(Path.Combine(AppContext.BaseDirectory, $"appsettings.json")));
26+
Services = services.BuildServiceProvider();
27+
28+
ISettingsService<FlaUiAppSettings> settingsService = Services.GetRequiredService<ISettingsService<FlaUiAppSettings>>();
29+
FlaUiAppSettings flaUiAppSettings = settingsService.Load();
30+
ApplyAppOption(flaUiAppSettings);
31+
32+
//InternalLogger logger = new ();
33+
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
34+
StartupViewModel startupViewModel = new ();
35+
StartupWindow startupWindow = new (Logger) { DataContext = startupViewModel };
36+
Current.MainWindow = startupWindow;
37+
startupWindow.Show();
38+
39+
//Preload light theme
40+
SetTheme(flaUiAppSettings);
41+
42+
Task.Run(() => startupViewModel.Init());
43+
44+
return;
1245
AssemblyFileVersionAttribute? versionAttribute = Assembly.GetEntryAssembly()?.GetCustomAttribute(typeof(AssemblyFileVersionAttribute)) as AssemblyFileVersionAttribute;
1346
string applicationVersion = versionAttribute?.Version ?? "N/A";
14-
InternalLogger logger = new ();
47+
string windowHandle = string.Empty;
48+
49+
if (e.Args.Length > 0) {
50+
windowHandle = e.Args[0];
51+
}
1552

1653
#if AUTOMATION_UIA3
17-
MainViewModel mainViewModel = new (AutomationType.UIA3, applicationVersion, logger);
54+
MainViewModel mainViewModel = new (AutomationType.UIA3, applicationVersion, windowHandle, logger);
1855
MainWindow mainWindow = new () { DataContext = mainViewModel };
1956

2057
//Re-enable normal shutdown mode.
2158
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
2259
Current.MainWindow = mainWindow;
2360
mainWindow.Show();
2461
#elif AUTOMATION_UIA2
25-
MainViewModel mainViewModel = new (AutomationType.UIA2, applicationVersion, logger);
62+
MainViewModel mainViewModel = new (AutomationType.UIA2, applicationVersion, windowHandle, logger);
2663
MainWindow mainWindow = new() { DataContext = mainViewModel };
2764

2865
//Re-enable normal shutdown mode.
2966
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
3067
Current.MainWindow = mainWindow;
3168
mainWindow.Show();
3269
#else
33-
Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
34-
ChooseVersionWindow dialog = new ();
70+
// Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
71+
// ChooseVersionWindow dialog = new ();
72+
//
73+
// if (dialog.ShowDialog() == true) {
74+
//
75+
// MainViewModel mainViewModel = new (dialog.SelectedAutomationType, applicationVersion, windowHandle, Logger);
76+
// MainWindow mainWindow = new () { DataContext = mainViewModel };
77+
//
78+
// //Re-enable normal shutdown mode.
79+
// Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
80+
// Current.MainWindow = mainWindow;
81+
// mainWindow.Show();
82+
// }
83+
#endif
84+
}
3585

36-
if (dialog.ShowDialog() == true) {
86+
public static void ApplyAppOption(FlaUiAppSettings settings) {
87+
// Apply theme
88+
Current.Dispatcher.Invoke(() => {
89+
SetTheme(settings);
90+
});
3791

38-
MainViewModel mainViewModel = new (dialog.SelectedAutomationType, applicationVersion, logger);
39-
MainWindow mainWindow = new () { DataContext = mainViewModel };
92+
ThicknessConverter converter = new ();
93+
FlaUiAppSettings cloneSetting = settings.Clone() as FlaUiAppSettings;
4094

41-
//Re-enable normal shutdown mode.
42-
Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
43-
Current.MainWindow = mainWindow;
44-
mainWindow.Show();
95+
if (settings.HoverOverlay != null) {
96+
Thickness hoverMargin = (Thickness)converter.ConvertFromString(cloneSetting.HoverOverlay.Margin);
97+
FlaUiAppOptions.HoverOverlay = () => new ElementOverlay(
98+
new ElementOverlayConfiguration(cloneSetting.HoverOverlay.Size,
99+
hoverMargin,
100+
ColorTranslator.FromHtml(cloneSetting.HoverOverlay.OverlayColor),
101+
ElementOverlay.GetRectangleFactory(cloneSetting.HoverOverlay.OverlayMode)));
102+
} else {
103+
FlaUiAppOptions.HoverOverlay = FlaUiAppOptions.DefaultOverlay;
45104
}
46-
#endif
105+
106+
if (settings.SelectionOverlay != null) {
107+
Thickness selectionMargin = (Thickness)converter.ConvertFromString(cloneSetting.SelectionOverlay.Margin);
108+
FlaUiAppOptions.SelectionOverlay = () => new ElementOverlay(
109+
new ElementOverlayConfiguration(cloneSetting.SelectionOverlay.Size,
110+
selectionMargin,
111+
ColorTranslator.FromHtml(cloneSetting.SelectionOverlay.OverlayColor),
112+
ElementOverlay.GetRectangleFactory(cloneSetting.SelectionOverlay.OverlayMode)));
113+
} else {
114+
FlaUiAppOptions.SelectionOverlay = FlaUiAppOptions.DefaultOverlay;
115+
}
116+
117+
if (settings.PickOverlay != null) {
118+
Thickness pickMargin = (Thickness)converter.ConvertFromString(cloneSetting.PickOverlay.Margin);
119+
FlaUiAppOptions.PickOverlay = () => new ElementOverlay(
120+
new ElementOverlayConfiguration(cloneSetting.PickOverlay.Size,
121+
pickMargin,
122+
ColorTranslator.FromHtml(cloneSetting.PickOverlay.OverlayColor),
123+
ElementOverlay.GetRectangleFactory(cloneSetting.PickOverlay.OverlayMode)));
124+
} else {
125+
FlaUiAppOptions.PickOverlay = FlaUiAppOptions.DefaultOverlay;
126+
}
127+
}
128+
129+
private static void SetTheme(FlaUiAppSettings settings) {
130+
ResourceDictionary newTheme = new();
131+
132+
switch (settings.Theme) {
133+
case "Dark":
134+
newTheme.Source = new Uri("/FlaUInspect;component/Themes/DarkTheme.xaml", UriKind.Relative);
135+
break;
136+
default:
137+
newTheme.Source = new Uri("/FlaUInspect;component/Themes/LightTheme.xaml", UriKind.Relative);
138+
break;
139+
}
140+
141+
// Remove existing theme dictionaries
142+
for (int i = Current.Resources.MergedDictionaries.Count - 1; i >= 0; i--) {
143+
ResourceDictionary dict = Current.Resources.MergedDictionaries[i];
144+
145+
if (dict.Source != null && (dict.Source.OriginalString.Contains("Themes/DarkTheme.xaml") || dict.Source.OriginalString.Contains("Themes/LightTheme.xaml"))) {
146+
Current.Resources.MergedDictionaries.RemoveAt(i);
147+
}
148+
}
149+
150+
// Add the new theme dictionary
151+
Current.Resources.MergedDictionaries.Add(newTheme);
47152
}
48153
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
3+
<Style TargetType="Button" >
4+
<Setter Property="BorderThickness" Value="{DynamicResource PrimaryThickness}"/>
5+
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}"/>
6+
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBorderBrush}"/>
7+
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
8+
<Setter Property="Width" Value="96"/>
9+
<Setter Property="Padding" Value="10"></Setter>
10+
<Setter Property="Template">
11+
<Setter.Value>
12+
<ControlTemplate TargetType="Button">
13+
<Border Background="{TemplateBinding Background}"
14+
BorderBrush="{TemplateBinding BorderBrush}"
15+
BorderThickness="{TemplateBinding BorderThickness}"
16+
CornerRadius="{DynamicResource PrimaryCornerRadius}"
17+
Padding="{TemplateBinding Padding}">
18+
<ContentPresenter HorizontalAlignment="Center"
19+
VerticalAlignment="Center"/>
20+
</Border>
21+
<ControlTemplate.Triggers>
22+
<Trigger Property="IsMouseOver" Value="True">
23+
<Setter Property="Background" Value="{DynamicResource PrimaryHoverBrush}"/>
24+
</Trigger>
25+
<Trigger Property="IsPressed" Value="True">
26+
<Setter Property="Background" Value="{DynamicResource PrimaryPressedBrush}"/>
27+
</Trigger>
28+
<Trigger Property="IsEnabled" Value="False">
29+
<Setter Property="Background" Value="{DynamicResource PrimaryDisabledBrush}"/>
30+
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryDisabledBrush}"/>
31+
<Setter Property="Foreground" Value="{DynamicResource DisabledTextBrush}"/>
32+
</Trigger>
33+
</ControlTemplate.Triggers>
34+
</ControlTemplate>
35+
</Setter.Value>
36+
</Setter>
37+
</Style>
38+
</ResourceDictionary>

0 commit comments

Comments
 (0)