SEBWIN-312: Finished first draft of task view.
This commit is contained in:
parent
08bf49b61b
commit
fbe03b86ea
20 changed files with 227 additions and 85 deletions
|
@ -21,13 +21,12 @@ namespace SafeExamBrowser.Applications
|
|||
private const int ONE_SECOND = 1000;
|
||||
|
||||
private ILogger logger;
|
||||
private string name;
|
||||
private IProcess process;
|
||||
private Timer timer;
|
||||
|
||||
public IconResource Icon { get; }
|
||||
public InstanceIdentifier Id { get; }
|
||||
public string Name { get; }
|
||||
public string Name { get; private set; }
|
||||
|
||||
public event IconChangedEventHandler IconChanged { add { } remove { } }
|
||||
public event NameChangedEventHandler NameChanged;
|
||||
|
@ -114,12 +113,12 @@ namespace SafeExamBrowser.Applications
|
|||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
var success = process.TryGetWindowTitle(out var title);
|
||||
var hasChanged = name?.Equals(title, StringComparison.Ordinal) != true;
|
||||
var hasChanged = Name?.Equals(title, StringComparison.Ordinal) != true;
|
||||
|
||||
if (success && hasChanged)
|
||||
{
|
||||
name = title;
|
||||
NameChanged?.Invoke(name);
|
||||
Name = title;
|
||||
NameChanged?.Invoke(Name);
|
||||
}
|
||||
|
||||
timer.Start();
|
||||
|
|
|
@ -194,8 +194,9 @@ namespace SafeExamBrowser.Browser
|
|||
|
||||
private void Control_TitleChanged(string title)
|
||||
{
|
||||
window.UpdateTitle(title);
|
||||
NameChanged?.Invoke(title);
|
||||
Name = title;
|
||||
window.UpdateTitle(Name);
|
||||
NameChanged?.Invoke(Name);
|
||||
}
|
||||
|
||||
private void DisplayHandler_FaviconChanged(string uri)
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
private ClientContext context;
|
||||
private Mock<ILogger> logger;
|
||||
private Mock<ITaskbar> taskbar;
|
||||
private Mock<ITaskView> taskView;
|
||||
private Mock<IUserInterfaceFactory> uiFactory;
|
||||
|
||||
private BrowserOperation sut;
|
||||
|
@ -36,11 +37,12 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
context = new ClientContext();
|
||||
logger = new Mock<ILogger>();
|
||||
taskbar = new Mock<ITaskbar>();
|
||||
taskView = new Mock<ITaskView>();
|
||||
uiFactory = new Mock<IUserInterfaceFactory>();
|
||||
|
||||
context.Browser = browser.Object;
|
||||
|
||||
sut = new BrowserOperation(actionCenter.Object, context, logger.Object, taskbar.Object, uiFactory.Object);
|
||||
sut = new BrowserOperation(actionCenter.Object, context, logger.Object, taskbar.Object, taskView.Object, uiFactory.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -59,5 +61,11 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
sut.Revert();
|
||||
browser.Verify(c => c.Terminate(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TODO()
|
||||
{
|
||||
// TODO: Test initialization of task view!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ namespace SafeExamBrowser.Client
|
|||
private IRuntimeProxy runtimeProxy;
|
||||
private ISystemInfo systemInfo;
|
||||
private ITaskbar taskbar;
|
||||
private ITaskView taskView;
|
||||
private IText text;
|
||||
private ITextResource textResource;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
|
@ -94,6 +95,7 @@ namespace SafeExamBrowser.Client
|
|||
uiFactory = BuildUserInterfaceFactory();
|
||||
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), ModuleLogger(nameof(RuntimeProxy)), Interlocutor.Client);
|
||||
taskbar = BuildTaskbar();
|
||||
taskView = BuildTaskView();
|
||||
|
||||
var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory)));
|
||||
var applicationFactory = new ApplicationFactory(ModuleLogger(nameof(ApplicationFactory)), processFactory);
|
||||
|
@ -197,7 +199,7 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
||||
var browser = new BrowserApplication(context.AppConfig, context.Settings.Browser, messageBox, moduleLogger, text, uiFactory);
|
||||
var operation = new BrowserOperation(actionCenter, context, logger, taskbar, uiFactory);
|
||||
var operation = new BrowserOperation(actionCenter, context, logger, taskbar, taskView, uiFactory);
|
||||
|
||||
context.Browser = browser;
|
||||
|
||||
|
@ -242,7 +244,6 @@ namespace SafeExamBrowser.Client
|
|||
var logInfo = new LogNotificationInfo(text);
|
||||
var logController = new LogNotificationController(logger, uiFactory);
|
||||
var powerSupply = new PowerSupply(ModuleLogger(nameof(PowerSupply)));
|
||||
var taskView = BuildTaskView();
|
||||
var wirelessAdapter = new WirelessAdapter(ModuleLogger(nameof(WirelessAdapter)));
|
||||
var operation = new ShellOperation(
|
||||
actionCenter,
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
private IActionCenter actionCenter;
|
||||
private ILogger logger;
|
||||
private ITaskbar taskbar;
|
||||
private ITaskView taskView;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
|
||||
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
|
||||
|
@ -30,11 +31,13 @@ namespace SafeExamBrowser.Client.Operations
|
|||
ClientContext context,
|
||||
ILogger logger,
|
||||
ITaskbar taskbar,
|
||||
ITaskView taskView,
|
||||
IUserInterfaceFactory uiFactory) : base(context)
|
||||
{
|
||||
this.actionCenter = actionCenter;
|
||||
this.logger = logger;
|
||||
this.taskbar = taskbar;
|
||||
this.taskView = taskView;
|
||||
this.uiFactory = uiFactory;
|
||||
}
|
||||
|
||||
|
@ -55,6 +58,8 @@ namespace SafeExamBrowser.Client.Operations
|
|||
taskbar.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.Taskbar), true);
|
||||
}
|
||||
|
||||
taskView.Add(Context.Browser);
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
mc:Ignorable="d" Title="ActionCenter" Height="1000" Width="400" Background="#EEF0F0F0" AllowsTransparency="True" WindowStyle="None" Topmost="True" ResizeMode="NoResize">
|
||||
mc:Ignorable="d" Title="ActionCenter" Height="1000" Width="400" Background="{DynamicResource BackgroundTransparentBrush}"
|
||||
AllowsTransparency="True" WindowStyle="None" Topmost="True" ResizeMode="NoResize">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" x:Name="ApplicationName" Background="#99D3D3D3" FontWeight="Bold" Padding="5" TextAlignment="Center" />
|
||||
<TextBlock Grid.Row="0" x:Name="ApplicationName" Background="{StaticResource BackgroundTransparentEmphasisBrush}" FontWeight="Bold" Padding="5" TextAlignment="Center" />
|
||||
<ContentControl Grid.Row="1" x:Name="ApplicationButton" FontWeight="Bold" />
|
||||
<StackPanel Grid.Row="2" x:Name="InstancePanel" Background="#99D3D3D3" Orientation="Vertical" />
|
||||
<StackPanel Grid.Row="2" x:Name="InstancePanel" Background="{StaticResource BackgroundTransparentEmphasisBrush}" Orientation="Vertical" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskViewInstanceControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="5" Height="150" Width="250">
|
||||
<Border Name="Border" Background="{StaticResource BackgroundTransparentEmphasisBrush}" BorderBrush="DarkGray" BorderThickness="2" Visibility="Hidden" />
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Vertical" VerticalAlignment="Center">
|
||||
<ContentControl Name="Icon" MaxWidth="40" />
|
||||
<TextBlock Name="Title" Margin="10" Foreground="{StaticResource PrimaryTextBrush}" TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class TaskViewInstanceControl : UserControl
|
||||
{
|
||||
private IApplicationInstance instance;
|
||||
|
||||
internal InstanceIdentifier Id => instance.Id;
|
||||
|
||||
public TaskViewInstanceControl(IApplicationInstance instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeControl();
|
||||
}
|
||||
|
||||
internal void Activate()
|
||||
{
|
||||
instance.Activate();
|
||||
}
|
||||
|
||||
internal void Deselect()
|
||||
{
|
||||
Border.Visibility = Visibility.Hidden;
|
||||
Icon.MaxWidth = 40;
|
||||
Title.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
internal void Select()
|
||||
{
|
||||
Border.Visibility = Visibility.Visible;
|
||||
Icon.MaxWidth = 50;
|
||||
Title.FontWeight = FontWeights.SemiBold;
|
||||
}
|
||||
|
||||
private void InitializeControl()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(instance.Icon);
|
||||
Title.Text = instance.Name;
|
||||
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Title.Text = name);
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(instance.Icon));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop"
|
||||
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Foreground="White" Height="500" Width="1100" MinHeight="350"
|
||||
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Foreground="White" Height="750" Width="1000" MinHeight="350"
|
||||
MinWidth="350" WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
|
|
|
@ -142,6 +142,9 @@
|
|||
<Compile Include="Controls\TaskbarWirelessNetworkControl.xaml.cs">
|
||||
<DependentUpon>TaskbarWirelessNetworkControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskViewInstanceControl.xaml.cs">
|
||||
<DependentUpon>TaskViewInstanceControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LockScreen.xaml.cs">
|
||||
<DependentUpon>LockScreen.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -314,6 +317,10 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Resource>
|
||||
<Page Include="Controls\TaskViewInstanceControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="LockScreen.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -4,8 +4,15 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop"
|
||||
mc:Ignorable="d" AllowsTransparency="True" Background="#AA000000" BorderBrush="DodgerBlue" BorderThickness="1" Title="TaskView"
|
||||
Topmost="True" Height="450" SizeToContent="WidthAndHeight" Width="800" WindowStartupLocation="CenterScreen" WindowStyle="None">
|
||||
mc:Ignorable="d" AllowsTransparency="True" Background="{DynamicResource BackgroundTransparentBrush}" BorderBrush="DodgerBlue" BorderThickness="1"
|
||||
Title="TaskView" Topmost="True" Height="450" SizeToContent="WidthAndHeight" Width="800" WindowStartupLocation="CenterScreen" WindowStyle="None">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<StackPanel Name="Rows" Margin="10" Orientation="Vertical" />
|
||||
</Grid>
|
||||
|
|
|
@ -11,23 +11,24 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Controls;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop
|
||||
{
|
||||
public partial class TaskView : Window, ITaskView
|
||||
{
|
||||
private IList<IApplicationInstance> instances;
|
||||
private LinkedListNode<TaskViewInstanceControl> current;
|
||||
private LinkedList<TaskViewInstanceControl> controls;
|
||||
private List<IApplicationInstance> instances;
|
||||
|
||||
public TaskView()
|
||||
{
|
||||
InitializeComponent();
|
||||
controls = new LinkedList<TaskViewInstanceControl>();
|
||||
instances = new List<IApplicationInstance>();
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Add(IApplication application)
|
||||
|
@ -44,61 +45,84 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
|
||||
private void Application_InstanceStarted(IApplicationInstance instance)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
instance.Terminated += Instance_Terminated;
|
||||
|
||||
instances.Add(instance);
|
||||
Update();
|
||||
});
|
||||
Dispatcher.InvokeAsync(() => Add(instance));
|
||||
}
|
||||
|
||||
private void Activator_Deactivated()
|
||||
{
|
||||
Dispatcher.InvokeAsync(Hide);
|
||||
Dispatcher.InvokeAsync(ActivateAndHide);
|
||||
}
|
||||
|
||||
private void Activator_Next()
|
||||
{
|
||||
Dispatcher.InvokeAsync(ShowConditional);
|
||||
Dispatcher.InvokeAsync(SelectNext);
|
||||
}
|
||||
|
||||
private void Activator_Previous()
|
||||
{
|
||||
Dispatcher.InvokeAsync(ShowConditional);
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
{
|
||||
// TODO Dispatcher.InvokeAsync(...);
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
{
|
||||
// TODO Dispatcher.InvokeAsync(...);
|
||||
Dispatcher.InvokeAsync(SelectPrevious);
|
||||
}
|
||||
|
||||
private void Instance_Terminated(InstanceIdentifier id)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var instance = instances.FirstOrDefault(i => i.Id == id);
|
||||
Dispatcher.InvokeAsync(() => Remove(id));
|
||||
}
|
||||
|
||||
if (instance != default(IApplicationInstance))
|
||||
{
|
||||
instances.Remove(instance);
|
||||
Update();
|
||||
}
|
||||
});
|
||||
private void ActivateAndHide()
|
||||
{
|
||||
Activate();
|
||||
current?.Value.Activate();
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void Add(IApplicationInstance instance)
|
||||
{
|
||||
instance.Terminated += Instance_Terminated;
|
||||
instances.Add(instance);
|
||||
Update();
|
||||
}
|
||||
|
||||
private void Remove(InstanceIdentifier id)
|
||||
{
|
||||
var instance = instances.FirstOrDefault(i => i.Id == id);
|
||||
|
||||
if (instance != default(IApplicationInstance))
|
||||
{
|
||||
instances.Remove(instance);
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectNext()
|
||||
{
|
||||
ShowConditional();
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
current.Value.Deselect();
|
||||
current = current.Next ?? controls.First;
|
||||
current.Value.Select();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectPrevious()
|
||||
{
|
||||
ShowConditional();
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
current.Value.Deselect();
|
||||
current = current.Previous ?? controls.Last;
|
||||
current.Value.Select();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowConditional()
|
||||
{
|
||||
if (Visibility != Visibility.Visible && instances.Any())
|
||||
if (instances.Any() && Visibility != Visibility.Visible)
|
||||
{
|
||||
Show();
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +131,7 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
var max = Math.Ceiling(Math.Sqrt(instances.Count));
|
||||
var stack = new Stack<IApplicationInstance>(instances);
|
||||
|
||||
controls.Clear();
|
||||
Rows.Children.Clear();
|
||||
|
||||
for (var rowCount = 0; rowCount < max && stack.Any(); rowCount++)
|
||||
|
@ -118,12 +143,16 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
for (var columnIndex = 0; columnIndex < max && stack.Any(); columnIndex++)
|
||||
{
|
||||
var instance = stack.Pop();
|
||||
var control = BuildInstanceControl(instance);
|
||||
var control = new TaskViewInstanceControl(instance);
|
||||
|
||||
controls.AddLast(control);
|
||||
row.Children.Add(control);
|
||||
}
|
||||
}
|
||||
|
||||
current = controls.First;
|
||||
current?.Value.Select();
|
||||
|
||||
UpdateLayout();
|
||||
|
||||
Left = (SystemParameters.WorkArea.Width - Width) / 2 + SystemParameters.WorkArea.Left;
|
||||
|
@ -134,28 +163,5 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
private UIElement BuildInstanceControl(IApplicationInstance instance)
|
||||
{
|
||||
var border = new Border();
|
||||
var stackPanel = new StackPanel();
|
||||
var icon = IconResourceLoader.Load(instance.Icon);
|
||||
|
||||
border.BorderBrush = Brushes.White;
|
||||
border.BorderThickness = new Thickness(1);
|
||||
border.Height = 150;
|
||||
border.Margin = new Thickness(5);
|
||||
border.Padding = new Thickness(2);
|
||||
border.Width = 250;
|
||||
border.Child = stackPanel;
|
||||
|
||||
stackPanel.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
stackPanel.Orientation = Orientation.Vertical;
|
||||
stackPanel.VerticalAlignment = VerticalAlignment.Center;
|
||||
stackPanel.Children.Add(new ContentControl { Content = icon, MaxWidth = 50 });
|
||||
stackPanel.Children.Add(new TextBlock(new Run($"Instance {instance.Name ?? "NULL"}") { Foreground = Brushes.White, FontWeight = FontWeights.Bold }));
|
||||
|
||||
return border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d" Title="Taskbar" Background="#FFF0F0F0" Height="40" Width="750" WindowStyle="None" Topmost="True" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico">
|
||||
mc:Ignorable="d" Title="Taskbar" Background="{DynamicResource BackgroundBrush}" Height="40" Width="750" WindowStyle="None" Topmost="True"
|
||||
ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
@ -26,7 +28,7 @@
|
|||
</ScrollViewer>
|
||||
<StackPanel Grid.Column="1" x:Name="NotificationStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
|
||||
<StackPanel Grid.Column="2" x:Name="SystemControlStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
|
||||
<local:TaskbarClock Grid.Column="3" x:Name="Clock" Foreground="DimGray" Padding="10,0,10,0" />
|
||||
<local:TaskbarClock Grid.Column="3" x:Name="Clock" Foreground="{StaticResource SecondaryTextBrush}" Padding="10,0,10,0" />
|
||||
<local:TaskbarQuitButton Grid.Column="4" x:Name="QuitButton" />
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<SolidColorBrush x:Key="BackgroundBrush">#FFF0F0F0</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ActionCenterDarkBrush">#AA808080</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="BackgroundBrush">#FFF0F0F0</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="BackgroundTransparentBrush">#EEF0F0F0</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="BackgroundTransparentEmphasisBrush">#99D3D3D3</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="PrimaryTextBrush">Black</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="SecondaryTextBrush">DimGray</SolidColorBrush>
|
||||
</ResourceDictionary>
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile"
|
||||
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Foreground="White" Height="500" Width="1100" MinHeight="350"
|
||||
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Foreground="White" Height="750" Width="1000" MinHeight="350"
|
||||
MinWidth="350" WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
|
|
|
@ -342,7 +342,7 @@ namespace SafeExamBrowser.WindowsApi
|
|||
|
||||
public void RestoreWindow(IntPtr window)
|
||||
{
|
||||
User32.ShowWindow(window, (int)ShowWindowCommand.Restore);
|
||||
User32.ShowWindow(window, (int) ShowWindowCommand.Restore);
|
||||
}
|
||||
|
||||
public bool ResumeThread(int threadId)
|
||||
|
|
|
@ -69,15 +69,18 @@ namespace SafeExamBrowser.WindowsApi
|
|||
{
|
||||
try
|
||||
{
|
||||
var success = User32.BringWindowToTop(process.MainWindowHandle);
|
||||
var success = true;
|
||||
var placement = new WINDOWPLACEMENT();
|
||||
|
||||
success &= User32.BringWindowToTop(process.MainWindowHandle);
|
||||
success &= User32.SetForegroundWindow(process.MainWindowHandle);
|
||||
|
||||
placement.length = Marshal.SizeOf(placement);
|
||||
User32.GetWindowPlacement(process.MainWindowHandle, ref placement);
|
||||
|
||||
if (placement.showCmd == (int) ShowWindowCommand.ShowMinimized)
|
||||
{
|
||||
success &= User32.ShowWindow(process.MainWindowHandle, (int) ShowWindowCommand.Restore);
|
||||
success &= User32.ShowWindowAsync(process.MainWindowHandle, (int) ShowWindowCommand.Restore);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace SafeExamBrowser.WindowsApi
|
|||
|
||||
logger.Info($"Attempting to start process '{path}'...");
|
||||
|
||||
// TODO: Fails for certain processes, whereas Process.Start() does not -> use different API?! Use (declare?) CreateProcessW / CreateProcessA?
|
||||
var success = Kernel32.CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, true, Constant.NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref startupInfo, ref processInfo);
|
||||
|
||||
if (!success)
|
||||
|
|
|
@ -83,6 +83,9 @@ namespace SafeExamBrowser.WindowsApi
|
|||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, EventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
|
||||
|
||||
|
@ -92,6 +95,9 @@ namespace SafeExamBrowser.WindowsApi
|
|||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
internal static extern bool SwitchDesktop(IntPtr hDesktop);
|
||||
|
||||
|
|
Loading…
Reference in a new issue