using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shell; using System.Windows.Threading; using C4IT.API; using C4IT.API.Contracts; using C4IT.Graphics; using C4IT.Logging; using C4IT.Matrix42.WebClient; using C4IT_CustomerPanel.forms; using C4IT_CustomerPanel.forms.AuthenticationSettings; using C4IT_CustomerPanel.libs; using C4IT_CustomerPanel.UserControls; using Microsoft.WindowsAPICodePack.Taskbar; using Newtonsoft.Json; using static C4IT.Logging.cLogManager; using Application = System.Windows.Application; using Button = System.Windows.Controls.Button; using Color = System.Windows.Media.Color; using HorizontalAlignment = System.Windows.HorizontalAlignment; using Image = System.Windows.Controls.Image; using KeyEventArgs = System.Windows.Input.KeyEventArgs; using Label = System.Windows.Controls.Label; using Orientation = System.Windows.Controls.Orientation; namespace C4IT_CustomerPanel { public partial class MainWindow { readonly Version constMinServerVersion = new Version("3.9.0.0"); public enum enumOnlineState { Initializing = 0, NoConfig, Online, Offline }; public static MainWindow MainInstance = null; public bool LowServerVersion = false; public enum enumOrderBy { ascTicketnumber = 0, descTicketnumber = 1, ascCreatedDate = 2, descCreatedDate = 3, ascState = 4, descState = 5 } public ConfigClass ConfigSettings { get; set; } private DispatcherTimer _reloadTimer; private DispatcherTimer _cleanUpTimer; private DispatcherTimer _adHocTimer; private DispatcherTimer _regularTimer; private DispatcherTimer _checkServerConnectionTimer; private const double HeaderCaptionHeight = 72d; private bool _initialTimerInvocationDone = false; private bool _manualRefreshInProgress = false; private TimeSpan _lastTicketInterval; private TimeSpan _lastAdHocInterval; private TimeSpan _lastRegularInterval; private bool _allowApplicationShutdown = false; internal DateTime lastUpdate; //private Dictionary> announcementIDCollection = new Dictionary>(); public bool _userIsAuthenticated = false; public enumOnlineState OnlineState = enumOnlineState.Initializing; public Dictionary NewContentSignals = new Dictionary(); public SortedList NewContentSignalsInfo = new SortedList(); internal bool _isRedDotActive = false; public Button ActiveButton; public Icon NotifierIconDefault = null; public NotifyIcon notifyIcon = new NotifyIcon(); public bool _initializedUiComponents = false; public Dictionary MainFunctionButtons = new Dictionary(); public ToolStripItem trayClosingItem; public ToolStripItem trayClosingStripSeparator; public ResourceDictionary _darkThemeMain = new ResourceDictionary() { Source = new Uri("/themes/ThemeDarkMain.xaml", UriKind.Relative) }; public ResourceDictionary _darkThemeNav = new ResourceDictionary() { Source = new Uri("/themes/ThemeDarkNav.xaml", UriKind.Relative) }; public ResourceDictionary _lightThemeMain = new ResourceDictionary() { Source = new Uri("/themes/ThemeLightMain.xaml", UriKind.Relative) }; public ResourceDictionary _lightThemeNav = new ResourceDictionary() { Source = new Uri("/themes/ThemeLightNav.xaml", UriKind.Relative) }; private const string ApiTicketsUrl = "m42Services/api/c4it/customerpanel/tickets"; private const string ApiCloseAllClientsUrl = "m42Services/api/c4it/customerpanel/closeallclients"; private const string ApiIsAliveUrl = "m42Services/api/c4it/customerpanel/isalive"; public MainWindow() { MainInstance = this; ConfigSettings = new ConfigClass(); ConfigSettings.Initialize(); Thread.CurrentThread.CurrentUICulture = new CultureInfo(InformationHelper.GetLanguageString(ConfigSettings.GetUserLanguage())); InitializeComponent(); } protected async override void OnInitialized(EventArgs e) { try { HideMainForm(); InitializeNotifyIcon(); NotifyerSupport.LoadSetFromResource("Default", "C4IT_CustomerPanel.Resources.logo_CustomerPanel.ico", NoRefresh: true); NotifyerSupport.LoadSetFromResource("Main", "C4IT_CustomerPanel.Resources.logo_CustomerPanel.ico", NoRefresh: true); NotifyerSupport.LoadSetFromResource("OverlayOffline", "C4IT_CustomerPanel.Resources.StateOverlays.Offline", NoRefresh: true)?.CreateSizeMap(0.45f); NotifyerSupport.LoadSetFromResource("OverlayNew", "C4IT_CustomerPanel.Resources.StateOverlays.NewContent", NoRefresh: true)?.CreateSizeMap(0.45f); NotifyerSupport.SetNotifyIcon("Main", null, NotifyerSupport.enumIconAlignment.BottomRight); NotifyerSupport.RegisterWindowIconFunc(ChangeWindowIcon); NotifyerSupport.RegisterNotifyControl(notifyIcon); RefreshTrayIcon(); RefreshLogo(); this.Connecting.Visibility = Visibility.Visible; this.ConnProblem.Visibility = Visibility.Collapsed; InitializeContracts(); base.OnInitialized(e); FormHelper.GetLocation((int)this.Width, (int)this.Height, (double)ConfigSettings.local_currentDPI / 96); SetAppearance(true); SetLocation(); CustomerPanelSecurePassword.Init(); PrivateCustomerPanelSecurePassword.Init(); InitTimer(); _userIsAuthenticated = await ConfigSettings.CreateM42ConnectionObject(); InitializeOrUpdateTrayMenu(); // Falls User nicht angemeldet werden konnte, initialen Status auf Offline if (!_userIsAuthenticated) { _initializedUiComponents = true; OnlineState = enumOnlineState.Offline; OnlineStatusChanged(); RefreshIcon.Visibility = Visibility.Visible; UpdateTimer(); } } catch (Exception E) { LogException(E); RequestApplicationShutdown(); Environment.Exit(0); } } private void InitializeContracts() { try { lastUpdate = ConfigClass.LoadFromJson("LastTicketUpdate", "run"); } catch { } IncidentCtrl.InitializeContracts(); AnnouncementCtrl.InitializeContracts(); if (lastUpdate == null) lastUpdate = DateTime.MinValue; } private void InitializeNotifyIcon() { notifyIcon.Text = !string.IsNullOrWhiteSpace(ConfigSettings.CustomerPanelTitle) ? ConfigSettings.CustomerPanelTitle : Properties.Resources.customerPanel; notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(); ; notifyIcon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(); notifyIcon.Visible = true; notifyIcon.Click += OnNotifyIconClicked; } private void OnNotifyIconClicked(object sender, EventArgs e) { System.Windows.Forms.MouseEventArgs me = (System.Windows.Forms.MouseEventArgs)e; int mouseY = System.Windows.Forms.Control.MousePosition.Y; int mouseX = System.Windows.Forms.Control.MousePosition.X; if (me.Button == System.Windows.Forms.MouseButtons.Right) { notifyIcon.ContextMenuStrip.Show(mouseX, mouseY); } else if (me.Button == System.Windows.Forms.MouseButtons.Left) { if (this.WindowState == WindowState.Normal) this.HideMainForm(); else this.SetMenuAktivInaktiv(ActiveButton, true); } } private void ChangeWindowIcon(Icon IC) { ImageSource imageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon( IC.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); this.Icon = imageSource; } private void Window_Loaded(object sender, RoutedEventArgs e) { ComputerInfoCtrl.FillMainInfoGrid(); NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(AddressChangedCallback); } static async void AddressChangedCallback(object sender, EventArgs e) { await Task.Delay(5000); MainWindow.MainInstance.Dispatcher.Invoke(new Action(() => { MainWindow.MainInstance.ComputerInfoCtrl.SetIpAddress(InformationHelper.GetIp4Address(MainWindow.MainInstance.ConfigSettings.ShowIpInfoOnlyInCorporateNetwork)); })); } public void RefreshLogo() { var CustomLogo = false; try { var FN = ConfigClass.GetLogoFilePath(); if (File.Exists(FN)) { Dispatcher.Invoke(new Action(() => { try { var ms = new MemoryStream(); using (var fs = new FileStream(FN, FileMode.Open, FileAccess.Read)) { fs.CopyTo(ms); ms.Position = 0; var BM = new System.Windows.Media.Imaging.BitmapImage(); BM.BeginInit(); BM.CacheOption = BitmapCacheOption.OnLoad; BM.StreamSource = ms; BM.EndInit(); if (BM.Width > 0 && BM.Height > 0) { Logo.Source = BM; CustomLogo = true; } } } catch (Exception E) { LogException(E); } })); } } catch { } try { if (!CustomLogo) { Dispatcher.Invoke(new Action(() => { try { Logo.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("Resources/consulting4it-header1.png", UriKind.Relative)); } catch { } })); } } catch { } } public void RefreshTrayIcon() { var CustomIcon = false; try { var FN = ConfigClass.GetTrayIconFilePath(); if (File.Exists(FN)) { var Set = NotifyerSupport.LoadSet("Main", FN); if (Set != null) { CustomIcon = true; } } } catch (Exception E) { LogException(E); } try { if (!CustomIcon) NotifyerSupport.LoadSetFromResource("Main", "C4IT_CustomerPanel.Resources.logo_CustomerPanel.ico"); NotifierIconDefault = NotifyerSupport.GetIconSet("Main").GetIcon(); } catch (Exception E) { LogException(E); } } public void InitTimer() { _reloadTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 1) }; _reloadTimer.Tick += OnReloadTimerElapsed; _reloadTimer.Start(); _cleanUpTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 10) }; _cleanUpTimer.Tick += OnCleanUpTimerElapsed; _cleanUpTimer.Start(); _adHocTimer = new DispatcherTimer { Interval = new TimeSpan(0, 2, 0) }; _adHocTimer.Tick += OnAdHocTimerElapsed; _adHocTimer.Start(); _regularTimer = new DispatcherTimer { Interval = new TimeSpan(0, 10, 0) }; _regularTimer.Tick += OnRegularTimerElapsed; _regularTimer.Start(); _checkServerConnectionTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(30) }; _checkServerConnectionTimer.Tick += OnConnectionStatusCheckTimerElapsed; _checkServerConnectionTimer.Start(); } private async void OnConnectionStatusCheckTimerElapsed(object sender, EventArgs e) { _checkServerConnectionTimer.Stop(); await Task.Run(new Action(async () => { await RunConnectionStatusCheckAsync(); })); _checkServerConnectionTimer.Start(); } private async Task RunConnectionStatusCheckAsync() { var apiAccessable = false; eM42ApiReason result = eM42ApiReason.internalerror; if (!ConfigSettings.m42WebClient.IsInitialAuthenticated) { var _logRes = await ConfigSettings.m42WebClient.LogonAsync(); if (_logRes.Reason == eM42ApiReason.ok) await ConfigSettings.ReadConfigAsync(); result = _logRes.Reason; } else { Debug.WriteLine("RunConnectionStatusCheckAsync: starting CheckOnlineAsync..."); result = await ConfigSettings.m42WebClient.CheckOnlineAsync(true); Debug.WriteLine("RunConnectionStatusCheckAsync: finished CheckOnlineAsync"); } if (result != eM42ApiReason.ok) { LogEntry($"RunConnectionStatusCheckAsync.CheckOnlineAsync: {result}"); } if (result == eM42ApiReason.ok) { LogEntry($"RunConnectionStatusCheckAsync: {result}"); using (var _http = ConfigSettings.m42WebClient.GetHttp()) { var response = await _http.GetAsync(ApiIsAliveUrl); if (response != null) { apiAccessable = response.StatusCode == HttpStatusCode.NoContent; } else { LogEntry("RunConnectionStatusCheckAsync: response was null."); apiAccessable = false; } } } var _lastOnlineState = OnlineState; OnlineState = apiAccessable ? enumOnlineState.Online : enumOnlineState.Offline; if (_lastOnlineState != OnlineState) { LogEntry($"RunConnectionStatusCheckAsync: OnlineState changed to {OnlineState}"); OnlineStatusChanged(); UpdateTimer(); this.Dispatcher.Invoke(() => { if (OnlineState == enumOnlineState.Online) TaskbarItemInfo.Overlay = null; else TaskbarItemInfo.Overlay = (ImageSource)FindResource("OverlayOffline"); }); } } internal void UpdateTimer() { if (OnlineState == enumOnlineState.Online) { // ---- Intervalle holen und loggen ---- int ticketInterval = ConfigSettings.GetTimerIntervalTicket(); int adHocInterval = ConfigSettings.GetTimerIntervalAdHoc(); int regularInterval = ConfigSettings.GetTimerIntervalRegular(); LogEntry($"[UpdateTimer] Setting Ticket timer to {ticketInterval} minutes", LogLevels.Info); LogEntry($"[UpdateTimer] Setting AdHoc timer to {adHocInterval} minutes", LogLevels.Info); LogEntry($"[UpdateTimer] Setting Regular timer to {regularInterval} minutes", LogLevels.Info); // ---- Timer konfigurieren ---- _reloadTimer.Interval = TimeSpan.FromMinutes(ticketInterval); _adHocTimer.Interval = TimeSpan.FromMinutes(adHocInterval); _regularTimer.Interval = TimeSpan.FromMinutes(regularInterval); // ---- Timer starten ---- _reloadTimer.Start(); _adHocTimer.Start(); _regularTimer.Start(); _lastTicketInterval = _reloadTimer.Interval; _lastAdHocInterval = _adHocTimer.Interval; _lastRegularInterval = _regularTimer.Interval; if (!_initialTimerInvocationDone) { _initialTimerInvocationDone = true; // Manuelles Ausführen der Timer-Jobs, die ansonsten erst nach Interval-Ende laufen Task.Run(async () => { await OnReloadTimerElapsedAsync(false); await OnAnnoncementTimerReloadAsync(announcementType.Adhoc); await OnAnnoncementTimerReloadAsync(announcementType.Regular); }); } } else { // --- OFFLINE --- _reloadTimer.Stop(); _adHocTimer.Stop(); _regularTimer.Stop(); } } private void ControlMenu(MenuItems starter, bool force) { Button B = null; switch (starter) { case MenuItems.Ssp: B = BtnSsp; break; case MenuItems.Information: B = BtnInfo; break; case MenuItems.Announcement: B = BtnAnnouncements; break; case MenuItems.Incident: B = BtnIncident; break; case MenuItems.CustomLink: B = BtnCustomLink; break; } if (B != null) this.SetMenuAktivInaktiv(B, force); } #region Appearance Functions private void SetAppearance(bool firstStart) { ApplyWindowDraggableState(); System.Collections.ObjectModel.Collection themes = new System.Collections.ObjectModel.Collection(); if (ConfigSettings.GetConfig()._iconColor != 0) { if (ConfigSettings.GetConfig()._iconColor == 10) { themes.Add(MainWindow.MainInstance?._darkThemeNav); } else if (ConfigSettings.GetConfig()._iconColor == 20) { themes.Add(MainWindow.MainInstance?._lightThemeNav); } } if (ConfigSettings.GetConfig()._mainIconTextColor != 0) { if (ConfigSettings.GetConfig()._mainIconTextColor == 10) { themes.Add(MainWindow.MainInstance?._darkThemeMain); } else if (ConfigSettings.GetConfig()._mainIconTextColor == 20) { themes.Add(MainWindow.MainInstance?._lightThemeMain); } } if (themes.Count == 2 && Application.Current.Resources.MergedDictionaries.Count >=2) { Application.Current.Resources.MergedDictionaries.RemoveAt(0); Application.Current.Resources.MergedDictionaries.RemoveAt(0); Application.Current.Resources.MergedDictionaries.Insert(0,themes[0]); Application.Current.Resources.MergedDictionaries.Insert(1, themes[1]); } UpdateNavigationHoverResource(); UpdateLocalizedTooltips(); ComputerInfoCtrl.SetAppearence(); if (TryFindResource("navForeground") is SolidColorBrush navForeground) { Close_Text.Foreground = navForeground; } if (firstStart) { BtnAnnouncements.Tag = MenuItems.Announcement; BtnIncident.Tag = MenuItems.Incident; BtnSsp.Tag = MenuItems.Ssp; BtnInfo.Tag = MenuItems.Information; BtnCustomLink.Tag = MenuItems.CustomLink; } } private void UpdateNavigationHoverResource() { if (Application.Current?.Resources == null) return; SolidColorBrush navHover = GetNavigationHoverBrush(); Color subtleHoverColor = navHover.Color; subtleHoverColor.A = 96; Application.Current.Resources["navigationHoverColor"] = new SolidColorBrush(subtleHoverColor); } private void UpdateLocalizedTooltips() { if (RefreshIcon == null) return; string refreshToolTip = Properties.Resources.ResourceManager.GetString("refresh", Thread.CurrentThread.CurrentUICulture); RefreshIcon.ToolTip = string.IsNullOrWhiteSpace(refreshToolTip) ? "Refresh" : refreshToolTip; } private void ApplyWindowDraggableState() { bool draggable = ConfigSettings?.GetConfig()?._isDraggable ?? true; if (!draggable) ResetLocation(); WindowChrome chrome = WindowChrome.GetWindowChrome(this); if (chrome != null) chrome.CaptionHeight = draggable ? HeaderCaptionHeight : 0d; } public void ResetLocation() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { ConfigSettings.usr_windowPosition = FormHelper.GetLocation((int)Window.Width, (int)Window.Height, (double)ConfigSettings.local_currentDPI / 96); Window.Left = ConfigSettings.usr_windowPosition.X; Window.Top = ConfigSettings.usr_windowPosition.Y; ConfigSettings.SetWindowPos(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private void SetLocation() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (ConfigSettings.usr_windowPosition.X != 0 | ConfigSettings.usr_windowPosition.Y != 0) { var he = System.Windows.SystemParameters.WorkArea.Height; var wd = System.Windows.SystemParameters.WorkArea.Width; if (wd < ConfigSettings.usr_windowPosition.X + Application.Current.MainWindow.Width | ConfigSettings.usr_windowPosition.X < 0) { ResetLocation(); } if (he < ConfigSettings.usr_windowPosition.Y + Application.Current.MainWindow.Height) { ResetLocation(); } this.Left = ConfigSettings.usr_windowPosition.X; this.Top = ConfigSettings.usr_windowPosition.Y; } else { ConfigSettings.usr_windowPosition = FormHelper.GetLocation((int)Window.Width, (int)Window.Height, (double)ConfigSettings.local_currentDPI / 96); Window.Left = ConfigSettings.usr_windowPosition.X; Window.Top = ConfigSettings.usr_windowPosition.Y; } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } #endregion private void RefreshTrayMenu(bool ActivateFirstEntry) { var TopMarginCount = 0; const double railTopOffset = 14.5; foreach (var navButton in new[] { BtnAnnouncements, BtnIncident, BtnSsp, BtnCustomLink, BtnInfo }) { if (navButton != null) navButton.Visibility = Visibility.Hidden; } if (OnlineState != enumOnlineState.Online && ActiveButton != BtnInfo) ActivateFirstEntry = true; foreach (var entry in MainFunctionButtons) { try { var Info = entry.Value; var isVisible = OnlineState == enumOnlineState.Online ? ConfigSettings.GetConfig().MainFunctionActivation[entry.Key] : entry.Key == enumMainFunctions.Information; if (isVisible) { Info.button.Visibility = Visibility.Visible; Info.button.Margin = new Thickness(0, railTopOffset + (70 * TopMarginCount), 0, 0); TopMarginCount++; } else { Info.button.Visibility = Visibility.Hidden; if (Info.button == ActiveButton) ActivateFirstEntry = true; } if (entry.Value.MenuStrip != null) { entry.Value.MenuStrip.Enabled = isVisible; entry.Value.MenuStrip.Visible = isVisible; } } catch { } } if (ActivateFirstEntry) { foreach (var entry in MainFunctionButtons.Values) { if (entry.button.Visibility == Visibility.Visible) { SetMenuAktivInaktiv(entry.button, false, true); break; } } } if (trayClosingStripSeparator != null) trayClosingStripSeparator.Visible = !ConfigSettings.GetConfig()._disableClosing; if (trayClosingItem != null) trayClosingItem.Visible = !ConfigSettings.GetConfig()._disableClosing; } public void InitializeOrUpdateTrayMenu() { var methodInfo = MethodBase.GetCurrentMethod(); LogMethodBegin(methodInfo); try { var cms = new ContextMenuStrip(); if (ConfigSettings.m42WebClient.IsOnline) { LogEntry($"_userIsAuthenticated: {_userIsAuthenticated}", LogLevels.Debug); MainFunctionButtons = new Dictionary() { {enumMainFunctions.Announcement, new cMainFunctionInfo(){ Title= Properties.Resources.announcement, button = BtnAnnouncements, ReadAllImage=AnnouncementCtrl.ReadAllButton , image = Properties.Resources.appbar_newspaper, MenuItem = MenuItems.Announcement}}, {enumMainFunctions.Incident, new cMainFunctionInfo() { Title = Properties.Resources.incidents, button = BtnIncident, ReadAllImage=IncidentCtrl.buttonReadAllTickets , image = Properties.Resources.appbar_clipboard_variant_text, MenuItem = MenuItems.Incident}}, {enumMainFunctions.Ssp, new cMainFunctionInfo() { Title = Properties.Resources.ssp, button = BtnSsp, image = Properties.Resources.appbar_cart, MenuItem = MenuItems.Ssp}}, {enumMainFunctions.CustomLinks, new cMainFunctionInfo() { Title = Properties.Resources.CustomLink, button = BtnCustomLink, image = Properties.Resources.appbar_star, MenuItem = MenuItems.CustomLink}}, {enumMainFunctions.Information, new cMainFunctionInfo() { Title = Properties.Resources.information, button = BtnInfo, image = Properties.Resources.appbar_information, MenuItem = MenuItems.Information }} }; } else { MainFunctionButtons = new Dictionary() { {enumMainFunctions.Information, new cMainFunctionInfo() { Title = Properties.Resources.information, button = BtnInfo, image = Properties.Resources.appbar_information, MenuItem = MenuItems.Information }} }; } System.Windows.Forms.ToolStripItem trayStripItem; foreach (var entry in MainFunctionButtons) { if (entry.Value != null) { trayStripItem = cms.Items.Add(entry.Value.Title); trayStripItem.Tag = entry.Value.MenuItem; trayStripItem.Image = entry.Value.image; trayStripItem.Enabled = ConfigSettings.GetConfig().MainFunctionActivation[entry.Key]; trayStripItem.Click += OnClickTrayItem; entry.Value.MenuStrip = trayStripItem; } } ToolStripMenuItem trayMenuItem; ToolStripMenuItem trayMenuItem2; // add a separator trayStripItem = new ToolStripSeparator(); cms.Items.Add(trayStripItem); // add the 'presentation mode' tray menu item trayMenuItem = new ToolStripMenuItem(Properties.Resources.dnd); cms.Items.Add(trayMenuItem); // ad the 'presentation mode from OS' tray menu item trayMenuItem2 = new ToolStripMenuItem(Properties.Resources.dndFromOS) { Tag = MenuItems.pmodeOS, Image = Properties.Resources.SystemLanguage }; if (ConfigSettings.IsPresentationModeFromOS()) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem2.Click += OnPresentationModeClicked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // ad the 'presentation on' tray menu item trayMenuItem2 = new ToolStripMenuItem(Properties.Resources.dndActivate) { Tag = MenuItems.pmodeOn, Image = Properties.Resources.PresentationModeOn }; if (!ConfigSettings.IsPresentationModeFromOS() && ConfigSettings.GetPresentationMode()) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem2.Click += OnPresentationModeClicked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // ad the 'presentation off' tray menu item trayMenuItem2 = new ToolStripMenuItem(Properties.Resources.dndDeactivate) { Tag = MenuItems.pmodeOff, Image = Properties.Resources.PresentationModeOff }; if (!ConfigSettings.IsPresentationModeFromOS() && !ConfigSettings.GetPresentationMode()) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem2.Click += OnPresentationModeClicked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // add the 'notification' tray menu item trayMenuItem = new ToolStripMenuItem(Properties.Resources.NotificationMenu); cms.Items.Add(trayMenuItem); // add the 'notify by OS' tray menu item trayMenuItem2 = new ToolStripMenuItem(Properties.Resources.NotificationMenuOsDefault) { Image = Properties.Resources.NotifyByOS, Tag = true }; trayMenuItem2.Click += OnNotifierMenuClicked; //OnNotifierMenuClicked(trayMenuItem2, null); if (ConfigSettings.EnableNotifier) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // add the 'notify by Custemer Panel' tray menu item trayMenuItem2 = new ToolStripMenuItem(Properties.Resources.NotificationMenuDirect) { Image = Properties.Resources.NotifyByCP, Tag = false }; trayMenuItem2.Click += OnNotifierMenuClicked; if (!ConfigSettings.EnableNotifier) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // add the 'select language' tray menu item trayMenuItem = new System.Windows.Forms.ToolStripMenuItem(Properties.Resources.langMenu); cms.Items.Add(trayMenuItem); // add the system default language strip item var OsLang = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.ToUpper(); if (OsLang != "DE") OsLang = ("EN"); trayMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(string.Format(Properties.Resources.langSystemDefault, OsLang)) { Image = Properties.Resources.SystemLanguage, Tag = MenuItems.langOS }; trayMenuItem2.Click += OnLanguageClicked; if (ConfigSettings.IsUserLanguageOsDefault()) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // add the 'DE' language tray strip item trayMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(Properties.Resources.langDE) { Image = Properties.Resources.Germany_Flag_icon, Tag = MenuItems.langDE }; trayMenuItem2.Click += OnLanguageClicked; if (!ConfigSettings.IsUserLanguageOsDefault() && ConfigSettings.GetUserLanguage() == 1031) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // add the 'EN' language tray strip item trayMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(Properties.Resources.langUS) { Image = Properties.Resources.United_Kingdom_Flag_icon, Tag = MenuItems.langUS }; trayMenuItem2.Click += OnLanguageClicked; if (!ConfigSettings.IsUserLanguageOsDefault() && ConfigSettings.GetUserLanguage() != 1031) trayMenuItem2.CheckState = CheckState.Checked; trayMenuItem.DropDownItems.Add(trayMenuItem2); // Vorerst nur auskommentiert um die Einträge im Traymenü auszublenden. // Wenn Einträge in Zukunft nicht mehr benötigt werden, dann komplett herausnehmen (Stand: 28.01.2025) // add the config tray strip item trayStripItem = new System.Windows.Forms.ToolStripSeparator(); cms.Items.Add(trayStripItem); trayStripItem = cms.Items.Add(Properties.Resources.config); trayStripItem.Image = Properties.Resources.SettingsMenu; trayStripItem.Tag = MenuItems.Config; trayStripItem.Click += OnClickTrayItem; // add the M42Authentication tray strip item trayStripItem = new ToolStripSeparator(); cms.Items.Add(trayStripItem); trayStripItem = cms.Items.Add(Properties.Resources.m42Authentication); trayStripItem.Tag = MenuItems.M42Authentication; trayStripItem.Click += OnClickTrayItem; // add the close tray strip item trayStripItem = new System.Windows.Forms.ToolStripSeparator(); trayStripItem.Visible = !ConfigSettings.GetConfig()._disableClosing; cms.Items.Add(trayStripItem); trayClosingStripSeparator = trayStripItem; trayStripItem = cms.Items.Add(Properties.Resources.close); trayStripItem.Image = Properties.Resources.CloseMenu; trayStripItem.Tag = MenuItems.Close; trayStripItem.Visible = !ConfigSettings.GetConfig()._disableClosing; trayStripItem.Click += OnClickTrayItem; trayClosingItem = trayStripItem; notifyIcon.ContextMenuStrip = cms; RefreshTrayMenu(true); } catch (Exception ex) { LogEntry($"Ausnahme in {methodInfo.Name}: {ex.Message}", LogLevels.Debug); LogException(ex); } finally { LogMethodEnd(methodInfo); } } private void SetVisible(UIElement element) { AnnouncementCtrl.Visibility = (element is Announcements) ? Visibility.Visible : Visibility.Collapsed; CustomLinksCtrl.Visibility = (element is CustomLinks) ? Visibility.Visible : Visibility.Collapsed; PortalSearchCtrl.Visibility = (element is PortalSearch) ? Visibility.Visible : Visibility.Collapsed; IncidentCtrl.Visibility = (element is Incidents) ? Visibility.Visible : Visibility.Collapsed; ComputerInfoCtrl.Visibility = (element is C4IT_CustomerPanel.UserControls.ComputerInformation) ? Visibility.Visible : Visibility.Collapsed; } private void ShowTabContent(Canvas p, Button bu) { if (bu == null || p == null) return; switch (bu.Name) { case "BtnAnnouncements": SetVisible(AnnouncementCtrl); break; case "BtnInfo": SetVisible(ComputerInfoCtrl); break; case "BtnIncident": SetVisible(IncidentCtrl); break; case "BtnCustomLink": SetVisible(CustomLinksCtrl); break; case "BtnSsp": SetVisible(PortalSearchCtrl); break; } } private FrameworkElement GetActiveTabIndicator(Button button) { return button == null ? null : visualHelper.FindVisualChild(button, "ActiveIndicator"); } private FrameworkElement GetActiveTabIcon(Button button) { return button == null ? null : visualHelper.FindVisualChild(button, "ActiveIcon"); } private SolidColorBrush GetNavigationHoverBrush() { if (ConfigSettings == null) return System.Windows.Media.Brushes.Transparent; Color hoverColor = ConfigSettings.GetButtonHoverColor(ConfigSettings.GetBackgroundColor().Color, 1.30); return new SolidColorBrush(hoverColor); } public void SetMenuAktivInaktiv(object sender, bool force, bool Silent = false) { Button clickedButton = (Button)sender; ShowTabContent(this.StPaMain, clickedButton); SolidColorBrush navHoverBrush = GetNavigationHoverBrush(); if (ActiveButton != clickedButton) { clickedButton.Background = clickedButton.IsMouseOver ? navHoverBrush : System.Windows.Media.Brushes.Transparent; FrameworkElement activeIndicator = GetActiveTabIndicator(clickedButton); if (activeIndicator != null) activeIndicator.Visibility = Visibility.Visible; FrameworkElement activeIcon = GetActiveTabIcon(clickedButton); if (activeIcon != null) activeIcon.Visibility = Visibility.Visible; if (ActiveButton != null) { ActiveButton.Background = ActiveButton.IsMouseOver ? navHoverBrush : System.Windows.Media.Brushes.Transparent; FrameworkElement inactiveIndicator = GetActiveTabIndicator(ActiveButton); if (inactiveIndicator != null) inactiveIndicator.Visibility = Visibility.Hidden; FrameworkElement inactiveIcon = GetActiveTabIcon(ActiveButton); if (inactiveIcon != null) inactiveIcon.Visibility = Visibility.Hidden; } ActiveButton = clickedButton; } if (this.WindowState == WindowState.Minimized && !Silent) this.ShowMainForm(force); return; } private async Task CheckCustomerPanelCloseClients() { string strRes; try { using (var _http = ConfigSettings.m42WebClient.GetHttp()) { strRes = await _http.GetApiJsonAsync(ApiCloseAllClientsUrl, "Getting Close all clients"); } if (string.IsNullOrEmpty(strRes)) { strRes = "[]"; return false; } else { return ConverterHelper.ObjectToBoolConverter(JsonConvert.DeserializeObject(strRes)); } } catch (Exception e) { cLogManager.LogException(e); return false; } } private async Task LoadTicketsAsync() { string strRes = null; var RetVal = true; try { string reqUrl = ConfigSettings.usingGeneralAPIToken ? $"{ApiTicketsUrl}/{MainWindow.MainInstance.ConfigSettings.userInfo.Id}" : ApiTicketsUrl; LogEntry($"Requesting Tickets url: {reqUrl}", LogLevels.Debug); using (var _http = ConfigSettings.m42WebClient.GetHttp()) { strRes = await _http.GetApiJsonAsync(reqUrl, "Getting Tickets"); } if (string.IsNullOrEmpty(strRes)) { strRes = "[]"; RetVal = false; return RetVal; } } catch (Exception E) { RetVal = false; LogException(E); } List _Data = null; try { _Data = JsonConvert.DeserializeObject>(strRes); this.Dispatcher.Invoke(() => { IncidentCtrl.ProcessNewTickets(_Data); }); } catch (Exception E) { RetVal = false; _Data = null; LogException(E); } return RetVal; } private void OnBalloonTipClicked(Object sender, EventArgs e) { ControlMenu(MenuItems.Announcement, true); } public void ShowMainForm(bool force) { if (!ConfigSettings.GetPresentationMode() | force) { SetLocation(); Visibility = Visibility.Visible; WindowState = WindowState.Normal; if (Application.Current.MainWindow != null) Application.Current.MainWindow.Topmost = true; Show(); Activate(); Focus(); } } public void HideMainForm() { Hide(); Application.Current.MainWindow.WindowState = WindowState.Minimized; Application.Current.MainWindow.Topmost = false; } private void RequestApplicationShutdown() { _allowApplicationShutdown = true; Application.Current.Shutdown(); } private void ChangeLang(string lang) { System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang); System.Windows.Forms.Application.Restart(); RequestApplicationShutdown(); notifyIcon.Dispose(); } private void OnCleanUpTimerElapsed(object sender, EventArgs e) { if (GC.GetTotalMemory(true) > 50000) { int curGen = GC.GetGeneration(this); GC.Collect(curGen, GCCollectionMode.Forced); } } private void BuildCustomLinks() { try { CustomLinksCtrl.ClearLinks(); int t = 0; var LinkList = ConfigSettings.GetLinkList(); if (LinkList != null && LinkList.Count > 0) { foreach (var pair in LinkList) { Button btn = new Button(); if (!pair.Key.StartsWith("http://") & !pair.Key.StartsWith("https://")) { btn.Tag = "http://" + pair.Key; } else { btn.Tag = pair.Key; } btn.Content = pair.Value; btn.Width = 320; btn.Height = 40; btn.FontSize = 16; btn.Style = FindResource("PrimaryActionButtonStyle") as Style; btn.Margin = new Thickness(15, t == 0 ? 0 : 10, 0, 0); btn.PreviewMouseDown += OnCustomButtonClick; CustomLinksCtrl.AddLink(btn); t++; } } } catch (Exception E) { LogException(E); } } private async Task OnAnnoncementTimerReloadAsync(announcementType AnnType) { var methodInfo = MethodBase.GetCurrentMethod(); LogMethodBegin(methodInfo); try { var lastOnline = OnlineState; LogEntry($"OnAnnoncementTimerReloadAsync: Type = {AnnType}, lastOnline = {lastOnline}", LogLevels.Debug); if (OnlineState == enumOnlineState.Online) { // download the new server data var TL = new List(); if (ConfigSettings.GetConfig().MainFunctionActivation[C4IT.API.Contracts.enumMainFunctions.Announcement]) await AnnouncementCtrl.LoadAnnouncementsAsync(AnnType); } // correct the ui elements depending on server side configuration Dispatcher.Invoke(new Action(() => { UpdateNewContentSignals(); ProcessNewContentInfo(); })); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(methodInfo); } } private async Task OnReloadTimerElapsedAsync(bool force = false) { var methodInfo = MethodBase.GetCurrentMethod(); LogMethodBegin(methodInfo); try { // reload the server side configuration var lastOnline = OnlineState; await ReloadServerConfigAsync(force); if (OnlineState == enumOnlineState.Online) { // download the new server data var TL = new List { ConfigSettings.DownloadLogoAsync(), ConfigSettings.DownloadTrayIconAsync() }; if (ConfigSettings.GetConfig().MainFunctionActivation[C4IT.API.Contracts.enumMainFunctions.Incident]) TL.Add(LoadTicketsAsync()); await Task.WhenAll(TL); } // correct the ui elements depending on server side configuration Dispatcher.Invoke(new Action(() => { var SetFirstMenuEntry = OnlineState == enumOnlineState.Online && (lastOnline == enumOnlineState.Initializing || lastOnline == enumOnlineState.NoConfig); RefreshTrayMenu(SetFirstMenuEntry); UpdateNewContentSignals(); ComputerInfoCtrl.SetAppearence(); BuildCustomLinks(); UpdateLayout(); ProcessNewContentInfo(); })); } catch (Exception E) { LogException(E); } finally { Dispatcher.Invoke(new Action(() => { TimeSpan newTicketInterval = TimeSpan.FromMinutes(ConfigSettings.GetTimerIntervalTicket()); TimeSpan newAdHocInterval = TimeSpan.FromMinutes(ConfigSettings.GetTimerIntervalAdHoc()); TimeSpan newRegularInterval = TimeSpan.FromMinutes(ConfigSettings.GetTimerIntervalRegular()); bool ticketChanged = newTicketInterval != _lastTicketInterval; bool adHocChanged = newAdHocInterval != _lastAdHocInterval; bool regularChanged = newRegularInterval != _lastRegularInterval; if (ticketChanged || adHocChanged || regularChanged) { UpdateTimer(); } })); LogMethodEnd(methodInfo); } } private void ProcessNewContentInfo() { var methodInfo = MethodBase.GetCurrentMethod(); LogMethodBegin(methodInfo); try { if (ConfigSettings.GetPresentationMode()) return; foreach (var Entry in NewContentSignalsInfo) { if (ConfigSettings.EnableNotifier) { string strMsgTitle = null; switch (Entry.Key) { case enumMainFunctions.Announcement: strMsgTitle = Properties.Resources.newAnnouncement; break; case enumMainFunctions.Incident: strMsgTitle = Properties.Resources.NewTicketInfoTitle; break; } notifyIcon.Icon = NotifierIconDefault; notifyIcon.ShowBalloonTip(30000, strMsgTitle, Entry.Value, System.Windows.Forms.ToolTipIcon.Info); notifyIcon.BalloonTipClicked += OnBalloonTipClicked; System.Threading.Thread.Sleep(100); NotifyerSupport.Refresh(); } if (this.Visibility != Visibility.Visible) { var but = MainFunctionButtons[Entry.Key].button; this.SetMenuAktivInaktiv(but, false, ConfigSettings.EnableNotifier); LogEntry($"ConfigSettings.EnableNotifier: {methodInfo.Name}", LogLevels.Debug); } break; } NewContentSignalsInfo.Clear(); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(methodInfo); } } private void OnAdHocTimerElapsed(object sender, EventArgs e) { //await OnReloadTimerElapsedAsync(sender, e); _adHocTimer.Stop(); Task.Run(new Action(async () => { await OnAnnoncementTimerReloadAsync(announcementType.Adhoc); })); _adHocTimer.Start(); SetAppearance(false); } private void OnRegularTimerElapsed(object sender, EventArgs e) { _regularTimer.Stop(); Task.Run(new Action(async () => { await OnAnnoncementTimerReloadAsync(announcementType.Regular); })); _regularTimer.Start(); SetAppearance(false); } private void OnReloadTimerElapsed(object sender, EventArgs e) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { bool force = false; if (((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)) { force = true; } Task.Run(new Action(async () => { await OnReloadTimerElapsedAsync(force); })); SetAppearance(false); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private async Task ReloadServerConfigAsync(bool force = false) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (await CheckCustomerPanelCloseClients()) { Process.GetCurrentProcess().Kill(); } var bRes = await ConfigSettings.ReadConfigAsync(force); LowServerVersion = false; if (bRes) { if (ConfigSettings.GetConfig()._ServerVersion < constMinServerVersion) { LowServerVersion = true; bRes = false; LogEntry(string.Format("Server configuration version too low ({0} => {1})", ConfigSettings.GetConfig()._ServerVersion, constMinServerVersion), LogLevels.Fatal); } } if (bRes) { if (OnlineState != enumOnlineState.Online) { OnlineState = enumOnlineState.Online; OnlineStatusChanged(); } } else { if (OnlineState == enumOnlineState.Online) { OnlineState = enumOnlineState.Offline; OnlineStatusChanged(); } else if (OnlineState == enumOnlineState.Initializing) { OnlineState = enumOnlineState.NoConfig; OnlineStatusChanged(); } } } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } internal void OnlineStatusChanged() { var methodInfo = MethodBase.GetCurrentMethod(); LogMethodBegin(methodInfo); this.Dispatcher.Invoke(new Action(() => { try { string strOverlay = null; if (GetNewContentState()) strOverlay = "OverlayNew"; switch (OnlineState) { case enumOnlineState.Initializing: Connecting.Visibility = Visibility.Visible; ConnProblem.Visibility = Visibility.Collapsed; break; case enumOnlineState.NoConfig: case enumOnlineState.Offline: strOverlay = "OverlayOffline"; Connecting.Visibility = Visibility.Collapsed; ConnProblem.Visibility = Visibility.Visible; break; case enumOnlineState.Online: Connecting.Visibility = Visibility.Collapsed; ConnProblem.Visibility = Visibility.Collapsed; break; } LogEntry($"Onlinestatus: {OnlineState}"); NotifyerSupport.SetNotifyIcon("Main", strOverlay, NotifyerSupport.enumIconAlignment.BottomRight); InitializeOrUpdateTrayMenu(); } catch (Exception ex) { LogEntry($"Ausnahme in {methodInfo.Name}: {ex.Message}", LogLevels.Debug); LogException(ex); } finally { LogMethodEnd(methodInfo); } })); } public void OnClickTrayItem(object sender, EventArgs e) { System.Windows.Forms.ToolStripItem trayItem = (System.Windows.Forms.ToolStripItem)sender; switch ((MenuItems)trayItem.Tag) { case MenuItems.Config: ConfigInfo configInfo = new ConfigInfo(); configInfo.SetConfigInfo(ConfigSettings); configInfo.Show(); break; case MenuItems.M42Authentication: var frmAuthenticationSettings = new AuthenticationSettings(); frmAuthenticationSettings.ShowDialog(); break; case MenuItems.Announcement: ControlMenu(MenuItems.Announcement, true); break; case MenuItems.Incident: ControlMenu(MenuItems.Incident, true); break; case MenuItems.Ssp: ControlMenu(MenuItems.Ssp, true); break; case MenuItems.Information: ControlMenu(MenuItems.Information, true); break; case MenuItems.CustomLink: ControlMenu(MenuItems.CustomLink, true); break; case MenuItems.Close: notifyIcon.Dispose(); OnCloseClicked(sender, null); break; } } private async Task TriggerManualRefreshAsync() { if (_manualRefreshInProgress) return; var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); _manualRefreshInProgress = true; try { bool force = ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt); if (RefreshIcon != null) RefreshIcon.IsEnabled = false; await Task.WhenAll( OnReloadTimerElapsedAsync(force), OnAnnoncementTimerReloadAsync(announcementType.Adhoc), OnAnnoncementTimerReloadAsync(announcementType.Regular)); SetAppearance(false); } catch (Exception E) { LogException(E); } finally { if (RefreshIcon != null) RefreshIcon.IsEnabled = true; _manualRefreshInProgress = false; LogMethodEnd(CM); } } private async void OnRefreshClicked(object sender, MouseButtonEventArgs e) { await TriggerManualRefreshAsync(); } private void OnCloseClicked(object sender, MouseButtonEventArgs e) { if (sender is TextBlock) { HideMainForm(); } else { RequestApplicationShutdown(); Environment.Exit(0); } } private void OnMinimizeClicked(object sender, MouseButtonEventArgs e) { //ClearNewContentFlag(); HideMainForm(); } private async void OnRefreshButtonClick(object sender, RoutedEventArgs e) { await TriggerManualRefreshAsync(); } private void OnMinimizeButtonClick(object sender, RoutedEventArgs e) { OnMinimizeClicked(sender, null); } private void OnNotifierMenuClicked(object sender, EventArgs e) { if (!(sender is ToolStripMenuItem menuItem)) return; if (!(menuItem.Tag is bool useNotifier)) return; ConfigSettings.EnableNotifier = useNotifier; if (menuItem.OwnerItem is ToolStripMenuItem ownerItem) { foreach (var Entry in ownerItem.DropDownItems) { if (!(Entry is ToolStripMenuItem menuEntry)) continue; if (menuEntry != menuItem) menuEntry.CheckState = CheckState.Unchecked; } menuItem.CheckState = CheckState.Checked; } } private void OnPresentationModeClicked(object sender, EventArgs e) { if (!(sender is ToolStripMenuItem menuItem)) return; if (!(menuItem.Tag is MenuItems PMode)) return; switch (PMode) { case MenuItems.pmodeOS: ConfigSettings.SetPresentationMode(ConfigClass.enumPresentationMode.OS); break; case MenuItems.pmodeOn: ConfigSettings.SetPresentationMode(ConfigClass.enumPresentationMode.On); break; case MenuItems.pmodeOff: ConfigSettings.SetPresentationMode(ConfigClass.enumPresentationMode.Off); break; default: return; } if (menuItem.OwnerItem is ToolStripMenuItem ownerItem) { foreach (var Entry in ownerItem.DropDownItems) { if (!(Entry is ToolStripMenuItem menuEntry)) continue; if (menuEntry != menuItem) menuEntry.CheckState = CheckState.Unchecked; } menuItem.CheckState = CheckState.Checked; } } private void OnLanguageClicked(object sender, EventArgs e) { if (!(sender is ToolStripMenuItem menuItem)) return; if (!(menuItem.Tag is MenuItems Lang)) return; var oldLanguage = ConfigSettings.GetUserLanguage(); switch (Lang) { case MenuItems.langDE: ConfigSettings.SetUserLanguage(1031); break; case MenuItems.langUS: ConfigSettings.SetUserLanguage(1033); break; case MenuItems.langOS: ConfigSettings.SetUserLanguage(0); break; default: return; } if (menuItem.OwnerItem is ToolStripMenuItem ownerItem) { foreach (var Entry in ownerItem.DropDownItems) { if (!(Entry is ToolStripMenuItem menuEntry)) continue; if (menuEntry != menuItem) menuEntry.CheckState = CheckState.Unchecked; } menuItem.CheckState = CheckState.Checked; } var newLanguage = ConfigSettings.GetUserLanguage(); if (newLanguage != oldLanguage) ChangeLang(InformationHelper.GetLanguageString(newLanguage)); } private void OnCustomButtonClick(object sender, EventArgs e) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { Button btn = (Button)sender; var strUrl = btn.Tag.ToString(); Uri uri = new Uri(strUrl); Process.Start(uri.ToString()); } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } } private void GridTop_MouseDown(object sender, MouseButtonEventArgs e) { if (e.OriginalSource is DependencyObject source) { if (FindVisualParent