diff --git a/.gitremotes b/.gitremotes
index e2f42ce..be196eb 100644
--- a/.gitremotes
+++ b/.gitremotes
@@ -1,10 +1,10 @@
-FSI.Lib //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/fsi.lib.git (fetch)
-FSI.Lib //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/fsi.lib.git (push)
-NHotkey //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/nhotkey.git (fetch)
-NHotkey //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/nhotkey.git (push)
-NotifyIconWpf //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/notifyiconwpf.git (fetch)
-NotifyIconWpf //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/notifyiconwpf.git (push)
-RadialMenu //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/radialmenu.git (fetch)
-RadialMenu //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/radialmenu.git (push)
-origin //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/fsi.tools.git (fetch)
-origin //fondium.org/DESI$/AUG_Abteilung/Betriebstechnik/50_I&R/01_I&R Giesserei/100_Sicherung/E/99_Repositories/fsi/fsi.tools.git (push)
+FSI.Lib r:/fsi/fsi.lib.git (fetch)
+FSI.Lib r:/fsi/fsi.lib.git (push)
+NHotkey r:/fsi/nhotkey.git (fetch)
+NHotkey r:/fsi/nhotkey.git (push)
+NotifyIconWpf r:/fsi/notifyiconwpf.git (fetch)
+NotifyIconWpf r:/fsi/notifyiconwpf.git (push)
+RadialMenu r:/fsi/radialmenu.git (fetch)
+RadialMenu r:/fsi/radialmenu.git (push)
+origin r:/fsi/fsi.bt.tools.git (fetch)
+origin r:/fsi/fsi.bt.tools.git (push)
diff --git a/AutoCompleteTextBox/AutoCompleteTextBox.csproj b/AutoCompleteTextBox/AutoCompleteTextBox.csproj
new file mode 100644
index 0000000..4b2f404
--- /dev/null
+++ b/AutoCompleteTextBox/AutoCompleteTextBox.csproj
@@ -0,0 +1,32 @@
+
+
+
+ false
+ net48;netcoreapp3.1;net6.0-windows
+ true
+ 1.6.0.0
+ https://github.com/quicoli/WPF-AutoComplete-TextBox
+
+ https://github.com/quicoli/WPF-AutoComplete-TextBox
+ wpf, autocomplete, usercontrol
+ https://github.com/quicoli/WPF-AutoComplete-TextBox/blob/develop/AutoCompleteTextBox/Logo/AutoCompleteTextBox.ico?raw=true
+ true
+ AutoCompleteTextBox.ico
+
+ Better support for keyboard focus
+
+ An auto complete textbox and combo box for WPF
+ AutoCompleteTextBox.png
+ README.md
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+
diff --git a/AutoCompleteTextBox/AutoCompleteTextBox.ico b/AutoCompleteTextBox/AutoCompleteTextBox.ico
new file mode 100644
index 0000000..4cb9958
Binary files /dev/null and b/AutoCompleteTextBox/AutoCompleteTextBox.ico differ
diff --git a/AutoCompleteTextBox/BindingEvaluator.cs b/AutoCompleteTextBox/BindingEvaluator.cs
new file mode 100644
index 0000000..6b06a7c
--- /dev/null
+++ b/AutoCompleteTextBox/BindingEvaluator.cs
@@ -0,0 +1,49 @@
+using System.Windows;
+using System.Windows.Data;
+
+namespace AutoCompleteTextBox
+{
+ public class BindingEvaluator : FrameworkElement
+ {
+
+ #region "Fields"
+
+
+ public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(BindingEvaluator), new FrameworkPropertyMetadata(string.Empty));
+
+ #endregion
+
+ #region "Constructors"
+
+ public BindingEvaluator(Binding binding)
+ {
+ ValueBinding = binding;
+ }
+
+ #endregion
+
+ #region "Properties"
+
+ public string Value
+ {
+ get => (string)GetValue(ValueProperty);
+
+ set => SetValue(ValueProperty, value);
+ }
+
+ public Binding ValueBinding { get; set; }
+
+ #endregion
+
+ #region "Methods"
+
+ public string Evaluate(object dataItem)
+ {
+ DataContext = dataItem;
+ SetBinding(ValueProperty, ValueBinding);
+ return Value;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/AutoCompleteTextBox/Editors/AutoCompleteComboBox.cs b/AutoCompleteTextBox/Editors/AutoCompleteComboBox.cs
new file mode 100644
index 0000000..2b65103
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/AutoCompleteComboBox.cs
@@ -0,0 +1,612 @@
+using System;
+using System.Collections;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Threading;
+
+namespace AutoCompleteTextBox.Editors
+{
+ [TemplatePart(Name = PartEditor, Type = typeof(TextBox))]
+ [TemplatePart(Name = PartPopup, Type = typeof(Popup))]
+ [TemplatePart(Name = PartSelector, Type = typeof(Selector))]
+ [TemplatePart(Name = PartExpander, Type = typeof(Expander))]
+ public class AutoCompleteComboBox : Control
+ {
+
+ #region "Fields"
+
+ public const string PartEditor = "PART_Editor";
+ public const string PartPopup = "PART_Popup";
+
+ public const string PartSelector = "PART_Selector";
+ public const string PartExpander = "PART_Expander";
+ public static readonly DependencyProperty DelayProperty = DependencyProperty.Register("Delay", typeof(int), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(200));
+ public static readonly DependencyProperty DisplayMemberProperty = DependencyProperty.Register("DisplayMember", typeof(string), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(string.Empty));
+ public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register("IconPlacement", typeof(IconPlacement), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(IconPlacement.Left));
+ public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(object), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty IconVisibilityProperty = DependencyProperty.Register("IconVisibility", typeof(Visibility), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(Visibility.Visible));
+ public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register("IsLoading", typeof(bool), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty ItemTemplateSelectorProperty = DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(AutoCompleteComboBox));
+ public static readonly DependencyProperty LoadingContentProperty = DependencyProperty.Register("LoadingContent", typeof(object), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty ProviderProperty = DependencyProperty.Register("Provider", typeof(IComboSuggestionProvider), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(null, OnSelectedItemChanged));
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(string.Empty, propertyChangedCallback: null, coerceValueCallback: null, isAnimationProhibited: false, defaultUpdateSourceTrigger: UpdateSourceTrigger.LostFocus, flags: FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+ public static readonly DependencyProperty FilterProperty = DependencyProperty.Register("Filter", typeof(string), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(string.Empty));
+ public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(0));
+ public static readonly DependencyProperty CharacterCasingProperty = DependencyProperty.Register("CharacterCasing", typeof(CharacterCasing), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(CharacterCasing.Normal));
+ public static readonly DependencyProperty MaxPopUpHeightProperty = DependencyProperty.Register("MaxPopUpHeight", typeof(int), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(600));
+ public static readonly DependencyProperty MaxPopUpWidthProperty = DependencyProperty.Register("MaxPopUpWidth", typeof(int), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(2000));
+
+ public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(string.Empty));
+
+ public static readonly DependencyProperty SuggestionBackgroundProperty = DependencyProperty.Register("SuggestionBackground", typeof(Brush), typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(Brushes.White));
+ private bool _isUpdatingText;
+ private bool _selectionCancelled;
+
+ private SuggestionsAdapter _suggestionsAdapter;
+
+
+ #endregion
+
+ #region "Constructors"
+
+ static AutoCompleteComboBox()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoCompleteComboBox), new FrameworkPropertyMetadata(typeof(AutoCompleteComboBox)));
+ }
+
+ #endregion
+
+ #region "Properties"
+
+
+ public int MaxPopupHeight
+ {
+ get => (int)GetValue(MaxPopUpHeightProperty);
+ set => SetValue(MaxPopUpHeightProperty, value);
+ }
+ public int MaxPopupWidth
+ {
+ get => (int)GetValue(MaxPopUpWidthProperty);
+ set => SetValue(MaxPopUpWidthProperty, value);
+ }
+
+
+ public BindingEvaluator BindingEvaluator { get; set; }
+
+ public CharacterCasing CharacterCasing
+ {
+ get => (CharacterCasing)GetValue(CharacterCasingProperty);
+ set => SetValue(CharacterCasingProperty, value);
+ }
+
+ public int MaxLength
+ {
+ get => (int)GetValue(MaxLengthProperty);
+ set => SetValue(MaxLengthProperty, value);
+ }
+
+ public int Delay
+ {
+ get => (int)GetValue(DelayProperty);
+
+ set => SetValue(DelayProperty, value);
+ }
+
+ public string DisplayMember
+ {
+ get => (string)GetValue(DisplayMemberProperty);
+
+ set => SetValue(DisplayMemberProperty, value);
+ }
+
+ public TextBox Editor { get; set; }
+ public Expander Expander { get; set; }
+
+ public DispatcherTimer FetchTimer { get; set; }
+
+ public string Filter
+ {
+ get => (string)GetValue(FilterProperty);
+
+ set => SetValue(FilterProperty, value);
+ }
+
+ public object Icon
+ {
+ get => GetValue(IconProperty);
+
+ set => SetValue(IconProperty, value);
+ }
+
+ public IconPlacement IconPlacement
+ {
+ get => (IconPlacement)GetValue(IconPlacementProperty);
+
+ set => SetValue(IconPlacementProperty, value);
+ }
+
+ public Visibility IconVisibility
+ {
+ get => (Visibility)GetValue(IconVisibilityProperty);
+
+ set => SetValue(IconVisibilityProperty, value);
+ }
+
+ public bool IsDropDownOpen
+ {
+ get => (bool)GetValue(IsDropDownOpenProperty);
+
+ set
+ {
+ this.Expander.IsExpanded = value;
+ SetValue(IsDropDownOpenProperty, value);
+ }
+ }
+
+ public bool IsLoading
+ {
+ get => (bool)GetValue(IsLoadingProperty);
+
+ set => SetValue(IsLoadingProperty, value);
+ }
+
+ public bool IsReadOnly
+ {
+ get => (bool)GetValue(IsReadOnlyProperty);
+
+ set => SetValue(IsReadOnlyProperty, value);
+ }
+
+ public Selector ItemsSelector { get; set; }
+
+ public DataTemplate ItemTemplate
+ {
+ get => (DataTemplate)GetValue(ItemTemplateProperty);
+
+ set => SetValue(ItemTemplateProperty, value);
+ }
+
+ public DataTemplateSelector ItemTemplateSelector
+ {
+ get => ((DataTemplateSelector)(GetValue(ItemTemplateSelectorProperty)));
+ set => SetValue(ItemTemplateSelectorProperty, value);
+ }
+
+ public object LoadingContent
+ {
+ get => GetValue(LoadingContentProperty);
+
+ set => SetValue(LoadingContentProperty, value);
+ }
+
+ public Popup Popup { get; set; }
+
+ public IComboSuggestionProvider Provider
+ {
+ get => (IComboSuggestionProvider)GetValue(ProviderProperty);
+
+ set => SetValue(ProviderProperty, value);
+ }
+
+ public object SelectedItem
+ {
+ get => GetValue(SelectedItemProperty);
+
+ set => SetValue(SelectedItemProperty, value);
+ }
+
+ public SelectionAdapter SelectionAdapter { get; set; }
+
+ public string Text
+ {
+ get => (string)GetValue(TextProperty);
+
+ set => SetValue(TextProperty, value);
+ }
+
+ public string Watermark
+ {
+ get => (string)GetValue(WatermarkProperty);
+
+ set => SetValue(WatermarkProperty, value);
+ }
+ public Brush SuggestionBackground
+ {
+ get => (Brush)GetValue(SuggestionBackgroundProperty);
+
+ set => SetValue(SuggestionBackgroundProperty, value);
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ public static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ AutoCompleteComboBox act = null;
+ act = d as AutoCompleteComboBox;
+ if (act != null)
+ {
+ if (act.Editor != null & !act._isUpdatingText)
+ {
+ act._isUpdatingText = true;
+ act.Editor.Text = act.BindingEvaluator.Evaluate(e.NewValue);
+ act._isUpdatingText = false;
+ }
+ }
+ }
+
+ private void ScrollToSelectedItem()
+ {
+ if (ItemsSelector is ListBox listBox && listBox.SelectedItem != null)
+ listBox.ScrollIntoView(listBox.SelectedItem);
+ }
+
+ public new BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding){
+ var res = base.SetBinding(dp, binding);
+ CheckForParentTextBindingChange();
+ return res;
+ }
+ public new BindingExpressionBase SetBinding(DependencyProperty dp, String path) {
+ var res = base.SetBinding(dp, path);
+ CheckForParentTextBindingChange();
+ return res;
+ }
+ public new void ClearValue(DependencyPropertyKey key) {
+ base.ClearValue(key);
+ CheckForParentTextBindingChange();
+ }
+ public new void ClearValue(DependencyProperty dp) {
+ base.ClearValue(dp);
+ CheckForParentTextBindingChange();
+ }
+ private void CheckForParentTextBindingChange(bool force=false) {
+ var CurrentBindingMode = BindingOperations.GetBinding(this, TextProperty)?.UpdateSourceTrigger ?? UpdateSourceTrigger.Default;
+ if (CurrentBindingMode != UpdateSourceTrigger.PropertyChanged)//preventing going any less frequent than property changed
+ CurrentBindingMode = UpdateSourceTrigger.Default;
+
+
+ if (CurrentBindingMode == CurrentTextboxTextBindingUpdateMode && force == false)
+ return;
+ var binding = new Binding {
+ Mode = BindingMode.TwoWay,
+ UpdateSourceTrigger = CurrentBindingMode,
+ Path = new PropertyPath(nameof(Text)),
+ RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
+ };
+ CurrentTextboxTextBindingUpdateMode = CurrentBindingMode;
+ Editor?.SetBinding(TextBox.TextProperty, binding);
+ }
+
+ private UpdateSourceTrigger CurrentTextboxTextBindingUpdateMode;
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ Editor = Template.FindName(PartEditor, this) as TextBox;
+ Popup = Template.FindName(PartPopup, this) as Popup;
+ ItemsSelector = Template.FindName(PartSelector, this) as Selector;
+ Expander = Template.FindName(PartExpander, this) as Expander;
+
+ BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
+
+ if (Editor != null)
+ {
+ Editor.TextChanged += OnEditorTextChanged;
+ Editor.PreviewKeyDown += OnEditorKeyDown;
+ Editor.LostFocus += OnEditorLostFocus;
+ CheckForParentTextBindingChange(true);
+
+ if (SelectedItem != null)
+ {
+ _isUpdatingText = true;
+ Editor.Text = BindingEvaluator.Evaluate(SelectedItem);
+ _isUpdatingText = false;
+ }
+
+ }
+ if (Expander != null)
+ {
+ Expander.IsExpanded = false;
+ Expander.Collapsed += Expander_Expanded;
+ Expander.Expanded += Expander_Expanded;
+ }
+
+ GotFocus += AutoCompleteComboBox_GotFocus;
+
+ if (Popup != null)
+ {
+ Popup.StaysOpen = false;
+ Popup.Opened += OnPopupOpened;
+ Popup.Closed += OnPopupClosed;
+ }
+ if (ItemsSelector != null)
+ {
+ SelectionAdapter = new SelectionAdapter(ItemsSelector);
+ SelectionAdapter.Commit += OnSelectionAdapterCommit;
+ SelectionAdapter.Cancel += OnSelectionAdapterCancel;
+ SelectionAdapter.SelectionChanged += OnSelectionAdapterSelectionChanged;
+ ItemsSelector.PreviewMouseDown += ItemsSelector_PreviewMouseDown;
+ }
+ }
+
+ private void Expander_Expanded(object sender, RoutedEventArgs e)
+ {
+ this.IsDropDownOpen = Expander.IsExpanded;
+ if (!this.IsDropDownOpen)
+ {
+ return;
+ }
+ if (_suggestionsAdapter == null)
+ {
+ _suggestionsAdapter = new SuggestionsAdapter(this);
+ }
+ if (SelectedItem != null || String.IsNullOrWhiteSpace(Editor.Text))
+ _suggestionsAdapter.ShowFullCollection();
+
+ }
+
+ private void ItemsSelector_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ if ((e.OriginalSource as FrameworkElement)?.DataContext == null)
+ return;
+ if (!ItemsSelector.Items.Contains(((FrameworkElement)e.OriginalSource)?.DataContext))
+ return;
+ ItemsSelector.SelectedItem = ((FrameworkElement)e.OriginalSource)?.DataContext;
+ OnSelectionAdapterCommit(SelectionAdapter.EventCause.ItemClicked);
+ e.Handled = true;
+ }
+ private void AutoCompleteComboBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ Editor?.Focus();
+ }
+
+ private string GetDisplayText(object dataItem)
+ {
+ if (BindingEvaluator == null)
+ {
+ BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
+ }
+ if (dataItem == null)
+ {
+ return string.Empty;
+ }
+ if (string.IsNullOrEmpty(DisplayMember))
+ {
+ return dataItem.ToString();
+ }
+ return BindingEvaluator.Evaluate(dataItem);
+ }
+
+ private void OnEditorKeyDown(object sender, KeyEventArgs e)
+ {
+ if (SelectionAdapter != null)
+ {
+ if (IsDropDownOpen)
+ SelectionAdapter.HandleKeyDown(e);
+ else
+ IsDropDownOpen = e.Key == Key.Down || e.Key == Key.Up;
+ }
+ }
+
+ private void OnEditorLostFocus(object sender, RoutedEventArgs e)
+ {
+ if (!IsKeyboardFocusWithin)
+ {
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnEditorTextChanged(object sender, TextChangedEventArgs e)
+ {
+ Text = Editor.Text;
+ if (_isUpdatingText)
+ return;
+ if (FetchTimer == null)
+ {
+ FetchTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(Delay) };
+ FetchTimer.Tick += OnFetchTimerTick;
+ }
+ FetchTimer.IsEnabled = false;
+ FetchTimer.Stop();
+ SetSelectedItem(null);
+ if (Editor.Text.Length > 0)
+ {
+ FetchTimer.IsEnabled = true;
+ FetchTimer.Start();
+ }
+ else
+ {
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnFetchTimerTick(object sender, EventArgs e)
+ {
+ FetchTimer.IsEnabled = false;
+ FetchTimer.Stop();
+ if (Provider != null && ItemsSelector != null)
+ {
+ Filter = Editor.Text;
+ if (_suggestionsAdapter == null)
+ {
+ _suggestionsAdapter = new SuggestionsAdapter(this);
+ }
+ _suggestionsAdapter.GetSuggestions(Filter);
+ }
+ }
+
+ private void OnPopupClosed(object sender, EventArgs e)
+ {
+ if (!_selectionCancelled)
+ {
+ OnSelectionAdapterCommit(SelectionAdapter.EventCause.PopupClosed);
+ }
+ }
+
+ private void OnPopupOpened(object sender, EventArgs e)
+ {
+ _selectionCancelled = false;
+ ItemsSelector.SelectedItem = SelectedItem;
+ }
+
+ public event EventHandler PreSelectionAdapterFinish;
+ private bool PreSelectionEventSomeoneHandled(SelectionAdapter.EventCause cause, bool is_cancel) {
+ if (PreSelectionAdapterFinish == null)
+ return false;
+ var args = new SelectionAdapter.PreSelectionAdapterFinishArgs { cause = cause, is_cancel = is_cancel };
+ PreSelectionAdapterFinish?.Invoke(this, args);
+ return args.handled;
+
+ }
+ private void OnSelectionAdapterCancel(SelectionAdapter.EventCause cause)
+ {
+ if (PreSelectionEventSomeoneHandled(cause, true))
+ return;
+ _isUpdatingText = true;
+ Editor.Text = SelectedItem == null ? Filter : GetDisplayText(SelectedItem);
+ Editor.SelectionStart = Editor.Text.Length;
+ Editor.SelectionLength = 0;
+ _isUpdatingText = false;
+ IsDropDownOpen = false;
+ _selectionCancelled = true;
+ }
+
+ private void OnSelectionAdapterCommit(SelectionAdapter.EventCause cause)
+ {
+ if (PreSelectionEventSomeoneHandled(cause, false))
+ return;
+
+ if (ItemsSelector.SelectedItem != null)
+ {
+ SelectedItem = ItemsSelector.SelectedItem;
+ _isUpdatingText = true;
+ Editor.Text = GetDisplayText(ItemsSelector.SelectedItem);
+ SetSelectedItem(ItemsSelector.SelectedItem);
+ _isUpdatingText = false;
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnSelectionAdapterSelectionChanged()
+ {
+ _isUpdatingText = true;
+ Editor.Text = ItemsSelector.SelectedItem == null ? Filter : GetDisplayText(ItemsSelector.SelectedItem);
+ Editor.SelectionStart = Editor.Text.Length;
+ Editor.SelectionLength = 0;
+ ScrollToSelectedItem();
+ _isUpdatingText = false;
+ }
+
+ private void SetSelectedItem(object item)
+ {
+ _isUpdatingText = true;
+ SelectedItem = item;
+ _isUpdatingText = false;
+ }
+ #endregion
+
+ #region "Nested Types"
+
+ private class SuggestionsAdapter
+ {
+
+ #region "Fields"
+
+ private readonly AutoCompleteComboBox _actb;
+
+ private string _filter;
+ #endregion
+
+ #region "Constructors"
+
+ public SuggestionsAdapter(AutoCompleteComboBox actb)
+ {
+ _actb = actb;
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ public void GetSuggestions(string searchText)
+ {
+ _actb.IsLoading = true;
+ // Do not open drop down if control is not focused
+ if (_actb.IsKeyboardFocusWithin)
+ _actb.IsDropDownOpen = true;
+ _actb.ItemsSelector.ItemsSource = null;
+ ParameterizedThreadStart thInfo = GetSuggestionsAsync;
+ Thread th = new Thread(thInfo);
+ _filter = searchText;
+ th.Start(new object[] { searchText, _actb.Provider });
+ }
+ public void ShowFullCollection()
+ {
+ _filter = string.Empty;
+ _actb.IsLoading = true;
+ // Do not open drop down if control is not focused
+ if (_actb.IsKeyboardFocusWithin)
+ _actb.IsDropDownOpen = true;
+ _actb.ItemsSelector.ItemsSource = null;
+ ParameterizedThreadStart thInfo = GetFullCollectionAsync;
+ Thread th = new Thread(thInfo);
+ th.Start(_actb.Provider);
+ }
+
+ private void DisplaySuggestions(IEnumerable suggestions, string filter)
+ {
+ if (_filter != filter)
+ {
+ return;
+ }
+ _actb.IsLoading = false;
+ _actb.ItemsSelector.ItemsSource = suggestions;
+ // Close drop down if there are no items
+ if (_actb.IsDropDownOpen)
+ {
+ _actb.IsDropDownOpen = _actb.ItemsSelector.HasItems;
+ }
+ }
+
+ private void GetSuggestionsAsync(object param)
+ {
+ if (param is object[] args)
+ {
+ string searchText = Convert.ToString(args[0]);
+ if (args[1] is IComboSuggestionProvider provider)
+ {
+ IEnumerable list = provider.GetSuggestions(searchText);
+ _actb.Dispatcher.BeginInvoke(new Action(DisplaySuggestions), DispatcherPriority.Background, list, searchText);
+ }
+ }
+ }
+ private void GetFullCollectionAsync(object param)
+ {
+ if (param is IComboSuggestionProvider provider)
+ {
+ IEnumerable list = provider.GetFullCollection();
+ _actb.Dispatcher.BeginInvoke(new Action(DisplaySuggestions), DispatcherPriority.Background, list, string.Empty);
+ }
+
+ }
+
+ #endregion
+
+ }
+
+ #endregion
+
+ }
+
+}
diff --git a/AutoCompleteTextBox/Editors/AutoCompleteTextBox.cs b/AutoCompleteTextBox/Editors/AutoCompleteTextBox.cs
new file mode 100644
index 0000000..c2f3665
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/AutoCompleteTextBox.cs
@@ -0,0 +1,569 @@
+using System;
+using System.Collections;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Threading;
+
+namespace AutoCompleteTextBox.Editors
+{
+ [TemplatePart(Name = PartEditor, Type = typeof(TextBox))]
+ [TemplatePart(Name = PartPopup, Type = typeof(Popup))]
+ [TemplatePart(Name = PartSelector, Type = typeof(Selector))]
+ public class AutoCompleteTextBox : Control
+ {
+
+ #region "Fields"
+
+ public const string PartEditor = "PART_Editor";
+ public const string PartPopup = "PART_Popup";
+
+ public const string PartSelector = "PART_Selector";
+ public static readonly DependencyProperty DelayProperty = DependencyProperty.Register("Delay", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(200));
+ public static readonly DependencyProperty DisplayMemberProperty = DependencyProperty.Register("DisplayMember", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
+ public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register("IconPlacement", typeof(IconPlacement), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(IconPlacement.Left));
+ public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty IconVisibilityProperty = DependencyProperty.Register("IconVisibility", typeof(Visibility), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(Visibility.Visible));
+ public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty IsLoadingProperty = DependencyProperty.Register("IsLoading", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false));
+ public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty ItemTemplateSelectorProperty = DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(AutoCompleteTextBox));
+ public static readonly DependencyProperty LoadingContentProperty = DependencyProperty.Register("LoadingContent", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty ProviderProperty = DependencyProperty.Register("Provider", typeof(ISuggestionProvider), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null));
+ public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(null, OnSelectedItemChanged));
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty, propertyChangedCallback:null,coerceValueCallback:null, isAnimationProhibited:false, defaultUpdateSourceTrigger: UpdateSourceTrigger.LostFocus, flags: FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
+ public static readonly DependencyProperty FilterProperty = DependencyProperty.Register("Filter", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
+ public static readonly DependencyProperty MaxLengthProperty = DependencyProperty.Register("MaxLength", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(0));
+ public static readonly DependencyProperty CharacterCasingProperty = DependencyProperty.Register("CharacterCasing", typeof(CharacterCasing), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(CharacterCasing.Normal));
+ public static readonly DependencyProperty MaxPopUpHeightProperty = DependencyProperty.Register("MaxPopUpHeight", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(600));
+ public static readonly DependencyProperty MaxPopUpWidthProperty = DependencyProperty.Register("MaxPopUpWidth", typeof(int), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(2000));
+
+ public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty));
+
+ public static readonly DependencyProperty SuggestionBackgroundProperty = DependencyProperty.Register("SuggestionBackground", typeof(Brush), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(Brushes.White));
+ private bool _isUpdatingText;
+ private bool _selectionCancelled;
+
+ private SuggestionsAdapter _suggestionsAdapter;
+
+
+ #endregion
+
+ #region "Constructors"
+
+ static AutoCompleteTextBox()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(typeof(AutoCompleteTextBox)));
+ FocusableProperty.OverrideMetadata(typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(true));
+ }
+
+ #endregion
+
+ #region "Properties"
+
+
+ public int MaxPopupHeight
+ {
+ get => (int)GetValue(MaxPopUpHeightProperty);
+ set => SetValue(MaxPopUpHeightProperty, value);
+ }
+ public int MaxPopupWidth
+ {
+ get => (int)GetValue(MaxPopUpWidthProperty);
+ set => SetValue(MaxPopUpWidthProperty, value);
+ }
+
+ public BindingEvaluator BindingEvaluator { get; set; }
+
+ public CharacterCasing CharacterCasing
+ {
+ get => (CharacterCasing)GetValue(CharacterCasingProperty);
+ set => SetValue(CharacterCasingProperty, value);
+ }
+
+ public int MaxLength
+ {
+ get => (int)GetValue(MaxLengthProperty);
+ set => SetValue(MaxLengthProperty, value);
+ }
+
+ public int Delay
+ {
+ get => (int)GetValue(DelayProperty);
+
+ set => SetValue(DelayProperty, value);
+ }
+
+ public string DisplayMember
+ {
+ get => (string)GetValue(DisplayMemberProperty);
+
+ set => SetValue(DisplayMemberProperty, value);
+ }
+
+ public TextBox Editor { get; set; }
+
+ public DispatcherTimer FetchTimer { get; set; }
+
+ public string Filter
+ {
+ get => (string)GetValue(FilterProperty);
+
+ set => SetValue(FilterProperty, value);
+ }
+
+ public object Icon
+ {
+ get => GetValue(IconProperty);
+
+ set => SetValue(IconProperty, value);
+ }
+
+ public IconPlacement IconPlacement
+ {
+ get => (IconPlacement)GetValue(IconPlacementProperty);
+
+ set => SetValue(IconPlacementProperty, value);
+ }
+
+ public Visibility IconVisibility
+ {
+ get => (Visibility)GetValue(IconVisibilityProperty);
+
+ set => SetValue(IconVisibilityProperty, value);
+ }
+
+ public bool IsDropDownOpen
+ {
+ get => (bool)GetValue(IsDropDownOpenProperty);
+
+ set => SetValue(IsDropDownOpenProperty, value);
+ }
+
+ public bool IsLoading
+ {
+ get => (bool)GetValue(IsLoadingProperty);
+
+ set => SetValue(IsLoadingProperty, value);
+ }
+
+ public bool IsReadOnly
+ {
+ get => (bool)GetValue(IsReadOnlyProperty);
+
+ set => SetValue(IsReadOnlyProperty, value);
+ }
+
+ public Selector ItemsSelector { get; set; }
+
+ public DataTemplate ItemTemplate
+ {
+ get => (DataTemplate)GetValue(ItemTemplateProperty);
+
+ set => SetValue(ItemTemplateProperty, value);
+ }
+
+ public DataTemplateSelector ItemTemplateSelector
+ {
+ get => ((DataTemplateSelector)(GetValue(ItemTemplateSelectorProperty)));
+ set => SetValue(ItemTemplateSelectorProperty, value);
+ }
+
+ public object LoadingContent
+ {
+ get => GetValue(LoadingContentProperty);
+
+ set => SetValue(LoadingContentProperty, value);
+ }
+
+ public Popup Popup { get; set; }
+
+ public ISuggestionProvider Provider
+ {
+ get => (ISuggestionProvider)GetValue(ProviderProperty);
+
+ set => SetValue(ProviderProperty, value);
+ }
+
+ public object SelectedItem
+ {
+ get => GetValue(SelectedItemProperty);
+
+ set => SetValue(SelectedItemProperty, value);
+ }
+
+ public SelectionAdapter SelectionAdapter { get; set; }
+
+ public string Text
+ {
+ get => (string)GetValue(TextProperty);
+
+ set => SetValue(TextProperty, value);
+ }
+
+ public string Watermark
+ {
+ get => (string)GetValue(WatermarkProperty);
+
+ set => SetValue(WatermarkProperty, value);
+ }
+ public Brush SuggestionBackground
+ {
+ get => (Brush)GetValue(SuggestionBackgroundProperty);
+
+ set => SetValue(SuggestionBackgroundProperty, value);
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ public static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ AutoCompleteTextBox act = null;
+ act = d as AutoCompleteTextBox;
+ if (act != null)
+ {
+ if (act.Editor != null & !act._isUpdatingText)
+ {
+ act._isUpdatingText = true;
+ act.Editor.Text = act.BindingEvaluator.Evaluate(e.NewValue);
+ act._isUpdatingText = false;
+ }
+ }
+ }
+
+ private void ScrollToSelectedItem()
+ {
+ if (ItemsSelector is ListBox listBox && listBox.SelectedItem != null)
+ listBox.ScrollIntoView(listBox.SelectedItem);
+ }
+
+ public new BindingExpressionBase SetBinding(DependencyProperty dp, BindingBase binding){
+ var res = base.SetBinding(dp, binding);
+ CheckForParentTextBindingChange();
+ return res;
+ }
+ public new BindingExpressionBase SetBinding(DependencyProperty dp, String path) {
+ var res = base.SetBinding(dp, path);
+ CheckForParentTextBindingChange();
+ return res;
+ }
+ public new void ClearValue(DependencyPropertyKey key) {
+ base.ClearValue(key);
+ CheckForParentTextBindingChange();
+ }
+ public new void ClearValue(DependencyProperty dp) {
+ base.ClearValue(dp);
+ CheckForParentTextBindingChange();
+ }
+ private void CheckForParentTextBindingChange(bool force=false) {
+ var CurrentBindingMode = BindingOperations.GetBinding(this, TextProperty)?.UpdateSourceTrigger ?? UpdateSourceTrigger.Default;
+ if (CurrentBindingMode != UpdateSourceTrigger.PropertyChanged)//preventing going any less frequent than property changed
+ CurrentBindingMode = UpdateSourceTrigger.Default;
+
+
+ if (CurrentBindingMode == CurrentTextboxTextBindingUpdateMode && force == false)
+ return;
+ var binding = new Binding {
+ Mode = BindingMode.TwoWay,
+ UpdateSourceTrigger = CurrentBindingMode,
+ Path = new PropertyPath(nameof(Text)),
+ RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
+ };
+ CurrentTextboxTextBindingUpdateMode = CurrentBindingMode;
+ Editor?.SetBinding(TextBox.TextProperty, binding);
+ }
+
+ private UpdateSourceTrigger CurrentTextboxTextBindingUpdateMode;
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ Editor = Template.FindName(PartEditor, this) as TextBox;
+ Editor.Focus();
+ Popup = Template.FindName(PartPopup, this) as Popup;
+ ItemsSelector = Template.FindName(PartSelector, this) as Selector;
+ BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
+
+ if (Editor != null)
+ {
+ Editor.TextChanged += OnEditorTextChanged;
+ Editor.PreviewKeyDown += OnEditorKeyDown;
+ Editor.LostFocus += OnEditorLostFocus;
+ CheckForParentTextBindingChange(true);
+
+ if (SelectedItem != null)
+ {
+ _isUpdatingText = true;
+ Editor.Text = BindingEvaluator.Evaluate(SelectedItem);
+ _isUpdatingText = false;
+ }
+
+ }
+
+ GotFocus += AutoCompleteTextBox_GotFocus;
+ GotKeyboardFocus += AutoCompleteTextBox_GotKeyboardFocus;
+
+ if (Popup != null)
+ {
+ Popup.StaysOpen = false;
+ Popup.Opened += OnPopupOpened;
+ Popup.Closed += OnPopupClosed;
+ }
+ if (ItemsSelector != null)
+ {
+ SelectionAdapter = new SelectionAdapter(ItemsSelector);
+ SelectionAdapter.Commit += OnSelectionAdapterCommit;
+ SelectionAdapter.Cancel += OnSelectionAdapterCancel;
+ SelectionAdapter.SelectionChanged += OnSelectionAdapterSelectionChanged;
+ ItemsSelector.PreviewMouseDown += ItemsSelector_PreviewMouseDown;
+ }
+ }
+ private void ItemsSelector_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ if ((e.OriginalSource as FrameworkElement)?.DataContext == null)
+ return;
+ if (!ItemsSelector.Items.Contains(((FrameworkElement)e.OriginalSource)?.DataContext))
+ return;
+ ItemsSelector.SelectedItem = ((FrameworkElement)e.OriginalSource)?.DataContext;
+ OnSelectionAdapterCommit(SelectionAdapter.EventCause.MouseDown);
+ e.Handled = true;
+ }
+ private void AutoCompleteTextBox_GotFocus(object sender, RoutedEventArgs e)
+ {
+ Editor?.Focus();
+ }
+ private void AutoCompleteTextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) {
+ if (e.NewFocus != this)
+ return;
+ if (e.OldFocus == Editor)
+ MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
+
+ }
+
+ private string GetDisplayText(object dataItem)
+ {
+ if (BindingEvaluator == null)
+ {
+ BindingEvaluator = new BindingEvaluator(new Binding(DisplayMember));
+ }
+ if (dataItem == null)
+ {
+ return string.Empty;
+ }
+ if (string.IsNullOrEmpty(DisplayMember))
+ {
+ return dataItem.ToString();
+ }
+ return BindingEvaluator.Evaluate(dataItem);
+ }
+
+ private void OnEditorKeyDown(object sender, KeyEventArgs e)
+ {
+ if (SelectionAdapter != null)
+ {
+ if (IsDropDownOpen)
+ SelectionAdapter.HandleKeyDown(e);
+ else
+ IsDropDownOpen = e.Key == Key.Down || e.Key == Key.Up;
+ }
+ }
+
+ private void OnEditorLostFocus(object sender, RoutedEventArgs e)
+ {
+ if (!IsKeyboardFocusWithin)
+ {
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnEditorTextChanged(object sender, TextChangedEventArgs e)
+ {
+ Text = Editor.Text;
+ if (_isUpdatingText)
+ return;
+ if (FetchTimer == null)
+ {
+ FetchTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(Delay) };
+ FetchTimer.Tick += OnFetchTimerTick;
+ }
+ FetchTimer.IsEnabled = false;
+ FetchTimer.Stop();
+ SetSelectedItem(null);
+ if (Editor.Text.Length > 0)
+ {
+ FetchTimer.IsEnabled = true;
+ FetchTimer.Start();
+ }
+ else
+ {
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnFetchTimerTick(object sender, EventArgs e)
+ {
+ FetchTimer.IsEnabled = false;
+ FetchTimer.Stop();
+ if (Provider != null && ItemsSelector != null)
+ {
+ Filter = Editor.Text;
+ if (_suggestionsAdapter == null)
+ {
+ _suggestionsAdapter = new SuggestionsAdapter(this);
+ }
+ _suggestionsAdapter.GetSuggestions(Filter);
+ }
+ }
+
+ private void OnPopupClosed(object sender, EventArgs e)
+ {
+ if (!_selectionCancelled)
+ {
+ OnSelectionAdapterCommit(SelectionAdapter.EventCause.PopupClosed);
+ }
+ }
+
+ private void OnPopupOpened(object sender, EventArgs e)
+ {
+ _selectionCancelled = false;
+ ItemsSelector.SelectedItem = SelectedItem;
+ }
+
+ private void OnSelectionAdapterCancel(SelectionAdapter.EventCause cause)
+ {
+ if (PreSelectionEventSomeoneHandled(cause, true))
+ return;
+
+ _isUpdatingText = true;
+ Editor.Text = SelectedItem == null ? Filter : GetDisplayText(SelectedItem);
+ Editor.SelectionStart = Editor.Text.Length;
+ Editor.SelectionLength = 0;
+ _isUpdatingText = false;
+ IsDropDownOpen = false;
+ _selectionCancelled = true;
+
+ }
+
+ public event EventHandler PreSelectionAdapterFinish;
+ private bool PreSelectionEventSomeoneHandled(SelectionAdapter.EventCause cause, bool is_cancel) {
+ if (PreSelectionAdapterFinish == null)
+ return false;
+ var args = new SelectionAdapter.PreSelectionAdapterFinishArgs { cause = cause, is_cancel = is_cancel };
+ PreSelectionAdapterFinish?.Invoke(this, args);
+ return args.handled;
+
+ }
+ private void OnSelectionAdapterCommit(SelectionAdapter.EventCause cause)
+ {
+ if (PreSelectionEventSomeoneHandled(cause, false))
+ return;
+
+ if (ItemsSelector.SelectedItem != null)
+ {
+ SelectedItem = ItemsSelector.SelectedItem;
+ _isUpdatingText = true;
+ Editor.Text = GetDisplayText(ItemsSelector.SelectedItem);
+ SetSelectedItem(ItemsSelector.SelectedItem);
+ _isUpdatingText = false;
+ IsDropDownOpen = false;
+ }
+ }
+
+ private void OnSelectionAdapterSelectionChanged()
+ {
+ _isUpdatingText = true;
+ Editor.Text = ItemsSelector.SelectedItem == null ? Filter : GetDisplayText(ItemsSelector.SelectedItem);
+ Editor.SelectionStart = Editor.Text.Length;
+ Editor.SelectionLength = 0;
+ ScrollToSelectedItem();
+ _isUpdatingText = false;
+ }
+
+ private void SetSelectedItem(object item)
+ {
+ _isUpdatingText = true;
+ SelectedItem = item;
+ _isUpdatingText = false;
+ }
+ #endregion
+
+ #region "Nested Types"
+
+ private class SuggestionsAdapter
+ {
+
+ #region "Fields"
+
+ private readonly AutoCompleteTextBox _actb;
+
+ private string _filter;
+ #endregion
+
+ #region "Constructors"
+
+ public SuggestionsAdapter(AutoCompleteTextBox actb)
+ {
+ _actb = actb;
+ }
+
+ #endregion
+
+ #region "Methods"
+
+ public void GetSuggestions(string searchText)
+ {
+ _filter = searchText;
+ _actb.IsLoading = true;
+ // Do not open drop down if control is not focused
+ if (_actb.IsKeyboardFocusWithin)
+ _actb.IsDropDownOpen = true;
+ _actb.ItemsSelector.ItemsSource = null;
+ ParameterizedThreadStart thInfo = GetSuggestionsAsync;
+ Thread th = new Thread(thInfo);
+ th.Start(new object[] { searchText, _actb.Provider });
+ }
+
+ private void DisplaySuggestions(IEnumerable suggestions, string filter)
+ {
+ if (_filter != filter)
+ {
+ return;
+ }
+ _actb.IsLoading = false;
+ _actb.ItemsSelector.ItemsSource = suggestions;
+ // Close drop down if there are no items
+ if (_actb.IsDropDownOpen)
+ {
+ _actb.IsDropDownOpen = _actb.ItemsSelector.HasItems;
+ }
+ }
+
+ private void GetSuggestionsAsync(object param)
+ {
+ if (param is object[] args)
+ {
+ string searchText = Convert.ToString(args[0]);
+ if (args[1] is ISuggestionProvider provider)
+ {
+ IEnumerable list = provider.GetSuggestions(searchText);
+ _actb.Dispatcher.BeginInvoke(new Action(DisplaySuggestions), DispatcherPriority.Background, list, searchText);
+ }
+ }
+ }
+
+ #endregion
+
+ }
+
+ #endregion
+
+ }
+
+}
diff --git a/AutoCompleteTextBox/Editors/IComboSuggestionProvider.cs b/AutoCompleteTextBox/Editors/IComboSuggestionProvider.cs
new file mode 100644
index 0000000..ca95d08
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/IComboSuggestionProvider.cs
@@ -0,0 +1,16 @@
+using System.Collections;
+
+
+namespace AutoCompleteTextBox.Editors
+{
+ public interface IComboSuggestionProvider
+ {
+
+ #region Public Methods
+
+ IEnumerable GetSuggestions(string filter);
+ IEnumerable GetFullCollection();
+
+ #endregion Public Methods
+ }
+}
diff --git a/AutoCompleteTextBox/Editors/ISuggestionProvider.cs b/AutoCompleteTextBox/Editors/ISuggestionProvider.cs
new file mode 100644
index 0000000..7887021
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/ISuggestionProvider.cs
@@ -0,0 +1,15 @@
+using System.Collections;
+
+namespace AutoCompleteTextBox.Editors
+{
+ public interface ISuggestionProvider
+ {
+
+ #region Public Methods
+
+ IEnumerable GetSuggestions(string filter);
+
+ #endregion Public Methods
+
+ }
+}
diff --git a/AutoCompleteTextBox/Editors/SelectionAdapter.cs b/AutoCompleteTextBox/Editors/SelectionAdapter.cs
new file mode 100644
index 0000000..a95f0fc
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/SelectionAdapter.cs
@@ -0,0 +1,122 @@
+using System.Diagnostics;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+
+namespace AutoCompleteTextBox.Editors
+{
+ public class SelectionAdapter
+ {
+ public class PreSelectionAdapterFinishArgs {
+ public EventCause cause;
+ public bool is_cancel;
+ public bool handled;
+ }
+
+ #region "Fields"
+ #endregion
+
+ #region "Constructors"
+
+ public SelectionAdapter(Selector selector)
+ {
+ SelectorControl = selector;
+ SelectorControl.PreviewMouseUp += OnSelectorMouseDown;
+ }
+
+ #endregion
+
+ #region "Events"
+
+ public enum EventCause { Other, PopupClosed, ItemClicked, EnterPressed, EscapePressed, TabPressed, MouseDown}
+ public delegate void CancelEventHandler(EventCause cause);
+
+ public delegate void CommitEventHandler(EventCause cause);
+
+ public delegate void SelectionChangedEventHandler();
+
+ public event CancelEventHandler Cancel;
+ public event CommitEventHandler Commit;
+ public event SelectionChangedEventHandler SelectionChanged;
+ #endregion
+
+ #region "Properties"
+
+ public Selector SelectorControl { get; set; }
+
+ #endregion
+
+ #region "Methods"
+
+ public void HandleKeyDown(KeyEventArgs key)
+ {
+ switch (key.Key)
+ {
+ case Key.Down:
+ IncrementSelection();
+ break;
+ case Key.Up:
+ DecrementSelection();
+ break;
+ case Key.Enter:
+ Commit?.Invoke(EventCause.EnterPressed);
+
+ break;
+ case Key.Escape:
+ Cancel?.Invoke(EventCause.EscapePressed);
+
+ break;
+ case Key.Tab:
+ Commit?.Invoke(EventCause.TabPressed);
+
+ break;
+ default:
+ return;
+ }
+ key.Handled = true;
+ }
+
+ private void DecrementSelection()
+ {
+ if (SelectorControl.SelectedIndex == -1)
+ {
+ SelectorControl.SelectedIndex = SelectorControl.Items.Count - 1;
+ }
+ else
+ {
+ SelectorControl.SelectedIndex -= 1;
+ }
+
+ SelectionChanged?.Invoke();
+ }
+
+ private void IncrementSelection()
+ {
+ if (SelectorControl.SelectedIndex == SelectorControl.Items.Count - 1)
+ {
+ SelectorControl.SelectedIndex = -1;
+ }
+ else
+ {
+ SelectorControl.SelectedIndex += 1;
+ }
+
+ SelectionChanged?.Invoke();
+ }
+
+ private void OnSelectorMouseDown(object sender, MouseButtonEventArgs e)
+ {
+ // If sender is the RepeatButton from the scrollbar we need to
+ // to skip this event otherwise focus get stuck in the RepeatButton
+ // and list is scrolled up or down til the end.
+ if (e.OriginalSource.GetType() != typeof(RepeatButton))
+ {
+ Commit?.Invoke(EventCause.MouseDown);
+ e.Handled = true;
+ }
+ }
+
+ #endregion
+
+ }
+
+}
\ No newline at end of file
diff --git a/AutoCompleteTextBox/Editors/SuggestionProvider.cs b/AutoCompleteTextBox/Editors/SuggestionProvider.cs
new file mode 100644
index 0000000..b63234f
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/SuggestionProvider.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections;
+
+namespace AutoCompleteTextBox.Editors
+{
+ public class SuggestionProvider : ISuggestionProvider
+ {
+
+
+ #region Private Fields
+
+ private readonly Func _method;
+
+ #endregion Private Fields
+
+ #region Public Constructors
+
+ public SuggestionProvider(Func method)
+ {
+ _method = method ?? throw new ArgumentNullException(nameof(method));
+ }
+
+ #endregion Public Constructors
+
+ #region Public Methods
+
+ public IEnumerable GetSuggestions(string filter)
+ {
+ return _method(filter);
+ }
+
+ #endregion Public Methods
+
+ }
+}
\ No newline at end of file
diff --git a/AutoCompleteTextBox/Editors/Themes/Generic.xaml b/AutoCompleteTextBox/Editors/Themes/Generic.xaml
new file mode 100644
index 0000000..fe4d0f3
--- /dev/null
+++ b/AutoCompleteTextBox/Editors/Themes/Generic.xaml
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoCompleteTextBox/Enumerations.cs b/AutoCompleteTextBox/Enumerations.cs
new file mode 100644
index 0000000..d5c0e1a
--- /dev/null
+++ b/AutoCompleteTextBox/Enumerations.cs
@@ -0,0 +1,8 @@
+namespace AutoCompleteTextBox
+{
+ public enum IconPlacement
+ {
+ Left,
+ Right
+ }
+}
\ No newline at end of file
diff --git a/AutoCompleteTextBox/Properties/AssemblyInfo.cs b/AutoCompleteTextBox/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..93c0d2c
--- /dev/null
+++ b/AutoCompleteTextBox/Properties/AssemblyInfo.cs
@@ -0,0 +1,53 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Markup;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AutoCompleteTextBox")]
+[assembly: AssemblyDescription("An autocomplete textbox for WPF")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AutoCompleteTextBox")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly:ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.1.1.0")]
+[assembly: AssemblyFileVersion("1.1.1.0")]
+[assembly: XmlnsDefinition("http://wpfcontrols.com/", "AutoCompleteTextBox")]
+[assembly: XmlnsDefinition("http://wpfcontrols.com/", "AutoCompleteTextBox.Editors")]
diff --git a/AutoCompleteTextBox/Properties/Resources.Designer.cs b/AutoCompleteTextBox/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..2d4da73
--- /dev/null
+++ b/AutoCompleteTextBox/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AutoCompleteTextBox.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoCompleteTextBox.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/AutoCompleteTextBox/Properties/Resources.resx b/AutoCompleteTextBox/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/AutoCompleteTextBox/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/AutoCompleteTextBox/Properties/Settings.Designer.cs b/AutoCompleteTextBox/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..5bc23d8
--- /dev/null
+++ b/AutoCompleteTextBox/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AutoCompleteTextBox.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/AutoCompleteTextBox/Properties/Settings.settings b/AutoCompleteTextBox/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/AutoCompleteTextBox/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AutoCompleteTextBox/Themes/Generic.xaml b/AutoCompleteTextBox/Themes/Generic.xaml
new file mode 100644
index 0000000..173cb11
--- /dev/null
+++ b/AutoCompleteTextBox/Themes/Generic.xaml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/Config.Net/Stores/JsonConfigStore.cs b/Config.Net/Stores/JsonConfigStore.cs
index 1859ec3..adb9326 100644
--- a/Config.Net/Stores/JsonConfigStore.cs
+++ b/Config.Net/Stores/JsonConfigStore.cs
@@ -43,7 +43,7 @@ namespace Config.Net.Stores
// nothing to dispose.
}
- public string Name => "json";
+ public static string Name => "json";
public bool CanRead => true;
@@ -70,7 +70,7 @@ namespace Config.Net.Stores
if (isIndex)
{
- if (!(node is JsonArray ja)) return null;
+ if (node is not JsonArray ja) return null;
if (partIndex < ja.Count)
{
@@ -132,7 +132,7 @@ namespace Config.Net.Stores
string js = _j.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
- FileInfo file = new FileInfo(_pathName);
+ FileInfo file = new(_pathName);
if (file is not null)
{
diff --git a/FSI.BT.Tools.sln b/FSI.BT.Tools.sln
index 8a3d777..fb92665 100644
--- a/FSI.BT.Tools.sln
+++ b/FSI.BT.Tools.sln
@@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoboSharp", "RoboSharp\Robo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Config.Net", "Config.Net\Config.Net.csproj", "{D5C7AFF9-2226-4CC4-87F6-6303DB60FEA0}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoCompleteTextBox", "AutoCompleteTextBox\AutoCompleteTextBox.csproj", "{3162765C-B702-4927-8276-833E9046716D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -51,6 +53,10 @@ Global
{D5C7AFF9-2226-4CC4-87F6-6303DB60FEA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5C7AFF9-2226-4CC4-87F6-6303DB60FEA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5C7AFF9-2226-4CC4-87F6-6303DB60FEA0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3162765C-B702-4927-8276-833E9046716D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3162765C-B702-4927-8276-833E9046716D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3162765C-B702-4927-8276-833E9046716D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3162765C-B702-4927-8276-833E9046716D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/FSI.BT.Tools/App.xaml.cs b/FSI.BT.Tools/App.xaml.cs
index cb7e4d5..b34617d 100644
--- a/FSI.BT.Tools/App.xaml.cs
+++ b/FSI.BT.Tools/App.xaml.cs
@@ -1,15 +1,13 @@
-using Hardcodet.Wpf.TaskbarNotification;
+using Config.Net;
+using Config.Net.Stores;
+using Hardcodet.Wpf.TaskbarNotification;
using NHotkey;
using NHotkey.Wpf;
+using System.IO;
+using System.IO.Compression;
+using System.Reflection;
using System.Windows;
using System.Windows.Input;
-using FSI.Lib.CompareNetObjects;
-using Config.Net.Stores;
-using System.IO;
-using Config.Net;
-using System.Collections.Generic;
-using System.Linq;
-using System;
namespace FSI.BT.Tools
{
@@ -23,11 +21,14 @@ namespace FSI.BT.Tools
public void Application_Startup(object sender, StartupEventArgs e)
- {
+ {
+
Global.Log.Info("Anwendung wurde gestartet!");
+ ExtractEmbeddedZip("FSI.BT.Tools.ExtTools.kalk.zip", Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\ExtTools\\");
+
// App-Settings
- JsonConfigStore _store = new JsonConfigStore(System.IO.Path.Combine(Directory.GetCurrentDirectory(), "config.json"), true);
+ JsonConfigStore _store = new(System.IO.Path.Combine(Directory.GetCurrentDirectory(), "config.json"), true);
Global.AppSettings = new ConfigurationBuilder()
.UseConfigStore(_store)
.Build();
@@ -40,9 +41,9 @@ namespace FSI.BT.Tools
HotkeyManager.Current.AddOrReplace("RadialMenu", RadialMenu, ShowRadialMenu);
HotkeyManager.Current.AddOrReplace("TimeStampToClipboard", TimeStamp, TimeStampToClipboard);
-
+
Global.FrmRadialMenu = new FrmRadialMenu();
-
+
Global.WinCC = new Lib.Guis.SieTiaWinCCMsgMgt.ViewModel()
{
Data = Global.AppSettings.WinCC
@@ -54,7 +55,6 @@ namespace FSI.BT.Tools
Data = Global.AppSettings.IbaDirSync
};
Global.Iba.Init();
-
}
private void ShowRadialMenu(object sender, HotkeyEventArgs e)
@@ -75,13 +75,13 @@ namespace FSI.BT.Tools
e.Handled = true;
}
- private void DeCrypt(ref IEnumerable values)
+ private static void ExtractEmbeddedZip(string zipName, string destPath)
{
- var valuesToDeCrypt = values.ToList();
-
- foreach (var value in valuesToDeCrypt.ToList())
- value.ValueDeCrypt = Lib.DeEncryptString.DeEncrypt.DecryptString(value.Value, AppDomain.CurrentDomain.FriendlyName);
-
+ System.IO.Directory.CreateDirectory(destPath); // Erstellt alle fehlenden Verzeichnisse
+ using Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(zipName);
+ using ZipArchive zip = new(_pluginZipResourceStream);
+ zip.ExtractToDirectory(destPath, true);
+ Global.Log.Info("Externes Tool \"{0}\" wurde in das Verzeichnis \"{1}\" entpackt", zipName, destPath);
}
private void Application_Exit(object sender, ExitEventArgs e)
@@ -94,5 +94,6 @@ namespace FSI.BT.Tools
}
}
+
}
}
\ No newline at end of file
diff --git a/FSI.BT.Tools/Commands/CmdCommand.cs b/FSI.BT.Tools/Commands/CmdCommand.cs
index d7964b1..5fb03b5 100644
--- a/FSI.BT.Tools/Commands/CmdCommand.cs
+++ b/FSI.BT.Tools/Commands/CmdCommand.cs
@@ -26,26 +26,24 @@ namespace FSI.BT.Tools.Commands
var cmds = Global.AppSettings.Cmds.ToList();
ICmd selectedCmd = null;
- // IEnumerable files = new List();
- IExe selectedFile;
+
switch ((string)parameter)
{
-
- case "EplPrj":
- //selectedFile = GetApp(Global.AppSettings.Apps.Epl);
- //Lib.Guis.Prj.Mgt.FrmMain frmMainEplPrj = new()
- //{
- // ShowPdf = false,
- // CloseAtLostFocus = true,
- // WindowStartupLocation = WindowStartupLocation.CenterScreen,
- // Path = FSI.BT.Tools.Settings.AppSettings.GetFolderByName(Global.AppSettings.Folders, "EplPrj").path,
- // EplExe = selectedFile.ExePath,
- //};
- //frmMainEplPrj.Show();
+
+ case "Epl.Prj":
+ Lib.Guis.Prj.Mgt.FrmMain frmMainEplPrj = new()
+ {
+ ShowPdf = false,
+ CloseAtLostFocus = true,
+ WindowStartupLocation = WindowStartupLocation.CenterScreen,
+ Path = FSI.BT.Tools.Settings.AppSettings.GetFolderByName(Global.AppSettings.Folders, "EplPrj").path,
+ EplExe = GetExeByCmdName("Epl").ExePath,
+ };
+ frmMainEplPrj.Show();
return;
- case "EplPdf":
+ case "Epl.Pdf":
Lib.Guis.Prj.Mgt.FrmMain frmMainEplPdf = new()
{
ShowPdf = true,
@@ -56,7 +54,7 @@ namespace FSI.BT.Tools.Commands
frmMainEplPdf.Show();
return;
- case "EplPdfMgt":
+ case "Epl.PdfMgt":
Lib.Guis.Pdf.Mgt.FrmMain frmMainEplPdfMgt = new()
{
CloseAtLostFocus = true
@@ -96,14 +94,22 @@ namespace FSI.BT.Tools.Commands
};
frmTxtToClipMain.Show();
return;
-
+
+ case "Rdp.Mgt":
+ Lib.Guis.Rdp.Mgt.FrmMain frmRdpMain = new()
+ {
+ CloseAtLostFocus = true,
+ InputData = Global.AppSettings.Rdps,
+ Exe = GetExeByCmdName("Rdp").ExePath,
+ };
+ frmRdpMain.Show();
+ break;
+
default:
foreach (ICmd cmd in cmds)
{
- if (String.Equals(parameter.ToString().ToLower(), cmd.Cmd.ToLower()))
- {
+ if (String.Equals(parameter.ToString(), cmd.Cmd))
selectedCmd = cmd;
- }
}
break;
}
@@ -121,14 +127,14 @@ namespace FSI.BT.Tools.Commands
ICmd selectedCmd = null;
switch ((string)parameter)
- {
- case "EplPrj":
+ {
+ case "Epl.Prj":
return true;
- case "EplPdf":
+ case "Epl.Pdf":
return true;
- case "EplPdfMgt":
+ case "Epl.PdfMgt":
return Global.AdminRights;
case "DeEncrypt":
@@ -143,16 +149,16 @@ namespace FSI.BT.Tools.Commands
case "TxtToClip":
return Global.AppSettings.TxtToClip != null;
+ case "Rdp.Mgt":
+ return Global.AppSettings.Rdps != null;
+
default:
foreach (ICmd cmd in cmds)
{
- if (String.Equals(parameter.ToString().ToLower(), cmd.Cmd.ToLower()))
- {
+ if (String.Equals(parameter.ToString(), cmd.Cmd))
selectedCmd = cmd;
- }
}
- break;
-
+ break;
}
if (selectedCmd == null)
@@ -160,26 +166,24 @@ namespace FSI.BT.Tools.Commands
foreach (var file in selectedCmd.Exe.ToList())
{
+
if (File.Exists(Environment.ExpandEnvironmentVariables(file.ExePath.Trim())))
- {
return true;
- }
+ else if (File.Exists(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), file.ExePath.Trim())))
+ return true;
}
foreach (var url in selectedCmd.Urls)
{
if (url != String.Empty)
- {
return true;
- }
}
return false;
}
-
- private static void OpenExe(ICmd selectedCmd)
- {
+ private static void OpenExe(ICmd selectedCmd)
+ {
IExe selectedFile = GetApp(selectedCmd.Exe);
if (selectedFile == null)
@@ -196,8 +200,8 @@ namespace FSI.BT.Tools.Commands
else
{
Process process = new();
- process.StartInfo.FileName = selectedFile.ExePath;
- process.StartInfo.WorkingDirectory = selectedFile.Path == null ? selectedFile.Path : Path.GetDirectoryName(selectedFile.ExePath);
+ process.StartInfo.FileName = Environment.ExpandEnvironmentVariables(selectedFile.ExePath);
+ process.StartInfo.WorkingDirectory = selectedFile.Path ?? Path.GetDirectoryName(Environment.ExpandEnvironmentVariables(selectedFile.ExePath));
process.StartInfo.Arguments = selectedFile.Arguments;
try
@@ -237,7 +241,20 @@ namespace FSI.BT.Tools.Commands
Thread.Sleep(100);
}
}
-
+
+ private static IExe GetExeByCmdName(string cmdName)
+ {
+ foreach (var cmd in Global.AppSettings.Cmds)
+ {
+ if (string.Equals(cmd.Cmd, cmdName, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return GetApp(cmd.Exe);
+ }
+ }
+
+ return null;
+ }
+
private static bool ProgramIsRunning(string FullPath)
{
string FilePath = Path.GetDirectoryName(FullPath);
@@ -260,7 +277,7 @@ namespace FSI.BT.Tools.Commands
private static IExe GetApp(IEnumerable files)
{
- if(files.ToList().Count == 0)
+ if (files.ToList().Count == 0)
return null;
var selectedFile = files.ToList()[0];
diff --git a/FSI.BT.Tools/ExtTools/kalk.zip b/FSI.BT.Tools/ExtTools/kalk.zip
new file mode 100644
index 0000000..bcc31d6
Binary files /dev/null and b/FSI.BT.Tools/ExtTools/kalk.zip differ
diff --git a/FSI.BT.Tools/FSI.BT.Tools.csproj b/FSI.BT.Tools/FSI.BT.Tools.csproj
index 774aaa7..9fc8407 100644
--- a/FSI.BT.Tools/FSI.BT.Tools.csproj
+++ b/FSI.BT.Tools/FSI.BT.Tools.csproj
@@ -1,22 +1,35 @@
-
+
net6.0-windows
- WinExe
+ WinExe
true
true
Icons\FondiumU.ico
2.0
+ 2.0
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -59,10 +72,24 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -73,7 +100,7 @@
- Never
+ Never
@@ -109,6 +136,7 @@
+
@@ -116,14 +144,19 @@
-
- Always
-
-
- Always
-
+
+ Always
+
+
+ Always
+
-
+
+
+
+
+
+
diff --git a/FSI.BT.Tools/FrmRadialMenu.xaml b/FSI.BT.Tools/FrmRadialMenu.xaml
index d00d865..189c215 100644
--- a/FSI.BT.Tools/FrmRadialMenu.xaml
+++ b/FSI.BT.Tools/FrmRadialMenu.xaml
@@ -1,14 +1,18 @@
@@ -39,6 +43,7 @@
FontSize="10" />
+
@@ -207,7 +212,7 @@
+ CommandParameter="Epl.Prj">
@@ -223,7 +228,7 @@
+ CommandParameter="Epl.Pdf">
@@ -239,7 +244,7 @@
+ CommandParameter="Epl.PdfMgt">
@@ -728,7 +733,7 @@
+ CommandParameter="PL1.Pls">
@@ -744,7 +749,7 @@
+ CommandParameter="PL1.Lst">
@@ -775,7 +780,7 @@
+ CommandParameter="PL2.Alg">
@@ -792,7 +797,7 @@
+ CommandParameter="PL2.Pls">
@@ -808,7 +813,7 @@
+ CommandParameter="PL2.Als">
@@ -824,7 +829,7 @@
+ CommandParameter="PL2.Lst">
@@ -840,7 +845,7 @@
+ CommandParameter="PL2.Nc">
@@ -856,7 +861,7 @@
+ CommandParameter="PL2.Key">
@@ -887,7 +892,7 @@
+ CommandParameter="PL3.Pls">
@@ -903,7 +908,7 @@
+ CommandParameter="PL3.Lst">
@@ -1109,19 +1114,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ Canvas.Bottom="0"
+ Canvas.Left="50">
-
+
+
diff --git a/FSI.BT.Tools/FrmRadialMenu.xaml.cs b/FSI.BT.Tools/FrmRadialMenu.xaml.cs
index 2bd562c..06b6269 100644
--- a/FSI.BT.Tools/FrmRadialMenu.xaml.cs
+++ b/FSI.BT.Tools/FrmRadialMenu.xaml.cs
@@ -1,429 +1,128 @@
-using FSI.BT.Tools.Commands;
+using AutoCompleteTextBox.Editors;
+using FSI.BT.Tools.Commands;
using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
+using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
+using System.Windows.Media.Imaging;
namespace FSI.BT.Tools
{
///
/// Interaction logic for MainWindow.xaml
///
- public partial class FrmRadialMenu : Window, INotifyPropertyChanged
+ public partial class FrmRadialMenu : Window//, INotifyPropertyChanged
{
private CmdCommand _cmd;
-
+
public FrmRadialMenu()
{
InitializeComponent();
- DataContext = this;
- _isOpenHome = true;
+
+ List cmds = new List();
+ foreach(var cmd in Global.AppSettings.Cmds)
+ {
+ cmds.Add(cmd.Cmd);
+ }
+ DataContext = new RadialMenu.MainViewModel(this, cmds);
+
tbversion.Text = "v" + Assembly.GetExecutingAssembly().GetName().Version.Major + "." + Assembly.GetExecutingAssembly().GetName().Version.Minor + "b";
- _cmd = new ();
+ _cmd = new();
}
- #region Home
- private bool _isOpenHome = true;
- public bool IsOpenHome
+ private void Window_Activated(object sender, EventArgs e)
{
- get
- {
- return _isOpenHome;
- }
- set
- {
- _isOpenHome = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand CloseRadialMenuHome
- {
- get
- {
- return new RelayCommand(() => Visibility = Visibility.Hidden);
- }
- }
-
- public ICommand OpenRadialMenuHome
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenHome = true;
- IsOpenEpl =
- IsOpenTools =
- IsOpenSie =
- IsOpenApps =
- IsOpenPlantLinksPl1 =
- IsOpenPlantLinksPl2 =
- IsOpenPlantLinksPl3 =
- IsOpenAppsVncRdp =
- IsOpenLinks = false;
- });
- }
- }
- #endregion
-
- #region Epl
-
- private bool _isOpenEpl = false;
- public bool IsOpenEpl
- {
- get
- {
- return _isOpenEpl;
- }
- set
- {
- _isOpenEpl = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuEpl
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenEpl = true;
- IsOpenHome = false;
- });
- }
- }
-
- #endregion
-
- #region Tools
-
- private bool _isOpenTools = false;
- public bool IsOpenTools
- {
- get
- {
- return _isOpenTools;
- }
- set
- {
- _isOpenTools = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuTools
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenTools = true;
- IsOpenHome = false;
- });
- }
- }
-
- #endregion
-
- #region Siemens
-
- private bool _isOpenSie = false;
- public bool IsOpenSie
- {
- get
- {
- return _isOpenSie;
- }
- set
- {
- _isOpenSie = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuSie
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenSie = true;
- IsOpenHome = false;
- });
- }
- }
-
- #endregion
-
- #region Links
-
- private bool _isOpenLinks = false;
- public bool IsOpenLinks
- {
- get
- {
- return _isOpenLinks;
- }
- set
- {
- _isOpenLinks = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuLinks
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenLinks = true;
- IsOpenPlantLinks =
- IsOpenHome = false;
- });
- }
- }
-
- #endregion
-
- #region Anlagen Links
-
- private bool _isOpenPlantLinks = false;
- public bool IsOpenPlantLinks
- {
- get
- {
- return _isOpenPlantLinks;
- }
- set
- {
- _isOpenPlantLinks = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuPlantLinks
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenPlantLinks = true;
- IsOpenPlantLinksPl1 =
- IsOpenPlantLinksPl2 =
- IsOpenPlantLinksPl3 =
- IsOpenLinks = false;
- });
- }
- }
-
- #endregion
-
- #region Anlagen Links Pl1
-
- private bool _isOpenPlantLinksPl1 = false;
- public bool IsOpenPlantLinksPl1
- {
- get
- {
- return _isOpenPlantLinksPl1;
- }
- set
- {
- _isOpenPlantLinksPl1 = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuPlantLinksPl1
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenPlantLinksPl1 = true;
- IsOpenPlantLinks = false;
-
- });
- }
- }
-
- #endregion
-
- #region Anlagen Links Pl2
-
- private bool _isOpenPlantLinksPl2 = false;
- public bool IsOpenPlantLinksPl2
- {
- get
- {
- return _isOpenPlantLinksPl2;
- }
- set
- {
- _isOpenPlantLinksPl2 = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuPlantLinksPl2
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenPlantLinksPl2 = true;
- IsOpenPlantLinks = false;
-
- });
- }
- }
-
- #endregion
-
- #region Anlagen Links Pl3
-
- private bool _isOpenPlantLinksPl3 = false;
- public bool IsOpenPlantLinksPl3
- {
- get
- {
- return _isOpenPlantLinksPl3;
- }
- set
- {
- _isOpenPlantLinksPl3 = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuPlantLinksPl3
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenPlantLinksPl3 = true;
- IsOpenPlantLinks = false;
-
- });
- }
- }
-
- #endregion
-
- #region Apps
-
- private bool _isOpenApps = false;
- public bool IsOpenApps
- {
- get
- {
- return _isOpenApps;
- }
- set
- {
- _isOpenApps = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuApps
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenApps = true;
- IsOpenAppsVncRdp =
- IsOpenHome = false;
- });
- }
- }
-
- #endregion
-
- #region Apps RDP VNC
-
- private bool _isOpenAppsVncRdp = false;
- public bool IsOpenAppsVncRdp
- {
- get
- {
- return _isOpenAppsVncRdp;
- }
- set
- {
- _isOpenAppsVncRdp = value;
- RaisePropertyChanged();
- }
- }
-
- public ICommand OpenRadialMenuAppsVncRdp
- {
- get
- {
- return new RelayCommand(() =>
- {
- IsOpenAppsVncRdp = true;
- IsOpenApps = false;
- });
- }
- }
-
- #endregion
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- void RaisePropertyChanged([CallerMemberName] string propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ tbCmd.Focus();
+
+ ChangeBtnIcon();
}
private void Window_Deactivated(object sender, EventArgs e)
{
tbCmd.Text = String.Empty;
- tbCmd.Focus();
- Visibility = Visibility.Hidden;
-
- IsOpenHome = true;
- IsOpenEpl =
- IsOpenTools =
- IsOpenSie =
- IsOpenLinks =
- IsOpenApps =
- IsOpenPlantLinksPl1 =
- IsOpenPlantLinksPl2 =
- IsOpenPlantLinksPl3 =
- IsOpenAppsVncRdp =
- IsOpenPlantLinks = false;
+ tbCmd.Focus();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
- tbCmd.Focus();
+ ChangeBtnIcon();
+
+ tbCmd.Focus();
}
private void tbCmd_KeyDown(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Enter && _cmd.CanExecute(((TextBox)sender).Text))
- {
- _cmd.Execute(((TextBox)sender).Text);
- }
+ {
+ if (e.Key == Key.Enter && _cmd.CanExecute(tbCmd.Text))
+ {
+ _cmd.Execute(tbCmd.Text);
+ }
}
private void tbCmd_TextChanged(object sender, TextChangedEventArgs e)
{
if (_cmd.CanExecute(((TextBox)sender).Text))
- ((TextBox)sender).Background = new SolidColorBrush(Colors.Green);
+ ((TextBox)sender).Background = new SolidColorBrush(Colors.Green);
else
((TextBox)sender).Background = new SolidColorBrush(Colors.White);
}
+
+ private void btnMute_Click(object sender, RoutedEventArgs e)
+ {
+ Lib.Audio.AudioManager.SetMasterVolumeMute(!Lib.Audio.AudioManager.GetMasterVolumeMute());
+ ChangeBtnIcon();
+ }
+
+ private void btnVolUp_Click(object sender, RoutedEventArgs e)
+ {
+ Lib.Audio.AudioManager.StepMasterVolume(2F);
+ }
+
+ private void btnVolDwn_Click(object sender, RoutedEventArgs e)
+ {
+ Lib.Audio.AudioManager.StepMasterVolume(-2F);
+ }
+
+ private void ChangeBtnIcon()
+ {
+ if (FSI.Lib.Audio.AudioManager.GetMasterVolumeMute())
+ {
+ btnMute.Content = new System.Windows.Controls.Image
+ {
+ Source = new BitmapImage(new Uri("../../Icons/VolOff.png", UriKind.RelativeOrAbsolute)),
+ Width = 15,
+ };
+ }
+ else
+ {
+ btnMute.Content = new System.Windows.Controls.Image
+ {
+ Source = new BitmapImage(new Uri("../../Icons/VolOn.png", UriKind.RelativeOrAbsolute)),
+ Width = 15,
+ };
+ }
+
+ btnVolUp.Content = new System.Windows.Controls.Image
+ {
+ Source = new BitmapImage(new Uri("../../Icons/VolUp.png", UriKind.RelativeOrAbsolute)),
+ Width = 15,
+ };
+
+ btnVolDwn.Content = new System.Windows.Controls.Image
+ {
+ Source = new BitmapImage(new Uri("../../Icons/VolDown.png", UriKind.RelativeOrAbsolute)),
+ Width = 15,
+ };
+ }
}
+
+
}
diff --git a/FSI.BT.Tools/Icons/VolDown.png b/FSI.BT.Tools/Icons/VolDown.png
new file mode 100644
index 0000000..e1924f9
Binary files /dev/null and b/FSI.BT.Tools/Icons/VolDown.png differ
diff --git a/FSI.BT.Tools/Icons/VolOff.png b/FSI.BT.Tools/Icons/VolOff.png
new file mode 100644
index 0000000..934cebe
Binary files /dev/null and b/FSI.BT.Tools/Icons/VolOff.png differ
diff --git a/FSI.BT.Tools/Icons/VolOn.png b/FSI.BT.Tools/Icons/VolOn.png
new file mode 100644
index 0000000..611bc45
Binary files /dev/null and b/FSI.BT.Tools/Icons/VolOn.png differ
diff --git a/FSI.BT.Tools/Icons/VolUp.png b/FSI.BT.Tools/Icons/VolUp.png
new file mode 100644
index 0000000..a3f5a6b
Binary files /dev/null and b/FSI.BT.Tools/Icons/VolUp.png differ
diff --git a/FSI.BT.Tools/RadialMenu/CmdProvider.cs b/FSI.BT.Tools/RadialMenu/CmdProvider.cs
new file mode 100644
index 0000000..59ecc3d
--- /dev/null
+++ b/FSI.BT.Tools/RadialMenu/CmdProvider.cs
@@ -0,0 +1,26 @@
+using AutoCompleteTextBox.Editors;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FSI.BT.Tools.RadialMenu
+{
+ public class CmdProvider : ISuggestionProvider
+ {
+ private readonly ObservableCollection _cmds;
+
+ public IEnumerable GetSuggestions(string filter)
+ {
+ return _cmds.Where(x => x.StartsWith(filter, StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ public CmdProvider(ref ObservableCollection cmds)
+ {
+ this._cmds = cmds;
+ }
+ }
+}
diff --git a/FSI.BT.Tools/RadialMenu/MainViewModel.cs b/FSI.BT.Tools/RadialMenu/MainViewModel.cs
new file mode 100644
index 0000000..8bf50fe
--- /dev/null
+++ b/FSI.BT.Tools/RadialMenu/MainViewModel.cs
@@ -0,0 +1,442 @@
+using FSI.Lib.MVVM;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Windows;
+using System.Windows.Input;
+
+namespace FSI.BT.Tools.RadialMenu
+{
+ public class MainViewModel : ViewModelBase
+ {
+ public MainViewModel(Window win, List cmds)
+ {
+ _window = win;
+ _window.Deactivated += _window_Deactivated;
+ _isOpenHome = true;
+
+ Cmds = new();
+
+ if (cmds != null)
+ {
+ foreach (string cmd in cmds)
+ Cmds.Add(cmd);
+ }
+
+ Cmds.Add("Rdp.Mgt");
+ Provider = new(ref _cmds);
+ }
+
+
+ private ObservableCollection _cmds;
+
+ public ObservableCollection Cmds
+ {
+ get { return _cmds; }
+ set
+ {
+ _cmds = value;
+ OnPropertyChanged();
+ }
+ }
+
+ private CmdProvider _cmdProvider;
+
+ public CmdProvider Provider
+ {
+ get { return _cmdProvider; }
+ set { _cmdProvider = value; }
+ }
+
+
+ private string _cmd;
+
+ public string Cmd
+ {
+ get { return _cmd; }
+ set
+ {
+ _cmd = value;
+ OnPropertyChanged();
+ }
+ }
+
+
+ private Window _window;
+
+ public Window Window
+ {
+ get { return _window; }
+ set { _window = value; }
+ }
+
+ #region Home
+ private bool _isOpenHome = true;
+ public bool IsOpenHome
+ {
+ get
+ {
+ return _isOpenHome;
+ }
+ set
+ {
+ _isOpenHome = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand CloseRadialMenuHome
+ {
+ get
+ {
+ return new RelayCommand(() => _window.Visibility = Visibility.Hidden);
+ }
+ }
+
+ public ICommand OpenRadialMenuHome
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenHome = true;
+ IsOpenEpl =
+ IsOpenTools =
+ IsOpenSie =
+ IsOpenApps =
+ IsOpenPlantLinksPl1 =
+ IsOpenPlantLinksPl2 =
+ IsOpenPlantLinksPl3 =
+ IsOpenAppsVncRdp =
+ IsOpenLinks = false;
+ });
+ }
+ }
+ #endregion
+
+ #region Epl
+
+ private bool _isOpenEpl = false;
+ public bool IsOpenEpl
+ {
+ get
+ {
+ return _isOpenEpl;
+ }
+ set
+ {
+ _isOpenEpl = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuEpl
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenEpl = true;
+ IsOpenHome = false;
+ });
+ }
+ }
+
+ #endregion
+
+ #region Tools
+
+ private bool _isOpenTools = false;
+ public bool IsOpenTools
+ {
+ get
+ {
+ return _isOpenTools;
+ }
+ set
+ {
+ _isOpenTools = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuTools
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenTools = true;
+ IsOpenHome = false;
+ });
+ }
+ }
+
+ #endregion
+
+ #region Siemens
+
+ private bool _isOpenSie = false;
+ public bool IsOpenSie
+ {
+ get
+ {
+ return _isOpenSie;
+ }
+ set
+ {
+ _isOpenSie = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuSie
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenSie = true;
+ IsOpenHome = false;
+ });
+ }
+ }
+
+ #endregion
+
+ #region Links
+
+ private bool _isOpenLinks = false;
+ public bool IsOpenLinks
+ {
+ get
+ {
+ return _isOpenLinks;
+ }
+ set
+ {
+ _isOpenLinks = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuLinks
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenLinks = true;
+ IsOpenPlantLinks =
+ IsOpenHome = false;
+ });
+ }
+ }
+
+ #endregion
+
+ #region Anlagen Links
+
+ private bool _isOpenPlantLinks = false;
+ public bool IsOpenPlantLinks
+ {
+ get
+ {
+ return _isOpenPlantLinks;
+ }
+ set
+ {
+ _isOpenPlantLinks = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuPlantLinks
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenPlantLinks = true;
+ IsOpenPlantLinksPl1 =
+ IsOpenPlantLinksPl2 =
+ IsOpenPlantLinksPl3 =
+ IsOpenLinks = false;
+ });
+ }
+ }
+
+ #endregion
+
+ #region Anlagen Links Pl1
+
+ private bool _isOpenPlantLinksPl1 = false;
+ public bool IsOpenPlantLinksPl1
+ {
+ get
+ {
+ return _isOpenPlantLinksPl1;
+ }
+ set
+ {
+ _isOpenPlantLinksPl1 = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuPlantLinksPl1
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenPlantLinksPl1 = true;
+ IsOpenPlantLinks = false;
+
+ });
+ }
+ }
+
+ #endregion
+
+ #region Anlagen Links Pl2
+
+ private bool _isOpenPlantLinksPl2 = false;
+ public bool IsOpenPlantLinksPl2
+ {
+ get
+ {
+ return _isOpenPlantLinksPl2;
+ }
+ set
+ {
+ _isOpenPlantLinksPl2 = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuPlantLinksPl2
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenPlantLinksPl2 = true;
+ IsOpenPlantLinks = false;
+
+ });
+ }
+ }
+
+ #endregion
+
+ #region Anlagen Links Pl3
+
+ private bool _isOpenPlantLinksPl3 = false;
+ public bool IsOpenPlantLinksPl3
+ {
+ get
+ {
+ return _isOpenPlantLinksPl3;
+ }
+ set
+ {
+ _isOpenPlantLinksPl3 = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuPlantLinksPl3
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenPlantLinksPl3 = true;
+ IsOpenPlantLinks = false;
+
+ });
+ }
+ }
+
+ #endregion
+
+ #region Apps
+
+ private bool _isOpenApps = false;
+ public bool IsOpenApps
+ {
+ get
+ {
+ return _isOpenApps;
+ }
+ set
+ {
+ _isOpenApps = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuApps
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenApps = true;
+ IsOpenAppsVncRdp =
+ IsOpenHome = false;
+ });
+ }
+ }
+
+ #endregion
+
+ #region Apps RDP VNC
+
+ private bool _isOpenAppsVncRdp = false;
+ public bool IsOpenAppsVncRdp
+ {
+ get
+ {
+ return _isOpenAppsVncRdp;
+ }
+ set
+ {
+ _isOpenAppsVncRdp = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public ICommand OpenRadialMenuAppsVncRdp
+ {
+ get
+ {
+ return new RelayCommand(() =>
+ {
+ IsOpenAppsVncRdp = true;
+ IsOpenApps = false;
+ });
+ }
+ }
+
+ #endregion
+
+ private void _window_Deactivated(object sender, EventArgs e)
+ {
+ _window.Visibility = Visibility.Hidden;
+
+ IsOpenHome = true;
+ IsOpenEpl =
+ IsOpenTools =
+ IsOpenSie =
+ IsOpenLinks =
+ IsOpenApps =
+ IsOpenPlantLinksPl1 =
+ IsOpenPlantLinksPl2 =
+ IsOpenPlantLinksPl3 =
+ IsOpenAppsVncRdp =
+ IsOpenPlantLinks = false;
+ }
+ }
+}
diff --git a/FSI.BT.Tools/ResourceManager.cs b/FSI.BT.Tools/ResourceManager.cs
new file mode 100644
index 0000000..45b2b9b
--- /dev/null
+++ b/FSI.BT.Tools/ResourceManager.cs
@@ -0,0 +1,6 @@
+namespace FSI.BT.Tools
+{
+ internal class ResourceManager
+ {
+ }
+}
\ No newline at end of file
diff --git a/FSI.BT.Tools/Settings/IAppSettings.cs b/FSI.BT.Tools/Settings/IAppSettings.cs
index 0cd0ce7..f602083 100644
--- a/FSI.BT.Tools/Settings/IAppSettings.cs
+++ b/FSI.BT.Tools/Settings/IAppSettings.cs
@@ -20,6 +20,7 @@ namespace FSI.BT.Tools.Settings
IEnumerable Folders { get; }
IEnumerable TxtToClip { get; }
+ IEnumerable Rdps { get; }
Lib.Guis.SieTiaWinCCMsgMgt.IInterface WinCC { get; set; }
diff --git a/FSI.BT.Tools/Settings/RdpMgt.cs b/FSI.BT.Tools/Settings/RdpMgt.cs
new file mode 100644
index 0000000..76f1ae9
--- /dev/null
+++ b/FSI.BT.Tools/Settings/RdpMgt.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FSI.BT.Tools.Settings
+{
+ public class RdpMgt
+ {
+ public interface IRdp : Lib.Guis.Rdp.Mgt.IInterface { }
+ }
+}
diff --git a/FSI.BT.Tools/config.json b/FSI.BT.Tools/config.json
index a7c5794..6f1158c 100644
--- a/FSI.BT.Tools/config.json
+++ b/FSI.BT.Tools/config.json
@@ -277,49 +277,49 @@
]
},
{
- "Cmd": "Pl1Pls",
+ "Cmd": "Pl1.Pls",
"Urls": [
"http://10.10.200.2/SKPL1Web/index.aspx"
]
},
{
- "Cmd": "Pl1Lst",
+ "Cmd": "Pl1.Lst",
"Urls": [
"http://desiaugetwf.fondium.org/web/Seiten/Leistungsdaten_FuG.aspx?Fkt=PL1"
]
},
{
- "Cmd": "Pl2Als",
+ "Cmd": "Pl2.Als",
"Urls": [
"http://10.10.213.234:84/emb_1/index.html"
]
},
{
- "Cmd": "Pl2Pls",
+ "Cmd": "Pl2.Pls",
"Urls": [
"http://10.10.213.4/SKPL2Web/index.aspx"
]
},
{
- "Cmd": "Pl2Lst",
+ "Cmd": "Pl2.Lst",
"Urls": [
"http://desiaugetwf/web/Seiten/Leistungsdaten_PL2.aspx"
]
},
{
- "Cmd": "Pl2Nc",
+ "Cmd": "Pl2.Nc",
"Urls": [
"http://10.10.213.4/SKPL2Web/Seiten/Taktzeiten_PopUp.aspx"
]
},
{
- "Cmd": "Pl2Key",
+ "Cmd": "Pl2.Key",
"Urls": [
"http://10.10.213.4/skkeymanager-pl2"
]
},
{
- "Cmd": "Pl2Alg",
+ "Cmd": "Pl2.Alg",
"Urls": [
"http://10.10.213.4/SKPL2Web/index.aspx",
"http://10.10.213.234:84/emb_1/index.html",
@@ -355,6 +355,34 @@
"Urls": [
"https://mingle-portal.eu1.inforcloudsuite.com/FONDIUM_prd"
]
+ },
+ {
+ "Cmd": "Epl.Pdf"
+ },
+ {
+ "Cmd": "Epl.Prj"
+ },
+ {
+ "Cmd": "Rdp.Mgt"
+ },
+ {
+ "Cmd": "Epl.PdfMgt"
+ },
+ {
+ "Cmd": "Calc",
+ "Exe": [
+ {
+ "ExePath": "ExtTools\\kalk\\net6.0\\kalk.exe"
+ }
+ ]
+ },
+ {
+ "Cmd": "Iba.Pda",
+ "Exe": [
+ {
+ "ExePath": "C:\\Program Files (x86)\\iba\\ibaPDA\\Client\\ibaPda.exe"
+ }
+ ]
}
],
"Folders": [
@@ -424,6 +452,20 @@
"Txt": "\\\\fondium.org\\DESI$\\AUG_Abteilung\\Betriebstechnik\\EPL\\P8\\Data\\Projekte\\FSI\\"
}
],
+ "Rdps": [
+ {
+ "Plant": "PL1",
+ "SubPlant": "Alg",
+ "Description": "Programmier PC",
+ "Host": "10.10.200.28"
+ },
+ {
+ "Plant": "Alg",
+ "SubPlant": "Alg",
+ "Description": "Programmier Maier St.",
+ "Host": "10.10.199.92"
+ }
+ ],
"WinCC": {
"AutoStart": false,
"UpdateIntervall": 10,
diff --git a/FSI.Lib/FSI.Lib/Audio/AudioManager.cs b/FSI.Lib/FSI.Lib/Audio/AudioManager.cs
new file mode 100644
index 0000000..3cca7df
--- /dev/null
+++ b/FSI.Lib/FSI.Lib/Audio/AudioManager.cs
@@ -0,0 +1,608 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace FSI.Lib.Audio
+{
+ ///
+ /// Controls audio using the Windows CoreAudio API
+ /// from: http://stackoverflow.com/questions/14306048/controling-volume-mixer
+ /// and: http://netcoreaudio.codeplex.com/
+ ///
+ public static class AudioManager
+ {
+ #region Master Volume Manipulation
+
+ ///
+ /// Gets the current master volume in scalar values (percentage)
+ ///
+ /// -1 in case of an error, if successful the value will be between 0 and 100
+ public static float GetMasterVolume()
+ {
+ IAudioEndpointVolume masterVol = null;
+ try
+ {
+ masterVol = GetMasterVolumeObject();
+ if (masterVol == null)
+ return -1;
+
+ masterVol.GetMasterVolumeLevelScalar(out float volumeLevel);
+ return volumeLevel * 100;
+ }
+ finally
+ {
+ if (masterVol != null)
+ Marshal.ReleaseComObject(masterVol);
+ }
+ }
+
+ ///
+ /// Gets the mute state of the master volume.
+ /// While the volume can be muted the will still return the pre-muted volume value.
+ ///
+ /// false if not muted, true if volume is muted
+ public static bool GetMasterVolumeMute()
+ {
+ IAudioEndpointVolume masterVol = null;
+ try
+ {
+ masterVol = GetMasterVolumeObject();
+ if (masterVol == null)
+ return false;
+
+ masterVol.GetMute(out bool isMuted);
+ return isMuted;
+ }
+ finally
+ {
+ if (masterVol != null)
+ Marshal.ReleaseComObject(masterVol);
+ }
+ }
+
+ ///
+ /// Sets the master volume to a specific level
+ ///
+ /// Value between 0 and 100 indicating the desired scalar value of the volume
+ public static void SetMasterVolume(float newLevel)
+ {
+ IAudioEndpointVolume masterVol = null;
+ try
+ {
+ masterVol = GetMasterVolumeObject();
+ if (masterVol == null)
+ return;
+
+ masterVol.SetMasterVolumeLevelScalar(newLevel / 100, Guid.Empty);
+ }
+ finally
+ {
+ if (masterVol != null)
+ Marshal.ReleaseComObject(masterVol);
+ }
+ }
+
+ ///
+ /// Increments or decrements the current volume level by the .
+ ///
+ /// Value between -100 and 100 indicating the desired step amount. Use negative numbers to decrease
+ /// the volume and positive numbers to increase it.
+ /// the new volume level assigned
+ public static float StepMasterVolume(float stepAmount)
+ {
+ IAudioEndpointVolume masterVol = null;
+ try
+ {
+ masterVol = GetMasterVolumeObject();
+ if (masterVol == null)
+ return -1;
+
+ float stepAmountScaled = stepAmount / 100;
+
+ // Get the level
+ masterVol.GetMasterVolumeLevelScalar(out float volumeLevel);
+
+ // Calculate the new level
+ float newLevel = volumeLevel + stepAmountScaled;
+ newLevel = Math.Min(1, newLevel);
+ newLevel = Math.Max(0, newLevel);
+
+ masterVol.SetMasterVolumeLevelScalar(newLevel, Guid.Empty);
+
+ // Return the new volume level that was set
+ return newLevel * 100;
+ }
+ finally
+ {
+ if (masterVol != null)
+ Marshal.ReleaseComObject(masterVol);
+ }
+ }
+
+ ///
+ /// Mute or unmute the master volume
+ ///
+ /// true to mute the master volume, false to unmute
+ public static void SetMasterVolumeMute(bool isMuted)
+ {
+ IAudioEndpointVolume masterVol = null;
+ try
+ {
+ masterVol = GetMasterVolumeObject();
+ if (masterVol == null)
+ return;
+
+ masterVol.SetMute(isMuted, Guid.Empty);
+ }
+ finally
+ {
+ if (masterVol != null)
+ Marshal.ReleaseComObject(masterVol);
+ }
+ }
+
+ ///
+ /// Switches between the master volume mute states depending on the current state
+ ///
+ /// the current mute state, true if the volume was muted, false if unmuted
+ public static bool ToggleMasterVolumeMute()
+ {
+ IAudioEndpointVolume masterVol = null;
+ try
+ {
+ masterVol = GetMasterVolumeObject();
+ if (masterVol == null)
+ return false;
+
+ masterVol.GetMute(out bool isMuted);
+ masterVol.SetMute(!isMuted, Guid.Empty);
+
+ return !isMuted;
+ }
+ finally
+ {
+ if (masterVol != null)
+ Marshal.ReleaseComObject(masterVol);
+ }
+ }
+
+ private static IAudioEndpointVolume GetMasterVolumeObject()
+ {
+ IMMDeviceEnumerator deviceEnumerator = null;
+ IMMDevice speakers = null;
+ try
+ {
+ deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
+ deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
+
+ Guid IID_IAudioEndpointVolume = typeof(IAudioEndpointVolume).GUID;
+ speakers.Activate(ref IID_IAudioEndpointVolume, 0, IntPtr.Zero, out object o);
+ IAudioEndpointVolume masterVol = (IAudioEndpointVolume)o;
+
+ return masterVol;
+ }
+ finally
+ {
+ if (speakers != null) Marshal.ReleaseComObject(speakers);
+ if (deviceEnumerator != null) Marshal.ReleaseComObject(deviceEnumerator);
+ }
+ }
+
+ #endregion
+
+ #region Individual Application Volume Manipulation
+
+ public static float? GetApplicationVolume(int pid)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return null;
+
+ volume.GetMasterVolume(out float level);
+ Marshal.ReleaseComObject(volume);
+ return level * 100;
+ }
+
+ public static bool? GetApplicationMute(int pid)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return null;
+
+ volume.GetMute(out bool mute);
+ Marshal.ReleaseComObject(volume);
+ return mute;
+ }
+
+ public static void SetApplicationVolume(int pid, float level)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return;
+
+ Guid guid = Guid.Empty;
+ volume.SetMasterVolume(level / 100, ref guid);
+ Marshal.ReleaseComObject(volume);
+ }
+
+ public static void SetApplicationMute(int pid, bool mute)
+ {
+ ISimpleAudioVolume volume = GetVolumeObject(pid);
+ if (volume == null)
+ return;
+
+ Guid guid = Guid.Empty;
+ volume.SetMute(mute, ref guid);
+ Marshal.ReleaseComObject(volume);
+ }
+
+ private static ISimpleAudioVolume GetVolumeObject(int pid)
+ {
+ IMMDeviceEnumerator deviceEnumerator = null;
+ IAudioSessionEnumerator sessionEnumerator = null;
+ IAudioSessionManager2 mgr = null;
+ IMMDevice speakers = null;
+ try
+ {
+ // get the speakers (1st render + multimedia) device
+ deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
+ deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
+
+ // activate the session manager. we need the enumerator
+ Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID;
+ speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out object o);
+ mgr = (IAudioSessionManager2)o;
+
+ // enumerate sessions for on this device
+ mgr.GetSessionEnumerator(out sessionEnumerator);
+ sessionEnumerator.GetCount(out int count);
+
+ // search for an audio session with the required process-id
+ ISimpleAudioVolume volumeControl = null;
+ for (int i = 0; i < count; ++i)
+ {
+ IAudioSessionControl2 ctl = null;
+ try
+ {
+ sessionEnumerator.GetSession(i, out ctl);
+
+ // NOTE: we could also use the app name from ctl.GetDisplayName()
+ ctl.GetProcessId(out int cpid);
+
+ if (cpid == pid)
+ {
+ volumeControl = ctl as ISimpleAudioVolume;
+ break;
+ }
+ }
+ finally
+ {
+ if (ctl != null) Marshal.ReleaseComObject(ctl);
+ }
+ }
+
+ return volumeControl;
+ }
+ finally
+ {
+ if (sessionEnumerator != null) Marshal.ReleaseComObject(sessionEnumerator);
+ if (mgr != null) Marshal.ReleaseComObject(mgr);
+ if (speakers != null) Marshal.ReleaseComObject(speakers);
+ if (deviceEnumerator != null) Marshal.ReleaseComObject(deviceEnumerator);
+ }
+ }
+
+ #endregion
+
+ }
+
+ #region Abstracted COM interfaces from Windows CoreAudio API
+
+ [ComImport]
+ [Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
+ internal class MMDeviceEnumerator
+ {
+ }
+
+ internal enum EDataFlow
+ {
+ eRender,
+ eCapture,
+ eAll,
+ EDataFlow_enum_count
+ }
+
+ internal enum ERole
+ {
+ eConsole,
+ eMultimedia,
+ eCommunications,
+ ERole_enum_count
+ }
+
+ [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IMMDeviceEnumerator
+ {
+ int NotImpl1();
+
+ [PreserveSig]
+ int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
+
+ // the rest is not implemented
+ }
+
+ [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IMMDevice
+ {
+ [PreserveSig]
+ int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
+
+ // the rest is not implemented
+ }
+
+ [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioSessionManager2
+ {
+ int NotImpl1();
+ int NotImpl2();
+
+ [PreserveSig]
+ int GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum);
+
+ // the rest is not implemented
+ }
+
+ [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioSessionEnumerator
+ {
+ [PreserveSig]
+ int GetCount(out int SessionCount);
+
+ [PreserveSig]
+ int GetSession(int SessionCount, out IAudioSessionControl2 Session);
+ }
+
+ [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface ISimpleAudioVolume
+ {
+ [PreserveSig]
+ int SetMasterVolume(float fLevel, ref Guid EventContext);
+
+ [PreserveSig]
+ int GetMasterVolume(out float pfLevel);
+
+ [PreserveSig]
+ int SetMute(bool bMute, ref Guid EventContext);
+
+ [PreserveSig]
+ int GetMute(out bool pbMute);
+ }
+
+ [Guid("bfb7ff88-7239-4fc9-8fa2-07c950be9c6d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IAudioSessionControl2
+ {
+ // IAudioSessionControl
+ [PreserveSig]
+ int NotImpl0();
+
+ [PreserveSig]
+ int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int SetDisplayName([MarshalAs(UnmanagedType.LPWStr)] string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext);
+
+ [PreserveSig]
+ int GetIconPath([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int SetIconPath([MarshalAs(UnmanagedType.LPWStr)] string Value, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext);
+
+ [PreserveSig]
+ int GetGroupingParam(out Guid pRetVal);
+
+ [PreserveSig]
+ int SetGroupingParam([MarshalAs(UnmanagedType.LPStruct)] Guid Override, [MarshalAs(UnmanagedType.LPStruct)] Guid EventContext);
+
+ [PreserveSig]
+ int NotImpl1();
+
+ [PreserveSig]
+ int NotImpl2();
+
+ // IAudioSessionControl2
+ [PreserveSig]
+ int GetSessionIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int GetSessionInstanceIdentifier([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
+
+ [PreserveSig]
+ int GetProcessId(out int pRetVal);
+
+ [PreserveSig]
+ int IsSystemSoundsSession();
+
+ [PreserveSig]
+ int SetDuckingPreference(bool optOut);
+ }
+
+ // http://netcoreaudio.codeplex.com/SourceControl/latest#trunk/Code/CoreAudio/Interfaces/IAudioEndpointVolume.cs
+ [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IAudioEndpointVolume
+ {
+ [PreserveSig]
+ int NotImpl1();
+
+ [PreserveSig]
+ int NotImpl2();
+
+ ///
+ /// Gets a count of the channels in the audio stream.
+ ///
+ /// The number of channels.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetChannelCount(
+ [Out][MarshalAs(UnmanagedType.U4)] out UInt32 channelCount);
+
+ ///
+ /// Sets the master volume level of the audio stream, in decibels.
+ ///
+ /// The new master volume level in decibels.
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int SetMasterVolumeLevel(
+ [In][MarshalAs(UnmanagedType.R4)] float level,
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Sets the master volume level, expressed as a normalized, audio-tapered value.
+ ///
+ /// The new master volume level expressed as a normalized value between 0.0 and 1.0.
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int SetMasterVolumeLevelScalar(
+ [In][MarshalAs(UnmanagedType.R4)] float level,
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Gets the master volume level of the audio stream, in decibels.
+ ///
+ /// The volume level in decibels.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetMasterVolumeLevel(
+ [Out][MarshalAs(UnmanagedType.R4)] out float level);
+
+ ///
+ /// Gets the master volume level, expressed as a normalized, audio-tapered value.
+ ///
+ /// The volume level expressed as a normalized value between 0.0 and 1.0.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetMasterVolumeLevelScalar(
+ [Out][MarshalAs(UnmanagedType.R4)] out float level);
+
+ ///
+ /// Sets the volume level, in decibels, of the specified channel of the audio stream.
+ ///
+ /// The channel number.
+ /// The new volume level in decibels.
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int SetChannelVolumeLevel(
+ [In][MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
+ [In][MarshalAs(UnmanagedType.R4)] float level,
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Sets the normalized, audio-tapered volume level of the specified channel in the audio stream.
+ ///
+ /// The channel number.
+ /// The new master volume level expressed as a normalized value between 0.0 and 1.0.
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int SetChannelVolumeLevelScalar(
+ [In][MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
+ [In][MarshalAs(UnmanagedType.R4)] float level,
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Gets the volume level, in decibels, of the specified channel in the audio stream.
+ ///
+ /// The zero-based channel number.
+ /// The volume level in decibels.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetChannelVolumeLevel(
+ [In][MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
+ [Out][MarshalAs(UnmanagedType.R4)] out float level);
+
+ ///
+ /// Gets the normalized, audio-tapered volume level of the specified channel of the audio stream.
+ ///
+ /// The zero-based channel number.
+ /// The volume level expressed as a normalized value between 0.0 and 1.0.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetChannelVolumeLevelScalar(
+ [In][MarshalAs(UnmanagedType.U4)] UInt32 channelNumber,
+ [Out][MarshalAs(UnmanagedType.R4)] out float level);
+
+ ///
+ /// Sets the muting state of the audio stream.
+ ///
+ /// True to mute the stream, or false to unmute the stream.
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int SetMute(
+ [In][MarshalAs(UnmanagedType.Bool)] Boolean isMuted,
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Gets the muting state of the audio stream.
+ ///
+ /// The muting state. True if the stream is muted, false otherwise.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetMute(
+ [Out][MarshalAs(UnmanagedType.Bool)] out Boolean isMuted);
+
+ ///
+ /// Gets information about the current step in the volume range.
+ ///
+ /// The current zero-based step index.
+ /// The total number of steps in the volume range.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetVolumeStepInfo(
+ [Out][MarshalAs(UnmanagedType.U4)] out UInt32 step,
+ [Out][MarshalAs(UnmanagedType.U4)] out UInt32 stepCount);
+
+ ///
+ /// Increases the volume level by one step.
+ ///
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int VolumeStepUp(
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Decreases the volume level by one step.
+ ///
+ /// A user context value that is passed to the notification callback.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int VolumeStepDown(
+ [In][MarshalAs(UnmanagedType.LPStruct)] Guid eventContext);
+
+ ///
+ /// Queries the audio endpoint device for its hardware-supported functions.
+ ///
+ /// A hardware support mask that indicates the capabilities of the endpoint.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int QueryHardwareSupport(
+ [Out][MarshalAs(UnmanagedType.U4)] out UInt32 hardwareSupportMask);
+
+ ///
+ /// Gets the volume range of the audio stream, in decibels.
+ ///
+ /// The minimum volume level in decibels.
+ /// The maximum volume level in decibels.
+ /// The volume increment level in decibels.
+ /// An HRESULT code indicating whether the operation passed of failed.
+ [PreserveSig]
+ int GetVolumeRange(
+ [Out][MarshalAs(UnmanagedType.R4)] out float volumeMin,
+ [Out][MarshalAs(UnmanagedType.R4)] out float volumeMax,
+ [Out][MarshalAs(UnmanagedType.R4)] out float volumeStep);
+ }
+
+ #endregion
+}
diff --git a/FSI.Lib/FSI.Lib/FSI.Lib.csproj b/FSI.Lib/FSI.Lib/FSI.Lib.csproj
index 8539040..31c72c5 100644
--- a/FSI.Lib/FSI.Lib/FSI.Lib.csproj
+++ b/FSI.Lib/FSI.Lib/FSI.Lib.csproj
@@ -5,6 +5,7 @@
Library
true
true
+ true
true
3.0
@@ -38,6 +39,7 @@
+
diff --git a/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/FrmMain.xaml b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/FrmMain.xaml
new file mode 100644
index 0000000..a6a3e2d
--- /dev/null
+++ b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/FrmMain.xaml
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/FrmMain.xaml.cs b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/FrmMain.xaml.cs
new file mode 100644
index 0000000..c3c25fa
--- /dev/null
+++ b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/FrmMain.xaml.cs
@@ -0,0 +1,55 @@
+using System.Collections.Generic;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace FSI.Lib.Guis.Rdp.Mgt
+{
+ ///
+ /// Interaktionslogik für FrmMain.xaml
+ ///
+ public partial class FrmMain : Window
+ {
+ public ViewModel Rdps { get; set; }
+ public bool CloseAtLostFocus { get; set; }
+ public IEnumerable InputData { get; set; }
+
+ public string Exe { get; set; }
+
+ public FrmMain()
+ {
+ InitializeComponent();
+ Loaded += Main_Loaded;
+ Deactivated += FrmMain_Deactivated;
+ }
+
+ private void FrmMain_Deactivated(object sender, System.EventArgs e)
+ {
+ if (CloseAtLostFocus)
+ Visibility = Visibility.Hidden;
+ }
+
+ private void Main_Loaded(object sender, RoutedEventArgs e)
+ {
+
+ Title = "FSI Text in die Zwischenablage kopieren";
+ Title += " v" + Assembly.GetExecutingAssembly().GetName().Version; // Version in Titel eintragen
+
+ Rdps = new ViewModel(new DataProvider())
+ {
+ InputData = InputData,
+ Exe = Exe,
+ };
+ DataContext = Rdps;
+
+ Rdps.Load();
+ }
+
+ private void tbSearch_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ tbSearch.Select(tbSearch.Text.Length, 0);
+ }
+
+ }
+}
+
diff --git a/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/Model.cs b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/Model.cs
new file mode 100644
index 0000000..830477a
--- /dev/null
+++ b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/Model.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+namespace FSI.Lib.Guis.Rdp.Mgt
+{
+ public interface IInterface
+ {
+ string Plant { get; set; }
+ string SubPlant { get; set; }
+ string Description { get; set; }
+ string Host { get; set; }
+ }
+
+ public struct Model : IInterface
+ {
+ private string _plant;
+ private string _subPlant;
+ private string _description;
+ private string _host;
+ public string Plant { get => _plant; set => _plant = value; }
+ public string SubPlant { get => _subPlant; set => _subPlant = value; }
+ public string Description { get => _description; set => _description = value; }
+ public string Host { get => _host; set => _host = value; }
+ public string DescriptionDtl { get => _plant + " " + SubPlant + " " + Description + " " + Host; }
+ }
+
+ public interface IDataProvider
+ {
+ IEnumerable Load(IEnumerable datas);
+ }
+}
diff --git a/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/ViewModel.cs b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/ViewModel.cs
new file mode 100644
index 0000000..c712447
--- /dev/null
+++ b/FSI.Lib/FSI.Lib/Guis/Rdp.Mgt/ViewModel.cs
@@ -0,0 +1,187 @@
+using FSI.Lib.MVVM;
+using Microsoft.Extensions.Logging;
+using NLog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace FSI.Lib.Guis.Rdp.Mgt
+{
+ public class ViewModel : MVVM.ViewModelBase
+ {
+ readonly IDataProvider _dataProvider;
+ private string _search;
+ private ICollectionView _collView;
+
+ public ICommand RefreshCommand => new DelegateCommand(RefreshData);
+ private ICommand _cmdQuickSearch;
+ private ICommand _cmdOpen;
+
+ public Logger _log;
+
+ public ViewModel(IDataProvider dataProvider)
+ {
+ Datas = new ObservableCollection();
+ _dataProvider = dataProvider;
+
+ _cmdQuickSearch = new RelayCommand